Files
MWClash/lib/models/config.dart
chen08209 ed7868282a Add android separates the core process
Support core status check and force restart

Optimize proxies page and access page

Update flutter and pub dependencies

Update go version

Optimize more details
2025-09-23 15:23:58 +08:00

285 lines
8.3 KiB
Dart

import 'package:fl_clash/common/common.dart';
import 'package:fl_clash/enum/enum.dart';
import 'package:flutter/material.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'models.dart';
part 'generated/config.freezed.dart';
part 'generated/config.g.dart';
const defaultBypassDomain = [
'*zhihu.com',
'*zhimg.com',
'*jd.com',
'100ime-iat-api.xfyun.cn',
'*360buyimg.com',
'localhost',
'*.local',
'127.*',
'10.*',
'172.16.*',
'172.17.*',
'172.18.*',
'172.19.*',
'172.2*',
'172.30.*',
'172.31.*',
'192.168.*',
];
const defaultAppSettingProps = AppSettingProps();
const defaultVpnProps = VpnProps();
const defaultNetworkProps = NetworkProps();
const defaultProxiesStyle = ProxiesStyle();
const defaultWindowProps = WindowProps();
const defaultAccessControl = AccessControl();
final defaultThemeProps = ThemeProps(primaryColor: defaultPrimaryColor);
const List<DashboardWidget> defaultDashboardWidgets = [
DashboardWidget.networkSpeed,
DashboardWidget.systemProxyButton,
DashboardWidget.tunButton,
DashboardWidget.outboundMode,
DashboardWidget.networkDetection,
DashboardWidget.trafficUsage,
DashboardWidget.intranetIp,
];
List<DashboardWidget> dashboardWidgetsSafeFormJson(
List<dynamic>? dashboardWidgets,
) {
try {
return dashboardWidgets
?.map((e) => $enumDecode(_$DashboardWidgetEnumMap, e))
.toList() ??
defaultDashboardWidgets;
} catch (_) {
return defaultDashboardWidgets;
}
}
@freezed
abstract class AppSettingProps with _$AppSettingProps {
const factory AppSettingProps({
String? locale,
@Default(defaultDashboardWidgets)
@JsonKey(fromJson: dashboardWidgetsSafeFormJson)
List<DashboardWidget> dashboardWidgets,
@Default(false) bool onlyStatisticsProxy,
@Default(false) bool autoLaunch,
@Default(false) bool silentLaunch,
@Default(false) bool autoRun,
@Default(false) bool openLogs,
@Default(true) bool closeConnections,
@Default(defaultTestUrl) String testUrl,
@Default(true) bool isAnimateToPage,
@Default(true) bool autoCheckUpdate,
@Default(false) bool showLabel,
@Default(false) bool disclaimerAccepted,
@Default(false) bool crashlyticsTip,
@Default(false) bool crashlytics,
@Default(true) bool minimizeOnExit,
@Default(false) bool hidden,
@Default(false) bool developerMode,
@Default(RecoveryStrategy.compatible) RecoveryStrategy recoveryStrategy,
}) = _AppSettingProps;
factory AppSettingProps.fromJson(Map<String, Object?> json) =>
_$AppSettingPropsFromJson(json);
factory AppSettingProps.safeFromJson(Map<String, Object?>? json) {
return json == null
? defaultAppSettingProps
: AppSettingProps.fromJson(json);
}
}
@freezed
abstract class AccessControl with _$AccessControl {
const factory AccessControl({
@Default(false) bool enable,
@Default(AccessControlMode.rejectSelected) AccessControlMode mode,
@Default([]) List<String> acceptList,
@Default([]) List<String> rejectList,
@Default(AccessSortType.none) AccessSortType sort,
@Default(true) bool isFilterSystemApp,
@Default(true) bool isFilterNonInternetApp,
}) = _AccessControl;
factory AccessControl.fromJson(Map<String, Object?> json) =>
_$AccessControlFromJson(json);
}
extension AccessControlExt on AccessControl {
List<String> get currentList => switch (mode) {
AccessControlMode.acceptSelected => acceptList,
AccessControlMode.rejectSelected => rejectList,
};
}
@freezed
abstract class WindowProps with _$WindowProps {
const factory WindowProps({
@Default(750) double width,
@Default(600) double height,
double? top,
double? left,
}) = _WindowProps;
factory WindowProps.fromJson(Map<String, Object?>? json) =>
json == null ? const WindowProps() : _$WindowPropsFromJson(json);
}
@freezed
abstract class VpnProps with _$VpnProps {
const factory VpnProps({
@Default(true) bool enable,
@Default(true) bool systemProxy,
@Default(false) bool ipv6,
@Default(true) bool allowBypass,
@Default(false) bool dnsHijacking,
@Default(defaultAccessControl) AccessControl accessControl,
}) = _VpnProps;
factory VpnProps.fromJson(Map<String, Object?>? json) =>
json == null ? defaultVpnProps : _$VpnPropsFromJson(json);
}
@freezed
abstract class NetworkProps with _$NetworkProps {
const factory NetworkProps({
@Default(true) bool systemProxy,
@Default(defaultBypassDomain) List<String> bypassDomain,
@Default(RouteMode.config) RouteMode routeMode,
@Default(true) bool autoSetSystemDns,
}) = _NetworkProps;
factory NetworkProps.fromJson(Map<String, Object?>? json) =>
json == null ? const NetworkProps() : _$NetworkPropsFromJson(json);
}
@freezed
abstract class ProxiesStyle with _$ProxiesStyle {
const factory ProxiesStyle({
@Default(ProxiesType.tab) ProxiesType type,
@Default(ProxiesSortType.none) ProxiesSortType sortType,
@Default(ProxiesLayout.standard) ProxiesLayout layout,
@Default(ProxiesIconStyle.standard) ProxiesIconStyle iconStyle,
@Default(ProxyCardType.expand) ProxyCardType cardType,
@Default({}) Map<String, String> iconMap,
}) = _ProxiesStyle;
factory ProxiesStyle.fromJson(Map<String, Object?>? json) =>
json == null ? defaultProxiesStyle : _$ProxiesStyleFromJson(json);
}
@freezed
abstract class TextScale with _$TextScale {
const factory TextScale({
@Default(false) bool enable,
@Default(1.0) double scale,
}) = _TextScale;
factory TextScale.fromJson(Map<String, Object?> json) =>
_$TextScaleFromJson(json);
}
@freezed
abstract class ThemeProps with _$ThemeProps {
const factory ThemeProps({
int? primaryColor,
@Default(defaultPrimaryColors) List<int> primaryColors,
@Default(ThemeMode.dark) ThemeMode themeMode,
@Default(DynamicSchemeVariant.content) DynamicSchemeVariant schemeVariant,
@Default(false) bool pureBlack,
@Default(TextScale()) TextScale textScale,
}) = _ThemeProps;
factory ThemeProps.fromJson(Map<String, Object?> json) =>
_$ThemePropsFromJson(json);
factory ThemeProps.safeFromJson(Map<String, Object?>? json) {
if (json == null) {
return defaultThemeProps;
}
try {
return ThemeProps.fromJson(json);
} catch (_) {
return defaultThemeProps;
}
}
}
@freezed
abstract class ScriptProps with _$ScriptProps {
const factory ScriptProps({
String? currentId,
@Default([]) List<Script> scripts,
}) = _ScriptProps;
factory ScriptProps.fromJson(Map<String, Object?> json) =>
_$ScriptPropsFromJson(json);
}
extension ScriptPropsExt on ScriptProps {
String? get realId {
final index = scripts.indexWhere((script) => script.id == currentId);
if (index != -1) {
return currentId;
}
return null;
}
Script? get currentScript {
final index = scripts.indexWhere((script) => script.id == currentId);
if (index != -1) {
return scripts[index];
}
return null;
}
}
@freezed
abstract class Config with _$Config {
const factory Config({
@JsonKey(fromJson: AppSettingProps.safeFromJson)
@Default(defaultAppSettingProps)
AppSettingProps appSetting,
@Default([]) List<Profile> profiles,
@Default([]) List<HotKeyAction> hotKeyActions,
String? currentProfileId,
@Default(false) bool overrideDns,
DAV? dav,
@Default(defaultNetworkProps) NetworkProps networkProps,
@Default(defaultVpnProps) VpnProps vpnProps,
@JsonKey(fromJson: ThemeProps.safeFromJson) required ThemeProps themeProps,
@Default(defaultProxiesStyle) ProxiesStyle proxiesStyle,
@Default(defaultWindowProps) WindowProps windowProps,
@Default(defaultClashConfig) ClashConfig patchClashConfig,
@Default(ScriptProps()) ScriptProps scriptProps,
}) = _Config;
factory Config.fromJson(Map<String, Object?> json) => _$ConfigFromJson(json);
factory Config.compatibleFromJson(Map<String, Object?> json) {
try {
final accessControlMap = json['accessControl'];
final isAccessControl = json['isAccessControl'];
if (accessControlMap != null) {
(accessControlMap as Map)['enable'] = isAccessControl;
if (json['vpnProps'] != null) {
(json['vpnProps'] as Map)['accessControl'] = accessControlMap;
}
}
} catch (_) {}
return Config.fromJson(json);
}
}
extension ConfigExt on Config {
Profile? get currentProfile {
return profiles.getProfile(currentProfileId);
}
}