2024-05-22 20:48:44 +00:00
|
|
|
import 'dart:async';
|
|
|
|
|
|
|
|
|
|
import 'package:flutter/cupertino.dart';
|
2024-06-14 19:47:28 +00:00
|
|
|
import 'package:mnemo_cards/main.dart';
|
2024-06-15 15:42:18 +00:00
|
|
|
import 'package:mnemo_cards_common/mnemo_cards_common.dart';
|
2024-05-22 20:48:44 +00:00
|
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
|
|
|
|
2024-06-15 15:42:18 +00:00
|
|
|
class SharedPrefButton<T> extends StatefulWidget {
|
|
|
|
|
final Function(T)? onClick;
|
2024-05-22 20:48:44 +00:00
|
|
|
final String spKey;
|
2024-06-15 15:42:18 +00:00
|
|
|
final T Function(T? current)? setOnTap;
|
|
|
|
|
final bool Function(T? current)? shouldRebuild;
|
|
|
|
|
final Widget Function(T? value, ValueSetter<T> setValue)? builder;
|
2024-05-22 20:48:44 +00:00
|
|
|
|
|
|
|
|
SharedPrefButton({
|
2024-06-15 15:42:18 +00:00
|
|
|
this.builder,
|
2024-05-22 20:48:44 +00:00
|
|
|
required this.spKey,
|
2024-06-15 15:42:18 +00:00
|
|
|
this.setOnTap,
|
2024-05-22 20:48:44 +00:00
|
|
|
this.onClick,
|
2024-06-15 15:42:18 +00:00
|
|
|
this.shouldRebuild,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
SharedPrefButton.builder({
|
|
|
|
|
this.builder,
|
|
|
|
|
required this.spKey,
|
|
|
|
|
this.setOnTap,
|
|
|
|
|
this.onClick,
|
|
|
|
|
this.shouldRebuild,
|
2024-05-22 20:48:44 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
@override
|
2024-06-15 15:42:18 +00:00
|
|
|
State<StatefulWidget> createState() => _SharedPrefButtonState<T>();
|
2024-05-22 20:48:44 +00:00
|
|
|
}
|
|
|
|
|
|
2024-06-15 15:42:18 +00:00
|
|
|
class _SharedPrefButtonState<T> extends State<SharedPrefButton<T>> {
|
2024-05-22 20:48:44 +00:00
|
|
|
SharedPreferences? _sp;
|
2024-06-15 15:42:18 +00:00
|
|
|
T? value;
|
2024-05-22 20:48:44 +00:00
|
|
|
|
|
|
|
|
StreamSubscription? _streamSubscription;
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
void dispose() {
|
|
|
|
|
_streamSubscription?.cancel();
|
|
|
|
|
_streamSubscription = null;
|
|
|
|
|
super.dispose();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
void initState() {
|
|
|
|
|
super.initState();
|
2024-06-14 19:47:28 +00:00
|
|
|
_sp = globalSharedPreferences;
|
2024-06-15 15:42:18 +00:00
|
|
|
value = valueFromSp;
|
|
|
|
|
_streamSubscription =
|
|
|
|
|
Stream.periodic(const Duration(milliseconds: 500), (_) => valueFromSp)
|
|
|
|
|
.distinct()
|
|
|
|
|
.listen((v) {
|
|
|
|
|
if (value != v) {
|
|
|
|
|
value = v;
|
|
|
|
|
if (mounted && widget.shouldRebuild?.call(value) != false) {
|
|
|
|
|
setState(() {});
|
|
|
|
|
}
|
2024-05-22 20:48:44 +00:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-15 15:42:18 +00:00
|
|
|
T? get valueFromSp {
|
|
|
|
|
if (T == bool) {
|
|
|
|
|
return (_sp?.getBool(widget.spKey) ?? false).as<T?>();
|
|
|
|
|
} else if (T == int) {
|
|
|
|
|
return _sp?.getInt(widget.spKey).as<T?>();
|
|
|
|
|
} else if (T == num || T == double) {
|
|
|
|
|
return _sp?.getDouble(widget.spKey).as<T?>();
|
|
|
|
|
} else if (T == String) {
|
|
|
|
|
return _sp?.getString(widget.spKey).as<T?>();
|
|
|
|
|
} else if (T == Iterable<String>) {
|
|
|
|
|
return _sp?.getStringList(widget.spKey).as<T?>();
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<void> setValue(T value) async {
|
|
|
|
|
if (T == bool) {
|
|
|
|
|
_sp?.setBool(widget.spKey, value as bool);
|
|
|
|
|
} else if (T == int) {
|
|
|
|
|
_sp?.setInt(widget.spKey, value as int);
|
|
|
|
|
} else if (T == num || T == double) {
|
|
|
|
|
_sp?.setDouble(widget.spKey, value as double);
|
|
|
|
|
} else if (T == String) {
|
|
|
|
|
_sp?.setString(widget.spKey, value as String);
|
|
|
|
|
} else if (T == Iterable<String>) {
|
|
|
|
|
_sp?.setStringList(widget.spKey, (value as Iterable<String>).toList());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-22 20:48:44 +00:00
|
|
|
@override
|
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
|
return GestureDetector(
|
2024-06-15 15:42:18 +00:00
|
|
|
behavior: HitTestBehavior.opaque,
|
|
|
|
|
onTap: widget.setOnTap != null
|
|
|
|
|
? () async {
|
|
|
|
|
value = widget.setOnTap!.call(value);
|
|
|
|
|
if (value != null) {
|
|
|
|
|
_setValue(value!);
|
|
|
|
|
}
|
2024-05-22 20:48:44 +00:00
|
|
|
}
|
|
|
|
|
: null,
|
2024-06-15 15:42:18 +00:00
|
|
|
child: widget.builder?.call(value, _setValue),
|
2024-05-22 20:48:44 +00:00
|
|
|
);
|
|
|
|
|
}
|
2024-06-15 15:42:18 +00:00
|
|
|
|
|
|
|
|
Future<void> _setValue(T value) async {
|
|
|
|
|
await setValue(value!);
|
|
|
|
|
if (widget.shouldRebuild?.call(value) != false) {
|
|
|
|
|
setState(() {});
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-05-22 20:48:44 +00:00
|
|
|
}
|