import 'dart:developer'; import 'package:easy_debounce/easy_debounce.dart'; import 'package:hydrated_bloc/hydrated_bloc.dart'; import '../../../../../storage/settings.dart'; import '../../../../../view/pages/settings/data/default_settings.dart'; import '../../app_modules.dart'; class SettingsCubit extends HydratedCubit { 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 reset() async { emit(DefaultSettings.get()); } @override Settings fromJson(Map 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? toJson(Settings state) => state.toJson(); Map _mergeSettings(Map oldMap, Map newMap) { final merged = Map.from(newMap); oldMap.forEach((key, value) { if (merged.containsKey(key)) { if (value is Map && merged[key] is Map) { merged[key] = _mergeSettings(value, merged[key]); } else { merged[key] = value; } } }); return merged; } }