From 7f187b24f1a6dd6b0aa79e19ef077643c5e32bfd Mon Sep 17 00:00:00 2001 From: problematicconsumer Date: Sat, 17 Feb 2024 14:49:44 +0330 Subject: [PATCH] Change ip refresh --- assets/translations/strings_en.i18n.json | 2 + .../proxy/active/active_proxy_footer.dart | 20 +++- .../proxy/active/active_proxy_notifier.dart | 40 +++++-- .../active/active_proxy_sidebar_card.dart | 16 ++- lib/features/proxy/active/ip_widget.dart | 109 +++++++++++------- 5 files changed, 132 insertions(+), 55 deletions(-) diff --git a/assets/translations/strings_en.i18n.json b/assets/translations/strings_en.i18n.json index 77a5876a..d1d4691d 100644 --- a/assets/translations/strings_en.i18n.json +++ b/assets/translations/strings_en.i18n.json @@ -125,6 +125,8 @@ "emptyProxiesMsg": "No proxies available", "delayTestTooltip": "Test Delay", "sortTooltip": "Sort Proxies", + "checkIp": "Check IP", + "unknownIp": "Unknown IP", "sortOptions": { "unsorted": "Default", "name": "Alphabetically", diff --git a/lib/features/proxy/active/active_proxy_footer.dart b/lib/features/proxy/active/active_proxy_footer.dart index 1f855fc4..0f705524 100644 --- a/lib/features/proxy/active/active_proxy_footer.dart +++ b/lib/features/proxy/active/active_proxy_footer.dart @@ -7,6 +7,7 @@ import 'package:hiddify/core/widget/animated_visibility.dart'; import 'package:hiddify/core/widget/shimmer_skeleton.dart'; import 'package:hiddify/features/proxy/active/active_proxy_notifier.dart'; import 'package:hiddify/features/proxy/active/ip_widget.dart'; +import 'package:hiddify/features/proxy/model/proxy_failure.dart'; import 'package:hiddify/features/stats/notifier/stats_notifier.dart'; import 'package:hiddify/utils/utils.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -56,12 +57,27 @@ class ActiveProxyFooter extends HookConsumerWidget { ), ], ), + AsyncError(error: final UnknownIp _) => Row( + children: [ + const Icon(FluentIcons.arrow_sync_20_regular), + const Gap(8), + UnknownIPText( + text: t.proxies.checkIp, + onTap: () async { + ref + .read(ipInfoNotifierProvider.notifier) + .refresh(); + }, + ), + ], + ), AsyncError() => Row( children: [ const Icon(FluentIcons.error_circle_20_regular), const Gap(8), - IPText.unknown( - onLongPress: () async { + UnknownIPText( + text: t.proxies.unknownIp, + onTap: () async { ref .read(ipInfoNotifierProvider.notifier) .refresh(); diff --git a/lib/features/proxy/active/active_proxy_notifier.dart b/lib/features/proxy/active/active_proxy_notifier.dart index 1b60bc31..6b7cb260 100644 --- a/lib/features/proxy/active/active_proxy_notifier.dart +++ b/lib/features/proxy/active/active_proxy_notifier.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:dio/dio.dart'; import 'package:hiddify/core/haptic/haptic_service.dart'; import 'package:hiddify/core/preferences/general_preferences.dart'; @@ -19,21 +21,32 @@ class IpInfoNotifier extends _$IpInfoNotifier with AppLogger { Future build() async { ref.disposeDelay(const Duration(seconds: 20)); final cancelToken = CancelToken(); + Timer? timer; ref.onDispose(() { loggy.debug("disposing"); cancelToken.cancel(); + timer?.cancel(); }); + ref.listen( + serviceRunningProvider, + (_, next) => _idle = false, + ); + final autoCheck = ref.watch(autoCheckIpProvider); final serviceRunning = await ref.watch(serviceRunningProvider.future); - if (!_userRequestedFetch && !serviceRunning) { + // loggy.debug( + // "idle? [$_idle], forced? [$_forceCheck], connected? [$serviceRunning]", + // ); + if (!_forceCheck && !serviceRunning) { throw const ServiceNotRunning(); - } else if (!_userRequestedFetch && serviceRunning && !autoCheck) { + } else if ((_idle && !_forceCheck) || + (!_forceCheck && serviceRunning && !autoCheck)) { throw const UnknownIp(); } - _userRequestedFetch = false; - return ref + _forceCheck = false; + final info = await ref .watch(proxyRepositoryProvider) .getCurrentIpInfo(cancelToken) .getOrElse( @@ -42,15 +55,28 @@ class IpInfoNotifier extends _$IpInfoNotifier with AppLogger { throw err; }, ).run(); + + timer = Timer( + const Duration(seconds: 10), + () { + loggy.debug("entering idle mode"); + _idle = true; + ref.invalidateSelf(); + }, + ); + + return info; } - bool _userRequestedFetch = false; + bool _idle = false; + bool _forceCheck = false; Future refresh() async { - if (state is AsyncLoading) return; + if (state.isLoading) return; loggy.debug("refreshing"); + state = const AsyncLoading(); await ref.read(hapticServiceProvider.notifier).lightImpact(); - _userRequestedFetch = true; + _forceCheck = true; ref.invalidateSelf(); } } diff --git a/lib/features/proxy/active/active_proxy_sidebar_card.dart b/lib/features/proxy/active/active_proxy_sidebar_card.dart index a5c230b7..0e1424ab 100644 --- a/lib/features/proxy/active/active_proxy_sidebar_card.dart +++ b/lib/features/proxy/active/active_proxy_sidebar_card.dart @@ -6,6 +6,7 @@ import 'package:hiddify/core/localization/translations.dart'; import 'package:hiddify/core/widget/shimmer_skeleton.dart'; import 'package:hiddify/features/proxy/active/active_proxy_notifier.dart'; import 'package:hiddify/features/proxy/active/ip_widget.dart'; +import 'package:hiddify/features/proxy/model/proxy_failure.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; class ActiveProxySideBarCard extends HookConsumerWidget { @@ -84,10 +85,21 @@ class ActiveProxySideBarCard extends HookConsumerWidget { const Icon(FluentIcons.question_circle_20_regular), const ShimmerSkeleton(widthFactor: .85, height: 14), ), + AsyncError(error: final UnknownIp _) => buildProp( + const Icon(FluentIcons.arrow_sync_20_regular), + UnknownIPText( + text: t.proxies.checkIp, + onTap: () async { + ref.read(ipInfoNotifierProvider.notifier).refresh(); + }, + constrained: true, + ), + ), _ => buildProp( const Icon(FluentIcons.error_circle_20_regular), - IPText.unknown( - onLongPress: () async { + UnknownIPText( + text: t.proxies.unknownIp, + onTap: () async { ref.read(ipInfoNotifierProvider.notifier).refresh(); }, constrained: true, diff --git a/lib/features/proxy/active/ip_widget.dart b/lib/features/proxy/active/ip_widget.dart index 2099248c..f16d0c1f 100644 --- a/lib/features/proxy/active/ip_widget.dart +++ b/lib/features/proxy/active/ip_widget.dart @@ -12,20 +12,14 @@ final _showIp = StateProvider.autoDispose((ref) { class IPText extends HookConsumerWidget { const IPText({ - required String this.ip, - required VoidCallback this.onLongPress, + required this.ip, + required this.onLongPress, this.constrained = false, super.key, }); - const IPText.unknown({ - this.onLongPress, - this.constrained = false, - super.key, - }) : ip = null; - - final String? ip; - final VoidCallback? onLongPress; + final String ip; + final VoidCallback onLongPress; final bool constrained; @override @@ -38,46 +32,73 @@ class IPText extends HookConsumerWidget { return Semantics( label: t.proxies.ipInfoSemantics.address, child: InkWell( - onTap: ip == null - ? null - : () { - ref.read(_showIp.notifier).state = !isVisible; - }, + onTap: () { + ref.read(_showIp.notifier).state = !isVisible; + }, onLongPress: onLongPress, borderRadius: BorderRadius.circular(12), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 2), - child: switch (ip) { - final ip? => AnimatedCrossFade( - firstChild: Text( - ip, - style: ipStyle, - textDirection: TextDirection.ltr, - overflow: TextOverflow.ellipsis, - ), - secondChild: Padding( - padding: constrained - ? EdgeInsets.zero - : const EdgeInsetsDirectional.only(end: 48), - child: Text( - obscureIp(ip), - semanticsLabel: t.general.hidden, - style: ipStyle, - textDirection: TextDirection.ltr, - overflow: TextOverflow.ellipsis, - ), - ), - crossFadeState: isVisible - ? CrossFadeState.showFirst - : CrossFadeState.showSecond, - duration: const Duration(milliseconds: 200), - ), - _ => Text( - t.general.unknown, - style: constrained ? textTheme.bodySmall : ipStyle, + child: AnimatedCrossFade( + firstChild: Text( + ip, + style: ipStyle, + textDirection: TextDirection.ltr, + overflow: TextOverflow.ellipsis, + ), + secondChild: Padding( + padding: constrained + ? EdgeInsets.zero + : const EdgeInsetsDirectional.only(end: 48), + child: Text( + obscureIp(ip), + semanticsLabel: t.general.hidden, + style: ipStyle, + textDirection: TextDirection.ltr, overflow: TextOverflow.ellipsis, ), - }, + ), + crossFadeState: isVisible + ? CrossFadeState.showFirst + : CrossFadeState.showSecond, + duration: const Duration(milliseconds: 200), + ), + ), + ), + ); + } +} + +class UnknownIPText extends HookConsumerWidget { + const UnknownIPText({ + required this.text, + required this.onTap, + this.constrained = false, + super.key, + }); + + final String text; + final VoidCallback onTap; + final bool constrained; + + @override + Widget build(BuildContext context, WidgetRef ref) { + final t = ref.watch(translationsProvider); + final textTheme = Theme.of(context).textTheme; + final style = constrained ? textTheme.bodySmall : textTheme.labelMedium; + + return Semantics( + label: t.proxies.ipInfoSemantics.address, + child: InkWell( + onTap: onTap, + borderRadius: BorderRadius.circular(12), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 2), + child: Text( + text, + style: style, + overflow: TextOverflow.ellipsis, + ), ), ), );