diff --git a/lib/app_state.dart b/lib/app_state.dart index 448ef41..d3ae4f0 100644 --- a/lib/app_state.dart +++ b/lib/app_state.dart @@ -29,12 +29,16 @@ class AppState extends ChangeNotifier { final List _profiles = []; final Set _enabled = {}; + static const String _enabledPrefsKey = 'enabled_profiles'; // Test mode - prevents actual uploads to OSM bool _testMode = false; + static const String _testModePrefsKey = 'test_mode'; bool get testMode => _testMode; - void setTestMode(bool enabled) { + Future setTestMode(bool enabled) async { _testMode = enabled; + final prefs = await SharedPreferences.getInstance(); + await prefs.setBool(_testModePrefsKey, enabled); print('AppState: Test mode ${enabled ? 'enabled' : 'disabled'}'); notifyListeners(); } @@ -53,7 +57,18 @@ class AppState extends ChangeNotifier { // Initialize profiles: built-in + custom _profiles.add(CameraProfile.alpr()); _profiles.addAll(await ProfileService().load()); - _enabled.addAll(_profiles); + + // Load enabled profile IDs and test mode from prefs + final prefs = await SharedPreferences.getInstance(); + final enabledIds = prefs.getStringList(_enabledPrefsKey); + if (enabledIds != null && enabledIds.isNotEmpty) { + // Restore enabled profiles by id + _enabled.addAll(_profiles.where((p) => enabledIds.contains(p.id))); + } else { + // By default, all are enabled + _enabled.addAll(_profiles); + } + _testMode = prefs.getBool(_testModePrefsKey) ?? false; await _loadQueue(); @@ -158,6 +173,7 @@ class AppState extends ChangeNotifier { _profiles.where(isEnabled).toList(growable: false); void toggleProfile(CameraProfile p, bool e) { e ? _enabled.add(p) : _enabled.remove(p); + _saveEnabledProfiles(); notifyListeners(); } @@ -168,6 +184,7 @@ class AppState extends ChangeNotifier { } else { _profiles.add(p); _enabled.add(p); + _saveEnabledProfiles(); } ProfileService().save(_profiles); notifyListeners(); @@ -177,10 +194,20 @@ class AppState extends ChangeNotifier { if (p.builtin) return; _enabled.remove(p); _profiles.removeWhere((x) => x.id == p.id); + _saveEnabledProfiles(); ProfileService().save(_profiles); notifyListeners(); } + // Save enabled profile IDs to disk + Future _saveEnabledProfiles() async { + final prefs = await SharedPreferences.getInstance(); + await prefs.setStringList( + _enabledPrefsKey, + _enabled.map((p) => p.id).toList(), + ); + } + // ---------- Add‑camera session ---------- void startAddSession() { _session = AddCameraSession(profile: enabledProfiles.first); diff --git a/lib/widgets/camera_tag_sheet.dart b/lib/widgets/camera_tag_sheet.dart new file mode 100644 index 0000000..bee8657 --- /dev/null +++ b/lib/widgets/camera_tag_sheet.dart @@ -0,0 +1,61 @@ +import 'package:flutter/material.dart'; +import '../models/osm_camera_node.dart'; + +class CameraTagSheet extends StatelessWidget { + final OsmCameraNode node; + + const CameraTagSheet({super.key, required this.node}); + + @override + Widget build(BuildContext context) { + return SafeArea( + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 20), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Camera #${node.id}', + style: Theme.of(context).textTheme.titleLarge), + const SizedBox(height: 12), + ...node.tags.entries.map( + (e) => Padding( + padding: const EdgeInsets.symmetric(vertical: 2), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + e.key, + style: const TextStyle( + fontWeight: FontWeight.w500, + color: Colors.black87, + ), + ), + const SizedBox(width: 8), + Expanded( + child: Text( + e.value, + style: const TextStyle( + color: Colors.black54, + ), + softWrap: true, + ), + ), + ], + ), + ), + ), + const SizedBox(height: 8), + Align( + alignment: Alignment.centerRight, + child: TextButton( + onPressed: () => Navigator.pop(context), + child: const Text('Close'), + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/widgets/map_view.dart b/lib/widgets/map_view.dart index fb7b569..8f4e4af 100644 --- a/lib/widgets/map_view.dart +++ b/lib/widgets/map_view.dart @@ -13,6 +13,7 @@ import '../app_state.dart'; import '../services/overpass_service.dart'; import '../models/osm_camera_node.dart'; import 'debouncer.dart'; +import 'camera_tag_sheet.dart'; class MapView extends StatefulWidget { const MapView({ @@ -123,7 +124,16 @@ class _MapViewState extends State { point: n.coord, width: 24, height: 24, - child: const Icon(Icons.videocam, color: Colors.orange), + child: GestureDetector( + onTap: () { + showModalBottomSheet( + context: context, + builder: (_) => CameraTagSheet(node: n), + showDragHandle: true, // for better UX on Material3 + ); + }, + child: const Icon(Icons.videocam, color: Colors.orange), + ), ), ), ];