Change theme prefs
This commit is contained in:
@@ -129,11 +129,11 @@
|
||||
"themeModes": {
|
||||
"system": "Follow system theme",
|
||||
"dark": "Dark mode",
|
||||
"light": "Light mode"
|
||||
"light": "Light mode",
|
||||
"black": "Black mode"
|
||||
},
|
||||
"enableAnalytics": "Enable Analytics",
|
||||
"enableAnalyticsMsg": "Give permission to collect analytics and send crash reports to improve the app",
|
||||
"trueBlack": "Pure Black",
|
||||
"autoStart": "Start on Boot",
|
||||
"silentStart": "Silent Start",
|
||||
"openWorkingDir": "Open Working Directory",
|
||||
|
||||
@@ -129,11 +129,11 @@
|
||||
"themeModes": {
|
||||
"system": "پیروی از تم دستگاه",
|
||||
"dark": "تم تیره",
|
||||
"light": "تم روشن"
|
||||
"light": "تم روشن",
|
||||
"black": "تم سیاه"
|
||||
},
|
||||
"enableAnalytics": "فعالسازی آنالیتیکز",
|
||||
"enableAnalyticsMsg": "ارائه دسترسی آنالیز و گزارش خطا برای بهبود عملکرد برنامه",
|
||||
"trueBlack": "کاملا سیاه",
|
||||
"autoStart": "اجرا با روشن شدن سیستم",
|
||||
"silentStart": "اجرای ساکت",
|
||||
"openWorkingDir": "باز کردن دایرکتوری کاری",
|
||||
|
||||
@@ -129,11 +129,11 @@
|
||||
"themeModes": {
|
||||
"system": "Системная тема",
|
||||
"dark": "Тёмная тема",
|
||||
"light": "Светлая тема"
|
||||
"light": "Светлая тема",
|
||||
"black": "Черный режим"
|
||||
},
|
||||
"enableAnalytics": "Сбор аналитики",
|
||||
"enableAnalyticsMsg": "Сбор аналитических данных и отправка отчётов о сбоях для улучшения приложения.",
|
||||
"trueBlack": "Чистый чёрный цвет",
|
||||
"autoStart": "Запуск при загрузке",
|
||||
"silentStart": "Тихий запуск",
|
||||
"openWorkingDir": "Открыть рабочую папку",
|
||||
|
||||
@@ -129,11 +129,11 @@
|
||||
"themeModes": {
|
||||
"system": "遵循系统主题",
|
||||
"dark": "深色模式",
|
||||
"light": "灯光模式"
|
||||
"light": "灯光模式",
|
||||
"black": "黑色模式"
|
||||
},
|
||||
"enableAnalytics": "启用分析",
|
||||
"enableAnalyticsMsg": "授予收集分析并发送崩溃报告以改进应用程序的权限",
|
||||
"trueBlack": "纯黑",
|
||||
"autoStart": "开机启动",
|
||||
"silentStart": "无声启动",
|
||||
"openWorkingDir": "打开工作目录",
|
||||
|
||||
@@ -33,7 +33,7 @@ class AppView extends HookConsumerWidget with PresLogger {
|
||||
supportedLocales: AppLocaleUtils.supportedLocales,
|
||||
localizationsDelegates: GlobalMaterialLocalizations.delegates,
|
||||
debugShowCheckedModeBanner: false,
|
||||
themeMode: theme.mode,
|
||||
themeMode: theme.mode.flutterThemeMode,
|
||||
theme: theme.light(),
|
||||
darkTheme: theme.dark(),
|
||||
title: Constants.appName,
|
||||
|
||||
@@ -19,6 +19,5 @@ TranslationsEn translations(TranslationsRef ref) =>
|
||||
@Riverpod(keepAlive: true)
|
||||
AppTheme theme(ThemeRef ref) => AppTheme(
|
||||
ref.watch(themeModeNotifierProvider),
|
||||
ref.watch(trueBlackThemeNotifierProvider),
|
||||
ref.watch(localeNotifierProvider).preferredFontFamily,
|
||||
);
|
||||
|
||||
@@ -1,16 +1,38 @@
|
||||
import 'package:flex_color_scheme/flex_color_scheme.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hiddify/core/prefs/locale_prefs.dart';
|
||||
|
||||
enum AppThemeMode {
|
||||
system,
|
||||
light,
|
||||
dark,
|
||||
black;
|
||||
|
||||
String present(TranslationsEn t) => switch (this) {
|
||||
system => t.settings.general.themeModes.system,
|
||||
light => t.settings.general.themeModes.light,
|
||||
dark => t.settings.general.themeModes.dark,
|
||||
black => t.settings.general.themeModes.black,
|
||||
};
|
||||
|
||||
ThemeMode get flutterThemeMode => switch (this) {
|
||||
system => ThemeMode.system,
|
||||
light => ThemeMode.light,
|
||||
dark => ThemeMode.dark,
|
||||
black => ThemeMode.dark,
|
||||
};
|
||||
|
||||
bool get trueBlack => this == black;
|
||||
}
|
||||
|
||||
// mostly exact copy of flex color scheme 7.1's fabulous 12 theme
|
||||
class AppTheme {
|
||||
AppTheme(
|
||||
this.mode,
|
||||
this.trueBlack,
|
||||
this.fontFamily,
|
||||
);
|
||||
|
||||
final ThemeMode mode;
|
||||
final bool trueBlack;
|
||||
final AppThemeMode mode;
|
||||
final String fontFamily;
|
||||
|
||||
ThemeData light() {
|
||||
@@ -81,7 +103,7 @@ class AppTheme {
|
||||
useMaterial3: true,
|
||||
swapLegacyOnMaterial3: true,
|
||||
useMaterial3ErrorColors: true,
|
||||
darkIsTrueBlack: trueBlack,
|
||||
darkIsTrueBlack: mode.trueBlack,
|
||||
surfaceMode: FlexSurfaceMode.highScaffoldLowSurface,
|
||||
// blendLevel: 1,
|
||||
subThemesData: const FlexSubThemesData(
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hiddify/core/prefs/app_theme.dart';
|
||||
import 'package:hiddify/data/data_providers.dart';
|
||||
import 'package:hiddify/utils/pref_notifier.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
@@ -10,29 +10,15 @@ class ThemeModeNotifier extends _$ThemeModeNotifier {
|
||||
late final _pref = Pref(
|
||||
ref.watch(sharedPreferencesProvider),
|
||||
"theme_mode",
|
||||
ThemeMode.system,
|
||||
mapFrom: ThemeMode.values.byName,
|
||||
AppThemeMode.system,
|
||||
mapFrom: AppThemeMode.values.byName,
|
||||
mapTo: (value) => value.name,
|
||||
);
|
||||
|
||||
@override
|
||||
ThemeMode build() => _pref.getValue();
|
||||
AppThemeMode build() => _pref.getValue();
|
||||
|
||||
Future<void> update(ThemeMode value) {
|
||||
state = value;
|
||||
return _pref.update(value);
|
||||
}
|
||||
}
|
||||
|
||||
@Riverpod(keepAlive: true)
|
||||
class TrueBlackThemeNotifier extends _$TrueBlackThemeNotifier {
|
||||
late final _pref =
|
||||
Pref(ref.watch(sharedPreferencesProvider), "true_black_theme", false);
|
||||
|
||||
@override
|
||||
bool build() => _pref.getValue();
|
||||
|
||||
Future<void> update(bool value) {
|
||||
Future<void> update(AppThemeMode value) {
|
||||
state = value;
|
||||
return _pref.update(value);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ import 'package:go_router/go_router.dart';
|
||||
import 'package:hiddify/core/core_providers.dart';
|
||||
import 'package:hiddify/core/prefs/prefs.dart';
|
||||
import 'package:hiddify/features/common/common.dart';
|
||||
import 'package:hiddify/features/settings/widgets/theme_mode_switch_button.dart';
|
||||
import 'package:hiddify/services/auto_start_service.dart';
|
||||
import 'package:hiddify/utils/utils.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
@@ -44,31 +43,34 @@ class GeneralSettingTiles extends HookConsumerWidget {
|
||||
),
|
||||
ListTile(
|
||||
title: Text(t.settings.general.themeMode),
|
||||
subtitle: Text(
|
||||
switch (theme.mode) {
|
||||
ThemeMode.system => t.settings.general.themeModes.system,
|
||||
ThemeMode.light => t.settings.general.themeModes.light,
|
||||
ThemeMode.dark => t.settings.general.themeModes.dark,
|
||||
},
|
||||
),
|
||||
trailing: ThemeModeSwitch(
|
||||
themeMode: theme.mode,
|
||||
onChanged: ref.read(themeModeNotifierProvider.notifier).update,
|
||||
),
|
||||
subtitle: Text(theme.mode.present(t)),
|
||||
leading: const Icon(Icons.light_mode),
|
||||
onTap: () async {
|
||||
await ref.read(themeModeNotifierProvider.notifier).update(
|
||||
Theme.of(context).brightness == Brightness.light
|
||||
? ThemeMode.dark
|
||||
: ThemeMode.light,
|
||||
final selectedThemeMode = await showDialog<AppThemeMode>(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return SimpleDialog(
|
||||
title: Text(t.settings.general.themeMode),
|
||||
children: AppThemeMode.values
|
||||
.map(
|
||||
(e) => RadioListTile(
|
||||
title: Text(e.present(t)),
|
||||
value: e,
|
||||
groupValue: theme.mode,
|
||||
onChanged: (e) => context.pop(e),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
);
|
||||
},
|
||||
);
|
||||
if (selectedThemeMode != null) {
|
||||
await ref
|
||||
.read(themeModeNotifierProvider.notifier)
|
||||
.update(selectedThemeMode);
|
||||
}
|
||||
},
|
||||
),
|
||||
SwitchListTile(
|
||||
title: Text(t.settings.general.trueBlack),
|
||||
value: theme.trueBlack,
|
||||
onChanged: ref.read(trueBlackThemeNotifierProvider.notifier).update,
|
||||
),
|
||||
if (PlatformUtils.isDesktop) ...[
|
||||
SwitchListTile(
|
||||
title: Text(t.settings.general.autoStart),
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hiddify/core/core_providers.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
|
||||
class ThemeModeSwitch extends HookConsumerWidget {
|
||||
const ThemeModeSwitch({
|
||||
super.key,
|
||||
required this.themeMode,
|
||||
required this.onChanged,
|
||||
});
|
||||
final ThemeMode themeMode;
|
||||
final ValueChanged<ThemeMode> onChanged;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final t = ref.watch(translationsProvider);
|
||||
|
||||
final List<bool> isSelected = <bool>[
|
||||
themeMode == ThemeMode.light,
|
||||
themeMode == ThemeMode.system,
|
||||
themeMode == ThemeMode.dark,
|
||||
];
|
||||
|
||||
return ToggleButtons(
|
||||
isSelected: isSelected,
|
||||
onPressed: (int newIndex) {
|
||||
if (newIndex == 0) {
|
||||
onChanged(ThemeMode.light);
|
||||
} else if (newIndex == 1) {
|
||||
onChanged(ThemeMode.system);
|
||||
} else {
|
||||
onChanged(ThemeMode.dark);
|
||||
}
|
||||
},
|
||||
children: <Widget>[
|
||||
Icon(
|
||||
Icons.wb_sunny,
|
||||
semanticLabel: t.settings.general.themeModes.light,
|
||||
),
|
||||
Icon(
|
||||
Icons.phone_iphone,
|
||||
semanticLabel: t.settings.general.themeModes.system,
|
||||
),
|
||||
Icon(
|
||||
Icons.bedtime,
|
||||
semanticLabel: t.settings.general.themeModes.dark,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user