class AppSettings { static const Object _unset = Object(); final bool clearPathOnMaxRetry; final bool mapShowRepeaters; final bool mapShowChatNodes; final bool mapShowOtherNodes; final double mapTimeFilterHours; // 0 = all time final bool mapKeyPrefixEnabled; final String mapKeyPrefix; final bool mapShowMarkers; final Map? mapCacheBounds; final int mapCacheMinZoom; final int mapCacheMaxZoom; final bool notificationsEnabled; final bool notifyOnNewMessage; final bool notifyOnNewChannelMessage; final bool notifyOnNewAdvert; final bool autoRouteRotationEnabled; final String themeMode; final String? languageOverride; // null = system default final bool appDebugLogEnabled; final Map batteryChemistryByDeviceId; AppSettings({ this.clearPathOnMaxRetry = false, this.mapShowRepeaters = true, this.mapShowChatNodes = true, this.mapShowOtherNodes = true, this.mapTimeFilterHours = 0, // Default to all time this.mapKeyPrefixEnabled = false, this.mapKeyPrefix = '', this.mapShowMarkers = true, this.mapCacheBounds, this.mapCacheMinZoom = 10, this.mapCacheMaxZoom = 15, this.notificationsEnabled = true, this.notifyOnNewMessage = true, this.notifyOnNewChannelMessage = true, this.notifyOnNewAdvert = true, this.autoRouteRotationEnabled = false, this.themeMode = 'system', this.languageOverride, this.appDebugLogEnabled = false, Map? batteryChemistryByDeviceId, }) : batteryChemistryByDeviceId = batteryChemistryByDeviceId ?? {}; Map toJson() { return { 'clear_path_on_max_retry': clearPathOnMaxRetry, 'map_show_repeaters': mapShowRepeaters, 'map_show_chat_nodes': mapShowChatNodes, 'map_show_other_nodes': mapShowOtherNodes, 'map_time_filter_hours': mapTimeFilterHours, 'map_key_prefix_enabled': mapKeyPrefixEnabled, 'map_key_prefix': mapKeyPrefix, 'map_show_markers': mapShowMarkers, 'map_cache_bounds': mapCacheBounds, 'map_cache_min_zoom': mapCacheMinZoom, 'map_cache_max_zoom': mapCacheMaxZoom, 'notifications_enabled': notificationsEnabled, 'notify_on_new_message': notifyOnNewMessage, 'notify_on_new_channel_message': notifyOnNewChannelMessage, 'notify_on_new_advert': notifyOnNewAdvert, 'auto_route_rotation_enabled': autoRouteRotationEnabled, 'theme_mode': themeMode, 'language_override': languageOverride, 'app_debug_log_enabled': appDebugLogEnabled, 'battery_chemistry_by_device_id': batteryChemistryByDeviceId, }; } factory AppSettings.fromJson(Map json) { return AppSettings( clearPathOnMaxRetry: json['clear_path_on_max_retry'] as bool? ?? false, mapShowRepeaters: json['map_show_repeaters'] as bool? ?? true, mapShowChatNodes: json['map_show_chat_nodes'] as bool? ?? true, mapShowOtherNodes: json['map_show_other_nodes'] as bool? ?? true, mapTimeFilterHours: (json['map_time_filter_hours'] as num?)?.toDouble() ?? 0, mapKeyPrefixEnabled: json['map_key_prefix_enabled'] as bool? ?? false, mapKeyPrefix: json['map_key_prefix'] as String? ?? '', mapShowMarkers: json['map_show_markers'] as bool? ?? true, mapCacheBounds: (json['map_cache_bounds'] as Map?)?.map( (key, value) => MapEntry(key.toString(), (value as num).toDouble()), ), mapCacheMinZoom: json['map_cache_min_zoom'] as int? ?? 10, mapCacheMaxZoom: json['map_cache_max_zoom'] as int? ?? 15, notificationsEnabled: json['notifications_enabled'] as bool? ?? true, notifyOnNewMessage: json['notify_on_new_message'] as bool? ?? true, notifyOnNewChannelMessage: json['notify_on_new_channel_message'] as bool? ?? true, notifyOnNewAdvert: json['notify_on_new_advert'] as bool? ?? true, autoRouteRotationEnabled: json['auto_route_rotation_enabled'] as bool? ?? false, themeMode: json['theme_mode'] as String? ?? 'system', languageOverride: json['language_override'] as String?, appDebugLogEnabled: json['app_debug_log_enabled'] as bool? ?? false, batteryChemistryByDeviceId: (json['battery_chemistry_by_device_id'] as Map?)?.map( (key, value) => MapEntry(key.toString(), value.toString()), ) ?? {}, ); } AppSettings copyWith({ bool? clearPathOnMaxRetry, bool? mapShowRepeaters, bool? mapShowChatNodes, bool? mapShowOtherNodes, double? mapTimeFilterHours, bool? mapKeyPrefixEnabled, String? mapKeyPrefix, bool? mapShowMarkers, Object? mapCacheBounds = _unset, int? mapCacheMinZoom, int? mapCacheMaxZoom, bool? notificationsEnabled, bool? notifyOnNewMessage, bool? notifyOnNewChannelMessage, bool? notifyOnNewAdvert, bool? autoRouteRotationEnabled, String? themeMode, Object? languageOverride = _unset, bool? appDebugLogEnabled, Map? batteryChemistryByDeviceId, }) { return AppSettings( clearPathOnMaxRetry: clearPathOnMaxRetry ?? this.clearPathOnMaxRetry, mapShowRepeaters: mapShowRepeaters ?? this.mapShowRepeaters, mapShowChatNodes: mapShowChatNodes ?? this.mapShowChatNodes, mapShowOtherNodes: mapShowOtherNodes ?? this.mapShowOtherNodes, mapTimeFilterHours: mapTimeFilterHours ?? this.mapTimeFilterHours, mapKeyPrefixEnabled: mapKeyPrefixEnabled ?? this.mapKeyPrefixEnabled, mapKeyPrefix: mapKeyPrefix ?? this.mapKeyPrefix, mapShowMarkers: mapShowMarkers ?? this.mapShowMarkers, mapCacheBounds: mapCacheBounds == _unset ? this.mapCacheBounds : mapCacheBounds as Map?, mapCacheMinZoom: mapCacheMinZoom ?? this.mapCacheMinZoom, mapCacheMaxZoom: mapCacheMaxZoom ?? this.mapCacheMaxZoom, notificationsEnabled: notificationsEnabled ?? this.notificationsEnabled, notifyOnNewMessage: notifyOnNewMessage ?? this.notifyOnNewMessage, notifyOnNewChannelMessage: notifyOnNewChannelMessage ?? this.notifyOnNewChannelMessage, notifyOnNewAdvert: notifyOnNewAdvert ?? this.notifyOnNewAdvert, autoRouteRotationEnabled: autoRouteRotationEnabled ?? this.autoRouteRotationEnabled, themeMode: themeMode ?? this.themeMode, languageOverride: languageOverride == _unset ? this.languageOverride : languageOverride as String?, appDebugLogEnabled: appDebugLogEnabled ?? this.appDebugLogEnabled, batteryChemistryByDeviceId: batteryChemistryByDeviceId ?? this.batteryChemistryByDeviceId, ); } }