|
abstract class Preference<T> { |
|
String get key; |
|
|
|
T? get value; |
|
set value(T? newValue); |
|
|
|
T? get(); |
|
Future<bool> set(T? newValue); |
|
|
|
Future<bool> remove(); |
|
} |
|
|
|
class BasePreference<T> implements Preference<T> { |
|
const BasePreference( |
|
this.key, |
|
this._getter, |
|
this._setter, |
|
this._remove, |
|
); |
|
|
|
@override |
|
final String key; |
|
final T? Function(String key) _getter; |
|
final Future<bool> Function(String key, T value) _setter; |
|
final Future<bool> Function(String key) _remove; |
|
|
|
@override |
|
T? get value => get(); |
|
@override |
|
set value(T? newValue) => set(newValue); |
|
|
|
@override |
|
T? get() => _getter(key); |
|
|
|
@override |
|
Future<bool> set(T? newValue) => newValue == null |
|
? remove() |
|
: _setter(key, newValue); |
|
|
|
@override |
|
Future<bool> remove() => _remove(key); |
|
} |
|
|
|
extension SharedPreferencesX on SharedPreferences { |
|
Preference<bool> asBool(String key) => asPreference(key, getBool, setBool); |
|
Preference<String> asString(String key) => asPreference(key, getString, setString); |
|
Preference<int> asInt(String key) => asPreference(key, getInt, setInt); |
|
Preference<double> asDouble(String key) => asPreference(key, getDouble, setDouble); |
|
Preference<List<String>> asStringList(String key) => asPreference(key, getStringList, setStringList); |
|
|
|
Preference<T> asPreference<T>(String key, |
|
T? Function(String key) getter, |
|
Future<bool> Function(String key, T value) setter, |
|
) => BasePreference(key, getter, setter, remove); |
|
} |
|
|
|
|
|
extension PreferenceStateX<T> on Preference<T> { |
|
/// Custom hook to get and set the preference value, treating it like useState(). |
|
ValueNotifier<T?> asState() { |
|
final state = useState<T?>(value); // Initialize state with preference value |
|
|
|
// Sync changes back to the preference whenever state.value changes. |
|
useEffect(() { |
|
final listener = () { |
|
value = state.value; // Update preference whenever state changes |
|
}; |
|
state.addListener(listener); |
|
|
|
// Clean up the listener when the widget is disposed |
|
return () => state.removeListener(listener); |
|
}, [state]); |
|
|
|
return state; |
|
} |
|
} |
|
|
|
class PreferenceSwitch extends HookWidget { |
|
final Preference<bool> preference; |
|
|
|
const PreferenceSwitch({ |
|
super.key, |
|
required this.preference, |
|
}); |
|
|
|
@override |
|
Widget build(BuildContext context) { |
|
final preferenceState = preference.asState(); |
|
|
|
return Switch( |
|
value: preferenceState.value ?? false, |
|
onChanged: (newValue) { |
|
preferenceState.value = newValue; |
|
}, |
|
); |
|
} |
|
} |