Optimize desktop view
Optimize logs, requests, connection pages Optimize windows tray auto hide Optimize some details Update core
This commit is contained in:
224
lib/state.dart
224
lib/state.dart
@@ -11,8 +11,8 @@ import 'package:fl_clash/enum/enum.dart';
|
||||
import 'package:fl_clash/l10n/l10n.dart';
|
||||
import 'package:fl_clash/plugins/service.dart';
|
||||
import 'package:fl_clash/widgets/dialog.dart';
|
||||
import 'package:fl_clash/widgets/scaffold.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_js/flutter_js.dart';
|
||||
import 'package:material_color_utilities/palettes/core_palette.dart';
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
@@ -26,8 +26,10 @@ typedef UpdateTasks = List<FutureOr Function()>;
|
||||
|
||||
class GlobalState {
|
||||
static GlobalState? _instance;
|
||||
Map<CacheTag, double> cacheScrollPosition = {};
|
||||
Map<CacheTag, FixedMap<String, double>> cacheHeightMap = {};
|
||||
Map<CacheTag, FixedMap<String, double>> computeHeightMapCache = {};
|
||||
|
||||
// Map<CacheTag, double> computeScrollPositionCache = {};
|
||||
// final Map<String, double> scrollPositionCache = {};
|
||||
bool isService = false;
|
||||
Timer? timer;
|
||||
Timer? groupsUpdateTimer;
|
||||
@@ -45,7 +47,8 @@ class GlobalState {
|
||||
UpdateTasks tasks = [];
|
||||
final navigatorKey = GlobalKey<NavigatorState>();
|
||||
AppController? _appController;
|
||||
GlobalKey<CommonScaffoldState> homeScaffoldKey = GlobalKey();
|
||||
|
||||
// GlobalKey<CommonScaffoldState> homeScaffoldKey = GlobalKey();
|
||||
bool isInit = false;
|
||||
|
||||
bool get isStart => startTime != null && startTime!.isBeforeNow;
|
||||
@@ -64,22 +67,24 @@ class GlobalState {
|
||||
return _instance!;
|
||||
}
|
||||
|
||||
initApp(int version) async {
|
||||
coreSHA256 = const String.fromEnvironment("CORE_SHA256");
|
||||
isPre = const String.fromEnvironment("APP_ENV") != 'stable';
|
||||
Future<void> initApp(int version) async {
|
||||
coreSHA256 = const String.fromEnvironment('CORE_SHA256');
|
||||
isPre = const String.fromEnvironment('APP_ENV') != 'stable';
|
||||
appState = AppState(
|
||||
brightness: WidgetsBinding.instance.platformDispatcher.platformBrightness,
|
||||
version: version,
|
||||
viewSize: Size.zero,
|
||||
requests: FixedList(maxLength),
|
||||
logs: FixedList(maxLength),
|
||||
traffics: FixedList(30),
|
||||
totalTraffic: Traffic(),
|
||||
systemUiOverlayStyle: const SystemUiOverlayStyle(),
|
||||
);
|
||||
await _initDynamicColor();
|
||||
await init();
|
||||
}
|
||||
|
||||
_initDynamicColor() async {
|
||||
Future<void> _initDynamicColor() async {
|
||||
try {
|
||||
corePalette = await DynamicColorPlugin.getCorePalette();
|
||||
accentColor = await DynamicColorPlugin.getAccentColor() ??
|
||||
@@ -87,7 +92,7 @@ class GlobalState {
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
init() async {
|
||||
Future<void> init() async {
|
||||
packageInfo = await PackageInfo.fromPlatform();
|
||||
config = await preferences.getConfig() ??
|
||||
Config(
|
||||
@@ -102,7 +107,7 @@ class GlobalState {
|
||||
|
||||
String get ua => config.patchClashConfig.globalUa ?? packageInfo.ua;
|
||||
|
||||
startUpdateTasks([UpdateTasks? tasks]) async {
|
||||
Future<void> startUpdateTasks([UpdateTasks? tasks]) async {
|
||||
if (timer != null && timer!.isActive == true) return;
|
||||
if (tasks != null) {
|
||||
this.tasks = tasks;
|
||||
@@ -113,20 +118,20 @@ class GlobalState {
|
||||
});
|
||||
}
|
||||
|
||||
executorUpdateTask() async {
|
||||
Future<void> executorUpdateTask() async {
|
||||
for (final task in tasks) {
|
||||
await task();
|
||||
}
|
||||
timer = null;
|
||||
}
|
||||
|
||||
stopUpdateTasks() {
|
||||
void stopUpdateTasks() {
|
||||
if (timer == null || timer?.isActive == false) return;
|
||||
timer?.cancel();
|
||||
timer = null;
|
||||
}
|
||||
|
||||
handleStart([UpdateTasks? tasks]) async {
|
||||
Future<void> handleStart([UpdateTasks? tasks]) async {
|
||||
startTime ??= DateTime.now();
|
||||
await clashCore.startListener();
|
||||
await service?.startVpn();
|
||||
@@ -227,38 +232,14 @@ class GlobalState {
|
||||
);
|
||||
}
|
||||
|
||||
Future<T?> safeRun<T>(
|
||||
FutureOr<T> Function() futureFunction, {
|
||||
String? title,
|
||||
bool silence = true,
|
||||
}) async {
|
||||
try {
|
||||
final res = await futureFunction();
|
||||
return res;
|
||||
} catch (e) {
|
||||
commonPrint.log("$e");
|
||||
if (silence) {
|
||||
showNotifier(e.toString());
|
||||
} else {
|
||||
showMessage(
|
||||
title: title ?? appLocalizations.tip,
|
||||
message: TextSpan(
|
||||
text: e.toString(),
|
||||
),
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
showNotifier(String text) {
|
||||
void showNotifier(String text) {
|
||||
if (text.isEmpty) {
|
||||
return;
|
||||
}
|
||||
navigatorKey.currentContext?.showNotifier(text);
|
||||
}
|
||||
|
||||
openUrl(String url) async {
|
||||
Future<void> openUrl(String url) async {
|
||||
final res = await showMessage(
|
||||
message: TextSpan(text: url),
|
||||
title: appLocalizations.externalLink,
|
||||
@@ -286,7 +267,7 @@ class GlobalState {
|
||||
return CoreState(
|
||||
vpnProps: config.vpnProps,
|
||||
onlyStatisticsProxy: config.appSetting.onlyStatisticsProxy,
|
||||
currentProfileName: currentProfile?.label ?? currentProfile?.id ?? "",
|
||||
currentProfileName: currentProfile?.label ?? currentProfile?.id ?? '',
|
||||
bypassDomain: config.networkProps.bypassDomain,
|
||||
);
|
||||
}
|
||||
@@ -318,112 +299,112 @@ class GlobalState {
|
||||
final realPatchConfig = patchConfig.copyWith(
|
||||
tun: patchConfig.tun.getRealTun(config.networkProps.routeMode),
|
||||
);
|
||||
rawConfig["external-controller"] = realPatchConfig.externalController.value;
|
||||
rawConfig["external-ui"] = "";
|
||||
rawConfig["interface-name"] = "";
|
||||
rawConfig["external-ui-url"] = "";
|
||||
rawConfig["tcp-concurrent"] = realPatchConfig.tcpConcurrent;
|
||||
rawConfig["unified-delay"] = realPatchConfig.unifiedDelay;
|
||||
rawConfig["ipv6"] = realPatchConfig.ipv6;
|
||||
rawConfig["log-level"] = realPatchConfig.logLevel.name;
|
||||
rawConfig["port"] = 0;
|
||||
rawConfig["socks-port"] = 0;
|
||||
rawConfig["keep-alive-interval"] = realPatchConfig.keepAliveInterval;
|
||||
rawConfig["mixed-port"] = realPatchConfig.mixedPort;
|
||||
rawConfig["port"] = realPatchConfig.port;
|
||||
rawConfig["socks-port"] = realPatchConfig.socksPort;
|
||||
rawConfig["redir-port"] = realPatchConfig.redirPort;
|
||||
rawConfig["tproxy-port"] = realPatchConfig.tproxyPort;
|
||||
rawConfig["find-process-mode"] = realPatchConfig.findProcessMode.name;
|
||||
rawConfig["allow-lan"] = realPatchConfig.allowLan;
|
||||
rawConfig["mode"] = realPatchConfig.mode.name;
|
||||
if (rawConfig["tun"] == null) {
|
||||
rawConfig["tun"] = {};
|
||||
rawConfig['external-controller'] = realPatchConfig.externalController.value;
|
||||
rawConfig['external-ui'] = '';
|
||||
rawConfig['interface-name'] = '';
|
||||
rawConfig['external-ui-url'] = '';
|
||||
rawConfig['tcp-concurrent'] = realPatchConfig.tcpConcurrent;
|
||||
rawConfig['unified-delay'] = realPatchConfig.unifiedDelay;
|
||||
rawConfig['ipv6'] = realPatchConfig.ipv6;
|
||||
rawConfig['log-level'] = realPatchConfig.logLevel.name;
|
||||
rawConfig['port'] = 0;
|
||||
rawConfig['socks-port'] = 0;
|
||||
rawConfig['keep-alive-interval'] = realPatchConfig.keepAliveInterval;
|
||||
rawConfig['mixed-port'] = realPatchConfig.mixedPort;
|
||||
rawConfig['port'] = realPatchConfig.port;
|
||||
rawConfig['socks-port'] = realPatchConfig.socksPort;
|
||||
rawConfig['redir-port'] = realPatchConfig.redirPort;
|
||||
rawConfig['tproxy-port'] = realPatchConfig.tproxyPort;
|
||||
rawConfig['find-process-mode'] = realPatchConfig.findProcessMode.name;
|
||||
rawConfig['allow-lan'] = realPatchConfig.allowLan;
|
||||
rawConfig['mode'] = realPatchConfig.mode.name;
|
||||
if (rawConfig['tun'] == null) {
|
||||
rawConfig['tun'] = {};
|
||||
}
|
||||
rawConfig["tun"]["enable"] = realPatchConfig.tun.enable;
|
||||
rawConfig["tun"]["device"] = realPatchConfig.tun.device;
|
||||
rawConfig["tun"]["dns-hijack"] = realPatchConfig.tun.dnsHijack;
|
||||
rawConfig["tun"]["stack"] = realPatchConfig.tun.stack.name;
|
||||
rawConfig["tun"]["route-address"] = realPatchConfig.tun.routeAddress;
|
||||
rawConfig["tun"]["auto-route"] = realPatchConfig.tun.autoRoute;
|
||||
rawConfig["geodata-loader"] = realPatchConfig.geodataLoader.name;
|
||||
if (rawConfig["sniffer"]?["sniff"] != null) {
|
||||
for (final value in (rawConfig["sniffer"]?["sniff"] as Map).values) {
|
||||
if (value["ports"] != null && value["ports"] is List) {
|
||||
value["ports"] =
|
||||
value["ports"]?.map((item) => item.toString()).toList() ?? [];
|
||||
rawConfig['tun']['enable'] = realPatchConfig.tun.enable;
|
||||
rawConfig['tun']['device'] = realPatchConfig.tun.device;
|
||||
rawConfig['tun']['dns-hijack'] = realPatchConfig.tun.dnsHijack;
|
||||
rawConfig['tun']['stack'] = realPatchConfig.tun.stack.name;
|
||||
rawConfig['tun']['route-address'] = realPatchConfig.tun.routeAddress;
|
||||
rawConfig['tun']['auto-route'] = realPatchConfig.tun.autoRoute;
|
||||
rawConfig['geodata-loader'] = realPatchConfig.geodataLoader.name;
|
||||
if (rawConfig['sniffer']?['sniff'] != null) {
|
||||
for (final value in (rawConfig['sniffer']?['sniff'] as Map).values) {
|
||||
if (value['ports'] != null && value['ports'] is List) {
|
||||
value['ports'] =
|
||||
value['ports']?.map((item) => item.toString()).toList() ?? [];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rawConfig["profile"] == null) {
|
||||
rawConfig["profile"] = {};
|
||||
if (rawConfig['profile'] == null) {
|
||||
rawConfig['profile'] = {};
|
||||
}
|
||||
if (rawConfig["proxy-providers"] != null) {
|
||||
final proxyProviders = rawConfig["proxy-providers"] as Map;
|
||||
if (rawConfig['proxy-providers'] != null) {
|
||||
final proxyProviders = rawConfig['proxy-providers'] as Map;
|
||||
for (final key in proxyProviders.keys) {
|
||||
final proxyProvider = proxyProviders[key];
|
||||
if (proxyProvider["type"] != "http") {
|
||||
if (proxyProvider['type'] != 'http') {
|
||||
continue;
|
||||
}
|
||||
if (proxyProvider["url"] != null) {
|
||||
proxyProvider["path"] = await appPath.getProvidersFilePath(
|
||||
if (proxyProvider['url'] != null) {
|
||||
proxyProvider['path'] = await appPath.getProvidersFilePath(
|
||||
profile.id,
|
||||
"proxies",
|
||||
proxyProvider["url"],
|
||||
'proxies',
|
||||
proxyProvider['url'],
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rawConfig["rule-providers"] != null) {
|
||||
final ruleProviders = rawConfig["rule-providers"] as Map;
|
||||
if (rawConfig['rule-providers'] != null) {
|
||||
final ruleProviders = rawConfig['rule-providers'] as Map;
|
||||
for (final key in ruleProviders.keys) {
|
||||
final ruleProvider = ruleProviders[key];
|
||||
if (ruleProvider["type"] != "http") {
|
||||
if (ruleProvider['type'] != 'http') {
|
||||
continue;
|
||||
}
|
||||
if (ruleProvider["url"] != null) {
|
||||
ruleProvider["path"] = await appPath.getProvidersFilePath(
|
||||
if (ruleProvider['url'] != null) {
|
||||
ruleProvider['path'] = await appPath.getProvidersFilePath(
|
||||
profile.id,
|
||||
"rules",
|
||||
ruleProvider["url"],
|
||||
'rules',
|
||||
ruleProvider['url'],
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rawConfig["profile"]["store-selected"] = false;
|
||||
rawConfig["geox-url"] = realPatchConfig.geoXUrl.toJson();
|
||||
rawConfig["global-ua"] = realPatchConfig.globalUa;
|
||||
if (rawConfig["hosts"] == null) {
|
||||
rawConfig["hosts"] = {};
|
||||
rawConfig['profile']['store-selected'] = false;
|
||||
rawConfig['geox-url'] = realPatchConfig.geoXUrl.toJson();
|
||||
rawConfig['global-ua'] = realPatchConfig.globalUa;
|
||||
if (rawConfig['hosts'] == null) {
|
||||
rawConfig['hosts'] = {};
|
||||
}
|
||||
for (final host in realPatchConfig.hosts.entries) {
|
||||
rawConfig["hosts"][host.key] = host.value.splitByMultipleSeparators;
|
||||
rawConfig['hosts'][host.key] = host.value.splitByMultipleSeparators;
|
||||
}
|
||||
if (rawConfig["dns"] == null) {
|
||||
rawConfig["dns"] = {};
|
||||
if (rawConfig['dns'] == null) {
|
||||
rawConfig['dns'] = {};
|
||||
}
|
||||
final isEnableDns = rawConfig["dns"]["enable"] == true;
|
||||
final isEnableDns = rawConfig['dns']['enable'] == true;
|
||||
final overrideDns = globalState.config.overrideDns;
|
||||
if (overrideDns || !isEnableDns) {
|
||||
final dns = switch (!isEnableDns) {
|
||||
true => realPatchConfig.dns.copyWith(
|
||||
nameserver: [...realPatchConfig.dns.nameserver, "system://"]),
|
||||
nameserver: [...realPatchConfig.dns.nameserver, 'system://']),
|
||||
false => realPatchConfig.dns,
|
||||
};
|
||||
rawConfig["dns"] = dns.toJson();
|
||||
rawConfig["dns"]["nameserver-policy"] = {};
|
||||
rawConfig['dns'] = dns.toJson();
|
||||
rawConfig['dns']['nameserver-policy'] = {};
|
||||
for (final entry in dns.nameserverPolicy.entries) {
|
||||
rawConfig["dns"]["nameserver-policy"][entry.key] =
|
||||
rawConfig['dns']['nameserver-policy'][entry.key] =
|
||||
entry.value.splitByMultipleSeparators;
|
||||
}
|
||||
}
|
||||
var rules = [];
|
||||
if (rawConfig["rules"] != null) {
|
||||
rules = rawConfig["rules"];
|
||||
if (rawConfig['rules'] != null) {
|
||||
rules = rawConfig['rules'];
|
||||
}
|
||||
rawConfig.remove("rules");
|
||||
rawConfig.remove('rules');
|
||||
|
||||
final overrideData = profile.overrideData;
|
||||
if (overrideData.enable && config.scriptProps.currentScript == null) {
|
||||
@@ -433,7 +414,7 @@ class GlobalState {
|
||||
rules = [...overrideData.runningRule, ...rules];
|
||||
}
|
||||
}
|
||||
rawConfig["rule"] = rules;
|
||||
rawConfig['rule'] = rules;
|
||||
return rawConfig;
|
||||
}
|
||||
|
||||
@@ -442,8 +423,8 @@ class GlobalState {
|
||||
true => clashLibHandler!.getConfig(profileId),
|
||||
false => clashCore.getConfig(profileId),
|
||||
};
|
||||
configMap["rules"] = configMap["rule"];
|
||||
configMap.remove("rule");
|
||||
configMap['rules'] = configMap['rule'];
|
||||
configMap.remove('rule');
|
||||
return configMap;
|
||||
}
|
||||
|
||||
@@ -454,15 +435,15 @@ class GlobalState {
|
||||
if (currentScript == null) {
|
||||
return config;
|
||||
}
|
||||
if (config["proxy-providers"] == null) {
|
||||
config["proxy-providers"] = {};
|
||||
if (config['proxy-providers'] == null) {
|
||||
config['proxy-providers'] = {};
|
||||
}
|
||||
final configJs = json.encode(config);
|
||||
final runtime = getJavascriptRuntime();
|
||||
final res = await runtime.evaluateAsync("""
|
||||
final res = await runtime.evaluateAsync('''
|
||||
${currentScript.content}
|
||||
main($configJs)
|
||||
""");
|
||||
''');
|
||||
if (res.isError) {
|
||||
throw res.stringResult;
|
||||
}
|
||||
@@ -484,7 +465,6 @@ class DetectionState {
|
||||
|
||||
final state = ValueNotifier<NetworkDetectionState>(
|
||||
const NetworkDetectionState(
|
||||
isTesting: false,
|
||||
isLoading: true,
|
||||
ipInfo: null,
|
||||
),
|
||||
@@ -497,7 +477,7 @@ class DetectionState {
|
||||
return _instance!;
|
||||
}
|
||||
|
||||
startCheck() {
|
||||
void startCheck() {
|
||||
debouncer.call(
|
||||
FunctionTag.checkIp,
|
||||
_checkIp,
|
||||
@@ -507,7 +487,13 @@ class DetectionState {
|
||||
);
|
||||
}
|
||||
|
||||
_checkIp() async {
|
||||
void tryStartCheck() {
|
||||
if (state.value.isLoading == false && state.value.ipInfo == null) {
|
||||
startCheck();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _checkIp() async {
|
||||
final appState = globalState.appState;
|
||||
final isInit = appState.isInit;
|
||||
if (!isInit) return;
|
||||
@@ -528,9 +514,6 @@ class DetectionState {
|
||||
cancelToken = null;
|
||||
}
|
||||
cancelToken = CancelToken();
|
||||
state.value = state.value.copyWith(
|
||||
isTesting: true,
|
||||
);
|
||||
final res = await request.checkIp(cancelToken: cancelToken);
|
||||
if (res.isError) {
|
||||
state.value = state.value.copyWith(
|
||||
@@ -540,9 +523,6 @@ class DetectionState {
|
||||
return;
|
||||
}
|
||||
final ipInfo = res.data;
|
||||
state.value = state.value.copyWith(
|
||||
isTesting: false,
|
||||
);
|
||||
if (ipInfo != null) {
|
||||
state.value = state.value.copyWith(
|
||||
isLoading: false,
|
||||
@@ -559,7 +539,7 @@ class DetectionState {
|
||||
});
|
||||
}
|
||||
|
||||
_clearSetTimeoutTimer() {
|
||||
void _clearSetTimeoutTimer() {
|
||||
if (_setTimeoutTimer != null) {
|
||||
_setTimeoutTimer?.cancel();
|
||||
_setTimeoutTimer = null;
|
||||
|
||||
Reference in New Issue
Block a user