diff --git a/assets/fonts/MiSans-Regular.ttf b/assets/fonts/MiSans-Regular.ttf new file mode 100644 index 0000000..a408ed8 Binary files /dev/null and b/assets/fonts/MiSans-Regular.ttf differ diff --git a/core/common.go b/core/common.go index 66e593f..3f8955e 100644 --- a/core/common.go +++ b/core/common.go @@ -158,10 +158,12 @@ func getRawConfigWithId(id string) *config.RawConfig { } mapping["path"] = filepath.Join(getProfileProvidersPath(id), value) if configParams.TestURL != nil { - hc := mapping["health-check"].(map[string]any) - if hc != nil { - if hc["url"] != nil { - hc["url"] = *configParams.TestURL + if mapping["health-check"] != nil { + hc := mapping["health-check"].(map[string]any) + if hc != nil { + if hc["url"] != nil { + hc["url"] = *configParams.TestURL + } } } } diff --git a/lib/application.dart b/lib/application.dart index db20920..eb6d524 100644 --- a/lib/application.dart +++ b/lib/application.dart @@ -163,9 +163,10 @@ class ApplicationState extends State { child: Selector2( selector: (_, appState, config) => ApplicationSelectorState( locale: config.appSetting.locale, - themeMode: config.themeMode, - primaryColor: config.primaryColor, - prueBlack: config.prueBlack, + themeMode: config.themeProps.themeMode, + primaryColor: config.themeProps.primaryColor, + prueBlack: config.themeProps.prueBlack, + fontFamily: config.themeProps.fontFamily, ), builder: (_, state, child) { return DynamicColorBuilder( @@ -199,6 +200,7 @@ class ApplicationState extends State { themeMode: state.themeMode, theme: ThemeData( useMaterial3: true, + fontFamily: state.fontFamily.value, pageTransitionsTheme: _pageTransitionsTheme, colorScheme: _getAppColorScheme( brightness: Brightness.light, @@ -208,6 +210,7 @@ class ApplicationState extends State { ), darkTheme: ThemeData( useMaterial3: true, + fontFamily: state.fontFamily.value, pageTransitionsTheme: _pageTransitionsTheme, colorScheme: _getAppColorScheme( brightness: Brightness.dark, diff --git a/lib/common/common.dart b/lib/common/common.dart index f3fd19a..fcea849 100644 --- a/lib/common/common.dart +++ b/lib/common/common.dart @@ -29,5 +29,4 @@ export 'scroll.dart'; export 'icons.dart'; export 'http.dart'; export 'keyboard.dart'; -export 'network.dart'; -export 'font.dart'; \ No newline at end of file +export 'network.dart'; \ No newline at end of file diff --git a/lib/common/font.dart b/lib/common/font.dart deleted file mode 100644 index c1eb1e7..0000000 --- a/lib/common/font.dart +++ /dev/null @@ -1,3 +0,0 @@ -class Fonts{ - static String get twEmoji => "Twemoji"; -} \ No newline at end of file diff --git a/lib/enum/enum.dart b/lib/enum/enum.dart index 847b8a2..7a72811 100644 --- a/lib/enum/enum.dart +++ b/lib/enum/enum.dart @@ -162,3 +162,14 @@ enum ProxiesIconStyle { none, icon, } + +enum FontFamily { + system(), + miSans("MiSans"), + twEmoji("Twemoji"), + icon("Icons"); + + final String? value; + + const FontFamily([this.value]); +} diff --git a/lib/fragments/dashboard/network_detection.dart b/lib/fragments/dashboard/network_detection.dart index 48ec7a4..0472c2b 100644 --- a/lib/fragments/dashboard/network_detection.dart +++ b/lib/fragments/dashboard/network_detection.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:dio/dio.dart'; import 'package:fl_clash/common/common.dart'; +import 'package:fl_clash/enum/enum.dart'; import 'package:fl_clash/models/models.dart'; import 'package:fl_clash/state.dart'; import 'package:fl_clash/widgets/widgets.dart'; @@ -69,7 +70,7 @@ class _NetworkDetectionState extends State { } _clearSetTimeoutTimer() { - if(_setTimeoutTimer != null){ + if (_setTimeoutTimer != null) { _setTimeoutTimer?.cancel(); _setTimeoutTimer = null; } @@ -155,7 +156,7 @@ class _NetworkDetectionState extends State { .textTheme .titleLarge ?.copyWith( - fontFamily: Fonts.twEmoji, + fontFamily: FontFamily.twEmoji.value, ), ), ) diff --git a/lib/fragments/theme.dart b/lib/fragments/theme.dart index ff50dd0..99867f7 100644 --- a/lib/fragments/theme.dart +++ b/lib/fragments/theme.dart @@ -1,4 +1,5 @@ import 'package:fl_clash/common/common.dart'; +import 'package:fl_clash/enum/enum.dart'; import 'package:fl_clash/models/models.dart'; import 'package:fl_clash/state.dart'; import 'package:flutter/material.dart'; @@ -18,6 +19,16 @@ class ThemeModeItem { }); } +class FontFamilyItem { + final FontFamily fontFamily; + final String label; + + const FontFamilyItem({ + required this.fontFamily, + required this.label, + }); +} + class ThemeFragment extends StatelessWidget { const ThemeFragment({super.key}); @@ -92,7 +103,11 @@ class _ThemeColorsBoxState extends State { return CommonCard( isSelected: isSelected, onPressed: () { - globalState.appController.config.themeMode = themeModeItem.themeMode; + final appController = globalState.appController; + appController.config.themeProps = + appController.config.themeProps.copyWith( + themeMode: themeModeItem.themeMode, + ); }, child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16), @@ -125,11 +140,45 @@ class _ThemeColorsBoxState extends State { isSelected: isSelected, primaryColor: color, onPressed: () { - globalState.appController.config.primaryColor = color?.value; + final appController = globalState.appController; + appController.config.themeProps = + appController.config.themeProps.copyWith( + primaryColor: color?.value, + ); }, ); } + Widget _fontFamilyCheckBox({ + bool? isSelected, + required FontFamilyItem fontFamilyItem, + }) { + return CommonCard( + isSelected: isSelected, + onPressed: () { + final appController = globalState.appController; + appController.config.themeProps = + appController.config.themeProps.copyWith( + fontFamily: fontFamilyItem.fontFamily, + ); + }, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 8), + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Flexible( + child: Text( + fontFamilyItem.label, + ), + ), + ], + ), + ), + ); + } + @override Widget build(BuildContext context) { List themeModeItems = [ @@ -158,15 +207,59 @@ class _ThemeColorsBoxState extends State { Colors.yellowAccent, Colors.purple, ]; + List fontFamilyItems = [ + FontFamilyItem( + label: appLocalizations.systemFont, + fontFamily: FontFamily.system, + ), + const FontFamilyItem( + label: "MiSans", + fontFamily: FontFamily.miSans, + ), + ]; return Column( children: [ + ItemCard( + info: Info( + label: appLocalizations.fontFamily, + iconData: Icons.text_fields, + ), + child: Container( + margin: const EdgeInsets.only( + left: 16, + right: 16, + ), + height: 48, + child: Selector( + selector: (_, config) => config.themeProps.fontFamily, + builder: (_, fontFamily, __) { + return ListView.separated( + scrollDirection: Axis.horizontal, + itemBuilder: (_, index) { + final fontFamilyItem = fontFamilyItems[index]; + return _fontFamilyCheckBox( + isSelected: fontFamily == fontFamilyItem.fontFamily, + fontFamilyItem: fontFamilyItem, + ); + }, + separatorBuilder: (_, __) { + return const SizedBox( + width: 16, + ); + }, + itemCount: fontFamilyItems.length, + ); + }, + ), + ), + ), ItemCard( info: Info( label: appLocalizations.themeMode, iconData: Icons.brightness_high, ), child: Selector( - selector: (_, config) => config.themeMode, + selector: (_, config) => config.themeProps.themeMode, builder: (_, themeMode, __) { return Container( padding: const EdgeInsets.symmetric(horizontal: 16), @@ -204,7 +297,7 @@ class _ThemeColorsBoxState extends State { ), height: 88, child: Selector( - selector: (_, config) => config.primaryColor, + selector: (_, config) => config.themeProps.primaryColor, builder: (_, currentPrimaryColor, __) { return ListView.separated( scrollDirection: Axis.horizontal, @@ -229,7 +322,7 @@ class _ThemeColorsBoxState extends State { Padding( padding: const EdgeInsets.symmetric(vertical: 16), child: Selector( - selector: (_, config) => config.prueBlack, + selector: (_, config) => config.themeProps.prueBlack, builder: (_, value, ___) { return ListItem.switchItem( leading: Icon( @@ -238,63 +331,19 @@ class _ThemeColorsBoxState extends State { ), title: Text(appLocalizations.prueBlackMode), delegate: SwitchDelegate( - value: value, - onChanged: (value) { - globalState.appController.config.prueBlack = value; - }), + value: value, + onChanged: (value) { + final appController = globalState.appController; + appController.config.themeProps = + appController.config.themeProps.copyWith( + prueBlack: value, + ); + }, + ), ); }, ), ), - // Padding( - // padding: const EdgeInsets.symmetric(vertical: 16), - // child: Selector( - // selector: (_, config) => config.scaleProps.custom, - // builder: (_, value, ___) { - // return ListItem.switchItem( - // leading: Icon( - // Icons.format_size_sharp, - // color: context.colorScheme.primary, - // ), - // title: const Text("自定义字体大小"), - // delegate: SwitchDelegate( - // value: value, - // onChanged: (value) { - // globalState.appController.config.scaleProps = - // globalState.appController.config.scaleProps.copyWith( - // custom: value, - // ); - // }, - // ), - // ); - // }, - // ), - // ), - // SizedBox( - // height: 20, - // child: Selector( - // selector: (_, config) => config.scaleProps, - // builder: (_, props, ___) { - // return AbsorbPointer( - // absorbing: !props.custom, - // child: DisabledMask( - // status: !props.custom, - // child: Slider( - // value: props.scale, - // min: 0.8, - // max: 1.2, - // onChanged: (value) { - // globalState.appController.config.scaleProps = - // globalState.appController.config.scaleProps.copyWith( - // scale: value, - // ); - // }, - // ), - // ), - // ); - // }, - // ), - // ), const SizedBox( height: 64, ), diff --git a/lib/l10n/arb/intl_en.arb b/lib/l10n/arb/intl_en.arb index 4d70ca9..8f8b2fb 100644 --- a/lib/l10n/arb/intl_en.arb +++ b/lib/l10n/arb/intl_en.arb @@ -320,5 +320,7 @@ "iconConfiguration": "Icon configuration", "noData": "No data", "adminAutoLaunch": "Admin auto launch", - "adminAutoLaunchDesc": "Boot up by using admin mode" + "adminAutoLaunchDesc": "Boot up by using admin mode", + "fontFamily": "FontFamily", + "systemFont": "System font" } \ No newline at end of file diff --git a/lib/l10n/arb/intl_zh_CN.arb b/lib/l10n/arb/intl_zh_CN.arb index acb6a36..789f050 100644 --- a/lib/l10n/arb/intl_zh_CN.arb +++ b/lib/l10n/arb/intl_zh_CN.arb @@ -320,5 +320,7 @@ "iconConfiguration": "图片配置", "noData": "暂无数据", "adminAutoLaunch": "管理员自启动", - "adminAutoLaunchDesc": "使用管理员模式开机自启动" + "adminAutoLaunchDesc": "使用管理员模式开机自启动", + "fontFamily": "字体", + "systemFont": "系统字体" } \ No newline at end of file diff --git a/lib/l10n/intl/messages_en.dart b/lib/l10n/intl/messages_en.dart index 305dd7d..dc9015f 100644 --- a/lib/l10n/intl/messages_en.dart +++ b/lib/l10n/intl/messages_en.dart @@ -192,6 +192,7 @@ class MessageLookup extends MessageLookupByLibrary { "findProcessMode": MessageLookupByLibrary.simpleMessage("Find process"), "findProcessModeDesc": MessageLookupByLibrary.simpleMessage( "There is a risk of flashback after opening"), + "fontFamily": MessageLookupByLibrary.simpleMessage("FontFamily"), "fourColumns": MessageLookupByLibrary.simpleMessage("Four columns"), "general": MessageLookupByLibrary.simpleMessage("General"), "generalDesc": @@ -425,6 +426,7 @@ class MessageLookup extends MessageLookupByLibrary { "style": MessageLookupByLibrary.simpleMessage("Style"), "submit": MessageLookupByLibrary.simpleMessage("Submit"), "sync": MessageLookupByLibrary.simpleMessage("Sync"), + "systemFont": MessageLookupByLibrary.simpleMessage("System font"), "systemProxy": MessageLookupByLibrary.simpleMessage("System proxy"), "systemProxyDesc": MessageLookupByLibrary.simpleMessage( "Attach HTTP proxy to VpnService"), diff --git a/lib/l10n/intl/messages_zh_CN.dart b/lib/l10n/intl/messages_zh_CN.dart index bef1211..f038d9b 100644 --- a/lib/l10n/intl/messages_zh_CN.dart +++ b/lib/l10n/intl/messages_zh_CN.dart @@ -155,6 +155,7 @@ class MessageLookup extends MessageLookupByLibrary { "findProcessMode": MessageLookupByLibrary.simpleMessage("查找进程"), "findProcessModeDesc": MessageLookupByLibrary.simpleMessage("开启后存在闪退风险"), + "fontFamily": MessageLookupByLibrary.simpleMessage("字体"), "fourColumns": MessageLookupByLibrary.simpleMessage("四列"), "general": MessageLookupByLibrary.simpleMessage("基础"), "generalDesc": MessageLookupByLibrary.simpleMessage("覆写基础设置"), @@ -339,6 +340,7 @@ class MessageLookup extends MessageLookupByLibrary { "style": MessageLookupByLibrary.simpleMessage("风格"), "submit": MessageLookupByLibrary.simpleMessage("提交"), "sync": MessageLookupByLibrary.simpleMessage("同步"), + "systemFont": MessageLookupByLibrary.simpleMessage("系统字体"), "systemProxy": MessageLookupByLibrary.simpleMessage("系统代理"), "systemProxyDesc": MessageLookupByLibrary.simpleMessage("为VpnService附加HTTP代理"), diff --git a/lib/l10n/l10n.dart b/lib/l10n/l10n.dart index e837ff2..7b1da52 100644 --- a/lib/l10n/l10n.dart +++ b/lib/l10n/l10n.dart @@ -3269,6 +3269,26 @@ class AppLocalizations { args: [], ); } + + /// `FontFamily` + String get fontFamily { + return Intl.message( + 'FontFamily', + name: 'fontFamily', + desc: '', + args: [], + ); + } + + /// `System font` + String get systemFont { + return Intl.message( + 'System font', + name: 'systemFont', + desc: '', + args: [], + ); + } } class AppLocalizationDelegate extends LocalizationsDelegate { diff --git a/lib/models/config.dart b/lib/models/config.dart index 85c2e90..6b4e2a0 100644 --- a/lib/models/config.dart +++ b/lib/models/config.dart @@ -141,6 +141,35 @@ class ProxiesStyle with _$ProxiesStyle { json == null ? defaultProxiesStyle : _$ProxiesStyleFromJson(json); } +const defaultThemeProps = ThemeProps(); + +@freezed +class ThemeProps with _$ThemeProps { + const factory ThemeProps({ + @Default(0xFF795548) int? primaryColor, + @Default(ThemeMode.system) ThemeMode themeMode, + @Default(false) bool prueBlack, + @Default(FontFamily.system) FontFamily fontFamily, + }) = _ThemeProps; + + factory ThemeProps.fromJson(Map json) => _$ThemePropsFromJson(json); + + factory ThemeProps.realFromJson(Map? json) { + if (json == null) { + return Platform.isWindows + ? defaultThemeProps.copyWith(fontFamily: FontFamily.miSans) + : defaultThemeProps; + } + try { + return ThemeProps.fromJson(json); + } catch (_) { + return Platform.isWindows + ? defaultThemeProps.copyWith(fontFamily: FontFamily.miSans) + : defaultThemeProps; + } + } +} + const defaultCustomFontSizeScale = 1.0; @JsonSerializable() @@ -148,13 +177,11 @@ class Config extends ChangeNotifier { AppSetting _appSetting; List _profiles; String? _currentProfileId; - ThemeMode _themeMode; - int? _primaryColor; bool _isAccessControl; AccessControl _accessControl; DAV? _dav; WindowProps _windowProps; - bool _prueBlack; + ThemeProps _themeProps; VpnProps _vpnProps; DesktopProps _desktopProps; bool _overrideDns; @@ -163,18 +190,16 @@ class Config extends ChangeNotifier { Config() : _profiles = [], - _themeMode = ThemeMode.system, - _primaryColor = defaultPrimaryColor.value, _isAccessControl = false, _accessControl = const AccessControl(), _windowProps = const WindowProps(), - _prueBlack = false, _vpnProps = defaultVpnProps, _desktopProps = const DesktopProps(), _overrideDns = false, _appSetting = defaultAppSetting, _hotKeyActions = [], - _proxiesStyle = defaultProxiesStyle; + _proxiesStyle = defaultProxiesStyle, + _themeProps = defaultThemeProps; @JsonKey(fromJson: AppSetting.realFromJson) AppSetting get appSetting => _appSetting; @@ -305,25 +330,6 @@ class Config extends ChangeNotifier { } } - @JsonKey(defaultValue: ThemeMode.system) - ThemeMode get themeMode => _themeMode; - - set themeMode(ThemeMode value) { - if (_themeMode != value) { - _themeMode = value; - notifyListeners(); - } - } - - int? get primaryColor => _primaryColor; - - set primaryColor(int? value) { - if (_primaryColor != value) { - _primaryColor = value; - notifyListeners(); - } - } - @JsonKey(defaultValue: false) bool get isAccessControl { if (!Platform.isAndroid) return false; @@ -355,18 +361,6 @@ class Config extends ChangeNotifier { } } - @JsonKey(defaultValue: false) - bool get prueBlack { - return _prueBlack; - } - - set prueBlack(bool value) { - if (_prueBlack != value) { - _prueBlack = value; - notifyListeners(); - } - } - WindowProps get windowProps => _windowProps; set windowProps(WindowProps value) { @@ -427,6 +421,16 @@ class Config extends ChangeNotifier { } } + @JsonKey(fromJson: ThemeProps.realFromJson) + ThemeProps get themeProps => _themeProps; + + set themeProps(ThemeProps value) { + if (_themeProps != value) { + _themeProps = value; + notifyListeners(); + } + } + updateOrAddHotKeyAction(HotKeyAction hotKeyAction) { final index = _hotKeyActions.indexWhere((item) => item.action == hotKeyAction.action); @@ -455,11 +459,9 @@ class Config extends ChangeNotifier { _appSetting = config._appSetting; _currentProfileId = config._currentProfileId; _dav = config._dav; - _themeMode = config._themeMode; - _primaryColor = config._primaryColor; _isAccessControl = config._isAccessControl; _accessControl = config._accessControl; - _prueBlack = config._prueBlack; + _themeProps = config._themeProps; _windowProps = config._windowProps; _proxiesStyle = config._proxiesStyle; _vpnProps = config._vpnProps; diff --git a/lib/models/generated/config.freezed.dart b/lib/models/generated/config.freezed.dart index 80ea953..ee737c6 100644 --- a/lib/models/generated/config.freezed.dart +++ b/lib/models/generated/config.freezed.dart @@ -1541,3 +1541,212 @@ abstract class _ProxiesStyle implements ProxiesStyle { _$$ProxiesStyleImplCopyWith<_$ProxiesStyleImpl> get copyWith => throw _privateConstructorUsedError; } + +ThemeProps _$ThemePropsFromJson(Map json) { + return _ThemeProps.fromJson(json); +} + +/// @nodoc +mixin _$ThemeProps { + int? get primaryColor => throw _privateConstructorUsedError; + ThemeMode get themeMode => throw _privateConstructorUsedError; + bool get prueBlack => throw _privateConstructorUsedError; + FontFamily get fontFamily => throw _privateConstructorUsedError; + + Map toJson() => throw _privateConstructorUsedError; + @JsonKey(ignore: true) + $ThemePropsCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ThemePropsCopyWith<$Res> { + factory $ThemePropsCopyWith( + ThemeProps value, $Res Function(ThemeProps) then) = + _$ThemePropsCopyWithImpl<$Res, ThemeProps>; + @useResult + $Res call( + {int? primaryColor, + ThemeMode themeMode, + bool prueBlack, + FontFamily fontFamily}); +} + +/// @nodoc +class _$ThemePropsCopyWithImpl<$Res, $Val extends ThemeProps> + implements $ThemePropsCopyWith<$Res> { + _$ThemePropsCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? primaryColor = freezed, + Object? themeMode = null, + Object? prueBlack = null, + Object? fontFamily = null, + }) { + return _then(_value.copyWith( + primaryColor: freezed == primaryColor + ? _value.primaryColor + : primaryColor // ignore: cast_nullable_to_non_nullable + as int?, + themeMode: null == themeMode + ? _value.themeMode + : themeMode // ignore: cast_nullable_to_non_nullable + as ThemeMode, + prueBlack: null == prueBlack + ? _value.prueBlack + : prueBlack // ignore: cast_nullable_to_non_nullable + as bool, + fontFamily: null == fontFamily + ? _value.fontFamily + : fontFamily // ignore: cast_nullable_to_non_nullable + as FontFamily, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$ThemePropsImplCopyWith<$Res> + implements $ThemePropsCopyWith<$Res> { + factory _$$ThemePropsImplCopyWith( + _$ThemePropsImpl value, $Res Function(_$ThemePropsImpl) then) = + __$$ThemePropsImplCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {int? primaryColor, + ThemeMode themeMode, + bool prueBlack, + FontFamily fontFamily}); +} + +/// @nodoc +class __$$ThemePropsImplCopyWithImpl<$Res> + extends _$ThemePropsCopyWithImpl<$Res, _$ThemePropsImpl> + implements _$$ThemePropsImplCopyWith<$Res> { + __$$ThemePropsImplCopyWithImpl( + _$ThemePropsImpl _value, $Res Function(_$ThemePropsImpl) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? primaryColor = freezed, + Object? themeMode = null, + Object? prueBlack = null, + Object? fontFamily = null, + }) { + return _then(_$ThemePropsImpl( + primaryColor: freezed == primaryColor + ? _value.primaryColor + : primaryColor // ignore: cast_nullable_to_non_nullable + as int?, + themeMode: null == themeMode + ? _value.themeMode + : themeMode // ignore: cast_nullable_to_non_nullable + as ThemeMode, + prueBlack: null == prueBlack + ? _value.prueBlack + : prueBlack // ignore: cast_nullable_to_non_nullable + as bool, + fontFamily: null == fontFamily + ? _value.fontFamily + : fontFamily // ignore: cast_nullable_to_non_nullable + as FontFamily, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$ThemePropsImpl implements _ThemeProps { + const _$ThemePropsImpl( + {this.primaryColor = 0xFF795548, + this.themeMode = ThemeMode.system, + this.prueBlack = false, + this.fontFamily = FontFamily.system}); + + factory _$ThemePropsImpl.fromJson(Map json) => + _$$ThemePropsImplFromJson(json); + + @override + @JsonKey() + final int? primaryColor; + @override + @JsonKey() + final ThemeMode themeMode; + @override + @JsonKey() + final bool prueBlack; + @override + @JsonKey() + final FontFamily fontFamily; + + @override + String toString() { + return 'ThemeProps(primaryColor: $primaryColor, themeMode: $themeMode, prueBlack: $prueBlack, fontFamily: $fontFamily)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ThemePropsImpl && + (identical(other.primaryColor, primaryColor) || + other.primaryColor == primaryColor) && + (identical(other.themeMode, themeMode) || + other.themeMode == themeMode) && + (identical(other.prueBlack, prueBlack) || + other.prueBlack == prueBlack) && + (identical(other.fontFamily, fontFamily) || + other.fontFamily == fontFamily)); + } + + @JsonKey(ignore: true) + @override + int get hashCode => + Object.hash(runtimeType, primaryColor, themeMode, prueBlack, fontFamily); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$ThemePropsImplCopyWith<_$ThemePropsImpl> get copyWith => + __$$ThemePropsImplCopyWithImpl<_$ThemePropsImpl>(this, _$identity); + + @override + Map toJson() { + return _$$ThemePropsImplToJson( + this, + ); + } +} + +abstract class _ThemeProps implements ThemeProps { + const factory _ThemeProps( + {final int? primaryColor, + final ThemeMode themeMode, + final bool prueBlack, + final FontFamily fontFamily}) = _$ThemePropsImpl; + + factory _ThemeProps.fromJson(Map json) = + _$ThemePropsImpl.fromJson; + + @override + int? get primaryColor; + @override + ThemeMode get themeMode; + @override + bool get prueBlack; + @override + FontFamily get fontFamily; + @override + @JsonKey(ignore: true) + _$$ThemePropsImplCopyWith<_$ThemePropsImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/models/generated/config.g.dart b/lib/models/generated/config.g.dart index 4118f75..0afb281 100644 --- a/lib/models/generated/config.g.dart +++ b/lib/models/generated/config.g.dart @@ -14,16 +14,12 @@ Config _$ConfigFromJson(Map json) => Config() .toList() ?? [] ..currentProfileId = json['currentProfileId'] as String? - ..themeMode = $enumDecodeNullable(_$ThemeModeEnumMap, json['themeMode']) ?? - ThemeMode.system - ..primaryColor = (json['primaryColor'] as num?)?.toInt() ..isAccessControl = json['isAccessControl'] as bool? ?? false ..accessControl = AccessControl.fromJson(json['accessControl'] as Map) ..dav = json['dav'] == null ? null : DAV.fromJson(json['dav'] as Map) - ..prueBlack = json['prueBlack'] as bool? ?? false ..windowProps = WindowProps.fromJson(json['windowProps'] as Map?) ..vpnProps = VpnProps.fromJson(json['vpnProps'] as Map?) @@ -35,32 +31,26 @@ Config _$ConfigFromJson(Map json) => Config() .toList() ?? [] ..proxiesStyle = - ProxiesStyle.fromJson(json['proxiesStyle'] as Map?); + ProxiesStyle.fromJson(json['proxiesStyle'] as Map?) + ..themeProps = + ThemeProps.realFromJson(json['themeProps'] as Map?); Map _$ConfigToJson(Config instance) => { 'appSetting': instance.appSetting, 'profiles': instance.profiles, 'currentProfileId': instance.currentProfileId, - 'themeMode': _$ThemeModeEnumMap[instance.themeMode]!, - 'primaryColor': instance.primaryColor, 'isAccessControl': instance.isAccessControl, 'accessControl': instance.accessControl, 'dav': instance.dav, - 'prueBlack': instance.prueBlack, 'windowProps': instance.windowProps, 'vpnProps': instance.vpnProps, 'desktopProps': instance.desktopProps, 'overrideDns': instance.overrideDns, 'hotKeyActions': instance.hotKeyActions, 'proxiesStyle': instance.proxiesStyle, + 'themeProps': instance.themeProps, }; -const _$ThemeModeEnumMap = { - ThemeMode.system: 'system', - ThemeMode.light: 'light', - ThemeMode.dark: 'dark', -}; - _$AppSettingImpl _$$AppSettingImplFromJson(Map json) => _$AppSettingImpl( locale: json['locale'] as String?, @@ -241,3 +231,35 @@ const _$ProxyCardTypeEnumMap = { ProxyCardType.shrink: 'shrink', ProxyCardType.min: 'min', }; + +_$ThemePropsImpl _$$ThemePropsImplFromJson(Map json) => + _$ThemePropsImpl( + primaryColor: (json['primaryColor'] as num?)?.toInt() ?? 0xFF795548, + themeMode: $enumDecodeNullable(_$ThemeModeEnumMap, json['themeMode']) ?? + ThemeMode.system, + prueBlack: json['prueBlack'] as bool? ?? false, + fontFamily: + $enumDecodeNullable(_$FontFamilyEnumMap, json['fontFamily']) ?? + FontFamily.system, + ); + +Map _$$ThemePropsImplToJson(_$ThemePropsImpl instance) => + { + 'primaryColor': instance.primaryColor, + 'themeMode': _$ThemeModeEnumMap[instance.themeMode]!, + 'prueBlack': instance.prueBlack, + 'fontFamily': _$FontFamilyEnumMap[instance.fontFamily]!, + }; + +const _$ThemeModeEnumMap = { + ThemeMode.system: 'system', + ThemeMode.light: 'light', + ThemeMode.dark: 'dark', +}; + +const _$FontFamilyEnumMap = { + FontFamily.system: 'system', + FontFamily.miSans: 'miSans', + FontFamily.twEmoji: 'twEmoji', + FontFamily.icon: 'icon', +}; diff --git a/lib/models/generated/selector.freezed.dart b/lib/models/generated/selector.freezed.dart index 9c07ca0..b3dad0b 100644 --- a/lib/models/generated/selector.freezed.dart +++ b/lib/models/generated/selector.freezed.dart @@ -772,6 +772,7 @@ mixin _$ApplicationSelectorState { ThemeMode? get themeMode => throw _privateConstructorUsedError; int? get primaryColor => throw _privateConstructorUsedError; bool get prueBlack => throw _privateConstructorUsedError; + FontFamily get fontFamily => throw _privateConstructorUsedError; @JsonKey(ignore: true) $ApplicationSelectorStateCopyWith get copyWith => @@ -788,7 +789,8 @@ abstract class $ApplicationSelectorStateCopyWith<$Res> { {String? locale, ThemeMode? themeMode, int? primaryColor, - bool prueBlack}); + bool prueBlack, + FontFamily fontFamily}); } /// @nodoc @@ -809,6 +811,7 @@ class _$ApplicationSelectorStateCopyWithImpl<$Res, Object? themeMode = freezed, Object? primaryColor = freezed, Object? prueBlack = null, + Object? fontFamily = null, }) { return _then(_value.copyWith( locale: freezed == locale @@ -827,6 +830,10 @@ class _$ApplicationSelectorStateCopyWithImpl<$Res, ? _value.prueBlack : prueBlack // ignore: cast_nullable_to_non_nullable as bool, + fontFamily: null == fontFamily + ? _value.fontFamily + : fontFamily // ignore: cast_nullable_to_non_nullable + as FontFamily, ) as $Val); } } @@ -844,7 +851,8 @@ abstract class _$$ApplicationSelectorStateImplCopyWith<$Res> {String? locale, ThemeMode? themeMode, int? primaryColor, - bool prueBlack}); + bool prueBlack, + FontFamily fontFamily}); } /// @nodoc @@ -864,6 +872,7 @@ class __$$ApplicationSelectorStateImplCopyWithImpl<$Res> Object? themeMode = freezed, Object? primaryColor = freezed, Object? prueBlack = null, + Object? fontFamily = null, }) { return _then(_$ApplicationSelectorStateImpl( locale: freezed == locale @@ -882,6 +891,10 @@ class __$$ApplicationSelectorStateImplCopyWithImpl<$Res> ? _value.prueBlack : prueBlack // ignore: cast_nullable_to_non_nullable as bool, + fontFamily: null == fontFamily + ? _value.fontFamily + : fontFamily // ignore: cast_nullable_to_non_nullable + as FontFamily, )); } } @@ -893,7 +906,8 @@ class _$ApplicationSelectorStateImpl implements _ApplicationSelectorState { {required this.locale, required this.themeMode, required this.primaryColor, - required this.prueBlack}); + required this.prueBlack, + required this.fontFamily}); @override final String? locale; @@ -903,10 +917,12 @@ class _$ApplicationSelectorStateImpl implements _ApplicationSelectorState { final int? primaryColor; @override final bool prueBlack; + @override + final FontFamily fontFamily; @override String toString() { - return 'ApplicationSelectorState(locale: $locale, themeMode: $themeMode, primaryColor: $primaryColor, prueBlack: $prueBlack)'; + return 'ApplicationSelectorState(locale: $locale, themeMode: $themeMode, primaryColor: $primaryColor, prueBlack: $prueBlack, fontFamily: $fontFamily)'; } @override @@ -920,12 +936,14 @@ class _$ApplicationSelectorStateImpl implements _ApplicationSelectorState { (identical(other.primaryColor, primaryColor) || other.primaryColor == primaryColor) && (identical(other.prueBlack, prueBlack) || - other.prueBlack == prueBlack)); + other.prueBlack == prueBlack) && + (identical(other.fontFamily, fontFamily) || + other.fontFamily == fontFamily)); } @override - int get hashCode => - Object.hash(runtimeType, locale, themeMode, primaryColor, prueBlack); + int get hashCode => Object.hash( + runtimeType, locale, themeMode, primaryColor, prueBlack, fontFamily); @JsonKey(ignore: true) @override @@ -940,7 +958,8 @@ abstract class _ApplicationSelectorState implements ApplicationSelectorState { {required final String? locale, required final ThemeMode? themeMode, required final int? primaryColor, - required final bool prueBlack}) = _$ApplicationSelectorStateImpl; + required final bool prueBlack, + required final FontFamily fontFamily}) = _$ApplicationSelectorStateImpl; @override String? get locale; @@ -951,6 +970,8 @@ abstract class _ApplicationSelectorState implements ApplicationSelectorState { @override bool get prueBlack; @override + FontFamily get fontFamily; + @override @JsonKey(ignore: true) _$$ApplicationSelectorStateImplCopyWith<_$ApplicationSelectorStateImpl> get copyWith => throw _privateConstructorUsedError; diff --git a/lib/models/selector.dart b/lib/models/selector.dart index 5d7b7db..0f5fd96 100644 --- a/lib/models/selector.dart +++ b/lib/models/selector.dart @@ -55,6 +55,7 @@ class ApplicationSelectorState with _$ApplicationSelectorState { required ThemeMode? themeMode, required int? primaryColor, required bool prueBlack, + required FontFamily fontFamily, }) = _ApplicationSelectorState; } diff --git a/lib/widgets/open_container.dart b/lib/widgets/open_container.dart index 0fcc0e5..31ad601 100644 --- a/lib/widgets/open_container.dart +++ b/lib/widgets/open_container.dart @@ -427,7 +427,7 @@ class _OpenContainerRoute extends ModalRoute { Animation secondaryAnimation, ) { return Selector( - selector: (_, config) => config.themeMode, + selector: (_, config) => config.themeProps.themeMode, builder: (_, __, ___) { _colorTween = _getColorTween( transitionType: transitionType, diff --git a/lib/widgets/text.dart b/lib/widgets/text.dart index ba3a6aa..ffcb8fe 100644 --- a/lib/widgets/text.dart +++ b/lib/widgets/text.dart @@ -1,4 +1,4 @@ -import 'package:fl_clash/common/common.dart'; +import 'package:fl_clash/enum/enum.dart'; import 'package:flutter/material.dart'; import 'package:emoji_regex/emoji_regex.dart'; @@ -63,7 +63,7 @@ class EmojiText extends StatelessWidget { TextSpan( text:match.group(0), style: style?.copyWith( - fontFamily: Fonts.twEmoji, + fontFamily: FontFamily.twEmoji.value, ), ), ); diff --git a/pubspec.yaml b/pubspec.yaml index 1cc98f1..61d32e9 100755 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -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.65+202410261 +version: 0.8.66+202410262 environment: sdk: '>=3.1.0 <4.0.0' @@ -72,6 +72,9 @@ flutter: - family: Twemoji fonts: - asset: assets/fonts/Twemoji.Mozilla.ttf + - family: MiSans + fonts: + - asset: assets/fonts/MiSans-Regular.ttf - family: Icons fonts: - asset: assets/fonts/Icons.ttf