fix: prefs persistence
This commit is contained in:
@@ -3,7 +3,7 @@ import 'package:hiddify/utils/custom_loggers.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
class Pref<T> with InfraLogger {
|
||||
class Pref<T, P> with InfraLogger {
|
||||
const Pref(
|
||||
this.prefs,
|
||||
this.key,
|
||||
@@ -15,28 +15,28 @@ class Pref<T> with InfraLogger {
|
||||
final SharedPreferences prefs;
|
||||
final String key;
|
||||
final T defaultValue;
|
||||
final T Function(String value)? mapFrom;
|
||||
final String Function(T value)? mapTo;
|
||||
final T Function(P value)? mapFrom;
|
||||
final P Function(T value)? mapTo;
|
||||
|
||||
/// Updates the value asynchronously.
|
||||
Future<void> update(T value) async {
|
||||
loggy.debug("updating preference [$key]($T) to [$value]");
|
||||
Object? mapped = value;
|
||||
if (mapTo != null) {
|
||||
mapped = mapTo!(value);
|
||||
}
|
||||
try {
|
||||
if (mapTo != null && mapFrom != null) {
|
||||
await prefs.setString(key, mapTo!(value));
|
||||
} else {
|
||||
switch (value) {
|
||||
case String _:
|
||||
await prefs.setString(key, value);
|
||||
case bool _:
|
||||
await prefs.setBool(key, value);
|
||||
case int _:
|
||||
await prefs.setInt(key, value);
|
||||
case double _:
|
||||
await prefs.setDouble(key, value);
|
||||
case List<String> _:
|
||||
await prefs.setStringList(key, value);
|
||||
}
|
||||
switch (mapped) {
|
||||
case String _:
|
||||
await prefs.setString(key, mapped);
|
||||
case bool _:
|
||||
await prefs.setBool(key, mapped);
|
||||
case int _:
|
||||
await prefs.setInt(key, mapped);
|
||||
case double _:
|
||||
await prefs.setDouble(key, mapped);
|
||||
case List<String> _:
|
||||
await prefs.setStringList(key, mapped);
|
||||
}
|
||||
} catch (e) {
|
||||
loggy.warning("error updating preference[$key]: $e");
|
||||
@@ -46,11 +46,12 @@ class Pref<T> with InfraLogger {
|
||||
T getValue() {
|
||||
try {
|
||||
loggy.debug("getting persisted preference [$key]($T)");
|
||||
if (mapTo != null && mapFrom != null) {
|
||||
final persisted = prefs.getString(key);
|
||||
return persisted != null ? mapFrom!(persisted) : defaultValue;
|
||||
if (mapFrom != null) {
|
||||
final persisted = prefs.get(key) as P?;
|
||||
if (persisted == null) return defaultValue;
|
||||
return mapFrom!(persisted);
|
||||
} else if (T == List<String>) {
|
||||
return prefs.getStringList(key) as T ?? defaultValue;
|
||||
return prefs.getStringList(key) as T? ?? defaultValue;
|
||||
}
|
||||
return prefs.get(key) as T? ?? defaultValue;
|
||||
} catch (e) {
|
||||
@@ -60,132 +61,42 @@ class Pref<T> with InfraLogger {
|
||||
}
|
||||
}
|
||||
|
||||
class PrefNotifier<T> extends AutoDisposeNotifier<T>
|
||||
with _Prefs<T>, InfraLogger {
|
||||
class PrefNotifier<T, P> extends AutoDisposeNotifier<T> with InfraLogger {
|
||||
PrefNotifier(
|
||||
this.key,
|
||||
this.defaultValue,
|
||||
this.mapFrom,
|
||||
this.mapTo,
|
||||
this._key,
|
||||
this._defaultValue,
|
||||
this._mapFrom,
|
||||
this._mapTo,
|
||||
);
|
||||
|
||||
@override
|
||||
final String key;
|
||||
@override
|
||||
final T defaultValue;
|
||||
@override
|
||||
final T Function(String)? mapFrom;
|
||||
@override
|
||||
final String Function(T)? mapTo;
|
||||
final String _key;
|
||||
final T _defaultValue;
|
||||
final T Function(P value)? _mapFrom;
|
||||
final P Function(T)? _mapTo;
|
||||
|
||||
static AutoDisposeNotifierProvider<PrefNotifier<T>, T> provider<T>(
|
||||
late final Pref<T, P> _pref = Pref(
|
||||
ref.watch(sharedPreferencesProvider),
|
||||
_key,
|
||||
_defaultValue,
|
||||
mapFrom: _mapFrom,
|
||||
mapTo: _mapTo,
|
||||
);
|
||||
|
||||
static AutoDisposeNotifierProvider<PrefNotifier<T, P>, T> provider<T, P>(
|
||||
String key,
|
||||
T defaultValue, {
|
||||
T Function(String value)? mapFrom,
|
||||
String Function(T value)? mapTo,
|
||||
T Function(P value)? mapFrom,
|
||||
P Function(T value)? mapTo,
|
||||
}) =>
|
||||
AutoDisposeNotifierProvider(
|
||||
() => PrefNotifier(key, defaultValue, mapFrom, mapTo),
|
||||
);
|
||||
|
||||
@override
|
||||
SharedPreferences get prefs => ref.read(sharedPreferencesProvider);
|
||||
|
||||
@override
|
||||
Future<void> update(T value) async {
|
||||
super.update(value);
|
||||
_pref.update(value);
|
||||
super.state = value;
|
||||
}
|
||||
|
||||
@override
|
||||
T build() => getValue();
|
||||
}
|
||||
|
||||
class AlwaysAlivePrefNotifier<T> extends Notifier<T>
|
||||
with _Prefs<T>, InfraLogger {
|
||||
AlwaysAlivePrefNotifier(
|
||||
this.key,
|
||||
this.defaultValue,
|
||||
this.mapFrom,
|
||||
this.mapTo,
|
||||
);
|
||||
|
||||
@override
|
||||
final String key;
|
||||
@override
|
||||
final T defaultValue;
|
||||
@override
|
||||
final T Function(String)? mapFrom;
|
||||
@override
|
||||
final String Function(T)? mapTo;
|
||||
|
||||
static NotifierProvider<AlwaysAlivePrefNotifier<T>, T> provider<T>(
|
||||
String key,
|
||||
T defaultValue, {
|
||||
T Function(String value)? mapFrom,
|
||||
String Function(T value)? mapTo,
|
||||
}) =>
|
||||
NotifierProvider(
|
||||
() => AlwaysAlivePrefNotifier(key, defaultValue, mapFrom, mapTo),
|
||||
);
|
||||
|
||||
@override
|
||||
SharedPreferences get prefs => ref.read(sharedPreferencesProvider);
|
||||
|
||||
@override
|
||||
Future<void> update(T value) async {
|
||||
super.update(value);
|
||||
super.state = value;
|
||||
}
|
||||
|
||||
@override
|
||||
T build() => getValue();
|
||||
}
|
||||
|
||||
mixin _Prefs<T> implements LoggerMixin {
|
||||
String get key;
|
||||
T get defaultValue;
|
||||
T Function(String)? get mapFrom;
|
||||
String Function(T)? get mapTo;
|
||||
|
||||
SharedPreferences get prefs;
|
||||
|
||||
/// Updates the value asynchronously.
|
||||
Future<void> update(T value) async {
|
||||
loggy.debug("updating preference [$key] to [$value]");
|
||||
try {
|
||||
if (mapTo != null && mapFrom != null) {
|
||||
await prefs.setString(key, mapTo!(value));
|
||||
} else {
|
||||
switch (value) {
|
||||
case String _:
|
||||
await prefs.setString(key, value);
|
||||
case bool _:
|
||||
await prefs.setBool(key, value);
|
||||
case int _:
|
||||
await prefs.setInt(key, value);
|
||||
case double _:
|
||||
await prefs.setDouble(key, value);
|
||||
case List<String> _:
|
||||
await prefs.setStringList(key, value);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
loggy.warning("error updating preference[$key]: $e");
|
||||
}
|
||||
}
|
||||
|
||||
T getValue() {
|
||||
try {
|
||||
loggy.debug("getting persisted preference [$key]");
|
||||
if (mapTo != null && mapFrom != null) {
|
||||
final persisted = prefs.getString(key);
|
||||
return persisted != null ? mapFrom!(persisted) : defaultValue;
|
||||
}
|
||||
return prefs.get(key) as T? ?? defaultValue;
|
||||
} catch (e) {
|
||||
loggy.warning("error getting preference[$key]: $e");
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
T build() => _pref.getValue();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user