Refactor preferences
This commit is contained in:
@@ -1,11 +1,10 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_animate/flutter_animate.dart';
|
||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
import 'package:hiddify/core/locale/locale.dart';
|
||||
import 'package:hiddify/core/core_providers.dart';
|
||||
import 'package:hiddify/core/prefs/prefs.dart';
|
||||
import 'package:hiddify/core/router/router.dart';
|
||||
import 'package:hiddify/core/theme/theme.dart';
|
||||
import 'package:hiddify/features/common/common_controllers.dart';
|
||||
import 'package:hiddify/gen/fonts.gen.dart';
|
||||
import 'package:hiddify/utils/utils.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
|
||||
@@ -15,24 +14,21 @@ class AppView extends HookConsumerWidget with PresLogger {
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final router = ref.watch(routerProvider);
|
||||
final locale = ref.watch(localeControllerProvider).locale;
|
||||
final theme = ref.watch(themeControllerProvider);
|
||||
final locale = ref.watch(localeProvider).locale;
|
||||
final theme = ref.watch(themeProvider);
|
||||
|
||||
ref.watch(commonControllersProvider);
|
||||
|
||||
// HACK temporary solution
|
||||
final fontFamily = locale.languageCode == "fa" ? FontFamily.shabnam : "";
|
||||
|
||||
return MaterialApp.router(
|
||||
routerConfig: router,
|
||||
locale: locale,
|
||||
supportedLocales: LocalePref.locales,
|
||||
supportedLocales: AppLocale.locales,
|
||||
localizationsDelegates: GlobalMaterialLocalizations.delegates,
|
||||
debugShowCheckedModeBanner: false,
|
||||
themeMode: theme.themeMode,
|
||||
theme: theme.light(fontFamily: fontFamily),
|
||||
darkTheme: theme.dark(fontFamily: fontFamily),
|
||||
title: 'Hiddify',
|
||||
themeMode: theme.mode,
|
||||
theme: theme.light(),
|
||||
darkTheme: theme.dark(),
|
||||
title: 'Hiddify Next',
|
||||
).animate().fadeIn();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
import 'package:hiddify/core/locale/locale.dart';
|
||||
import 'package:hiddify/core/prefs/prefs.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
|
||||
final translationsProvider = Provider<TranslationsEn>(
|
||||
(ref) => ref.watch(localeControllerProvider).translations(),
|
||||
);
|
||||
part 'core_providers.g.dart';
|
||||
|
||||
@Riverpod(keepAlive: true)
|
||||
TranslationsEn translations(TranslationsRef ref) =>
|
||||
ref.watch(localeProvider).translations();
|
||||
|
||||
@riverpod
|
||||
AppTheme theme(ThemeRef ref) => AppTheme(
|
||||
ref.watch(themeModeProvider),
|
||||
ref.watch(trueBlackThemeProvider),
|
||||
ref.watch(localeProvider).preferredFontFamily,
|
||||
);
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
export 'locale_controller.dart';
|
||||
export 'locale_pref.dart';
|
||||
@@ -1,24 +0,0 @@
|
||||
import 'package:hiddify/core/locale/locale_pref.dart';
|
||||
import 'package:hiddify/data/data_providers.dart';
|
||||
import 'package:hiddify/utils/utils.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
part 'locale_controller.g.dart';
|
||||
|
||||
@Riverpod(keepAlive: true)
|
||||
class LocaleController extends _$LocaleController with AppLogger {
|
||||
@override
|
||||
LocalePref build() {
|
||||
return LocalePref.values[_prefs.getInt(_localeKey) ?? 0];
|
||||
}
|
||||
|
||||
static const _localeKey = 'locale';
|
||||
SharedPreferences get _prefs => ref.read(sharedPreferencesProvider);
|
||||
|
||||
Future<void> change(LocalePref locale) async {
|
||||
loggy.debug('changing locale to [$locale]');
|
||||
await _prefs.setInt(_localeKey, locale.index);
|
||||
state = locale;
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
import 'package:dartx/dartx.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:hiddify/gen/translations.g.dart';
|
||||
|
||||
export 'package:hiddify/gen/translations.g.dart';
|
||||
|
||||
enum LocalePref {
|
||||
en,
|
||||
fa;
|
||||
|
||||
Locale get locale {
|
||||
return Locale(name);
|
||||
}
|
||||
|
||||
static List<Locale> get locales =>
|
||||
LocalePref.values.map((e) => e.locale).toList();
|
||||
|
||||
static LocalePref fromString(String e) {
|
||||
return LocalePref.values.firstOrNullWhere((element) => element.name == e) ??
|
||||
LocalePref.en;
|
||||
}
|
||||
|
||||
static LocalePref deviceLocale() {
|
||||
return LocalePref.fromString(
|
||||
AppLocaleUtils.findDeviceLocale().languageCode,
|
||||
);
|
||||
}
|
||||
|
||||
TranslationsEn translations() {
|
||||
final appLocale = AppLocaleUtils.parse(name);
|
||||
return appLocale.build();
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,19 @@
|
||||
import 'package:flex_color_scheme/flex_color_scheme.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hiddify/core/theme/theme_prefs.dart';
|
||||
|
||||
// mostly exact copy of flex color scheme 7.1's fabulous 12 theme
|
||||
extension AppTheme on ThemePrefs {
|
||||
ThemeData light({
|
||||
String fontFamily = "Shabnam",
|
||||
}) {
|
||||
class AppTheme {
|
||||
AppTheme(
|
||||
this.mode,
|
||||
this.trueBlack,
|
||||
this.fontFamily,
|
||||
);
|
||||
|
||||
final ThemeMode mode;
|
||||
final bool trueBlack;
|
||||
final String fontFamily;
|
||||
|
||||
ThemeData light() {
|
||||
return FlexThemeData.light(
|
||||
scheme: FlexScheme.indigoM3,
|
||||
surfaceMode: FlexSurfaceMode.highScaffoldLowSurface,
|
||||
@@ -62,12 +69,13 @@ extension AppTheme on ThemePrefs {
|
||||
tones: FlexTones.jolly(Brightness.light),
|
||||
visualDensity: FlexColorScheme.comfortablePlatformDensity,
|
||||
fontFamily: fontFamily,
|
||||
extensions: <ThemeExtension<dynamic>>{
|
||||
ConnectionButtonTheme.light,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
ThemeData dark({
|
||||
String fontFamily = "Shabnam",
|
||||
}) {
|
||||
ThemeData dark() {
|
||||
return FlexThemeData.dark(
|
||||
scheme: FlexScheme.indigoM3,
|
||||
useMaterial3: true,
|
||||
@@ -124,6 +132,48 @@ extension AppTheme on ThemePrefs {
|
||||
// tones: FlexTones.jolly(Brightness.dark),
|
||||
visualDensity: FlexColorScheme.comfortablePlatformDensity,
|
||||
fontFamily: fontFamily,
|
||||
extensions: <ThemeExtension<dynamic>>{
|
||||
ConnectionButtonTheme.light,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ConnectionButtonTheme extends ThemeExtension<ConnectionButtonTheme> {
|
||||
const ConnectionButtonTheme({
|
||||
this.idleColor,
|
||||
this.connectedColor,
|
||||
});
|
||||
|
||||
final Color? idleColor;
|
||||
final Color? connectedColor;
|
||||
|
||||
static const ConnectionButtonTheme light = ConnectionButtonTheme(
|
||||
idleColor: Color(0xFF4a4d8b),
|
||||
connectedColor: Color(0xFF44a334),
|
||||
);
|
||||
|
||||
@override
|
||||
ThemeExtension<ConnectionButtonTheme> copyWith({
|
||||
Color? idleColor,
|
||||
Color? connectedColor,
|
||||
}) =>
|
||||
ConnectionButtonTheme(
|
||||
idleColor: idleColor ?? this.idleColor,
|
||||
connectedColor: connectedColor ?? this.connectedColor,
|
||||
);
|
||||
|
||||
@override
|
||||
ThemeExtension<ConnectionButtonTheme> lerp(
|
||||
covariant ThemeExtension<ConnectionButtonTheme>? other,
|
||||
double t,
|
||||
) {
|
||||
if (other is! ConnectionButtonTheme) {
|
||||
return this;
|
||||
}
|
||||
return ConnectionButtonTheme(
|
||||
idleColor: Color.lerp(idleColor, other.idleColor, t),
|
||||
connectedColor: Color.lerp(connectedColor, other.connectedColor, t),
|
||||
);
|
||||
}
|
||||
}
|
||||
44
lib/core/prefs/locale_prefs.dart
Normal file
44
lib/core/prefs/locale_prefs.dart
Normal file
@@ -0,0 +1,44 @@
|
||||
import 'package:dartx/dartx.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:hiddify/gen/fonts.gen.dart';
|
||||
import 'package:hiddify/gen/translations.g.dart';
|
||||
import 'package:hiddify/utils/pref_notifier.dart';
|
||||
|
||||
export 'package:hiddify/gen/translations.g.dart';
|
||||
|
||||
final localeProvider = AlwaysAlivePrefNotifier.provider(
|
||||
"locale",
|
||||
AppLocale.deviceLocale(),
|
||||
mapFrom: AppLocale.values.byName,
|
||||
mapTo: (value) => value.name,
|
||||
);
|
||||
|
||||
enum AppLocale {
|
||||
en,
|
||||
fa;
|
||||
|
||||
Locale get locale {
|
||||
return Locale(name);
|
||||
}
|
||||
|
||||
static List<Locale> get locales =>
|
||||
AppLocale.values.map((e) => e.locale).toList();
|
||||
|
||||
static AppLocale fromString(String e) {
|
||||
return AppLocale.values.firstOrNullWhere((element) => element.name == e) ??
|
||||
AppLocale.en;
|
||||
}
|
||||
|
||||
static AppLocale deviceLocale() {
|
||||
return AppLocale.fromString(
|
||||
AppLocaleUtils.findDeviceLocale().languageCode,
|
||||
);
|
||||
}
|
||||
|
||||
TranslationsEn translations() {
|
||||
final appLocale = AppLocaleUtils.parse(name);
|
||||
return appLocale.build();
|
||||
}
|
||||
|
||||
String get preferredFontFamily => this == fa ? FontFamily.shabnam : "";
|
||||
}
|
||||
@@ -1 +1,4 @@
|
||||
export 'app_theme.dart';
|
||||
export 'general_prefs.dart';
|
||||
export 'locale_prefs.dart';
|
||||
export 'theme_prefs.dart';
|
||||
|
||||
14
lib/core/prefs/theme_prefs.dart
Normal file
14
lib/core/prefs/theme_prefs.dart
Normal file
@@ -0,0 +1,14 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hiddify/utils/pref_notifier.dart';
|
||||
|
||||
final themeModeProvider = AlwaysAlivePrefNotifier.provider(
|
||||
"theme_mode",
|
||||
ThemeMode.system,
|
||||
mapFrom: ThemeMode.values.byName,
|
||||
mapTo: (value) => value.name,
|
||||
);
|
||||
|
||||
final trueBlackThemeProvider = AlwaysAlivePrefNotifier.provider(
|
||||
"true_black_theme",
|
||||
false,
|
||||
);
|
||||
@@ -1,6 +0,0 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
abstract class ConnectionButtonColor {
|
||||
static const connected = Color.fromRGBO(89, 140, 82, 1);
|
||||
static const disconnected = Color.fromRGBO(74, 77, 139, 1);
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
export 'app_theme.dart';
|
||||
export 'constants.dart';
|
||||
export 'theme_controller.dart';
|
||||
export 'theme_prefs.dart';
|
||||
@@ -1,41 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hiddify/core/theme/theme_prefs.dart';
|
||||
import 'package:hiddify/data/data_providers.dart';
|
||||
import 'package:hiddify/utils/utils.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
part 'theme_controller.g.dart';
|
||||
|
||||
@Riverpod(keepAlive: true)
|
||||
class ThemeController extends _$ThemeController with AppLogger {
|
||||
@override
|
||||
ThemePrefs build() {
|
||||
return ThemePrefs(
|
||||
themeMode: ThemeMode.values[_prefs.getInt(_themeModeKey) ?? 0],
|
||||
trueBlack: _prefs.getBool(_trueBlackKey) ?? false,
|
||||
);
|
||||
}
|
||||
|
||||
SharedPreferences get _prefs => ref.read(sharedPreferencesProvider);
|
||||
|
||||
static const _themeModeKey = "theme_mode";
|
||||
static const _trueBlackKey = "true_black";
|
||||
|
||||
Future<void> change({
|
||||
ThemeMode? themeMode,
|
||||
bool? trueBlack,
|
||||
}) async {
|
||||
loggy.debug('changing theme, mode=$themeMode, trueBlack=$trueBlack');
|
||||
if (themeMode != null) {
|
||||
await _prefs.setInt(_themeModeKey, themeMode.index);
|
||||
}
|
||||
if (trueBlack != null) {
|
||||
await _prefs.setBool(_trueBlackKey, trueBlack);
|
||||
}
|
||||
state = state.copyWith(
|
||||
themeMode: themeMode ?? state.themeMode,
|
||||
trueBlack: trueBlack ?? state.trueBlack,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'theme_prefs.freezed.dart';
|
||||
|
||||
@freezed
|
||||
class ThemePrefs with _$ThemePrefs {
|
||||
const ThemePrefs._();
|
||||
|
||||
const factory ThemePrefs({
|
||||
@Default(ThemeMode.system) ThemeMode themeMode,
|
||||
@Default(false) bool trueBlack,
|
||||
}) = _ThemePrefs;
|
||||
}
|
||||
Reference in New Issue
Block a user