79 lines
2.5 KiB
Dart
79 lines
2.5 KiB
Dart
import 'dart:developer';
|
|
|
|
import 'package:easy_debounce/easy_debounce.dart';
|
|
import 'package:hydrated_bloc/hydrated_bloc.dart';
|
|
|
|
import '../../../../../storage/base/settings.dart';
|
|
import '../../../../../view/pages/settings/data/default_settings.dart';
|
|
import '../../app_modules.dart';
|
|
|
|
class SettingsCubit extends HydratedCubit<Settings> {
|
|
static const _debounceTag = 'settings_persist';
|
|
|
|
SettingsCubit() : super(DefaultSettings.get());
|
|
|
|
Settings val({bool write = false}) {
|
|
if (write) {
|
|
// Notify listeners immediately so the UI reflects the mutation right away;
|
|
// debounce the actual persistence to disk to avoid hammering on rapid edits.
|
|
_emitFreshInstance();
|
|
EasyDebounce.debounce(_debounceTag, const Duration(milliseconds: 500), _emitFreshInstance);
|
|
}
|
|
return state;
|
|
}
|
|
|
|
void _emitFreshInstance() {
|
|
try {
|
|
emit(Settings.fromJson(state.toJson()));
|
|
} catch (e) {
|
|
log('Failed to refresh settings state: $e');
|
|
}
|
|
}
|
|
|
|
Future<void> reset() async {
|
|
emit(DefaultSettings.get());
|
|
}
|
|
|
|
@override
|
|
Settings fromJson(Map<String, dynamic> json) {
|
|
try {
|
|
return _appendNewModules(Settings.fromJson(json));
|
|
} catch (_) {
|
|
try {
|
|
return _appendNewModules(Settings.fromJson(_mergeSettings(json, DefaultSettings.get().toJson())));
|
|
} catch (_) {
|
|
return DefaultSettings.get();
|
|
}
|
|
}
|
|
}
|
|
|
|
// Modules added in newer app versions won't appear in a previously persisted
|
|
// moduleOrder. Append any enum value that is neither ordered nor hidden so it
|
|
// becomes visible in the "Mehr" menu without forcing a full settings reset.
|
|
Settings _appendNewModules(Settings s) {
|
|
final order = s.modulesSettings.moduleOrder;
|
|
final hidden = s.modulesSettings.hiddenModules;
|
|
final missing = Modules.values.where((m) => !order.contains(m) && !hidden.contains(m));
|
|
if (missing.isEmpty) return s;
|
|
s.modulesSettings.moduleOrder = [...order, ...missing];
|
|
return s;
|
|
}
|
|
|
|
@override
|
|
Map<String, dynamic>? toJson(Settings state) => state.toJson();
|
|
|
|
Map<String, dynamic> _mergeSettings(Map<String, dynamic> oldMap, Map<String, dynamic> newMap) {
|
|
final merged = Map<String, dynamic>.from(newMap);
|
|
oldMap.forEach((key, value) {
|
|
if (merged.containsKey(key)) {
|
|
if (value is Map<String, dynamic> && merged[key] is Map<String, dynamic>) {
|
|
merged[key] = _mergeSettings(value, merged[key]);
|
|
} else {
|
|
merged[key] = value;
|
|
}
|
|
}
|
|
});
|
|
return merged;
|
|
}
|
|
}
|