Support core status check and force restart Optimize proxies page and access page Update flutter and pub dependencies Optimize more details
285 lines
8.3 KiB
Dart
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);
|
|
}
|
|
}
|