import 'dart:convert'; import 'dart:developer'; import 'package:easy_debounce/easy_debounce.dart'; import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../../view/settings/defaultSettings.dart'; import 'settings.dart'; class SettingsProvider extends ChangeNotifier { static const String _fieldName = 'settings'; late SharedPreferences _storage; late Settings _settings = DefaultSettings.get(); Settings val({bool write = false}) { if(write) { notifyListeners(); EasyDebounce.debounce( _fieldName, const Duration(milliseconds: 500), update ); } return _settings; } SettingsProvider() { _readFromStorage(); } Future reset() async { _storage = await SharedPreferences.getInstance(); _storage.remove(_fieldName); _settings = DefaultSettings.get(); await update(); notifyListeners(); } Future _readFromStorage() async { _storage = await SharedPreferences.getInstance(); try { _settings = Settings.fromJson(jsonDecode(_storage.getString(_fieldName)!)); } catch(exception) { try { log('Settings were changed, trying to recover from old Settings: ${exception.toString()}'); _settings = Settings.fromJson(_mergeSettings(jsonDecode(_storage.getString(_fieldName)!), DefaultSettings.get().toJson())); log('Settings recovered successfully: ${_settings.toJson().toString()}'); } catch(exception) { log('Settings are defective and not recoverable, using defaults: ${exception.toString()}'); _settings = DefaultSettings.get(); log('Settings were reset to defaults!'); } } notifyListeners(); } Future update() async { await _storage.setString(_fieldName, jsonEncode(_settings.toJson())); } Map _mergeSettings(Map oldMap, Map newMap) { var mergedMap = Map.from(newMap); oldMap.forEach((key, value) { if (mergedMap.containsKey(key)) { if (value is Map && mergedMap[key] is Map) { mergedMap[key] = _mergeSettings(value, mergedMap[key]); } else { mergedMap[key] = value; } } }); return mergedMap; } }