diff --git a/core/hub.go b/core/hub.go index c212734..750eddd 100644 --- a/core/hub.go +++ b/core/hub.go @@ -21,7 +21,7 @@ import ( "unsafe" ) -var currentConfig *config.RawConfig +var currentConfig = config.DefaultRawConfig() var isInit = false @@ -235,6 +235,7 @@ func getProviders() *C.char { return C.CString(string(data)) } + //export getProvider func getProvider(name *C.char) *C.char { providerName := C.GoString(name) diff --git a/lib/clash/core.dart b/lib/clash/core.dart index cccda16..5c73d7c 100644 --- a/lib/clash/core.dart +++ b/lib/clash/core.dart @@ -69,43 +69,30 @@ class ClashCore { 1; } - List getProxiesGroups() { + Future> getProxiesGroups() { final proxiesRaw = clashFFI.getProxies(); - final proxies = json.decode(proxiesRaw.cast().toDartString()); - final groupsRaw = List.from(proxies.values).where((e) { - final excludeName = !UsedProxyExtension.valueList - .where((element) => element != UsedProxy.GLOBAL.name) - .contains(e['name']); - final validType = GroupTypeExtension.valueList.contains(e['type']); - return excludeName && validType; - }).map( - (e) { - e["all"] = ((e["all"] ?? []) as List) + final proxiesRawString = proxiesRaw.cast().toDartString(); + return Isolate.run>(() { + final proxies = json.decode(proxiesRawString); + final groupsRaw = (proxies[UsedProxy.GLOBAL.name]["all"] as List) + .where((e) { + final proxy = proxies[e]; + final excludeName = !UsedProxyExtension.valueList + .where((element) => element != UsedProxy.GLOBAL.name) + .contains(proxy['name']); + final validType = GroupTypeExtension.valueList.contains(proxy['type']); + return excludeName && validType; + }).map((groupName) { + final group = proxies[groupName]; + group["all"] = ((group["all"] ?? []) as List) .map( (name) => proxies[name], - ) + ) .toList(); - return e; - }, - ).toList() - ..sort( - (a, b) { - final aIndex = GroupTypeExtension.getGroupType(a['type'])?.index; - final bIndex = GroupTypeExtension.getGroupType(b['type'])?.index; - if (a == null && b == null) { - return 0; - } - if (a == null) { - return 1; - } - if (b == null) { - return -1; - } - return aIndex! - bIndex!; - }, - ); - final groups = groupsRaw.map((e) => Group.fromJson(e)).toList(); - return groups; + return group; + }).toList(); + return groupsRaw.map((e) => Group.fromJson(e)).toList(); + }); } bool changeProxy(ChangeProxyParams changeProxyParams) { diff --git a/lib/controller.dart b/lib/controller.dart index de2be84..c84da66 100644 --- a/lib/controller.dart +++ b/lib/controller.dart @@ -127,7 +127,7 @@ class AppController { if (value == config.currentProfileId) return; config.currentProfileId = value; await updateClashConfig(isPatch: false); - updateGroups(); + await updateGroups(); changeProxy(); appState.delayMap = {}; saveConfigPreferences(); @@ -144,13 +144,13 @@ class AppController { if (isNotNeedUpdate == false) continue; final result = await profile.update(); if (result.type == ResultType.error) continue; - updateGroups(); + await updateGroups(); changeProxy(); } } - updateGroups() { - globalState.updateGroups(appState); + Future updateGroups() async { + await globalState.updateGroups(appState); } updateSystemColorSchemes(SystemColorSchemes systemColorSchemes) { diff --git a/lib/enum/enum.dart b/lib/enum/enum.dart index d30c856..9430e2c 100644 --- a/lib/enum/enum.dart +++ b/lib/enum/enum.dart @@ -9,8 +9,7 @@ extension GroupTypeExtension on GroupType { ) .toList(); - static GroupType? getGroupType(String? value) { - if (value == null) return null; + static GroupType? getGroupType(String value) { final index = GroupTypeExtension.valueList.indexOf(value); if (index == -1) return null; return GroupType.values[index]; diff --git a/lib/fragments/proxies.dart b/lib/fragments/proxies.dart index 8d57616..e594a19 100644 --- a/lib/fragments/proxies.dart +++ b/lib/fragments/proxies.dart @@ -1,4 +1,3 @@ -import 'package:collection/collection.dart'; import 'package:fl_clash/clash/clash.dart'; import 'package:flutter/material.dart'; import 'package:flutter_adaptive_scaffold/flutter_adaptive_scaffold.dart'; @@ -57,26 +56,6 @@ class _ProxiesFragmentState extends State }); } - _updateTabController(length) { - if (_tabController != null) { - _tabController!.dispose(); - _tabController = null; - } - _tabController = TabController( - length: length, - vsync: this, - ); - } - - @override - void dispose() { - if (_tabController != null) { - _tabController!.dispose(); - _tabController = null; - } - super.dispose(); - } - @override Widget build(BuildContext context) { return Selector( @@ -87,14 +66,32 @@ class _ProxiesFragmentState extends State } return child!; }, - child: Selector2>( - selector: (_, appState, clashConfig) => - appState.getCurrentGroups(clashConfig.mode), - shouldRebuild: (prev, next) => - !const ListEquality().equals(prev, next), - builder: (_, groups, __) { + child: Selector3( + selector: (_, appState, config, clashConfig) { + final currentGroups = appState.getCurrentGroups(clashConfig.mode); + final currentProxyName = appState.getCurrentGroupNameWithGroups( + currentGroups, + config.currentGroupName, + clashConfig.mode, + ); + final currentIndex = currentGroups + .indexWhere((element) => element.name == currentProxyName); + return ProxiesSelectorState( + currentIndex: currentIndex != -1 ? currentIndex : 0, + groups: currentGroups, + ); + }, + builder: (_, state, __) { + if (_tabController != null) { + _tabController!.dispose(); + _tabController = null; + } + _tabController = TabController( + length: state.groups.length, + vsync: this, + initialIndex: state.currentIndex, + ); debugPrint("[Proxies] update===>"); - _updateTabController(groups.length); return Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, @@ -108,7 +105,7 @@ class _ProxiesFragmentState extends State overlayColor: const MaterialStatePropertyAll(Colors.transparent), tabs: [ - for (final group in groups) + for (final group in state.groups) Tab( text: group.name, ), @@ -118,7 +115,7 @@ class _ProxiesFragmentState extends State child: TabBarView( controller: _tabController, children: [ - for (final group in groups) + for (final group in state.groups) KeepContainer( child: ProxiesTabView( group: group, diff --git a/lib/models/app.dart b/lib/models/app.dart index cbeadec..4e21faf 100644 --- a/lib/models/app.dart +++ b/lib/models/app.dart @@ -165,19 +165,26 @@ class AppState with ChangeNotifier { } } - String? getCurrentGroupName(String? groupName, Mode mode) { - final currentGroups = getCurrentGroups(mode); + String? getCurrentGroupNameWithGroups( + List groups, + String? groupName, + Mode mode, + ) { switch (mode) { case Mode.direct: return null; case Mode.global: return UsedProxy.GLOBAL.name; case Mode.rule: - return groupName ?? - (currentGroups.isNotEmpty ? currentGroups.first.name : null); + return groupName ?? (groups.isNotEmpty ? groups.first.name : null); } } + String? getCurrentGroupName(String? groupName, Mode mode) { + final currentGroups = getCurrentGroups(mode); + return getCurrentGroupNameWithGroups(currentGroups, groupName, mode); + } + String? getCurrentProxyName(String? proxyName, Mode mode) { final currentGroups = getCurrentGroups(mode); switch (mode) { diff --git a/lib/models/generated/selector.freezed.dart b/lib/models/generated/selector.freezed.dart index 3a747d5..7399578 100644 --- a/lib/models/generated/selector.freezed.dart +++ b/lib/models/generated/selector.freezed.dart @@ -1740,3 +1740,150 @@ abstract class _HomeNavigationSelectorState _$$HomeNavigationSelectorStateImplCopyWith<_$HomeNavigationSelectorStateImpl> get copyWith => throw _privateConstructorUsedError; } + +/// @nodoc +mixin _$ProxiesSelectorState { + int get currentIndex => throw _privateConstructorUsedError; + List get groups => throw _privateConstructorUsedError; + + @JsonKey(ignore: true) + $ProxiesSelectorStateCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ProxiesSelectorStateCopyWith<$Res> { + factory $ProxiesSelectorStateCopyWith(ProxiesSelectorState value, + $Res Function(ProxiesSelectorState) then) = + _$ProxiesSelectorStateCopyWithImpl<$Res, ProxiesSelectorState>; + @useResult + $Res call({int currentIndex, List groups}); +} + +/// @nodoc +class _$ProxiesSelectorStateCopyWithImpl<$Res, + $Val extends ProxiesSelectorState> + implements $ProxiesSelectorStateCopyWith<$Res> { + _$ProxiesSelectorStateCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? currentIndex = null, + Object? groups = null, + }) { + return _then(_value.copyWith( + currentIndex: null == currentIndex + ? _value.currentIndex + : currentIndex // ignore: cast_nullable_to_non_nullable + as int, + groups: null == groups + ? _value.groups + : groups // ignore: cast_nullable_to_non_nullable + as List, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$ProxiesSelectorStateImplCopyWith<$Res> + implements $ProxiesSelectorStateCopyWith<$Res> { + factory _$$ProxiesSelectorStateImplCopyWith(_$ProxiesSelectorStateImpl value, + $Res Function(_$ProxiesSelectorStateImpl) then) = + __$$ProxiesSelectorStateImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({int currentIndex, List groups}); +} + +/// @nodoc +class __$$ProxiesSelectorStateImplCopyWithImpl<$Res> + extends _$ProxiesSelectorStateCopyWithImpl<$Res, _$ProxiesSelectorStateImpl> + implements _$$ProxiesSelectorStateImplCopyWith<$Res> { + __$$ProxiesSelectorStateImplCopyWithImpl(_$ProxiesSelectorStateImpl _value, + $Res Function(_$ProxiesSelectorStateImpl) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? currentIndex = null, + Object? groups = null, + }) { + return _then(_$ProxiesSelectorStateImpl( + currentIndex: null == currentIndex + ? _value.currentIndex + : currentIndex // ignore: cast_nullable_to_non_nullable + as int, + groups: null == groups + ? _value._groups + : groups // ignore: cast_nullable_to_non_nullable + as List, + )); + } +} + +/// @nodoc + +class _$ProxiesSelectorStateImpl implements _ProxiesSelectorState { + const _$ProxiesSelectorStateImpl( + {required this.currentIndex, required final List groups}) + : _groups = groups; + + @override + final int currentIndex; + final List _groups; + @override + List get groups { + if (_groups is EqualUnmodifiableListView) return _groups; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_groups); + } + + @override + String toString() { + return 'ProxiesSelectorState(currentIndex: $currentIndex, groups: $groups)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ProxiesSelectorStateImpl && + (identical(other.currentIndex, currentIndex) || + other.currentIndex == currentIndex) && + const DeepCollectionEquality().equals(other._groups, _groups)); + } + + @override + int get hashCode => Object.hash( + runtimeType, currentIndex, const DeepCollectionEquality().hash(_groups)); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$ProxiesSelectorStateImplCopyWith<_$ProxiesSelectorStateImpl> + get copyWith => + __$$ProxiesSelectorStateImplCopyWithImpl<_$ProxiesSelectorStateImpl>( + this, _$identity); +} + +abstract class _ProxiesSelectorState implements ProxiesSelectorState { + const factory _ProxiesSelectorState( + {required final int currentIndex, + required final List groups}) = _$ProxiesSelectorStateImpl; + + @override + int get currentIndex; + @override + List get groups; + @override + @JsonKey(ignore: true) + _$$ProxiesSelectorStateImplCopyWith<_$ProxiesSelectorStateImpl> + get copyWith => throw _privateConstructorUsedError; +} diff --git a/lib/models/selector.dart b/lib/models/selector.dart index 469a559..3486260 100644 --- a/lib/models/selector.dart +++ b/lib/models/selector.dart @@ -5,6 +5,7 @@ import 'config.dart'; import 'navigation.dart'; import 'package.dart'; import 'profile.dart'; +import 'proxy.dart'; part 'generated/selector.freezed.dart'; @@ -101,3 +102,12 @@ class HomeNavigationSelectorState with _$HomeNavigationSelectorState{ required String? locale, }) = _HomeNavigationSelectorState; } + +@freezed +class ProxiesSelectorState with _$ProxiesSelectorState{ + const factory ProxiesSelectorState({ + required int currentIndex, + required List groups, + }) = _ProxiesSelectorState; +} + diff --git a/lib/state.dart b/lib/state.dart index 92cb91c..62fcf01 100644 --- a/lib/state.dart +++ b/lib/state.dart @@ -166,8 +166,8 @@ class GlobalState { ); } - updateGroups(AppState appState) { - appState.groups = clashCore.getProxiesGroups(); + Future updateGroups(AppState appState) async { + appState.groups = await clashCore.getProxiesGroups(); } showMessage({