Compare commits

..

1 Commits

Author SHA1 Message Date
chen08209
92bf322668 Add android separates the core process
Support core status check and force restart

Optimize proxies page and access page

Update flutter and pub dependencies
2025-09-05 19:55:08 +08:00
51 changed files with 596 additions and 416 deletions

View File

@@ -30,6 +30,10 @@ object Service {
delegate.bind()
}
fun unbind() {
delegate.unbind()
}
suspend fun invokeAction(
data: String, cb: (result: ByteArray?, isSuccess: Boolean) -> Unit
): Result<Unit> {

View File

@@ -57,9 +57,7 @@ class AppPlugin : FlutterPlugin, MethodChannel.MethodCallHandler, ActivityAware
private var vpnPrepareCallback: (suspend () -> Unit)? = null
private var requestNotificationCallback: (() -> Unit)? = null
private val iconMap = mutableMapOf<String, String?>()
private val packages = mutableListOf<Package>()
private val skipPrefixList = listOf(
@@ -172,8 +170,7 @@ class AppPlugin : FlutterPlugin, MethodChannel.MethodCallHandler, ActivityAware
result.success("")
return@launch
}
val path =
GlobalState.application.packageManager.getPackageIconPath(packageName)
val path = GlobalState.application.packageManager.getPackageIconPath(packageName)
result.success(path)
}
}
@@ -223,13 +220,12 @@ class AppPlugin : FlutterPlugin, MethodChannel.MethodCallHandler, ActivityAware
if (packages.isNotEmpty()) return packages
packageManager?.getInstalledPackages(PackageManager.GET_META_DATA or PackageManager.GET_PERMISSIONS)
?.filter {
it.packageName != GlobalState.application.packageName || it.packageName == "android"
it.packageName != GlobalState.application.packageName && it.packageName != "android"
}?.map {
Package(
packageName = it.packageName,
label = it.applicationInfo?.loadLabel(packageManager).toString(),
system = (it.applicationInfo?.flags?.and(ApplicationInfo.FLAG_SYSTEM)) == 1,
system = (it.applicationInfo?.flags?.and(ApplicationInfo.FLAG_SYSTEM)) != 0,
lastUpdateTime = it.lastUpdateTime,
internet = it.requestedPermissions?.contains(Manifest.permission.INTERNET) == true
)

View File

@@ -41,6 +41,10 @@ class ServicePlugin : FlutterPlugin, MethodChannel.MethodCallHandler,
handleInit(result)
}
"shutdown" -> {
handleShutdown(result)
}
"invokeAction" -> {
handleInvokeAction(call, result)
}
@@ -79,6 +83,11 @@ class ServicePlugin : FlutterPlugin, MethodChannel.MethodCallHandler,
}
}
private fun handleShutdown(result: MethodChannel.Result) {
Service.unbind()
result.success(true)
}
private fun handleStart(result: MethodChannel.Result) {
State.handleStartService()
result.success(true)

View File

@@ -102,7 +102,7 @@ class NetworkObserveModule(private val service: Service) : Module() {
return
}
preDnsList = dnsList
Core.updateDNS(dnsList.joinToString { "," })
Core.updateDNS(dnsList.toSet().joinToString(","))
}
fun setUnderlyingNetworks(network: Network) {

View File

@@ -115,11 +115,15 @@ func updateListeners() {
listeners := currentConfig.Listeners
general := currentConfig.General
listener.PatchInboundListeners(listeners, tunnel.Tunnel, true)
listener.SetAllowLan(general.AllowLan)
allowLan := general.AllowLan
listener.SetAllowLan(allowLan)
inbound.SetSkipAuthPrefixes(general.SkipAuthPrefixes)
inbound.SetAllowedIPs(general.LanAllowedIPs)
inbound.SetDisAllowedIPs(general.LanDisAllowedIPs)
listener.SetBindAddress(general.BindAddress)
bindAddress := general.BindAddress
listener.SetBindAddress(bindAddress)
listener.ReCreateHTTP(general.Port, tunnel.Tunnel)
listener.ReCreateSocks(general.SocksPort, tunnel.Tunnel)
listener.ReCreateRedir(general.RedirPort, tunnel.Tunnel)

View File

@@ -61,6 +61,7 @@ func handleStopListener() bool {
defer runLock.Unlock()
isRunning = false
listener.StopListener()
resolver.ResetConnection()
return true
}

View File

@@ -164,7 +164,7 @@ func (result ActionResult) send() {
}
invokeResult(result.callback, string(data))
if result.Method != messageMethod {
releaseObject(result.callback)
defer releaseObject(result.callback)
}
}

View File

@@ -66,7 +66,7 @@ class ApplicationState extends ConsumerState<Application> {
});
}
Widget _buildPlatformState(Widget child) {
Widget _buildPlatformState({required Widget child}) {
if (system.isDesktop) {
return WindowManager(
child: TrayManager(
@@ -77,7 +77,7 @@ class ApplicationState extends ConsumerState<Application> {
return AndroidManager(child: TileManager(child: child));
}
Widget _buildState(Widget child) {
Widget _buildState({required Widget child}) {
return AppStateManager(
child: CoreManager(
child: ConnectivityManager(
@@ -94,14 +94,14 @@ class ApplicationState extends ConsumerState<Application> {
);
}
Widget _buildPlatformApp(Widget child) {
Widget _buildPlatformApp({required Widget child}) {
if (system.isDesktop) {
return WindowHeaderContainer(child: child);
}
return VpnManager(child: child);
}
Widget _buildApp(Widget child) {
Widget _buildApp({required Widget child}) {
return MessageManager(child: ThemeManager(child: child));
}
@@ -125,9 +125,9 @@ class ApplicationState extends ConsumerState<Application> {
builder: (_, child) {
return AppEnvManager(
child: _buildApp(
_buildPlatformState(
_buildState(
AppSidebarContainer(child: _buildPlatformApp(child!)),
child: AppSidebarContainer(
child: _buildPlatformState(
child: _buildState(child: _buildPlatformApp(child: child!)),
),
),
),

View File

@@ -2,7 +2,6 @@ import 'package:fl_clash/enum/enum.dart';
import 'package:fl_clash/models/models.dart';
import 'string.dart';
import 'utils.dart';
List<Group> computeSort({
required List<Group> groups,
@@ -107,8 +106,5 @@ List<Proxy> _sortOfDelay({
}
List<Proxy> _sortOfName(List<Proxy> proxies) {
return List.of(proxies)..sort(
(a, b) =>
utils.sortByChar(utils.getPinyin(a.name), utils.getPinyin(b.name)),
);
return List.of(proxies)..sort((a, b) => a.name.compareTo(b.name));
}

View File

@@ -15,12 +15,14 @@ class Navigation {
keep: false,
icon: Icon(Icons.space_dashboard),
label: PageLabel.dashboard,
builder: (_) => const DashboardView(),
builder: (_) =>
const DashboardView(key: GlobalObjectKey(PageLabel.dashboard)),
),
NavigationItem(
icon: const Icon(Icons.article),
label: PageLabel.proxies,
builder: (_) => const ProxiesView(),
builder: (_) =>
const ProxiesView(key: GlobalObjectKey(PageLabel.proxies)),
modes: hasProxies
? [NavigationItemMode.mobile, NavigationItemMode.desktop]
: [],
@@ -28,19 +30,22 @@ class Navigation {
NavigationItem(
icon: Icon(Icons.folder),
label: PageLabel.profiles,
builder: (_) => const ProfilesView(),
builder: (_) =>
const ProfilesView(key: GlobalObjectKey(PageLabel.profiles)),
),
NavigationItem(
icon: Icon(Icons.view_timeline),
label: PageLabel.requests,
builder: (_) => const RequestsView(),
builder: (_) =>
const RequestsView(key: GlobalObjectKey(PageLabel.requests)),
description: 'requestsDesc',
modes: [NavigationItemMode.desktop, NavigationItemMode.more],
),
NavigationItem(
icon: Icon(Icons.ballot),
label: PageLabel.connections,
builder: (_) => const ConnectionsView(),
builder: (_) =>
const ConnectionsView(key: GlobalObjectKey(PageLabel.connections)),
description: 'connectionsDesc',
modes: [NavigationItemMode.desktop, NavigationItemMode.more],
),
@@ -48,13 +53,14 @@ class Navigation {
icon: Icon(Icons.storage),
label: PageLabel.resources,
description: 'resourcesDesc',
builder: (_) => const ResourcesView(),
builder: (_) =>
const ResourcesView(key: GlobalObjectKey(PageLabel.resources)),
modes: [NavigationItemMode.more],
),
NavigationItem(
icon: const Icon(Icons.adb),
label: PageLabel.logs,
builder: (_) => const LogsView(),
builder: (_) => const LogsView(key: GlobalObjectKey(PageLabel.logs)),
description: 'logsDesc',
modes: openLogs
? [NavigationItemMode.desktop, NavigationItemMode.more]
@@ -63,7 +69,7 @@ class Navigation {
NavigationItem(
icon: Icon(Icons.construction),
label: PageLabel.tools,
builder: (_) => const ToolsView(),
builder: (_) => const ToolsView(key: GlobalObjectKey(PageLabel.tools)),
modes: [NavigationItemMode.desktop, NavigationItemMode.mobile],
),
];

View File

@@ -8,13 +8,40 @@ import 'package:flutter/material.dart';
class BaseScrollBehavior extends MaterialScrollBehavior {
@override
Set<PointerDeviceKind> get dragDevices => {
PointerDeviceKind.touch,
PointerDeviceKind.stylus,
PointerDeviceKind.invertedStylus,
PointerDeviceKind.trackpad,
if (system.isDesktop) PointerDeviceKind.mouse,
PointerDeviceKind.unknown,
};
PointerDeviceKind.touch,
PointerDeviceKind.stylus,
PointerDeviceKind.invertedStylus,
PointerDeviceKind.trackpad,
if (system.isDesktop) PointerDeviceKind.mouse,
PointerDeviceKind.unknown,
};
@override
Widget buildScrollbar(
BuildContext context,
Widget child,
ScrollableDetails details,
) {
switch (axisDirectionToAxis(details.direction)) {
case Axis.horizontal:
return child;
case Axis.vertical:
switch (getPlatform(context)) {
case TargetPlatform.linux:
case TargetPlatform.macOS:
case TargetPlatform.windows:
assert(details.controller != null);
return CommonScrollBar(
controller: details.controller,
child: child,
);
case TargetPlatform.android:
case TargetPlatform.fuchsia:
case TargetPlatform.iOS:
return child;
}
}
}
}
class HiddenBarScrollBehavior extends BaseScrollBehavior {
@@ -35,10 +62,7 @@ class ShowBarScrollBehavior extends BaseScrollBehavior {
Widget child,
ScrollableDetails details,
) {
return CommonScrollBar(
controller: details.controller,
child: child,
);
return CommonScrollBar(controller: details.controller, child: child);
}
}
@@ -52,7 +76,9 @@ class NextClampingScrollPhysics extends ClampingScrollPhysics {
@override
Simulation? createBallisticSimulation(
ScrollMetrics position, double velocity) {
ScrollMetrics position,
double velocity,
) {
final Tolerance tolerance = toleranceFor(position);
if (position.outOfRange) {
double? end;

View File

@@ -8,7 +8,6 @@ import 'package:fl_clash/enum/enum.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:lpinyin/lpinyin.dart';
class Utils {
Color? getDelayColor(int? delay) {
@@ -178,11 +177,11 @@ class Utils {
return build1.compareTo(build2);
}
String getPinyin(String value) {
return value.isNotEmpty
? PinyinHelper.getFirstWordPinyin(value.substring(0, 1))
: '';
}
// String getPinyin(String value) {
// return value.isNotEmpty
// ? PinyinHelper.getFirstWordPinyin(value.substring(0, 1))
// : '';
// }
String? getFileNameForDisposition(String? disposition) {
if (disposition == null) return null;
@@ -228,7 +227,7 @@ class Utils {
}
int getProxiesColumns(double viewWidth, ProxiesLayout proxiesLayout) {
final columns = max((viewWidth / 300).ceil(), 2);
final columns = max((viewWidth / 250).ceil(), 2);
return switch (proxiesLayout) {
ProxiesLayout.tight => columns + 1,
ProxiesLayout.standard => columns,
@@ -237,7 +236,7 @@ class Utils {
}
int getProfilesColumns(double viewWidth) {
return max((viewWidth / 320).floor(), 1);
return max((viewWidth / 280).floor(), 1);
}
final _indexPrimary = [50, 100, 200, 300, 400, 500, 600, 700, 800, 850, 900];

View File

@@ -3,7 +3,6 @@ import 'dart:io';
import 'package:fl_clash/common/common.dart';
import 'package:fl_clash/state.dart';
import 'package:flutter/material.dart';
import 'package:flutter_acrylic/flutter_acrylic.dart' as acrylic;
import 'package:screen_retriever/screen_retriever.dart';
import 'package:window_manager/window_manager.dart';
@@ -19,9 +18,6 @@ class Window {
protocol.register('clashmeta');
protocol.register('flclash');
}
if ((version > 10 && system.isMacOS)) {
await acrylic.Window.initialize();
}
await windowManager.ensureInitialized();
WindowOptions windowOptions = WindowOptions(
size: Size(props.width, props.height),
@@ -39,25 +35,18 @@ class Window {
await windowManager.setAlignment(Alignment.center);
} else {
final displays = await screenRetriever.getAllDisplays();
final isPositionValid = displays.any(
(display) {
final displayBounds = Rect.fromLTWH(
display.visiblePosition!.dx,
display.visiblePosition!.dy,
display.size.width,
display.size.height,
);
return displayBounds.contains(Offset(left, top)) ||
displayBounds.contains(Offset(right, bottom));
},
);
if (isPositionValid) {
await windowManager.setPosition(
Offset(
left,
top,
),
final isPositionValid = displays.any((display) {
final displayBounds = Rect.fromLTWH(
display.visiblePosition!.dx,
display.visiblePosition!.dy,
display.size.width,
display.size.height,
);
return displayBounds.contains(Offset(left, top)) ||
displayBounds.contains(Offset(right, bottom));
});
if (isPositionValid) {
await windowManager.setPosition(Offset(left, top));
}
}
}
@@ -66,13 +55,6 @@ class Window {
});
}
void updateMacOSBrightness(Brightness brightness) {
if (!system.isMacOS) {
return;
}
acrylic.Window.overrideMacOSBrightness(dark: brightness == Brightness.dark);
}
Future<void> show() async {
render?.resume();
await windowManager.show();

View File

@@ -73,6 +73,7 @@ class AppController {
}
Future<void> restartCore() async {
globalState.isUserDisconnected = true;
await coreController.shutdown();
await _connectCore();
await _initCore();
@@ -561,9 +562,7 @@ class AppController {
}
return;
}
Future.delayed(const Duration(milliseconds: 600), () {
_ref.read(coreStatusProvider.notifier).value = CoreStatus.connected;
});
_ref.read(coreStatusProvider.notifier).value = CoreStatus.connected;
}
Future<void> _initStatus() async {

View File

@@ -35,6 +35,7 @@ class CoreLib extends CoreHandlerInterface {
@override
Future<bool> shutdown() async {
await service?.shutdown();
_connectedCompleter = Completer();
return true;
}

View File

@@ -7,7 +7,6 @@ import 'package:fl_clash/providers/providers.dart';
import 'package:fl_clash/state.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_acrylic/widgets/transparent_macos_sidebar.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:intl/intl.dart';
@@ -61,12 +60,6 @@ class _AppStateManagerState extends ConsumerState<AppStateManager>
macOS?.updateDns(true);
}
});
ref.listenManual(currentBrightnessProvider, (prev, next) {
if (prev == next) {
return;
}
window?.updateMacOSBrightness(next);
}, fireImmediately: true);
}
@override
@@ -158,15 +151,25 @@ class AppSidebarContainer extends ConsumerWidget {
required BuildContext context,
required Widget child,
}) {
if (!system.isMacOS) {
return Material(
color: context.colorScheme.surfaceContainer,
child: child,
);
}
return TransparentMacOSSidebar(
child: Material(color: Colors.transparent, child: child),
);
return Material(color: context.colorScheme.surfaceContainer, child: child);
// if (!system.isMacOS) {
// return Material(
// color: context.colorScheme.surfaceContainer,
// child: child,
// );
// }
// return child;
// return TransparentMacOSSidebar(
// child: Material(color: Colors.transparent, child: child),
// );
}
void _updateSideBarWidth(WidgetRef ref, double contentWidth) {
WidgetsBinding.instance.addPostFrameCallback((_) {
ref.read(sideWidthProvider.notifier).value =
ref.read(viewSizeProvider.select((state) => state.width)) -
contentWidth;
});
}
@override
@@ -178,7 +181,7 @@ class AppSidebarContainer extends ConsumerWidget {
return child;
}
final currentIndex = navigationState.currentIndex;
final showLabel = ref.watch(appSettingProvider).showLabel;
final isExtend = ref.watch(appSettingProvider).showLabel;
return Row(
children: [
Stack(
@@ -186,71 +189,106 @@ class AppSidebarContainer extends ConsumerWidget {
children: [
_buildBackground(
context: context,
child: Column(
children: [
SizedBox(height: 32),
if (!system.isMacOS) ...[AppIcon(), SizedBox(height: 12)],
Expanded(
child: ScrollConfiguration(
behavior: HiddenBarScrollBehavior(),
child: SingleChildScrollView(
child: IntrinsicHeight(
child: NavigationRail(
backgroundColor: Colors.transparent,
selectedLabelTextStyle: context
.textTheme
.labelLarge!
.copyWith(color: context.colorScheme.onSurface),
unselectedLabelTextStyle: context
.textTheme
.labelLarge!
.copyWith(color: context.colorScheme.onSurface),
destinations: navigationItems
.map(
(e) => NavigationRailDestination(
icon: e.icon,
label: Text(Intl.message(e.label.name)),
),
)
.toList(),
onDestinationSelected: (index) {
globalState.appController.toPage(
navigationItems[index].label,
);
},
extended: false,
selectedIndex: currentIndex,
labelType: showLabel
? NavigationRailLabelType.all
: NavigationRailLabelType.none,
child: SafeArea(
child: AnimatedSize(
curve: Curves.easeOut,
alignment: Alignment.centerLeft,
duration: commonDuration,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (system.isMacOS) SizedBox(height: 22),
SizedBox(height: 10),
if (!system.isMacOS) ...[
ClipRect(
child: Padding(
padding: EdgeInsets.only(left: 20),
child: AppIcon(),
),
),
SizedBox(height: 12),
],
Expanded(
child: ScrollConfiguration(
behavior: HiddenBarScrollBehavior(),
child: SingleChildScrollView(
child: IntrinsicHeight(
child: NavigationRail(
backgroundColor: Colors.transparent,
selectedLabelTextStyle: context
.textTheme
.labelLarge!
.copyWith(
color: context.colorScheme.onSurface,
),
unselectedLabelTextStyle: context
.textTheme
.labelLarge!
.copyWith(
color: context.colorScheme.onSurface,
),
destinations: navigationItems
.map(
(e) => NavigationRailDestination(
icon: e.icon,
label: Text(Intl.message(e.label.name)),
),
)
.toList(),
onDestinationSelected: (index) {
globalState.appController.toPage(
navigationItems[index].label,
);
},
extended: isExtend,
selectedIndex: currentIndex,
// labelType: showLabel
// ? NavigationRailLabelType.all
// : NavigationRailLabelType.none,
),
),
),
),
),
),
const SizedBox(height: 16),
Padding(
padding: EdgeInsets.only(left: 20),
child: IconButton(
onPressed: () {
ref
.read(appSettingProvider.notifier)
.updateState(
(state) => state.copyWith(
showLabel: !state.showLabel,
),
);
},
icon: Icon(
Icons.menu,
color: context.colorScheme.onSurfaceVariant,
),
),
),
const SizedBox(height: 16),
],
),
const SizedBox(height: 16),
IconButton(
onPressed: () {
ref
.read(appSettingProvider.notifier)
.updateState(
(state) =>
state.copyWith(showLabel: !state.showLabel),
);
},
icon: Icon(
Icons.menu,
color: context.colorScheme.onSurfaceVariant,
),
),
const SizedBox(height: 16),
],
),
),
),
_buildLoading(),
],
),
Expanded(flex: 1, child: ClipRect(child: child)),
Expanded(
flex: 1,
child: ClipRect(
child: LayoutBuilder(
builder: (_, constraints) {
_updateSideBarWidth(ref, constraints.maxWidth);
return child;
},
),
),
),
],
);
}

View File

@@ -93,7 +93,10 @@ class _CoreContainerState extends ConsumerState<CoreManager>
@override
Future<void> onCrash(String message) async {
context.showNotifier(message);
if (!globalState.isUserDisconnected) {
context.showNotifier(message);
globalState.isUserDisconnected = false;
}
if (ref.read(coreStatusProvider) != CoreStatus.connected) {
return;
}

View File

@@ -13,10 +13,7 @@ import '../providers/state.dart';
class ThemeManager extends ConsumerWidget {
final Widget child;
const ThemeManager({
super.key,
required this.child,
});
const ThemeManager({super.key, required this.child});
Widget _buildSystemUi(Widget child) {
if (!system.isAndroid) {
@@ -85,9 +82,7 @@ class ThemeManager extends ConsumerWidget {
final height = MediaQuery.of(context).size.height;
return MediaQuery(
data: MediaQuery.of(context).copyWith(
textScaler: TextScaler.linear(
textScaleFactor,
),
textScaler: TextScaler.linear(textScaleFactor),
padding: padding.copyWith(
top: padding.top > height * 0.3 ? 20.0 : padding.top,
),
@@ -95,10 +90,7 @@ class ThemeManager extends ConsumerWidget {
child: LayoutBuilder(
builder: (_, container) {
globalState.appController.updateViewSize(
Size(
container.maxWidth,
container.maxHeight,
),
Size(container.maxWidth, container.maxHeight),
);
return _buildSystemUi(child);
},

View File

@@ -20,6 +20,7 @@ abstract class AppState with _$AppState {
@Default([]) List<Package> packages,
@Default(0) int sortNum,
required Size viewSize,
@Default(0) double sideWidth,
@Default({}) DelayMap delayMap,
@Default([]) List<Group> groups,
@Default(0) int checkIpNum,

View File

@@ -14,7 +14,7 @@ T _$identity<T>(T value) => value;
/// @nodoc
mixin _$AppState {
bool get isInit; bool get backBlock; PageLabel get pageLabel; List<Package> get packages; int get sortNum; Size get viewSize; DelayMap get delayMap; List<Group> get groups; int get checkIpNum; Brightness get brightness; int? get runTime; List<ExternalProvider> get providers; String? get localIp; FixedList<TrackerInfo> get requests; int get version; FixedList<Log> get logs; FixedList<Traffic> get traffics; Traffic get totalTraffic; bool get realTunEnable; bool get loading; SystemUiOverlayStyle get systemUiOverlayStyle; ProfileOverrideModel? get profileOverrideModel; Map<QueryTag, String> get queryMap; CoreStatus get coreStatus;
bool get isInit; bool get backBlock; PageLabel get pageLabel; List<Package> get packages; int get sortNum; Size get viewSize; double get sideWidth; DelayMap get delayMap; List<Group> get groups; int get checkIpNum; Brightness get brightness; int? get runTime; List<ExternalProvider> get providers; String? get localIp; FixedList<TrackerInfo> get requests; int get version; FixedList<Log> get logs; FixedList<Traffic> get traffics; Traffic get totalTraffic; bool get realTunEnable; bool get loading; SystemUiOverlayStyle get systemUiOverlayStyle; ProfileOverrideModel? get profileOverrideModel; Map<QueryTag, String> get queryMap; CoreStatus get coreStatus;
/// Create a copy of AppState
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@@ -25,16 +25,16 @@ $AppStateCopyWith<AppState> get copyWith => _$AppStateCopyWithImpl<AppState>(thi
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is AppState&&(identical(other.isInit, isInit) || other.isInit == isInit)&&(identical(other.backBlock, backBlock) || other.backBlock == backBlock)&&(identical(other.pageLabel, pageLabel) || other.pageLabel == pageLabel)&&const DeepCollectionEquality().equals(other.packages, packages)&&(identical(other.sortNum, sortNum) || other.sortNum == sortNum)&&(identical(other.viewSize, viewSize) || other.viewSize == viewSize)&&const DeepCollectionEquality().equals(other.delayMap, delayMap)&&const DeepCollectionEquality().equals(other.groups, groups)&&(identical(other.checkIpNum, checkIpNum) || other.checkIpNum == checkIpNum)&&(identical(other.brightness, brightness) || other.brightness == brightness)&&(identical(other.runTime, runTime) || other.runTime == runTime)&&const DeepCollectionEquality().equals(other.providers, providers)&&(identical(other.localIp, localIp) || other.localIp == localIp)&&(identical(other.requests, requests) || other.requests == requests)&&(identical(other.version, version) || other.version == version)&&(identical(other.logs, logs) || other.logs == logs)&&(identical(other.traffics, traffics) || other.traffics == traffics)&&(identical(other.totalTraffic, totalTraffic) || other.totalTraffic == totalTraffic)&&(identical(other.realTunEnable, realTunEnable) || other.realTunEnable == realTunEnable)&&(identical(other.loading, loading) || other.loading == loading)&&(identical(other.systemUiOverlayStyle, systemUiOverlayStyle) || other.systemUiOverlayStyle == systemUiOverlayStyle)&&(identical(other.profileOverrideModel, profileOverrideModel) || other.profileOverrideModel == profileOverrideModel)&&const DeepCollectionEquality().equals(other.queryMap, queryMap)&&(identical(other.coreStatus, coreStatus) || other.coreStatus == coreStatus));
return identical(this, other) || (other.runtimeType == runtimeType&&other is AppState&&(identical(other.isInit, isInit) || other.isInit == isInit)&&(identical(other.backBlock, backBlock) || other.backBlock == backBlock)&&(identical(other.pageLabel, pageLabel) || other.pageLabel == pageLabel)&&const DeepCollectionEquality().equals(other.packages, packages)&&(identical(other.sortNum, sortNum) || other.sortNum == sortNum)&&(identical(other.viewSize, viewSize) || other.viewSize == viewSize)&&(identical(other.sideWidth, sideWidth) || other.sideWidth == sideWidth)&&const DeepCollectionEquality().equals(other.delayMap, delayMap)&&const DeepCollectionEquality().equals(other.groups, groups)&&(identical(other.checkIpNum, checkIpNum) || other.checkIpNum == checkIpNum)&&(identical(other.brightness, brightness) || other.brightness == brightness)&&(identical(other.runTime, runTime) || other.runTime == runTime)&&const DeepCollectionEquality().equals(other.providers, providers)&&(identical(other.localIp, localIp) || other.localIp == localIp)&&(identical(other.requests, requests) || other.requests == requests)&&(identical(other.version, version) || other.version == version)&&(identical(other.logs, logs) || other.logs == logs)&&(identical(other.traffics, traffics) || other.traffics == traffics)&&(identical(other.totalTraffic, totalTraffic) || other.totalTraffic == totalTraffic)&&(identical(other.realTunEnable, realTunEnable) || other.realTunEnable == realTunEnable)&&(identical(other.loading, loading) || other.loading == loading)&&(identical(other.systemUiOverlayStyle, systemUiOverlayStyle) || other.systemUiOverlayStyle == systemUiOverlayStyle)&&(identical(other.profileOverrideModel, profileOverrideModel) || other.profileOverrideModel == profileOverrideModel)&&const DeepCollectionEquality().equals(other.queryMap, queryMap)&&(identical(other.coreStatus, coreStatus) || other.coreStatus == coreStatus));
}
@override
int get hashCode => Object.hashAll([runtimeType,isInit,backBlock,pageLabel,const DeepCollectionEquality().hash(packages),sortNum,viewSize,const DeepCollectionEquality().hash(delayMap),const DeepCollectionEquality().hash(groups),checkIpNum,brightness,runTime,const DeepCollectionEquality().hash(providers),localIp,requests,version,logs,traffics,totalTraffic,realTunEnable,loading,systemUiOverlayStyle,profileOverrideModel,const DeepCollectionEquality().hash(queryMap),coreStatus]);
int get hashCode => Object.hashAll([runtimeType,isInit,backBlock,pageLabel,const DeepCollectionEquality().hash(packages),sortNum,viewSize,sideWidth,const DeepCollectionEquality().hash(delayMap),const DeepCollectionEquality().hash(groups),checkIpNum,brightness,runTime,const DeepCollectionEquality().hash(providers),localIp,requests,version,logs,traffics,totalTraffic,realTunEnable,loading,systemUiOverlayStyle,profileOverrideModel,const DeepCollectionEquality().hash(queryMap),coreStatus]);
@override
String toString() {
return 'AppState(isInit: $isInit, backBlock: $backBlock, pageLabel: $pageLabel, packages: $packages, sortNum: $sortNum, viewSize: $viewSize, delayMap: $delayMap, groups: $groups, checkIpNum: $checkIpNum, brightness: $brightness, runTime: $runTime, providers: $providers, localIp: $localIp, requests: $requests, version: $version, logs: $logs, traffics: $traffics, totalTraffic: $totalTraffic, realTunEnable: $realTunEnable, loading: $loading, systemUiOverlayStyle: $systemUiOverlayStyle, profileOverrideModel: $profileOverrideModel, queryMap: $queryMap, coreStatus: $coreStatus)';
return 'AppState(isInit: $isInit, backBlock: $backBlock, pageLabel: $pageLabel, packages: $packages, sortNum: $sortNum, viewSize: $viewSize, sideWidth: $sideWidth, delayMap: $delayMap, groups: $groups, checkIpNum: $checkIpNum, brightness: $brightness, runTime: $runTime, providers: $providers, localIp: $localIp, requests: $requests, version: $version, logs: $logs, traffics: $traffics, totalTraffic: $totalTraffic, realTunEnable: $realTunEnable, loading: $loading, systemUiOverlayStyle: $systemUiOverlayStyle, profileOverrideModel: $profileOverrideModel, queryMap: $queryMap, coreStatus: $coreStatus)';
}
@@ -45,7 +45,7 @@ abstract mixin class $AppStateCopyWith<$Res> {
factory $AppStateCopyWith(AppState value, $Res Function(AppState) _then) = _$AppStateCopyWithImpl;
@useResult
$Res call({
bool isInit, bool backBlock, PageLabel pageLabel, List<Package> packages, int sortNum, Size viewSize, DelayMap delayMap, List<Group> groups, int checkIpNum, Brightness brightness, int? runTime, List<ExternalProvider> providers, String? localIp, FixedList<TrackerInfo> requests, int version, FixedList<Log> logs, FixedList<Traffic> traffics, Traffic totalTraffic, bool realTunEnable, bool loading, SystemUiOverlayStyle systemUiOverlayStyle, ProfileOverrideModel? profileOverrideModel, Map<QueryTag, String> queryMap, CoreStatus coreStatus
bool isInit, bool backBlock, PageLabel pageLabel, List<Package> packages, int sortNum, Size viewSize, double sideWidth, DelayMap delayMap, List<Group> groups, int checkIpNum, Brightness brightness, int? runTime, List<ExternalProvider> providers, String? localIp, FixedList<TrackerInfo> requests, int version, FixedList<Log> logs, FixedList<Traffic> traffics, Traffic totalTraffic, bool realTunEnable, bool loading, SystemUiOverlayStyle systemUiOverlayStyle, ProfileOverrideModel? profileOverrideModel, Map<QueryTag, String> queryMap, CoreStatus coreStatus
});
@@ -62,7 +62,7 @@ class _$AppStateCopyWithImpl<$Res>
/// Create a copy of AppState
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? isInit = null,Object? backBlock = null,Object? pageLabel = null,Object? packages = null,Object? sortNum = null,Object? viewSize = null,Object? delayMap = null,Object? groups = null,Object? checkIpNum = null,Object? brightness = null,Object? runTime = freezed,Object? providers = null,Object? localIp = freezed,Object? requests = null,Object? version = null,Object? logs = null,Object? traffics = null,Object? totalTraffic = null,Object? realTunEnable = null,Object? loading = null,Object? systemUiOverlayStyle = null,Object? profileOverrideModel = freezed,Object? queryMap = null,Object? coreStatus = null,}) {
@pragma('vm:prefer-inline') @override $Res call({Object? isInit = null,Object? backBlock = null,Object? pageLabel = null,Object? packages = null,Object? sortNum = null,Object? viewSize = null,Object? sideWidth = null,Object? delayMap = null,Object? groups = null,Object? checkIpNum = null,Object? brightness = null,Object? runTime = freezed,Object? providers = null,Object? localIp = freezed,Object? requests = null,Object? version = null,Object? logs = null,Object? traffics = null,Object? totalTraffic = null,Object? realTunEnable = null,Object? loading = null,Object? systemUiOverlayStyle = null,Object? profileOverrideModel = freezed,Object? queryMap = null,Object? coreStatus = null,}) {
return _then(_self.copyWith(
isInit: null == isInit ? _self.isInit : isInit // ignore: cast_nullable_to_non_nullable
as bool,backBlock: null == backBlock ? _self.backBlock : backBlock // ignore: cast_nullable_to_non_nullable
@@ -70,7 +70,8 @@ as bool,pageLabel: null == pageLabel ? _self.pageLabel : pageLabel // ignore: ca
as PageLabel,packages: null == packages ? _self.packages : packages // ignore: cast_nullable_to_non_nullable
as List<Package>,sortNum: null == sortNum ? _self.sortNum : sortNum // ignore: cast_nullable_to_non_nullable
as int,viewSize: null == viewSize ? _self.viewSize : viewSize // ignore: cast_nullable_to_non_nullable
as Size,delayMap: null == delayMap ? _self.delayMap : delayMap // ignore: cast_nullable_to_non_nullable
as Size,sideWidth: null == sideWidth ? _self.sideWidth : sideWidth // ignore: cast_nullable_to_non_nullable
as double,delayMap: null == delayMap ? _self.delayMap : delayMap // ignore: cast_nullable_to_non_nullable
as DelayMap,groups: null == groups ? _self.groups : groups // ignore: cast_nullable_to_non_nullable
as List<Group>,checkIpNum: null == checkIpNum ? _self.checkIpNum : checkIpNum // ignore: cast_nullable_to_non_nullable
as int,brightness: null == brightness ? _self.brightness : brightness // ignore: cast_nullable_to_non_nullable
@@ -194,10 +195,10 @@ return $default(_that);case _:
/// }
/// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( bool isInit, bool backBlock, PageLabel pageLabel, List<Package> packages, int sortNum, Size viewSize, DelayMap delayMap, List<Group> groups, int checkIpNum, Brightness brightness, int? runTime, List<ExternalProvider> providers, String? localIp, FixedList<TrackerInfo> requests, int version, FixedList<Log> logs, FixedList<Traffic> traffics, Traffic totalTraffic, bool realTunEnable, bool loading, SystemUiOverlayStyle systemUiOverlayStyle, ProfileOverrideModel? profileOverrideModel, Map<QueryTag, String> queryMap, CoreStatus coreStatus)? $default,{required TResult orElse(),}) {final _that = this;
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( bool isInit, bool backBlock, PageLabel pageLabel, List<Package> packages, int sortNum, Size viewSize, double sideWidth, DelayMap delayMap, List<Group> groups, int checkIpNum, Brightness brightness, int? runTime, List<ExternalProvider> providers, String? localIp, FixedList<TrackerInfo> requests, int version, FixedList<Log> logs, FixedList<Traffic> traffics, Traffic totalTraffic, bool realTunEnable, bool loading, SystemUiOverlayStyle systemUiOverlayStyle, ProfileOverrideModel? profileOverrideModel, Map<QueryTag, String> queryMap, CoreStatus coreStatus)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _AppState() when $default != null:
return $default(_that.isInit,_that.backBlock,_that.pageLabel,_that.packages,_that.sortNum,_that.viewSize,_that.delayMap,_that.groups,_that.checkIpNum,_that.brightness,_that.runTime,_that.providers,_that.localIp,_that.requests,_that.version,_that.logs,_that.traffics,_that.totalTraffic,_that.realTunEnable,_that.loading,_that.systemUiOverlayStyle,_that.profileOverrideModel,_that.queryMap,_that.coreStatus);case _:
return $default(_that.isInit,_that.backBlock,_that.pageLabel,_that.packages,_that.sortNum,_that.viewSize,_that.sideWidth,_that.delayMap,_that.groups,_that.checkIpNum,_that.brightness,_that.runTime,_that.providers,_that.localIp,_that.requests,_that.version,_that.logs,_that.traffics,_that.totalTraffic,_that.realTunEnable,_that.loading,_that.systemUiOverlayStyle,_that.profileOverrideModel,_that.queryMap,_that.coreStatus);case _:
return orElse();
}
@@ -215,10 +216,10 @@ return $default(_that.isInit,_that.backBlock,_that.pageLabel,_that.packages,_tha
/// }
/// ```
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( bool isInit, bool backBlock, PageLabel pageLabel, List<Package> packages, int sortNum, Size viewSize, DelayMap delayMap, List<Group> groups, int checkIpNum, Brightness brightness, int? runTime, List<ExternalProvider> providers, String? localIp, FixedList<TrackerInfo> requests, int version, FixedList<Log> logs, FixedList<Traffic> traffics, Traffic totalTraffic, bool realTunEnable, bool loading, SystemUiOverlayStyle systemUiOverlayStyle, ProfileOverrideModel? profileOverrideModel, Map<QueryTag, String> queryMap, CoreStatus coreStatus) $default,) {final _that = this;
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( bool isInit, bool backBlock, PageLabel pageLabel, List<Package> packages, int sortNum, Size viewSize, double sideWidth, DelayMap delayMap, List<Group> groups, int checkIpNum, Brightness brightness, int? runTime, List<ExternalProvider> providers, String? localIp, FixedList<TrackerInfo> requests, int version, FixedList<Log> logs, FixedList<Traffic> traffics, Traffic totalTraffic, bool realTunEnable, bool loading, SystemUiOverlayStyle systemUiOverlayStyle, ProfileOverrideModel? profileOverrideModel, Map<QueryTag, String> queryMap, CoreStatus coreStatus) $default,) {final _that = this;
switch (_that) {
case _AppState():
return $default(_that.isInit,_that.backBlock,_that.pageLabel,_that.packages,_that.sortNum,_that.viewSize,_that.delayMap,_that.groups,_that.checkIpNum,_that.brightness,_that.runTime,_that.providers,_that.localIp,_that.requests,_that.version,_that.logs,_that.traffics,_that.totalTraffic,_that.realTunEnable,_that.loading,_that.systemUiOverlayStyle,_that.profileOverrideModel,_that.queryMap,_that.coreStatus);case _:
return $default(_that.isInit,_that.backBlock,_that.pageLabel,_that.packages,_that.sortNum,_that.viewSize,_that.sideWidth,_that.delayMap,_that.groups,_that.checkIpNum,_that.brightness,_that.runTime,_that.providers,_that.localIp,_that.requests,_that.version,_that.logs,_that.traffics,_that.totalTraffic,_that.realTunEnable,_that.loading,_that.systemUiOverlayStyle,_that.profileOverrideModel,_that.queryMap,_that.coreStatus);case _:
throw StateError('Unexpected subclass');
}
@@ -235,10 +236,10 @@ return $default(_that.isInit,_that.backBlock,_that.pageLabel,_that.packages,_tha
/// }
/// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( bool isInit, bool backBlock, PageLabel pageLabel, List<Package> packages, int sortNum, Size viewSize, DelayMap delayMap, List<Group> groups, int checkIpNum, Brightness brightness, int? runTime, List<ExternalProvider> providers, String? localIp, FixedList<TrackerInfo> requests, int version, FixedList<Log> logs, FixedList<Traffic> traffics, Traffic totalTraffic, bool realTunEnable, bool loading, SystemUiOverlayStyle systemUiOverlayStyle, ProfileOverrideModel? profileOverrideModel, Map<QueryTag, String> queryMap, CoreStatus coreStatus)? $default,) {final _that = this;
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( bool isInit, bool backBlock, PageLabel pageLabel, List<Package> packages, int sortNum, Size viewSize, double sideWidth, DelayMap delayMap, List<Group> groups, int checkIpNum, Brightness brightness, int? runTime, List<ExternalProvider> providers, String? localIp, FixedList<TrackerInfo> requests, int version, FixedList<Log> logs, FixedList<Traffic> traffics, Traffic totalTraffic, bool realTunEnable, bool loading, SystemUiOverlayStyle systemUiOverlayStyle, ProfileOverrideModel? profileOverrideModel, Map<QueryTag, String> queryMap, CoreStatus coreStatus)? $default,) {final _that = this;
switch (_that) {
case _AppState() when $default != null:
return $default(_that.isInit,_that.backBlock,_that.pageLabel,_that.packages,_that.sortNum,_that.viewSize,_that.delayMap,_that.groups,_that.checkIpNum,_that.brightness,_that.runTime,_that.providers,_that.localIp,_that.requests,_that.version,_that.logs,_that.traffics,_that.totalTraffic,_that.realTunEnable,_that.loading,_that.systemUiOverlayStyle,_that.profileOverrideModel,_that.queryMap,_that.coreStatus);case _:
return $default(_that.isInit,_that.backBlock,_that.pageLabel,_that.packages,_that.sortNum,_that.viewSize,_that.sideWidth,_that.delayMap,_that.groups,_that.checkIpNum,_that.brightness,_that.runTime,_that.providers,_that.localIp,_that.requests,_that.version,_that.logs,_that.traffics,_that.totalTraffic,_that.realTunEnable,_that.loading,_that.systemUiOverlayStyle,_that.profileOverrideModel,_that.queryMap,_that.coreStatus);case _:
return null;
}
@@ -250,7 +251,7 @@ return $default(_that.isInit,_that.backBlock,_that.pageLabel,_that.packages,_tha
class _AppState implements AppState {
const _AppState({this.isInit = false, this.backBlock = false, this.pageLabel = PageLabel.dashboard, final List<Package> packages = const [], this.sortNum = 0, required this.viewSize, final DelayMap delayMap = const {}, final List<Group> groups = const [], this.checkIpNum = 0, required this.brightness, this.runTime, final List<ExternalProvider> providers = const [], this.localIp, required this.requests, required this.version, required this.logs, required this.traffics, required this.totalTraffic, this.realTunEnable = false, this.loading = false, required this.systemUiOverlayStyle, this.profileOverrideModel, final Map<QueryTag, String> queryMap = const {}, this.coreStatus = CoreStatus.connecting}): _packages = packages,_delayMap = delayMap,_groups = groups,_providers = providers,_queryMap = queryMap;
const _AppState({this.isInit = false, this.backBlock = false, this.pageLabel = PageLabel.dashboard, final List<Package> packages = const [], this.sortNum = 0, required this.viewSize, this.sideWidth = 0, final DelayMap delayMap = const {}, final List<Group> groups = const [], this.checkIpNum = 0, required this.brightness, this.runTime, final List<ExternalProvider> providers = const [], this.localIp, required this.requests, required this.version, required this.logs, required this.traffics, required this.totalTraffic, this.realTunEnable = false, this.loading = false, required this.systemUiOverlayStyle, this.profileOverrideModel, final Map<QueryTag, String> queryMap = const {}, this.coreStatus = CoreStatus.connecting}): _packages = packages,_delayMap = delayMap,_groups = groups,_providers = providers,_queryMap = queryMap;
@override@JsonKey() final bool isInit;
@@ -265,6 +266,7 @@ class _AppState implements AppState {
@override@JsonKey() final int sortNum;
@override final Size viewSize;
@override@JsonKey() final double sideWidth;
final DelayMap _delayMap;
@override@JsonKey() DelayMap get delayMap {
if (_delayMap is EqualUnmodifiableMapView) return _delayMap;
@@ -318,16 +320,16 @@ _$AppStateCopyWith<_AppState> get copyWith => __$AppStateCopyWithImpl<_AppState>
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _AppState&&(identical(other.isInit, isInit) || other.isInit == isInit)&&(identical(other.backBlock, backBlock) || other.backBlock == backBlock)&&(identical(other.pageLabel, pageLabel) || other.pageLabel == pageLabel)&&const DeepCollectionEquality().equals(other._packages, _packages)&&(identical(other.sortNum, sortNum) || other.sortNum == sortNum)&&(identical(other.viewSize, viewSize) || other.viewSize == viewSize)&&const DeepCollectionEquality().equals(other._delayMap, _delayMap)&&const DeepCollectionEquality().equals(other._groups, _groups)&&(identical(other.checkIpNum, checkIpNum) || other.checkIpNum == checkIpNum)&&(identical(other.brightness, brightness) || other.brightness == brightness)&&(identical(other.runTime, runTime) || other.runTime == runTime)&&const DeepCollectionEquality().equals(other._providers, _providers)&&(identical(other.localIp, localIp) || other.localIp == localIp)&&(identical(other.requests, requests) || other.requests == requests)&&(identical(other.version, version) || other.version == version)&&(identical(other.logs, logs) || other.logs == logs)&&(identical(other.traffics, traffics) || other.traffics == traffics)&&(identical(other.totalTraffic, totalTraffic) || other.totalTraffic == totalTraffic)&&(identical(other.realTunEnable, realTunEnable) || other.realTunEnable == realTunEnable)&&(identical(other.loading, loading) || other.loading == loading)&&(identical(other.systemUiOverlayStyle, systemUiOverlayStyle) || other.systemUiOverlayStyle == systemUiOverlayStyle)&&(identical(other.profileOverrideModel, profileOverrideModel) || other.profileOverrideModel == profileOverrideModel)&&const DeepCollectionEquality().equals(other._queryMap, _queryMap)&&(identical(other.coreStatus, coreStatus) || other.coreStatus == coreStatus));
return identical(this, other) || (other.runtimeType == runtimeType&&other is _AppState&&(identical(other.isInit, isInit) || other.isInit == isInit)&&(identical(other.backBlock, backBlock) || other.backBlock == backBlock)&&(identical(other.pageLabel, pageLabel) || other.pageLabel == pageLabel)&&const DeepCollectionEquality().equals(other._packages, _packages)&&(identical(other.sortNum, sortNum) || other.sortNum == sortNum)&&(identical(other.viewSize, viewSize) || other.viewSize == viewSize)&&(identical(other.sideWidth, sideWidth) || other.sideWidth == sideWidth)&&const DeepCollectionEquality().equals(other._delayMap, _delayMap)&&const DeepCollectionEquality().equals(other._groups, _groups)&&(identical(other.checkIpNum, checkIpNum) || other.checkIpNum == checkIpNum)&&(identical(other.brightness, brightness) || other.brightness == brightness)&&(identical(other.runTime, runTime) || other.runTime == runTime)&&const DeepCollectionEquality().equals(other._providers, _providers)&&(identical(other.localIp, localIp) || other.localIp == localIp)&&(identical(other.requests, requests) || other.requests == requests)&&(identical(other.version, version) || other.version == version)&&(identical(other.logs, logs) || other.logs == logs)&&(identical(other.traffics, traffics) || other.traffics == traffics)&&(identical(other.totalTraffic, totalTraffic) || other.totalTraffic == totalTraffic)&&(identical(other.realTunEnable, realTunEnable) || other.realTunEnable == realTunEnable)&&(identical(other.loading, loading) || other.loading == loading)&&(identical(other.systemUiOverlayStyle, systemUiOverlayStyle) || other.systemUiOverlayStyle == systemUiOverlayStyle)&&(identical(other.profileOverrideModel, profileOverrideModel) || other.profileOverrideModel == profileOverrideModel)&&const DeepCollectionEquality().equals(other._queryMap, _queryMap)&&(identical(other.coreStatus, coreStatus) || other.coreStatus == coreStatus));
}
@override
int get hashCode => Object.hashAll([runtimeType,isInit,backBlock,pageLabel,const DeepCollectionEquality().hash(_packages),sortNum,viewSize,const DeepCollectionEquality().hash(_delayMap),const DeepCollectionEquality().hash(_groups),checkIpNum,brightness,runTime,const DeepCollectionEquality().hash(_providers),localIp,requests,version,logs,traffics,totalTraffic,realTunEnable,loading,systemUiOverlayStyle,profileOverrideModel,const DeepCollectionEquality().hash(_queryMap),coreStatus]);
int get hashCode => Object.hashAll([runtimeType,isInit,backBlock,pageLabel,const DeepCollectionEquality().hash(_packages),sortNum,viewSize,sideWidth,const DeepCollectionEquality().hash(_delayMap),const DeepCollectionEquality().hash(_groups),checkIpNum,brightness,runTime,const DeepCollectionEquality().hash(_providers),localIp,requests,version,logs,traffics,totalTraffic,realTunEnable,loading,systemUiOverlayStyle,profileOverrideModel,const DeepCollectionEquality().hash(_queryMap),coreStatus]);
@override
String toString() {
return 'AppState(isInit: $isInit, backBlock: $backBlock, pageLabel: $pageLabel, packages: $packages, sortNum: $sortNum, viewSize: $viewSize, delayMap: $delayMap, groups: $groups, checkIpNum: $checkIpNum, brightness: $brightness, runTime: $runTime, providers: $providers, localIp: $localIp, requests: $requests, version: $version, logs: $logs, traffics: $traffics, totalTraffic: $totalTraffic, realTunEnable: $realTunEnable, loading: $loading, systemUiOverlayStyle: $systemUiOverlayStyle, profileOverrideModel: $profileOverrideModel, queryMap: $queryMap, coreStatus: $coreStatus)';
return 'AppState(isInit: $isInit, backBlock: $backBlock, pageLabel: $pageLabel, packages: $packages, sortNum: $sortNum, viewSize: $viewSize, sideWidth: $sideWidth, delayMap: $delayMap, groups: $groups, checkIpNum: $checkIpNum, brightness: $brightness, runTime: $runTime, providers: $providers, localIp: $localIp, requests: $requests, version: $version, logs: $logs, traffics: $traffics, totalTraffic: $totalTraffic, realTunEnable: $realTunEnable, loading: $loading, systemUiOverlayStyle: $systemUiOverlayStyle, profileOverrideModel: $profileOverrideModel, queryMap: $queryMap, coreStatus: $coreStatus)';
}
@@ -338,7 +340,7 @@ abstract mixin class _$AppStateCopyWith<$Res> implements $AppStateCopyWith<$Res>
factory _$AppStateCopyWith(_AppState value, $Res Function(_AppState) _then) = __$AppStateCopyWithImpl;
@override @useResult
$Res call({
bool isInit, bool backBlock, PageLabel pageLabel, List<Package> packages, int sortNum, Size viewSize, DelayMap delayMap, List<Group> groups, int checkIpNum, Brightness brightness, int? runTime, List<ExternalProvider> providers, String? localIp, FixedList<TrackerInfo> requests, int version, FixedList<Log> logs, FixedList<Traffic> traffics, Traffic totalTraffic, bool realTunEnable, bool loading, SystemUiOverlayStyle systemUiOverlayStyle, ProfileOverrideModel? profileOverrideModel, Map<QueryTag, String> queryMap, CoreStatus coreStatus
bool isInit, bool backBlock, PageLabel pageLabel, List<Package> packages, int sortNum, Size viewSize, double sideWidth, DelayMap delayMap, List<Group> groups, int checkIpNum, Brightness brightness, int? runTime, List<ExternalProvider> providers, String? localIp, FixedList<TrackerInfo> requests, int version, FixedList<Log> logs, FixedList<Traffic> traffics, Traffic totalTraffic, bool realTunEnable, bool loading, SystemUiOverlayStyle systemUiOverlayStyle, ProfileOverrideModel? profileOverrideModel, Map<QueryTag, String> queryMap, CoreStatus coreStatus
});
@@ -355,7 +357,7 @@ class __$AppStateCopyWithImpl<$Res>
/// Create a copy of AppState
/// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? isInit = null,Object? backBlock = null,Object? pageLabel = null,Object? packages = null,Object? sortNum = null,Object? viewSize = null,Object? delayMap = null,Object? groups = null,Object? checkIpNum = null,Object? brightness = null,Object? runTime = freezed,Object? providers = null,Object? localIp = freezed,Object? requests = null,Object? version = null,Object? logs = null,Object? traffics = null,Object? totalTraffic = null,Object? realTunEnable = null,Object? loading = null,Object? systemUiOverlayStyle = null,Object? profileOverrideModel = freezed,Object? queryMap = null,Object? coreStatus = null,}) {
@override @pragma('vm:prefer-inline') $Res call({Object? isInit = null,Object? backBlock = null,Object? pageLabel = null,Object? packages = null,Object? sortNum = null,Object? viewSize = null,Object? sideWidth = null,Object? delayMap = null,Object? groups = null,Object? checkIpNum = null,Object? brightness = null,Object? runTime = freezed,Object? providers = null,Object? localIp = freezed,Object? requests = null,Object? version = null,Object? logs = null,Object? traffics = null,Object? totalTraffic = null,Object? realTunEnable = null,Object? loading = null,Object? systemUiOverlayStyle = null,Object? profileOverrideModel = freezed,Object? queryMap = null,Object? coreStatus = null,}) {
return _then(_AppState(
isInit: null == isInit ? _self.isInit : isInit // ignore: cast_nullable_to_non_nullable
as bool,backBlock: null == backBlock ? _self.backBlock : backBlock // ignore: cast_nullable_to_non_nullable
@@ -363,7 +365,8 @@ as bool,pageLabel: null == pageLabel ? _self.pageLabel : pageLabel // ignore: ca
as PageLabel,packages: null == packages ? _self._packages : packages // ignore: cast_nullable_to_non_nullable
as List<Package>,sortNum: null == sortNum ? _self.sortNum : sortNum // ignore: cast_nullable_to_non_nullable
as int,viewSize: null == viewSize ? _self.viewSize : viewSize // ignore: cast_nullable_to_non_nullable
as Size,delayMap: null == delayMap ? _self._delayMap : delayMap // ignore: cast_nullable_to_non_nullable
as Size,sideWidth: null == sideWidth ? _self.sideWidth : sideWidth // ignore: cast_nullable_to_non_nullable
as double,delayMap: null == delayMap ? _self._delayMap : delayMap // ignore: cast_nullable_to_non_nullable
as DelayMap,groups: null == groups ? _self._groups : groups // ignore: cast_nullable_to_non_nullable
as List<Group>,checkIpNum: null == checkIpNum ? _self.checkIpNum : checkIpNum // ignore: cast_nullable_to_non_nullable
as int,brightness: null == brightness ? _self.brightness : brightness // ignore: cast_nullable_to_non_nullable

View File

@@ -5457,7 +5457,7 @@ $OverrideDataCopyWith<$Res> get overrideData {
/// @nodoc
mixin _$DashboardState {
List<DashboardWidget> get dashboardWidgets; double get viewWidth;
List<DashboardWidget> get dashboardWidgets; double get contentWidth;
/// Create a copy of DashboardState
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@@ -5468,16 +5468,16 @@ $DashboardStateCopyWith<DashboardState> get copyWith => _$DashboardStateCopyWith
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is DashboardState&&const DeepCollectionEquality().equals(other.dashboardWidgets, dashboardWidgets)&&(identical(other.viewWidth, viewWidth) || other.viewWidth == viewWidth));
return identical(this, other) || (other.runtimeType == runtimeType&&other is DashboardState&&const DeepCollectionEquality().equals(other.dashboardWidgets, dashboardWidgets)&&(identical(other.contentWidth, contentWidth) || other.contentWidth == contentWidth));
}
@override
int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(dashboardWidgets),viewWidth);
int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(dashboardWidgets),contentWidth);
@override
String toString() {
return 'DashboardState(dashboardWidgets: $dashboardWidgets, viewWidth: $viewWidth)';
return 'DashboardState(dashboardWidgets: $dashboardWidgets, contentWidth: $contentWidth)';
}
@@ -5488,7 +5488,7 @@ abstract mixin class $DashboardStateCopyWith<$Res> {
factory $DashboardStateCopyWith(DashboardState value, $Res Function(DashboardState) _then) = _$DashboardStateCopyWithImpl;
@useResult
$Res call({
List<DashboardWidget> dashboardWidgets, double viewWidth
List<DashboardWidget> dashboardWidgets, double contentWidth
});
@@ -5505,10 +5505,10 @@ class _$DashboardStateCopyWithImpl<$Res>
/// Create a copy of DashboardState
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? dashboardWidgets = null,Object? viewWidth = null,}) {
@pragma('vm:prefer-inline') @override $Res call({Object? dashboardWidgets = null,Object? contentWidth = null,}) {
return _then(_self.copyWith(
dashboardWidgets: null == dashboardWidgets ? _self.dashboardWidgets : dashboardWidgets // ignore: cast_nullable_to_non_nullable
as List<DashboardWidget>,viewWidth: null == viewWidth ? _self.viewWidth : viewWidth // ignore: cast_nullable_to_non_nullable
as List<DashboardWidget>,contentWidth: null == contentWidth ? _self.contentWidth : contentWidth // ignore: cast_nullable_to_non_nullable
as double,
));
}
@@ -5594,10 +5594,10 @@ return $default(_that);case _:
/// }
/// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( List<DashboardWidget> dashboardWidgets, double viewWidth)? $default,{required TResult orElse(),}) {final _that = this;
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( List<DashboardWidget> dashboardWidgets, double contentWidth)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _DashboardState() when $default != null:
return $default(_that.dashboardWidgets,_that.viewWidth);case _:
return $default(_that.dashboardWidgets,_that.contentWidth);case _:
return orElse();
}
@@ -5615,10 +5615,10 @@ return $default(_that.dashboardWidgets,_that.viewWidth);case _:
/// }
/// ```
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( List<DashboardWidget> dashboardWidgets, double viewWidth) $default,) {final _that = this;
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( List<DashboardWidget> dashboardWidgets, double contentWidth) $default,) {final _that = this;
switch (_that) {
case _DashboardState():
return $default(_that.dashboardWidgets,_that.viewWidth);case _:
return $default(_that.dashboardWidgets,_that.contentWidth);case _:
throw StateError('Unexpected subclass');
}
@@ -5635,10 +5635,10 @@ return $default(_that.dashboardWidgets,_that.viewWidth);case _:
/// }
/// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( List<DashboardWidget> dashboardWidgets, double viewWidth)? $default,) {final _that = this;
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( List<DashboardWidget> dashboardWidgets, double contentWidth)? $default,) {final _that = this;
switch (_that) {
case _DashboardState() when $default != null:
return $default(_that.dashboardWidgets,_that.viewWidth);case _:
return $default(_that.dashboardWidgets,_that.contentWidth);case _:
return null;
}
@@ -5650,7 +5650,7 @@ return $default(_that.dashboardWidgets,_that.viewWidth);case _:
class _DashboardState implements DashboardState {
const _DashboardState({required final List<DashboardWidget> dashboardWidgets, required this.viewWidth}): _dashboardWidgets = dashboardWidgets;
const _DashboardState({required final List<DashboardWidget> dashboardWidgets, required this.contentWidth}): _dashboardWidgets = dashboardWidgets;
final List<DashboardWidget> _dashboardWidgets;
@@ -5660,7 +5660,7 @@ class _DashboardState implements DashboardState {
return EqualUnmodifiableListView(_dashboardWidgets);
}
@override final double viewWidth;
@override final double contentWidth;
/// Create a copy of DashboardState
/// with the given fields replaced by the non-null parameter values.
@@ -5672,16 +5672,16 @@ _$DashboardStateCopyWith<_DashboardState> get copyWith => __$DashboardStateCopyW
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _DashboardState&&const DeepCollectionEquality().equals(other._dashboardWidgets, _dashboardWidgets)&&(identical(other.viewWidth, viewWidth) || other.viewWidth == viewWidth));
return identical(this, other) || (other.runtimeType == runtimeType&&other is _DashboardState&&const DeepCollectionEquality().equals(other._dashboardWidgets, _dashboardWidgets)&&(identical(other.contentWidth, contentWidth) || other.contentWidth == contentWidth));
}
@override
int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(_dashboardWidgets),viewWidth);
int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(_dashboardWidgets),contentWidth);
@override
String toString() {
return 'DashboardState(dashboardWidgets: $dashboardWidgets, viewWidth: $viewWidth)';
return 'DashboardState(dashboardWidgets: $dashboardWidgets, contentWidth: $contentWidth)';
}
@@ -5692,7 +5692,7 @@ abstract mixin class _$DashboardStateCopyWith<$Res> implements $DashboardStateCo
factory _$DashboardStateCopyWith(_DashboardState value, $Res Function(_DashboardState) _then) = __$DashboardStateCopyWithImpl;
@override @useResult
$Res call({
List<DashboardWidget> dashboardWidgets, double viewWidth
List<DashboardWidget> dashboardWidgets, double contentWidth
});
@@ -5709,10 +5709,10 @@ class __$DashboardStateCopyWithImpl<$Res>
/// Create a copy of DashboardState
/// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? dashboardWidgets = null,Object? viewWidth = null,}) {
@override @pragma('vm:prefer-inline') $Res call({Object? dashboardWidgets = null,Object? contentWidth = null,}) {
return _then(_DashboardState(
dashboardWidgets: null == dashboardWidgets ? _self._dashboardWidgets : dashboardWidgets // ignore: cast_nullable_to_non_nullable
as List<DashboardWidget>,viewWidth: null == viewWidth ? _self.viewWidth : viewWidth // ignore: cast_nullable_to_non_nullable
as List<DashboardWidget>,contentWidth: null == contentWidth ? _self.contentWidth : contentWidth // ignore: cast_nullable_to_non_nullable
as double,
));
}

View File

@@ -1,5 +1,4 @@
import 'package:collection/collection.dart';
import 'package:fl_clash/common/common.dart';
import 'package:fl_clash/enum/enum.dart';
import 'package:fl_clash/models/models.dart';
import 'package:flutter/material.dart';
@@ -160,25 +159,20 @@ extension PackageListSelectorStateExt on PackageListSelectorState {
List<Package> getSortList(List<String> selectedList) {
final sort = accessControl.sort;
return list
.sorted((a, b) {
return switch (sort) {
AccessSortType.none => 0,
AccessSortType.name => utils.sortByChar(
utils.getPinyin(a.label),
utils.getPinyin(b.label),
),
AccessSortType.time => b.lastUpdateTime.compareTo(a.lastUpdateTime),
};
})
.sorted((a, b) {
final isSelectA = selectedList.contains(a.packageName);
final isSelectB = selectedList.contains(b.packageName);
if (isSelectA && isSelectB) return 0;
if (isSelectA) return -1;
if (isSelectB) return 1;
return 0;
});
return list.sorted((a, b) {
final isSelectA = selectedList.contains(a.packageName);
final isSelectB = selectedList.contains(b.packageName);
if (isSelectA != isSelectB) {
return isSelectA ? -1 : 1;
}
return switch (sort) {
AccessSortType.none => 0,
AccessSortType.name => a.label.compareTo(b.label),
AccessSortType.time => b.lastUpdateTime.compareTo(a.lastUpdateTime),
};
});
}
}
@@ -224,7 +218,7 @@ abstract class ClashConfigState with _$ClashConfigState {
abstract class DashboardState with _$DashboardState {
const factory DashboardState({
required List<DashboardWidget> dashboardWidgets,
required double viewWidth,
required double contentWidth,
}) = _DashboardState;
}

View File

@@ -156,7 +156,7 @@ class _EditorPageState extends ConsumerState<EditorPage> {
Widget build(BuildContext context) {
final isMobileView = ref.watch(isMobileViewProvider);
return CommonPopScope(
onPop: () async {
onPop: (context) async {
if (widget.onPop == null) {
return true;
}

View File

@@ -15,7 +15,7 @@ class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return HomeBackScope(
return HomeBackScopeContainer(
child: Material(
color: context.colorScheme.surface,
child: Consumer(
@@ -243,27 +243,27 @@ class _NavigationBarDefaultsM3 extends NavigationBarThemeData {
}
}
class HomeBackScope extends StatelessWidget {
class HomeBackScopeContainer extends ConsumerWidget {
final Widget child;
const HomeBackScope({super.key, required this.child});
const HomeBackScopeContainer({super.key, required this.child});
@override
Widget build(BuildContext context) {
if (system.isAndroid) {
return CommonPopScope(
onPop: () async {
final canPop = Navigator.canPop(context);
if (canPop) {
Navigator.pop(context);
} else {
await globalState.appController.handleBackOrExit();
}
return false;
},
child: child,
);
}
return child;
Widget build(BuildContext context, ref) {
return CommonPopScope(
onPop: (context) async {
final pageLabel = ref.read(currentPageLabelProvider);
final realContext =
GlobalObjectKey(pageLabel).currentContext ?? context;
final canPop = Navigator.canPop(realContext);
if (canPop) {
Navigator.of(realContext).pop();
} else {
await globalState.appController.handleBackOrExit();
}
return false;
},
child: child,
);
}
}

View File

@@ -89,6 +89,10 @@ class Service {
return await methodChannel.invokeMethod<String>('init') ?? '';
}
Future<bool> shutdown() async {
return await methodChannel.invokeMethod<bool>('shutdown') ?? true;
}
Future<DateTime?> getRunTime() async {
final ms = await methodChannel.invokeMethod<int>('getRunTime') ?? 0;
if (ms == 0) {

View File

@@ -185,6 +185,19 @@ class ViewSize extends _$ViewSize with AutoDisposeNotifierMixin {
}
}
@riverpod
class SideWidth extends _$SideWidth with AutoDisposeNotifierMixin {
@override
double build() {
return globalState.appState.sideWidth;
}
@override
onUpdate(value) {
globalState.appState = globalState.appState.copyWith(sideWidth: value);
}
}
@riverpod
double viewWidth(Ref ref) {
return ref.watch(viewSizeProvider).width;

View File

@@ -587,6 +587,58 @@ abstract class _$ViewSize extends $Notifier<Size> {
}
}
@ProviderFor(SideWidth)
const sideWidthProvider = SideWidthProvider._();
final class SideWidthProvider extends $NotifierProvider<SideWidth, double> {
const SideWidthProvider._()
: super(
from: null,
argument: null,
retry: null,
name: r'sideWidthProvider',
isAutoDispose: true,
dependencies: null,
$allTransitiveDependencies: null,
);
@override
String debugGetCreateSourceHash() => _$sideWidthHash();
@$internal
@override
SideWidth create() => SideWidth();
/// {@macro riverpod.override_with_value}
Override overrideWithValue(double value) {
return $ProviderOverride(
origin: this,
providerOverride: $SyncValueProvider<double>(value),
);
}
}
String _$sideWidthHash() => r'380c2ae2136dc75346259d3c1d0dd3325e41fe49';
abstract class _$SideWidth extends $Notifier<double> {
double build();
@$mustCallSuper
@override
void runBuild() {
final created = build();
final ref = this.ref as $Ref<double, double>;
final element =
ref.element
as $ClassProviderElement<
AnyNotifier<double, double>,
double,
Object?,
Object?
>;
element.handleValue(ref, created);
}
}
@ProviderFor(viewWidth)
const viewWidthProvider = ViewWidthProvider._();

View File

@@ -392,6 +392,47 @@ final class NavigationStateProvider
String _$navigationStateHash() => r'657dc47ecc35ba0807b58cb37e7f1baa14f6c2f9';
@ProviderFor(contentWidth)
const contentWidthProvider = ContentWidthProvider._();
final class ContentWidthProvider
extends $FunctionalProvider<double, double, double>
with $Provider<double> {
const ContentWidthProvider._()
: super(
from: null,
argument: null,
retry: null,
name: r'contentWidthProvider',
isAutoDispose: true,
dependencies: null,
$allTransitiveDependencies: null,
);
@override
String debugGetCreateSourceHash() => _$contentWidthHash();
@$internal
@override
$ProviderElement<double> $createElement($ProviderPointer pointer) =>
$ProviderElement(pointer);
@override
double create(Ref ref) {
return contentWidth(ref);
}
/// {@macro riverpod.override_with_value}
Override overrideWithValue(double value) {
return $ProviderOverride(
origin: this,
providerOverride: $SyncValueProvider<double>(value),
);
}
}
String _$contentWidthHash() => r'9ac0dc2bcdc957160f59d6065cd7f846f41a95b1';
@ProviderFor(dashboardState)
const dashboardStateProvider = DashboardStateProvider._();
@@ -431,7 +472,7 @@ final class DashboardStateProvider
}
}
String _$dashboardStateHash() => r'4434206df2753d7df9eb5223c07ddead4ed170fa';
String _$dashboardStateHash() => r'e8616e327c1b96658d917e4e4950f70ecb099d85';
@ProviderFor(proxiesActionsState)
const proxiesActionsStateProvider = ProxiesActionsStateProvider._();
@@ -575,7 +616,7 @@ final class ProfilesSelectorStateProvider
}
String _$profilesSelectorStateHash() =>
r'aac2deee6e747eceaf62cb5f279ec99ce9227a5a';
r'da4a4382d7054dfe4010e44e55368d31ec805536';
@ProviderFor(filterGroupsState)
const filterGroupsStateProvider = FilterGroupsStateFamily._();
@@ -1510,7 +1551,7 @@ final class GetProxiesColumnsProvider extends $FunctionalProvider<int, int, int>
}
}
String _$getProxiesColumnsHash() => r'725066b5fc21f590a4c2656a1fd5e14ab7079079';
String _$getProxiesColumnsHash() => r'd5340932d4812727caa670065bce30450f1c4da5';
@ProviderFor(realSelectedProxyState)
const realSelectedProxyStateProvider = RealSelectedProxyStateFamily._();

View File

@@ -192,15 +192,22 @@ NavigationState navigationState(Ref ref) {
);
}
@riverpod
double contentWidth(Ref ref) {
final viewWidth = ref.watch(viewWidthProvider);
final sideWidth = ref.watch(sideWidthProvider);
return viewWidth - sideWidth;
}
@riverpod
DashboardState dashboardState(Ref ref) {
final dashboardWidgets = ref.watch(
appSettingProvider.select((state) => state.dashboardWidgets),
);
final viewWidth = ref.watch(viewWidthProvider);
final contentWidth = ref.watch(contentWidthProvider);
return DashboardState(
dashboardWidgets: dashboardWidgets,
viewWidth: viewWidth,
contentWidth: contentWidth,
);
}
@@ -234,7 +241,7 @@ ProfilesSelectorState profilesSelectorState(Ref ref) {
final currentProfileId = ref.watch(currentProfileIdProvider);
final profiles = ref.watch(profilesProvider);
final columns = ref.watch(
viewWidthProvider.select((state) => utils.getProfilesColumns(state)),
contentWidthProvider.select((state) => utils.getProfilesColumns(state)),
);
return ProfilesSelectorState(
profiles: profiles,
@@ -453,11 +460,11 @@ Profile? currentProfile(Ref ref) {
@riverpod
int getProxiesColumns(Ref ref) {
final viewWidth = ref.watch(viewWidthProvider);
final contentWidth = ref.watch(contentWidthProvider);
final proxiesLayout = ref.watch(
proxiesStyleSettingProvider.select((state) => state.layout),
);
return utils.getProxiesColumns(viewWidth, proxiesLayout);
return utils.getProxiesColumns(contentWidth, proxiesLayout);
}
@riverpod

View File

@@ -47,6 +47,7 @@ class GlobalState {
final navigatorKey = GlobalKey<NavigatorState>();
AppController? _appController;
bool isInit = false;
bool isUserDisconnected = false;
bool get isStart => startTime != null && startTime!.isBeforeNow;

View File

@@ -63,64 +63,84 @@ class _DashboardViewState extends ConsumerState<DashboardView> {
Consumer(
builder: (_, ref, _) {
final coreStatus = ref.watch(coreStatusProvider);
return FadeScaleBox(
child: coreStatus == CoreStatus.connected
? SizedBox()
: FilledButton.icon(
key: ValueKey(coreStatus),
onPressed: coreStatus == CoreStatus.connecting
? () {}
: _handleConnection,
style: FilledButton.styleFrom(
return Tooltip(
message: appLocalizations.coreStatus,
child: FadeScaleBox(
alignment: Alignment.centerRight,
child: coreStatus == CoreStatus.connected
? IconButton.filled(
visualDensity: VisualDensity.compact,
padding: EdgeInsets.symmetric(horizontal: 12),
backgroundColor: switch (coreStatus) {
CoreStatus.connecting => null,
CoreStatus.connected => Colors.greenAccent,
CoreStatus.disconnected => context.colorScheme.error,
},
foregroundColor: switch (coreStatus) {
CoreStatus.connecting => null,
CoreStatus.connected => switch (Theme.brightnessOf(
iconSize: 20,
padding: EdgeInsets.zero,
style: IconButton.styleFrom(
backgroundColor: Colors.greenAccent,
foregroundColor: switch (Theme.brightnessOf(
context,
)) {
Brightness.light =>
context.colorScheme.onSurfaceVariant,
Brightness.dark => null,
Brightness.dark =>
context.colorScheme.onPrimaryFixedVariant,
},
CoreStatus.disconnected =>
context.colorScheme.onError,
},
),
icon: SizedBox(
height: globalState.measure.bodyMediumHeight,
width: globalState.measure.bodyMediumHeight,
child: switch (coreStatus) {
CoreStatus.connecting => Padding(
padding: EdgeInsets.all(2),
child: CircularProgressIndicator(
strokeWidth: 3,
color: context.colorScheme.onPrimary,
backgroundColor: Colors.transparent,
),
onPressed: _handleConnection,
icon: Icon(Icons.check, fontWeight: FontWeight.w900),
)
: FilledButton.icon(
key: ValueKey(coreStatus),
onPressed: _handleConnection,
style: FilledButton.styleFrom(
visualDensity: VisualDensity.compact,
padding: EdgeInsets.symmetric(horizontal: 12),
backgroundColor: switch (coreStatus) {
CoreStatus.connecting => null,
CoreStatus.connected => Colors.greenAccent,
CoreStatus.disconnected =>
context.colorScheme.error,
},
foregroundColor: switch (coreStatus) {
CoreStatus.connecting => null,
CoreStatus.connected => switch (Theme.brightnessOf(
context,
)) {
Brightness.light =>
context.colorScheme.onSurfaceVariant,
Brightness.dark => null,
},
CoreStatus.disconnected =>
context.colorScheme.onError,
},
),
icon: SizedBox(
height: globalState.measure.bodyMediumHeight,
width: globalState.measure.bodyMediumHeight,
child: switch (coreStatus) {
CoreStatus.connecting => Padding(
padding: EdgeInsets.all(2),
child: CircularProgressIndicator(
strokeWidth: 3,
color: context.colorScheme.onPrimary,
backgroundColor: Colors.transparent,
),
),
),
CoreStatus.connected => Icon(
Icons.check_sharp,
fontWeight: FontWeight.w900,
),
CoreStatus.disconnected => Icon(
Icons.restart_alt_sharp,
fontWeight: FontWeight.w900,
),
},
CoreStatus.connected => Icon(
Icons.check_sharp,
fontWeight: FontWeight.w900,
),
CoreStatus.disconnected => Icon(
Icons.restart_alt_sharp,
fontWeight: FontWeight.w900,
),
},
),
label: Text(switch (coreStatus) {
CoreStatus.connecting => appLocalizations.connecting,
CoreStatus.connected => appLocalizations.connected,
CoreStatus.disconnected =>
appLocalizations.disconnected,
}),
),
label: Text(switch (coreStatus) {
CoreStatus.connecting => appLocalizations.connecting,
CoreStatus.connected => appLocalizations.connected,
CoreStatus.disconnected =>
appLocalizations.disconnected,
}),
),
),
);
},
),
@@ -207,7 +227,7 @@ class _DashboardViewState extends ConsumerState<DashboardView> {
@override
Widget build(BuildContext context) {
final dashboardState = ref.watch(dashboardStateProvider);
final columns = max(4 * ((dashboardState.viewWidth / 320).ceil()), 8);
final columns = max(4 * ((dashboardState.contentWidth / 300).ceil()), 8);
final spacing = 16.ap;
final children = [
...dashboardState.dashboardWidgets
@@ -256,7 +276,7 @@ class _DashboardViewState extends ConsumerState<DashboardView> {
_handleSave();
},
),
onPop: () {
onPop: (context) {
_handleUpdateIsEdit();
return false;
},

View File

@@ -108,56 +108,75 @@ class OutboundModeV2 extends StatelessWidget {
Mode.global => globalState.theme.darken3PrimaryContainer,
Mode.direct => context.colorScheme.tertiaryContainer,
};
return Container(
constraints: BoxConstraints.expand(),
padding: EdgeInsets.all(4.ap),
color: thumbColor.opacity38,
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: context.colorScheme.surfaceContainer,
),
padding: EdgeInsets.all(12.ap),
child: LayoutBuilder(
builder: (_, constraints) {
return CommonTabBar<Mode>(
children: Map.fromEntries(
Mode.values.map(
(item) => MapEntry(
item,
Container(
clipBehavior: Clip.antiAlias,
alignment: Alignment.center,
decoration: BoxDecoration(),
height: constraints.maxHeight,
padding: EdgeInsets.all(4),
child: Text(
Intl.message(item.name),
style: Theme.of(context).textTheme.titleSmall
?.adjustSize(1)
.copyWith(
color: item == mode
? _getTextColor(context, item)
: null,
),
return LayoutBuilder(
builder: (_, constraints) {
return Column(
mainAxisSize: MainAxisSize.max,
children: [
Expanded(
child: Container(
padding: EdgeInsets.all(12),
constraints: BoxConstraints.expand(),
child: CommonTabBar<Mode>(
children: Map.fromEntries(
Mode.values.map(
(item) => MapEntry(
item,
Container(
clipBehavior: Clip.antiAlias,
alignment: Alignment.center,
decoration: BoxDecoration(),
height: height - 8.ap - 24,
padding: EdgeInsets.all(4),
child: Text(
Intl.message(item.name),
style: Theme.of(context)
.textTheme
.titleSmall
?.adjustSize(1)
.copyWith(
color: item == mode
? _getTextColor(context, item)
: null,
),
),
),
),
),
),
padding: EdgeInsets.symmetric(horizontal: 0),
groupValue: mode,
onValueChanged: (value) {
if (value == null) {
return;
}
globalState.appController.changeMode(value);
},
thumbColor: thumbColor,
),
),
padding: EdgeInsets.symmetric(horizontal: 0),
groupValue: mode,
onValueChanged: (value) {
if (value == null) {
return;
}
globalState.appController.changeMode(value);
},
thumbColor: thumbColor,
);
},
),
),
),
Container(
color: thumbColor.opacity50,
height: 8.ap,
width: constraints.maxWidth,
padding: EdgeInsets.symmetric(horizontal: 16),
// child: Row(
// children: [
// Container(
// width: (constraints.maxWidth - 32) / 3,
// height: 3,
// decoration: BoxDecoration(
// color: _getTextColor(context, mode),
// borderRadius: BorderRadius.circular(2),
// ),
// ),
// ],
// ),
),
],
);
},
);
},
),

View File

@@ -306,7 +306,7 @@ class _EditProfileViewState extends State<EditProfileView> {
),
];
return CommonPopScope(
onPop: () {
onPop: (context) {
if (fileData == null) {
return true;
}

View File

@@ -214,7 +214,7 @@ class _OverrideProfileViewState extends ConsumerState<OverrideProfileView> {
return SizedBox();
}
return CommonPopScope(
onPop: () async {
onPop: (context) async {
if (equals) {
return true;
}

View File

@@ -237,7 +237,7 @@ class ProfileItem extends StatelessWidget {
SubscriptionInfoView(subscriptionInfo: subscriptionInfo),
Text(
profile.lastUpdateDate?.lastUpdateTimeDesc ?? '',
style: context.textTheme.labelMedium?.toLight,
style: context.textTheme.labelMedium?.toLighter,
),
];
}

View File

@@ -575,7 +575,7 @@ class _ListHeaderState extends State<ListHeader> {
iconSize: 19,
icon: const Icon(Icons.adjust),
),
const SizedBox(width: 4),
const SizedBox(width: 2),
IconButton(
iconSize: 20,
visualDensity: VisualDensity.compact,
@@ -583,13 +583,13 @@ class _ListHeaderState extends State<ListHeader> {
onPressed: _delayTest,
icon: const Icon(Icons.network_ping),
),
const SizedBox(width: 8),
const SizedBox(width: 6),
] else
SizedBox(width: 6),
IconButton.filledTonal(
visualDensity: VisualDensity.compact,
padding: EdgeInsets.all(4),
iconSize: 22,
padding: EdgeInsets.all(2),
iconSize: 24,
onPressed: () {
_handleChange(groupName);
},

View File

@@ -277,7 +277,7 @@ class _PrimaryColorItemState extends ConsumerState<_PrimaryColorItem> {
final isEquals = vm4.d;
return CommonPopScope(
onPop: () {
onPop: (context) {
if (_removablePrimaryColor != null) {
setState(() {
_removablePrimaryColor = null;

View File

@@ -125,7 +125,7 @@ class CommonCard extends StatelessWidget {
if (isSelected) {
return colorScheme.secondaryContainer.opacity80;
}
return colorScheme.surfaceContainer;
return colorScheme.surfaceContainerHigh;
}
if (isSelected) {
return colorScheme.secondaryContainer;

View File

@@ -94,11 +94,13 @@ class FadeRotationScaleBox extends StatelessWidget {
class FadeScaleBox extends StatelessWidget {
final Widget child;
final AlignmentGeometry? alignment;
const FadeScaleBox({super.key, required this.child});
const FadeScaleBox({super.key, required this.child, this.alignment});
@override
Widget build(BuildContext context) {
final realAlignment = alignment ?? Alignment.center;
return AnimatedSwitcher(
duration: commonDuration,
switchOutCurve: Curves.easeOutBack,
@@ -112,6 +114,16 @@ class FadeScaleBox extends StatelessWidget {
),
);
},
layoutBuilder: (currentChild, previousChildren) => Align(
alignment: realAlignment,
child: Stack(
alignment: realAlignment,
children: <Widget>[
...previousChildren,
if (currentChild != null) currentChild,
],
),
),
child: child,
);
}

View File

@@ -5,7 +5,7 @@ import 'package:flutter/widgets.dart';
class CommonPopScope extends StatelessWidget {
final Widget child;
final FutureOr<bool> Function()? onPop;
final FutureOr<bool> Function(BuildContext context)? onPop;
final FutureOr<void> Function()? onPopSuccess;
const CommonPopScope({
@@ -25,7 +25,7 @@ class CommonPopScope extends StatelessWidget {
if (didPop) {
return;
}
final res = await onPop!();
final res = await onPop!(context);
if (!context.mounted) {
return;
}

View File

@@ -224,7 +224,7 @@ class CommonScaffoldState extends State<CommonScaffold> {
if (_isEdit || _isSearch) {
return SystemBackBlock(
child: CommonPopScope(
onPop: () {
onPop: (context) {
if (_isEdit || _isSearch) {
_handleExitSearching();
_appBarState.value.editState?.onExit();

View File

@@ -26,8 +26,8 @@ class CommonScrollBar extends StatelessWidget {
controller: controller,
thumbVisibility: thumbVisibility,
trackVisibility: trackVisibility,
thickness: 8,
radius: const Radius.circular(8),
thickness: 6,
radius: const Radius.circular(6),
interactive: true,
child: child,
);

View File

@@ -8,7 +8,6 @@
#include <dynamic_color/dynamic_color_plugin.h>
#include <file_selector_linux/file_selector_plugin.h>
#include <flutter_acrylic/flutter_acrylic_plugin.h>
#include <flutter_js/flutter_js_plugin.h>
#include <gtk/gtk_plugin.h>
#include <hotkey_manager_linux/hotkey_manager_linux_plugin.h>
@@ -24,9 +23,6 @@ void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) file_selector_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin");
file_selector_plugin_register_with_registrar(file_selector_linux_registrar);
g_autoptr(FlPluginRegistrar) flutter_acrylic_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterAcrylicPlugin");
flutter_acrylic_plugin_register_with_registrar(flutter_acrylic_registrar);
g_autoptr(FlPluginRegistrar) flutter_js_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterJsPlugin");
flutter_js_plugin_register_with_registrar(flutter_js_registrar);

View File

@@ -5,7 +5,6 @@
list(APPEND FLUTTER_PLUGIN_LIST
dynamic_color
file_selector_linux
flutter_acrylic
flutter_js
gtk
hotkey_manager_linux

View File

@@ -13,7 +13,6 @@ import file_picker
import file_selector_macos
import flutter_js
import hotkey_manager_macos
import macos_window_utils
import mobile_scanner
import package_info_plus
import path_provider_foundation
@@ -34,7 +33,6 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin"))
FlutterJsPlugin.register(with: registry.registrar(forPlugin: "FlutterJsPlugin"))
HotkeyManagerMacosPlugin.register(with: registry.registrar(forPlugin: "HotkeyManagerMacosPlugin"))
MacOSWindowUtilsPlugin.register(with: registry.registrar(forPlugin: "MacOSWindowUtilsPlugin"))
MobileScannerPlugin.register(with: registry.registrar(forPlugin: "MobileScannerPlugin"))
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))

View File

@@ -18,8 +18,6 @@ PODS:
- hotkey_manager_macos (0.0.1):
- FlutterMacOS
- HotKey
- macos_window_utils (1.0.0):
- FlutterMacOS
- mobile_scanner (7.0.0):
- Flutter
- FlutterMacOS
@@ -55,7 +53,6 @@ DEPENDENCIES:
- flutter_js (from `Flutter/ephemeral/.symlinks/plugins/flutter_js/macos`)
- FlutterMacOS (from `Flutter/ephemeral`)
- hotkey_manager_macos (from `Flutter/ephemeral/.symlinks/plugins/hotkey_manager_macos/macos`)
- macos_window_utils (from `Flutter/ephemeral/.symlinks/plugins/macos_window_utils/macos`)
- mobile_scanner (from `Flutter/ephemeral/.symlinks/plugins/mobile_scanner/darwin`)
- package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`)
- path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`)
@@ -90,8 +87,6 @@ EXTERNAL SOURCES:
:path: Flutter/ephemeral
hotkey_manager_macos:
:path: Flutter/ephemeral/.symlinks/plugins/hotkey_manager_macos/macos
macos_window_utils:
:path: Flutter/ephemeral/.symlinks/plugins/macos_window_utils/macos
mobile_scanner:
:path: Flutter/ephemeral/.symlinks/plugins/mobile_scanner/darwin
package_info_plus:
@@ -124,7 +119,6 @@ SPEC CHECKSUMS:
FlutterMacOS: d0db08ddef1a9af05a5ec4b724367152bb0500b1
HotKey: e96d8a2ddbf4591131e2bb3f54e69554d90cdca6
hotkey_manager_macos: a4317849af96d2430fa89944d3c58977ca089fbe
macos_window_utils: 23f54331a0fd51eea9e0ed347253bf48fd379d1d
mobile_scanner: 9157936403f5a0644ca3779a38ff8404c5434a93
package_info_plus: f0052d280d17aa382b932f399edf32507174e870
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564

View File

@@ -462,14 +462,6 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_acrylic:
dependency: "direct main"
description:
name: flutter_acrylic
sha256: b3996dbde5abf5823cc9ead4cf2e5267c3181f15585fe47ce4dc4472e7ec827a
url: "https://pub.dev"
source: hosted
version: "1.1.4"
flutter_cache_manager:
dependency: "direct main"
description:
@@ -822,22 +814,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.3.0"
lpinyin:
dependency: "direct main"
description:
name: lpinyin
sha256: "0bb843363f1f65170efd09fbdfc760c7ec34fc6354f9fcb2f89e74866a0d814a"
url: "https://pub.dev"
source: hosted
version: "2.0.3"
macos_window_utils:
dependency: transitive
description:
name: macos_window_utils
sha256: d4df3501fd32ac0d2d7590cb6a8e4758337d061c8fa0db816fdd636be63a8438
url: "https://pub.dev"
source: hosted
version: "1.9.0"
matcher:
dependency: transitive
description:

View File

@@ -1,7 +1,7 @@
name: fl_clash
description: A multi-platform proxy client based on ClashMeta, simple and easy to use, open-source and ad-free.
publish_to: 'none'
version: 0.8.88+2025083102
version: 0.8.88+2025090501
environment:
sdk: '>=3.8.0 <4.0.0'
@@ -43,7 +43,6 @@ dependencies:
ref: main
re_highlight: ^0.0.3
archive: ^4.0.7
lpinyin: ^2.0.3
emoji_regex: ^0.0.5
hotkey_manager: ^0.2.3
uni_platform: ^0.1.3
@@ -62,7 +61,6 @@ dependencies:
flutter_svg: ^2.1.0
flutter_cache_manager: ^3.4.1
crypto: ^3.0.3
flutter_acrylic: ^1.1.4
dev_dependencies:
flutter_test:
sdk: flutter

View File

@@ -10,7 +10,6 @@
#include <connectivity_plus/connectivity_plus_windows_plugin.h>
#include <dynamic_color/dynamic_color_plugin_c_api.h>
#include <file_selector_windows/file_selector_windows.h>
#include <flutter_acrylic/flutter_acrylic_plugin.h>
#include <flutter_js/flutter_js_plugin.h>
#include <hotkey_manager_windows/hotkey_manager_windows_plugin_c_api.h>
#include <proxy/proxy_plugin_c_api.h>
@@ -29,8 +28,6 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
registry->GetRegistrarForPlugin("DynamicColorPluginCApi"));
FileSelectorWindowsRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FileSelectorWindows"));
FlutterAcrylicPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FlutterAcrylicPlugin"));
FlutterJsPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FlutterJsPlugin"));
HotkeyManagerWindowsPluginCApiRegisterWithRegistrar(

View File

@@ -7,7 +7,6 @@ list(APPEND FLUTTER_PLUGIN_LIST
connectivity_plus
dynamic_color
file_selector_windows
flutter_acrylic
flutter_js
hotkey_manager_windows
proxy