286 lines
8.2 KiB
Dart
286 lines
8.2 KiB
Dart
// ignore_for_file: invalid_annotation_target
|
|
|
|
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
|
|
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(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
|
|
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
|
|
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
|
|
class VpnProps with _$VpnProps {
|
|
const factory VpnProps({
|
|
@Default(true) bool enable,
|
|
@Default(true) bool systemProxy,
|
|
@Default(false) bool ipv6,
|
|
@Default(true) bool allowBypass,
|
|
@Default(defaultAccessControl) AccessControl accessControl,
|
|
}) = _VpnProps;
|
|
|
|
factory VpnProps.fromJson(Map<String, Object?>? json) =>
|
|
json == null ? defaultVpnProps : _$VpnPropsFromJson(json);
|
|
}
|
|
|
|
@freezed
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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);
|
|
}
|
|
}
|