tap camera to see all tags, persistent settings

This commit is contained in:
stopflock
2025-08-05 18:09:58 -05:00
parent dcdff6abbd
commit faa40c6404
3 changed files with 101 additions and 3 deletions

View File

@@ -29,12 +29,16 @@ class AppState extends ChangeNotifier {
final List<CameraProfile> _profiles = [];
final Set<CameraProfile> _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<void> 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<void> _saveEnabledProfiles() async {
final prefs = await SharedPreferences.getInstance();
await prefs.setStringList(
_enabledPrefsKey,
_enabled.map((p) => p.id).toList(),
);
}
// ---------- Addcamera session ----------
void startAddSession() {
_session = AddCameraSession(profile: enabledProfiles.first);

View File

@@ -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'),
),
),
],
),
),
);
}
}

View File

@@ -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<MapView> {
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),
),
),
),
];