mnemo_cards/lib/widgets/shared_pref_button.dart
2024-06-15 18:42:18 +03:00

117 lines
3 KiB
Dart

import 'dart:async';
import 'package:flutter/cupertino.dart';
import 'package:mnemo_cards/main.dart';
import 'package:mnemo_cards_common/mnemo_cards_common.dart';
import 'package:shared_preferences/shared_preferences.dart';
class SharedPrefButton<T> extends StatefulWidget {
final Function(T)? onClick;
final String spKey;
final T Function(T? current)? setOnTap;
final bool Function(T? current)? shouldRebuild;
final Widget Function(T? value, ValueSetter<T> setValue)? builder;
SharedPrefButton({
this.builder,
required this.spKey,
this.setOnTap,
this.onClick,
this.shouldRebuild,
});
SharedPrefButton.builder({
this.builder,
required this.spKey,
this.setOnTap,
this.onClick,
this.shouldRebuild,
});
@override
State<StatefulWidget> createState() => _SharedPrefButtonState<T>();
}
class _SharedPrefButtonState<T> extends State<SharedPrefButton<T>> {
SharedPreferences? _sp;
T? value;
StreamSubscription? _streamSubscription;
@override
void dispose() {
_streamSubscription?.cancel();
_streamSubscription = null;
super.dispose();
}
@override
void initState() {
super.initState();
_sp = globalSharedPreferences;
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(() {});
}
}
});
}
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());
}
}
@override
Widget build(BuildContext context) {
return GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: widget.setOnTap != null
? () async {
value = widget.setOnTap!.call(value);
if (value != null) {
_setValue(value!);
}
}
: null,
child: widget.builder?.call(value, _setValue),
);
}
Future<void> _setValue(T value) async {
await setValue(value!);
if (widget.shouldRebuild?.call(value) != false) {
setState(() {});
}
}
}