mirror of
https://github.com/hiddify/hiddify-app.git
synced 2026-06-03 11:27:32 +00:00
189 lines
6.5 KiB
Dart
189 lines
6.5 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:go_router/go_router.dart';
|
|
import 'package:hiddify/core/localization/translations.dart';
|
|
import 'package:hiddify/core/router/dialog/dialog_notifier.dart';
|
|
import 'package:hiddify/features/connection/model/connection_status.dart';
|
|
import 'package:hiddify/features/connection/notifier/connection_notifier.dart';
|
|
import 'package:hiddify/features/proxy/active/active_proxy_notifier.dart';
|
|
import 'package:hiddify/features/proxy/active/ip_widget.dart';
|
|
import 'package:hiddify/hiddifycore/generated/v2/hcore/hcore.pb.dart';
|
|
import 'package:hiddify/utils/custom_loggers.dart';
|
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|
|
|
class ActiveProxyFooter extends ConsumerWidget with InfraLogger {
|
|
const ActiveProxyFooter({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context, WidgetRef ref) {
|
|
final connectionState = ref.watch(
|
|
connectionNotifierProvider.select((value) => value.valueOrNull ?? const Disconnected()),
|
|
);
|
|
|
|
final activeProxy = ref.watch(activeProxyNotifierProvider.select((value) => value.valueOrNull));
|
|
final t = ref.watch(translationsProvider).requireValue;
|
|
|
|
// Early return if required data is not available
|
|
if (connectionState != const Connected() || activeProxy == null) {
|
|
return const SizedBox.shrink();
|
|
}
|
|
|
|
final theme = Theme.of(context);
|
|
|
|
// Handle URL test in a way that won't trigger during build
|
|
Future<void> handleUrlTest() async {
|
|
try {
|
|
if (!context.mounted) return;
|
|
await ref.read(activeProxyNotifierProvider.notifier).urlTest("");
|
|
} catch (e) {
|
|
// Handle error here
|
|
loggy.error("Error during URL test: $e");
|
|
}
|
|
}
|
|
|
|
return Container(
|
|
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 16),
|
|
padding: const EdgeInsets.symmetric(vertical: 12),
|
|
decoration: BoxDecoration(
|
|
color: theme.colorScheme.background.withOpacity(1),
|
|
borderRadius: BorderRadius.circular(20),
|
|
boxShadow: [
|
|
BoxShadow(color: theme.colorScheme.secondary.withOpacity(.21), blurRadius: 10, offset: const Offset(0, 4)),
|
|
],
|
|
),
|
|
child: InkWell(
|
|
onTap: () {
|
|
context.goNamed('proxies');
|
|
},
|
|
child: Row(
|
|
children: [
|
|
InkWell(
|
|
onTap: () async {
|
|
await handleUrlTest();
|
|
await ref.read(dialogNotifierProvider.notifier).showProxyInfo(outboundInfo: activeProxy);
|
|
},
|
|
child: Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 8),
|
|
child: IPCountryFlag(
|
|
countryCode: activeProxy.ipinfo.countryCode,
|
|
organization: activeProxy.ipinfo.org,
|
|
size: 48,
|
|
),
|
|
),
|
|
),
|
|
Expanded(
|
|
child: Column(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Semantics(
|
|
label: t.pages.proxies.activeProxy,
|
|
child: Text(
|
|
// getRealOutboundTag(activeProxy),
|
|
activeProxy.tagDisplay,
|
|
style: theme.textTheme.bodyLarge?.copyWith(fontWeight: FontWeight.bold),
|
|
maxLines: 1,
|
|
overflow: TextOverflow.ellipsis,
|
|
),
|
|
),
|
|
const SizedBox(height: 4),
|
|
Row(
|
|
children: [
|
|
if (activeProxy.ipinfo.ip.isNotEmpty)
|
|
IPText(ip: activeProxy.ipinfo.ip, onLongPress: handleUrlTest, constrained: true)
|
|
else
|
|
UnknownIPText(text: t.pages.proxies.unknownIp, onTap: handleUrlTest),
|
|
const Spacer(),
|
|
Text(
|
|
// getRealOutboundTag(activeProxy),
|
|
activeProxy.type,
|
|
style: theme.textTheme.bodySmall?.copyWith(fontWeight: FontWeight.bold),
|
|
maxLines: 1,
|
|
overflow: TextOverflow.ellipsis,
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
const Padding(
|
|
padding: EdgeInsets.all(16.0),
|
|
child: Icon(Icons.arrow_forward_ios, color: Colors.blue),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
String getRealOutboundTag(OutboundInfo group) {
|
|
var tag = group.tagDisplay;
|
|
if (group.groupSelectedTagDisplay != "" && group.groupSelectedTagDisplay != tag) {
|
|
tag = "$tag → ${group.groupSelectedTagDisplay}";
|
|
}
|
|
return tag;
|
|
}
|
|
|
|
// class _StatsColumn extends HookConsumerWidget {
|
|
// const _StatsColumn();
|
|
|
|
// @override
|
|
// Widget build(BuildContext context, WidgetRef ref) {
|
|
// final t = ref.watch(translationsProvider).requireValue;
|
|
// final stats = ref.watch(statsNotifierProvider).value;
|
|
|
|
// return Directionality(
|
|
// textDirection: TextDirection.values[(Directionality.of(context).index + 1) % TextDirection.values.length],
|
|
// child: Flexible(
|
|
// child: Column(
|
|
// children: [
|
|
// _InfoProp(
|
|
// icon: FluentIcons.arrow_bidirectional_up_down_20_regular,
|
|
// text: (stats?.downlinkTotal ?? 0).size(),
|
|
// semanticLabel: t.stats.totalTransferred,
|
|
// ),
|
|
// const Gap(8),
|
|
// _InfoProp(
|
|
// icon: FluentIcons.arrow_download_20_regular,
|
|
// text: (stats?.downlink ?? 0).speed(),
|
|
// semanticLabel: t.stats.speed,
|
|
// ),
|
|
// ],
|
|
// ),
|
|
// ),
|
|
// );
|
|
// }
|
|
// }
|
|
|
|
// class _InfoProp extends StatelessWidget {
|
|
// const _InfoProp({
|
|
// required this.icon,
|
|
// required this.text,
|
|
// this.semanticLabel,
|
|
// });
|
|
|
|
// final IconData icon;
|
|
// final String text;
|
|
// final String? semanticLabel;
|
|
|
|
// @override
|
|
// Widget build(BuildContext context) {
|
|
// return Semantics(
|
|
// label: semanticLabel,
|
|
// child: Row(
|
|
// children: [
|
|
// Icon(icon),
|
|
// const Gap(8),
|
|
// Flexible(
|
|
// child: Text(
|
|
// text,
|
|
// style: Theme.of(context).textTheme.labelMedium?.copyWith(fontFamily: FontFamily.emoji),
|
|
// overflow: TextOverflow.ellipsis,
|
|
// ),
|
|
// ),
|
|
// ],
|
|
// ),
|
|
// );
|
|
// }
|
|
// }
|