From 1b3ef4e99ce709fd9656fc68c7dfb708ad0c9e51 Mon Sep 17 00:00:00 2001 From: problematicconsumer Date: Fri, 25 Aug 2023 13:29:39 +0330 Subject: [PATCH] Change proxies page --- .../proxies/model/group_with_proxies.dart | 1 + lib/features/proxies/view/proxies_page.dart | 172 ++++++++---------- lib/features/proxies/widgets/proxy_tile.dart | 43 ++--- .../widgets/miscellaneous_setting_tiles.dart | 3 +- 4 files changed, 103 insertions(+), 116 deletions(-) diff --git a/lib/features/proxies/model/group_with_proxies.dart b/lib/features/proxies/model/group_with_proxies.dart index 3f9252b3..c9f6bb2c 100644 --- a/lib/features/proxies/model/group_with_proxies.dart +++ b/lib/features/proxies/model/group_with_proxies.dart @@ -25,6 +25,7 @@ class GroupWithProxies with _$GroupWithProxies { for (final proxy in proxies) { if (proxy is ClashProxyGroup) { // if (mode != TunnelMode.global && proxy.name == "GLOBAL") continue; + if (proxy.name == "GLOBAL") continue; final current = []; for (final name in proxy.all) { current.addAll(proxies.where((e) => e.name == name).toList()); diff --git a/lib/features/proxies/view/proxies_page.dart b/lib/features/proxies/view/proxies_page.dart index 82346131..fad1472b 100644 --- a/lib/features/proxies/view/proxies_page.dart +++ b/lib/features/proxies/view/proxies_page.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hiddify/core/core_providers.dart'; import 'package:hiddify/domain/failures.dart'; import 'package:hiddify/features/common/common.dart'; @@ -10,7 +9,6 @@ import 'package:hiddify/utils/utils.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:recase/recase.dart'; -// TODO: rewrite, bugs with scroll class ProxiesPage extends HookConsumerWidget with PresLogger { const ProxiesPage({super.key}); @@ -18,9 +16,8 @@ class ProxiesPage extends HookConsumerWidget with PresLogger { Widget build(BuildContext context, WidgetRef ref) { final t = ref.watch(translationsProvider); - final notifier = ref.watch(proxiesNotifierProvider.notifier); final asyncProxies = ref.watch(proxiesNotifierProvider); - final proxies = asyncProxies.asData?.value ?? []; + final notifier = ref.watch(proxiesNotifierProvider.notifier); final delays = ref.watch(proxiesDelayNotifierProvider); final selectActiveProxyMutation = useMutation( @@ -28,14 +25,9 @@ class ProxiesPage extends HookConsumerWidget with PresLogger { CustomToast.error(t.presentError(error)).show(context), ); - final tabController = useTabController( - initialLength: proxies.length, - keys: [proxies.length], - ); - switch (asyncProxies) { - case AsyncData(value: final proxies): - if (proxies.isEmpty) { + case AsyncData(value: final groups): + if (groups.isEmpty) { return Scaffold( body: CustomScrollView( slivers: [ @@ -55,101 +47,93 @@ class ProxiesPage extends HookConsumerWidget with PresLogger { ); } - final tabs = [ - for (final groupWithProxies in proxies) - Tab( - child: Text( - groupWithProxies.group.name.toUpperCase(), - style: TextStyle( - color: Theme.of(context).appBarTheme.foregroundColor, - ), - ), - ) - ]; + final select = groups.first; - final tabViews = [ - for (final groupWithProxies in proxies) - SafeArea( - top: false, - bottom: false, - child: Builder( - builder: (BuildContext context) { - return CustomScrollView( - key: PageStorageKey( - groupWithProxies.group.name, + return Scaffold( + body: CustomScrollView( + slivers: [ + NestedTabAppBar( + title: Text(t.proxies.pageTitle.titleCase), + actions: [ + PopupMenuButton( + itemBuilder: (_) { + return [ + PopupMenuItem( + onTap: ref + .read(proxiesDelayNotifierProvider.notifier) + .cancelDelayTest, + child: Text( + t.proxies.cancelTestButtonText.sentenceCase, + ), + ), + ]; + }, + ), + ], + ), + SliverLayoutBuilder( + builder: (context, constraints) { + final width = constraints.crossAxisExtent; + if (!PlatformUtils.isDesktop && width < 648) { + return SliverList.builder( + itemBuilder: (_, index) { + final proxy = select.proxies[index]; + return ProxyTile( + proxy, + selected: select.group.now == proxy.name, + delay: delays[proxy.name], + onSelect: () async { + if (selectActiveProxyMutation.state.isInProgress) { + return; + } + selectActiveProxyMutation.setFuture( + notifier.changeProxy( + select.group.name, + proxy.name, + ), + ); + }, + ); + }, + itemCount: select.proxies.length, + ); + } + + return SliverGrid.builder( + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: (width / 268).floor(), + mainAxisExtent: 68, ), - slivers: [ - SliverList.builder( - itemBuilder: (_, index) { - final proxy = groupWithProxies.proxies[index]; - return ProxyTile( - proxy, - selected: groupWithProxies.group.now == proxy.name, - delay: delays[proxy.name], - onSelect: () async { - if (selectActiveProxyMutation - .state.isInProgress) { - return; - } - selectActiveProxyMutation.setFuture( - notifier.changeProxy( - groupWithProxies.group.name, - proxy.name, - ), - ); - }, + itemBuilder: (context, index) { + final proxy = select.proxies[index]; + return ProxyTile( + proxy, + selected: select.group.now == proxy.name, + delay: delays[proxy.name], + onSelect: () async { + if (selectActiveProxyMutation.state.isInProgress) { + return; + } + selectActiveProxyMutation.setFuture( + notifier.changeProxy( + select.group.name, + proxy.name, + ), ); }, - itemCount: groupWithProxies.proxies.length, - ), - ], + ); + }, + itemCount: select.proxies.length, ); }, ), - ), - ]; - - return Scaffold( - body: NestedScrollView( - headerSliverBuilder: (context, innerBoxIsScrolled) { - return [ - NestedTabAppBar( - title: Text(t.proxies.pageTitle.titleCase), - forceElevated: innerBoxIsScrolled, - actions: [ - PopupMenuButton( - itemBuilder: (_) { - return [ - PopupMenuItem( - onTap: ref - .read(proxiesDelayNotifierProvider.notifier) - .cancelDelayTest, - child: Text( - t.proxies.cancelTestButtonText.sentenceCase, - ), - ), - ]; - }, - ), - ], - bottom: TabBar( - controller: tabController, - isScrollable: true, - tabs: tabs, - ), - ), - ]; - }, - body: TabBarView( - controller: tabController, - children: tabViews, - ), + ], ), floatingActionButton: FloatingActionButton( onPressed: () async => // TODO: improve ref.read(proxiesDelayNotifierProvider.notifier).testDelay( - proxies[tabController.index].proxies.map((e) => e.name), + select.proxies.map((e) => e.name), ), tooltip: t.proxies.delayTestTooltip.titleCase, child: const Icon(Icons.bolt), diff --git a/lib/features/proxies/widgets/proxy_tile.dart b/lib/features/proxies/widgets/proxy_tile.dart index 0efc5dc0..4df44905 100644 --- a/lib/features/proxies/widgets/proxy_tile.dart +++ b/lib/features/proxies/widgets/proxy_tile.dart @@ -2,7 +2,6 @@ import 'package:flutter/material.dart'; import 'package:hiddify/domain/clash/clash.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -// TODO: rewrite class ProxyTile extends HookConsumerWidget { const ProxyTile( this.proxy, { @@ -22,6 +21,7 @@ class ProxyTile extends HookConsumerWidget { final theme = Theme.of(context); return ListTile( + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), title: Text( switch (proxy) { ClashProxyGroup(:final name) => name.toUpperCase(), @@ -44,31 +44,32 @@ class ProxyTile extends HookConsumerWidget { TextSpan( children: [ TextSpan(text: proxy.type.label), - if (proxy.udp) - WidgetSpan( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 4), - child: DecoratedBox( - decoration: BoxDecoration( - border: Border.all( - color: theme.colorScheme.tertiaryContainer, - ), - borderRadius: BorderRadius.circular(6), - ), - child: Text( - " UDP ", - style: TextStyle( - fontSize: theme.textTheme.labelSmall?.fontSize, - ), - ), - ), - ), - ), + // if (proxy.udp) + // WidgetSpan( + // child: Padding( + // padding: const EdgeInsets.symmetric(horizontal: 4), + // child: DecoratedBox( + // decoration: BoxDecoration( + // border: Border.all( + // color: theme.colorScheme.tertiaryContainer, + // ), + // borderRadius: BorderRadius.circular(6), + // ), + // child: Text( + // " UDP ", + // style: TextStyle( + // fontSize: theme.textTheme.labelSmall?.fontSize, + // ), + // ), + // ), + // ), + // ), if (proxy case ClashProxyGroup(:final now)) ...[ TextSpan(text: " ($now)"), ], ], ), + overflow: TextOverflow.ellipsis, ), trailing: delay != null ? Text(delay.toString()) : null, selected: selected, diff --git a/lib/features/settings/widgets/miscellaneous_setting_tiles.dart b/lib/features/settings/widgets/miscellaneous_setting_tiles.dart index 9aaeea1b..7eef99ef 100644 --- a/lib/features/settings/widgets/miscellaneous_setting_tiles.dart +++ b/lib/features/settings/widgets/miscellaneous_setting_tiles.dart @@ -36,7 +36,8 @@ class MiscellaneousSettingTiles extends HookConsumerWidget { ), ListTile( title: Text(t.settings.miscellaneous.concurrentTestCount.titleCase), - subtitle: Text(concurrentTestCount.toString()), + trailing: Text(concurrentTestCount.toString()), + leadingAndTrailingTextStyle: Theme.of(context).textTheme.bodyMedium, onTap: () async { final val = await SettingsInputDialog( title: t.settings.miscellaneous.concurrentTestCount.titleCase,