import 'dart:convert'; import 'dart:developer'; import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../../view/pages/files/files.dart'; import '../file/fileSettings.dart'; import '../gradeAverages/gradeAveragesSettings.dart'; import '../holidays/holidaysSettings.dart'; import '../talk/talkSettings.dart'; import '../timetable/timetableSettings.dart'; import 'settings.dart'; class SettingsProvider extends ChangeNotifier { static const String _fieldName = "settings"; late SharedPreferences _storage; late Settings _settings = _defaults(); Settings val({bool write = false}) { if(write) { notifyListeners(); Future.delayed(const Duration(milliseconds: 300)).then((_) => update()); } return _settings; } SettingsProvider() { _readFromStorage(); } void reset() async { _storage = await SharedPreferences.getInstance(); _storage.remove(_fieldName); notifyListeners(); } void _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)!), _defaults().toJson())); log("Settings recovered successfully: ${_settings.toJson().toString()}"); } catch(exception) { log("Settings are defective and not recoverable, using defaults: ${exception.toString()}"); _settings = _defaults(); log("Settings were reset to defaults!"); } } notifyListeners(); } void update() async { await _storage.setString(_fieldName, jsonEncode(_settings.toJson())); } Map _mergeSettings(Map oldMap, Map newMap) { Map 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; } Settings _defaults() { return Settings( appTheme: ThemeMode.system, devToolsEnabled: false, gradeAveragesSettings: GradeAveragesSettings( useGradeSystem: true, inputs: [] ), timetableSettings: TimetableSettings( zoom: 40, ), talkSettings: TalkSettings( sortFavoritesToTop: true, sortUnreadToTop: false, ), fileSettings: FileSettings( sortFoldersToTop: true, ascending: true, sortBy: SortOption.name ), holidaysSettings: HolidaysSettings( dismissedDisclaimer: false, showPastEvents: false, ), ); } }