From 07a5a191416196bb230de7b424ce13ed64731d4e Mon Sep 17 00:00:00 2001 From: Texas0295 Date: Fri, 5 Sep 2025 23:04:23 +0800 Subject: [PATCH] settings: add Data Saving Mode toggle (UI & i18n only) Signed-off-by: Texas0295 --- assets/i18n/en-US.json | 1 + assets/i18n/zh-CN.json | 1 + assets/i18n/zh-TW.json | 3 ++- lib/pods/config.dart | 9 +++++++++ lib/pods/config.freezed.dart | 39 +++++++++++++++++++----------------- lib/pods/config.g.dart | 2 +- lib/screens/explore.g.dart | 2 +- lib/screens/settings.dart | 14 +++++++++++++ 8 files changed, 50 insertions(+), 21 deletions(-) diff --git a/assets/i18n/en-US.json b/assets/i18n/en-US.json index c7525a26..2e18499b 100644 --- a/assets/i18n/en-US.json +++ b/assets/i18n/en-US.json @@ -349,6 +349,7 @@ "chatBreakNone": "None", "settingsRealmCompactView": "Compact Realm View", "settingsMixedFeed": "Mixed Feed", + "settingsDataSavingMode": "Data Saving Mode", "settingsAutoTranslate": "Auto Translate", "settingsHideBottomNav": "Hide Bottom Navigation", "settingsSoundEffects": "Sound Effects", diff --git a/assets/i18n/zh-CN.json b/assets/i18n/zh-CN.json index 8c44fac6..c87ea76e 100644 --- a/assets/i18n/zh-CN.json +++ b/assets/i18n/zh-CN.json @@ -315,6 +315,7 @@ "chatBreakNone": "无", "settingsRealmCompactView": "紧凑领域视图", "settingsMixedFeed": "混合动态", + "settingsDataSavingMode": "流量节省模式", "settingsAutoTranslate": "自动翻译", "settingsHideBottomNav": "隐藏底部导航", "settingsSoundEffects": "音效", diff --git a/assets/i18n/zh-TW.json b/assets/i18n/zh-TW.json index 50cc5c0d..cc5a1668 100644 --- a/assets/i18n/zh-TW.json +++ b/assets/i18n/zh-TW.json @@ -315,6 +315,7 @@ "settingsRealmCompactView": "緊湊領域視圖", "settingsMixedFeed": "混合動態", "settingsAutoTranslate": "自動翻譯", + "settingsDataSavingMode": "低數據模式", "settingsHideBottomNav": "隱藏底部導航", "settingsSoundEffects": "音效", "settingsAprilFoolFeatures": "愚人節功能", @@ -825,4 +826,4 @@ "copySecretHint": "請複製此密鑰並將其存放在安全的地方。您將無法再次看到它。", "expiresIn": "過期時間(秒)", "isOidc": "OIDC 相容" -} \ No newline at end of file +} diff --git a/lib/pods/config.dart b/lib/pods/config.dart index b109b84b..52def773 100644 --- a/lib/pods/config.dart +++ b/lib/pods/config.dart @@ -20,6 +20,7 @@ const kAppColorSchemeStoreKey = 'app_color_scheme'; const kAppNotifyWithHaptic = 'app_notify_with_haptic'; const kAppCustomFonts = 'app_custom_fonts'; const kAppAutoTranslate = 'app_auto_translate'; +const kAppDataSavingMode = 'app_data_saving_mode'; const kAppSoundEffects = 'app_sound_effects'; const kAppAprilFoolFeatures = 'app_april_fool_features'; const kAppWindowSize = 'app_window_size'; @@ -55,6 +56,7 @@ final serverUrlProvider = Provider((ref) { sealed class AppSettings with _$AppSettings { const factory AppSettings({ required bool autoTranslate, + required bool dataSavingMode, required bool soundEffects, required bool aprilFoolFeatures, required bool enterToSend, @@ -73,6 +75,7 @@ class AppSettingsNotifier extends _$AppSettingsNotifier { final prefs = ref.watch(sharedPreferencesProvider); return AppSettings( autoTranslate: prefs.getBool(kAppAutoTranslate) ?? false, + dataSavingMode: prefs.getBool(kAppDataSavingMode) ?? false, soundEffects: prefs.getBool(kAppSoundEffects) ?? true, aprilFoolFeatures: prefs.getBool(kAppAprilFoolFeatures) ?? true, enterToSend: prefs.getBool(kAppEnterToSend) ?? true, @@ -107,6 +110,12 @@ class AppSettingsNotifier extends _$AppSettingsNotifier { state = state.copyWith(autoTranslate: value); } + void setDataSavingMode(bool value){ + final prefs = ref.read(sharedPreferencesProvider); + prefs.setBool(kAppDataSavingMode, value); + state = state.copyWith(dataSavingMode: value); + } + void setSoundEffects(bool value) { final prefs = ref.read(sharedPreferencesProvider); prefs.setBool(kAppSoundEffects, value); diff --git a/lib/pods/config.freezed.dart b/lib/pods/config.freezed.dart index 500f586a..aa460bb0 100644 --- a/lib/pods/config.freezed.dart +++ b/lib/pods/config.freezed.dart @@ -14,7 +14,7 @@ T _$identity(T value) => value; /// @nodoc mixin _$AppSettings { - bool get autoTranslate; bool get soundEffects; bool get aprilFoolFeatures; bool get enterToSend; bool get appBarTransparent; bool get showBackgroundImage; String? get customFonts; int? get appColorScheme;// The color stored via the int type + bool get autoTranslate; bool get dataSavingMode; bool get soundEffects; bool get aprilFoolFeatures; bool get enterToSend; bool get appBarTransparent; bool get showBackgroundImage; String? get customFonts; int? get appColorScheme;// The color stored via the int type Size? get windowSize; /// Create a copy of AppSettings /// with the given fields replaced by the non-null parameter values. @@ -26,16 +26,16 @@ $AppSettingsCopyWith get copyWith => _$AppSettingsCopyWithImpl Object.hash(runtimeType,autoTranslate,soundEffects,aprilFoolFeatures,enterToSend,appBarTransparent,showBackgroundImage,customFonts,appColorScheme,windowSize); +int get hashCode => Object.hash(runtimeType,autoTranslate,dataSavingMode,soundEffects,aprilFoolFeatures,enterToSend,appBarTransparent,showBackgroundImage,customFonts,appColorScheme,windowSize); @override String toString() { - return 'AppSettings(autoTranslate: $autoTranslate, soundEffects: $soundEffects, aprilFoolFeatures: $aprilFoolFeatures, enterToSend: $enterToSend, appBarTransparent: $appBarTransparent, showBackgroundImage: $showBackgroundImage, customFonts: $customFonts, appColorScheme: $appColorScheme, windowSize: $windowSize)'; + return 'AppSettings(autoTranslate: $autoTranslate, dataSavingMode: $dataSavingMode, soundEffects: $soundEffects, aprilFoolFeatures: $aprilFoolFeatures, enterToSend: $enterToSend, appBarTransparent: $appBarTransparent, showBackgroundImage: $showBackgroundImage, customFonts: $customFonts, appColorScheme: $appColorScheme, windowSize: $windowSize)'; } @@ -46,7 +46,7 @@ abstract mixin class $AppSettingsCopyWith<$Res> { factory $AppSettingsCopyWith(AppSettings value, $Res Function(AppSettings) _then) = _$AppSettingsCopyWithImpl; @useResult $Res call({ - bool autoTranslate, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, String? customFonts, int? appColorScheme, Size? windowSize + bool autoTranslate, bool dataSavingMode, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, String? customFonts, int? appColorScheme, Size? windowSize }); @@ -63,9 +63,10 @@ class _$AppSettingsCopyWithImpl<$Res> /// Create a copy of AppSettings /// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') @override $Res call({Object? autoTranslate = null,Object? soundEffects = null,Object? aprilFoolFeatures = null,Object? enterToSend = null,Object? appBarTransparent = null,Object? showBackgroundImage = null,Object? customFonts = freezed,Object? appColorScheme = freezed,Object? windowSize = freezed,}) { +@pragma('vm:prefer-inline') @override $Res call({Object? autoTranslate = null,Object? dataSavingMode = null,Object? soundEffects = null,Object? aprilFoolFeatures = null,Object? enterToSend = null,Object? appBarTransparent = null,Object? showBackgroundImage = null,Object? customFonts = freezed,Object? appColorScheme = freezed,Object? windowSize = freezed,}) { return _then(_self.copyWith( autoTranslate: null == autoTranslate ? _self.autoTranslate : autoTranslate // ignore: cast_nullable_to_non_nullable +as bool,dataSavingMode: null == dataSavingMode ? _self.dataSavingMode : dataSavingMode // ignore: cast_nullable_to_non_nullable as bool,soundEffects: null == soundEffects ? _self.soundEffects : soundEffects // ignore: cast_nullable_to_non_nullable as bool,aprilFoolFeatures: null == aprilFoolFeatures ? _self.aprilFoolFeatures : aprilFoolFeatures // ignore: cast_nullable_to_non_nullable as bool,enterToSend: null == enterToSend ? _self.enterToSend : enterToSend // ignore: cast_nullable_to_non_nullable @@ -156,10 +157,10 @@ return $default(_that);case _: /// } /// ``` -@optionalTypeArgs TResult maybeWhen(TResult Function( bool autoTranslate, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, String? customFonts, int? appColorScheme, Size? windowSize)? $default,{required TResult orElse(),}) {final _that = this; +@optionalTypeArgs TResult maybeWhen(TResult Function( bool autoTranslate, bool dataSavingMode, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, String? customFonts, int? appColorScheme, Size? windowSize)? $default,{required TResult orElse(),}) {final _that = this; switch (_that) { case _AppSettings() when $default != null: -return $default(_that.autoTranslate,_that.soundEffects,_that.aprilFoolFeatures,_that.enterToSend,_that.appBarTransparent,_that.showBackgroundImage,_that.customFonts,_that.appColorScheme,_that.windowSize);case _: +return $default(_that.autoTranslate,_that.dataSavingMode,_that.soundEffects,_that.aprilFoolFeatures,_that.enterToSend,_that.appBarTransparent,_that.showBackgroundImage,_that.customFonts,_that.appColorScheme,_that.windowSize);case _: return orElse(); } @@ -177,10 +178,10 @@ return $default(_that.autoTranslate,_that.soundEffects,_that.aprilFoolFeatures,_ /// } /// ``` -@optionalTypeArgs TResult when(TResult Function( bool autoTranslate, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, String? customFonts, int? appColorScheme, Size? windowSize) $default,) {final _that = this; +@optionalTypeArgs TResult when(TResult Function( bool autoTranslate, bool dataSavingMode, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, String? customFonts, int? appColorScheme, Size? windowSize) $default,) {final _that = this; switch (_that) { case _AppSettings(): -return $default(_that.autoTranslate,_that.soundEffects,_that.aprilFoolFeatures,_that.enterToSend,_that.appBarTransparent,_that.showBackgroundImage,_that.customFonts,_that.appColorScheme,_that.windowSize);} +return $default(_that.autoTranslate,_that.dataSavingMode,_that.soundEffects,_that.aprilFoolFeatures,_that.enterToSend,_that.appBarTransparent,_that.showBackgroundImage,_that.customFonts,_that.appColorScheme,_that.windowSize);} } /// A variant of `when` that fallback to returning `null` /// @@ -194,10 +195,10 @@ return $default(_that.autoTranslate,_that.soundEffects,_that.aprilFoolFeatures,_ /// } /// ``` -@optionalTypeArgs TResult? whenOrNull(TResult? Function( bool autoTranslate, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, String? customFonts, int? appColorScheme, Size? windowSize)? $default,) {final _that = this; +@optionalTypeArgs TResult? whenOrNull(TResult? Function( bool autoTranslate, bool dataSavingMode, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, String? customFonts, int? appColorScheme, Size? windowSize)? $default,) {final _that = this; switch (_that) { case _AppSettings() when $default != null: -return $default(_that.autoTranslate,_that.soundEffects,_that.aprilFoolFeatures,_that.enterToSend,_that.appBarTransparent,_that.showBackgroundImage,_that.customFonts,_that.appColorScheme,_that.windowSize);case _: +return $default(_that.autoTranslate,_that.dataSavingMode,_that.soundEffects,_that.aprilFoolFeatures,_that.enterToSend,_that.appBarTransparent,_that.showBackgroundImage,_that.customFonts,_that.appColorScheme,_that.windowSize);case _: return null; } @@ -209,10 +210,11 @@ return $default(_that.autoTranslate,_that.soundEffects,_that.aprilFoolFeatures,_ class _AppSettings implements AppSettings { - const _AppSettings({required this.autoTranslate, required this.soundEffects, required this.aprilFoolFeatures, required this.enterToSend, required this.appBarTransparent, required this.showBackgroundImage, required this.customFonts, required this.appColorScheme, required this.windowSize}); + const _AppSettings({required this.autoTranslate, required this.dataSavingMode, required this.soundEffects, required this.aprilFoolFeatures, required this.enterToSend, required this.appBarTransparent, required this.showBackgroundImage, required this.customFonts, required this.appColorScheme, required this.windowSize}); @override final bool autoTranslate; +@override final bool dataSavingMode; @override final bool soundEffects; @override final bool aprilFoolFeatures; @override final bool enterToSend; @@ -233,16 +235,16 @@ _$AppSettingsCopyWith<_AppSettings> get copyWith => __$AppSettingsCopyWithImpl<_ @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is _AppSettings&&(identical(other.autoTranslate, autoTranslate) || other.autoTranslate == autoTranslate)&&(identical(other.soundEffects, soundEffects) || other.soundEffects == soundEffects)&&(identical(other.aprilFoolFeatures, aprilFoolFeatures) || other.aprilFoolFeatures == aprilFoolFeatures)&&(identical(other.enterToSend, enterToSend) || other.enterToSend == enterToSend)&&(identical(other.appBarTransparent, appBarTransparent) || other.appBarTransparent == appBarTransparent)&&(identical(other.showBackgroundImage, showBackgroundImage) || other.showBackgroundImage == showBackgroundImage)&&(identical(other.customFonts, customFonts) || other.customFonts == customFonts)&&(identical(other.appColorScheme, appColorScheme) || other.appColorScheme == appColorScheme)&&(identical(other.windowSize, windowSize) || other.windowSize == windowSize)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is _AppSettings&&(identical(other.autoTranslate, autoTranslate) || other.autoTranslate == autoTranslate)&&(identical(other.dataSavingMode, dataSavingMode) || other.dataSavingMode == dataSavingMode)&&(identical(other.soundEffects, soundEffects) || other.soundEffects == soundEffects)&&(identical(other.aprilFoolFeatures, aprilFoolFeatures) || other.aprilFoolFeatures == aprilFoolFeatures)&&(identical(other.enterToSend, enterToSend) || other.enterToSend == enterToSend)&&(identical(other.appBarTransparent, appBarTransparent) || other.appBarTransparent == appBarTransparent)&&(identical(other.showBackgroundImage, showBackgroundImage) || other.showBackgroundImage == showBackgroundImage)&&(identical(other.customFonts, customFonts) || other.customFonts == customFonts)&&(identical(other.appColorScheme, appColorScheme) || other.appColorScheme == appColorScheme)&&(identical(other.windowSize, windowSize) || other.windowSize == windowSize)); } @override -int get hashCode => Object.hash(runtimeType,autoTranslate,soundEffects,aprilFoolFeatures,enterToSend,appBarTransparent,showBackgroundImage,customFonts,appColorScheme,windowSize); +int get hashCode => Object.hash(runtimeType,autoTranslate,dataSavingMode,soundEffects,aprilFoolFeatures,enterToSend,appBarTransparent,showBackgroundImage,customFonts,appColorScheme,windowSize); @override String toString() { - return 'AppSettings(autoTranslate: $autoTranslate, soundEffects: $soundEffects, aprilFoolFeatures: $aprilFoolFeatures, enterToSend: $enterToSend, appBarTransparent: $appBarTransparent, showBackgroundImage: $showBackgroundImage, customFonts: $customFonts, appColorScheme: $appColorScheme, windowSize: $windowSize)'; + return 'AppSettings(autoTranslate: $autoTranslate, dataSavingMode: $dataSavingMode, soundEffects: $soundEffects, aprilFoolFeatures: $aprilFoolFeatures, enterToSend: $enterToSend, appBarTransparent: $appBarTransparent, showBackgroundImage: $showBackgroundImage, customFonts: $customFonts, appColorScheme: $appColorScheme, windowSize: $windowSize)'; } @@ -253,7 +255,7 @@ abstract mixin class _$AppSettingsCopyWith<$Res> implements $AppSettingsCopyWith factory _$AppSettingsCopyWith(_AppSettings value, $Res Function(_AppSettings) _then) = __$AppSettingsCopyWithImpl; @override @useResult $Res call({ - bool autoTranslate, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, String? customFonts, int? appColorScheme, Size? windowSize + bool autoTranslate, bool dataSavingMode, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, String? customFonts, int? appColorScheme, Size? windowSize }); @@ -270,9 +272,10 @@ class __$AppSettingsCopyWithImpl<$Res> /// Create a copy of AppSettings /// with the given fields replaced by the non-null parameter values. -@override @pragma('vm:prefer-inline') $Res call({Object? autoTranslate = null,Object? soundEffects = null,Object? aprilFoolFeatures = null,Object? enterToSend = null,Object? appBarTransparent = null,Object? showBackgroundImage = null,Object? customFonts = freezed,Object? appColorScheme = freezed,Object? windowSize = freezed,}) { +@override @pragma('vm:prefer-inline') $Res call({Object? autoTranslate = null,Object? dataSavingMode = null,Object? soundEffects = null,Object? aprilFoolFeatures = null,Object? enterToSend = null,Object? appBarTransparent = null,Object? showBackgroundImage = null,Object? customFonts = freezed,Object? appColorScheme = freezed,Object? windowSize = freezed,}) { return _then(_AppSettings( autoTranslate: null == autoTranslate ? _self.autoTranslate : autoTranslate // ignore: cast_nullable_to_non_nullable +as bool,dataSavingMode: null == dataSavingMode ? _self.dataSavingMode : dataSavingMode // ignore: cast_nullable_to_non_nullable as bool,soundEffects: null == soundEffects ? _self.soundEffects : soundEffects // ignore: cast_nullable_to_non_nullable as bool,aprilFoolFeatures: null == aprilFoolFeatures ? _self.aprilFoolFeatures : aprilFoolFeatures // ignore: cast_nullable_to_non_nullable as bool,enterToSend: null == enterToSend ? _self.enterToSend : enterToSend // ignore: cast_nullable_to_non_nullable diff --git a/lib/pods/config.g.dart b/lib/pods/config.g.dart index fe139735..1d9731cc 100644 --- a/lib/pods/config.g.dart +++ b/lib/pods/config.g.dart @@ -7,7 +7,7 @@ part of 'config.dart'; // ************************************************************************** String _$appSettingsNotifierHash() => - r'e3c13307eabb0201487b85ab67b1ab493e588e71'; + r'cd18bff2614a94e3523634e6c577cefad0367eba'; /// See also [AppSettingsNotifier]. @ProviderFor(AppSettingsNotifier) diff --git a/lib/screens/explore.g.dart b/lib/screens/explore.g.dart index 04da4d7a..e9ce4586 100644 --- a/lib/screens/explore.g.dart +++ b/lib/screens/explore.g.dart @@ -7,7 +7,7 @@ part of 'explore.dart'; // ************************************************************************** String _$activityListNotifierHash() => - r'a4968856ac34b59d47cfd4a7cbb39289aef2a1b1'; + r'167021cada54da7c8d8437eef1ffb387a92ea2e3'; /// Copied from Dart SDK class _SystemHash { diff --git a/lib/screens/settings.dart b/lib/screens/settings.dart index ff81437c..f92e50bc 100644 --- a/lib/screens/settings.dart +++ b/lib/screens/settings.dart @@ -450,6 +450,20 @@ class SettingsScreen extends HookConsumerWidget { }, ), ), + ListTile( + minLeadingWidth: 48, + title: Text('settingsDataSavingMode').tr(), + contentPadding: const EdgeInsets.only(left: 24, right: 17), + leading: const Icon(Symbols.data_saver_on_rounded), + trailing: Switch( + value: settings.dataSavingMode, + onChanged: (value) { + ref + .read(appSettingsNotifierProvider.notifier) + .setDataSavingMode(value); + }, + ), + ), ]; // Desktop-specific settings