More camera -> node

This commit is contained in:
stopflock
2025-12-02 21:17:07 -06:00
parent 3d5edf320e
commit bb3d398c9c
10 changed files with 91 additions and 72 deletions
+2 -2
View File
@@ -5,7 +5,7 @@ import 'package:latlong2/latlong.dart';
import '../../models/osm_node.dart';
import '../../app_state.dart';
import '../camera_provider_with_cache.dart';
import '../node_provider_with_cache.dart';
import '../../dev_config.dart';
/// Manages data fetching, filtering, and node limit logic for the map.
@@ -41,7 +41,7 @@ class MapDataManager {
if (currentZoom >= minZoom) {
// Above minimum zoom - get cached nodes directly (no Provider needed)
allNodes = (mapBounds != null)
? CameraProviderWithCache.instance.getCachedNodesForBounds(mapBounds)
? NodeProviderWithCache.instance.getCachedNodesForBounds(mapBounds)
: <OsmNode>[];
// Filter out invalid coordinates before applying limit
+3 -3
View File
@@ -10,7 +10,7 @@ import '../../state/session_state.dart';
import '../../dev_config.dart';
import '../camera_icon.dart';
import '../provisional_pin.dart';
import 'camera_markers.dart';
import 'node_markers.dart';
import 'suspected_location_markers.dart';
/// Enumeration for different pin types in navigation
@@ -65,8 +65,8 @@ class MarkerLayerBuilder {
// Determine if we should dim node markers (when suspected location is selected)
final shouldDimNodes = appState.selectedSuspectedLocation != null;
final markers = CameraMarkersBuilder.buildCameraMarkers(
cameras: nodesToRender,
final markers = NodeMarkersBuilder.buildNodeMarkers(
nodes: nodesToRender,
mapController: mapController.mapController,
userLocation: userLocation,
selectedNodeId: selectedNodeId,
@@ -8,13 +8,13 @@ import '../../models/osm_node.dart';
import '../node_tag_sheet.dart';
import '../camera_icon.dart';
/// Smart marker widget for camera with single/double tap distinction
class CameraMapMarker extends StatefulWidget {
/// Smart marker widget for surveillance node with single/double tap distinction
class NodeMapMarker extends StatefulWidget {
final OsmNode node;
final MapController mapController;
final void Function(OsmNode)? onNodeTap;
const CameraMapMarker({
const NodeMapMarker({
required this.node,
required this.mapController,
this.onNodeTap,
@@ -22,10 +22,10 @@ class CameraMapMarker extends StatefulWidget {
}) : super(key: key);
@override
State<CameraMapMarker> createState() => _CameraMapMarkerState();
State<NodeMapMarker> createState() => _NodeMapMarkerState();
}
class _CameraMapMarkerState extends State<CameraMapMarker> {
class _NodeMapMarkerState extends State<NodeMapMarker> {
Timer? _tapTimer;
// From dev_config.dart for build-time parameters
static const Duration tapTimeout = kMarkerTapTimeout;
@@ -60,7 +60,7 @@ class _CameraMapMarkerState extends State<CameraMapMarker> {
@override
Widget build(BuildContext context) {
// Check camera state
// Check node state
final isPendingUpload = widget.node.tags.containsKey('_pending_upload') &&
widget.node.tags['_pending_upload'] == 'true';
final isPendingEdit = widget.node.tags.containsKey('_pending_edit') &&
@@ -87,10 +87,10 @@ class _CameraMapMarkerState extends State<CameraMapMarker> {
}
}
/// Helper class to build marker layers for cameras and user location
class CameraMarkersBuilder {
static List<Marker> buildCameraMarkers({
required List<OsmNode> cameras,
/// Helper class to build marker layers for surveillance nodes and user location
class NodeMarkersBuilder {
static List<Marker> buildNodeMarkers({
required List<OsmNode> nodes,
required MapController mapController,
LatLng? userLocation,
int? selectedNodeId,
@@ -98,9 +98,9 @@ class CameraMarkersBuilder {
bool shouldDim = false,
}) {
final markers = <Marker>[
// Camera markers
...cameras
.where(_isValidCameraCoordinate)
// Node markers
...nodes
.where(_isValidNodeCoordinate)
.map((n) {
// Check if this node should be highlighted (selected) or dimmed
final isSelected = selectedNodeId == n.id;
@@ -112,7 +112,7 @@ class CameraMarkersBuilder {
height: kNodeIconDiameter,
child: Opacity(
opacity: shouldDimNode ? 0.5 : 1.0,
child: CameraMapMarker(
child: NodeMapMarker(
node: n,
mapController: mapController,
onNodeTap: onNodeTap,
@@ -134,7 +134,7 @@ class CameraMarkersBuilder {
return markers;
}
static bool _isValidCameraCoordinate(OsmNode node) {
static bool _isValidNodeCoordinate(OsmNode node) {
return (node.coord.latitude != 0 || node.coord.longitude != 0) &&
node.coord.latitude.abs() <= 90 &&
node.coord.longitude.abs() <= 180;
@@ -6,31 +6,31 @@ import 'package:latlong2/latlong.dart';
import '../../models/node_profile.dart';
import '../../app_state.dart' show UploadMode;
import '../../services/prefetch_area_service.dart';
import '../camera_provider_with_cache.dart';
import '../node_provider_with_cache.dart';
import '../../dev_config.dart';
/// Manages camera data refreshing, profile change detection, and camera cache operations.
/// Handles debounced camera fetching and profile-based cache invalidation.
class CameraRefreshController {
late final CameraProviderWithCache _cameraProvider;
/// Manages node data refreshing, profile change detection, and node cache operations.
/// Handles debounced node fetching and profile-based cache invalidation.
class NodeRefreshController {
late final NodeProviderWithCache _nodeProvider;
List<NodeProfile>? _lastEnabledProfiles;
VoidCallback? _onCamerasUpdated;
VoidCallback? _onNodesUpdated;
/// Initialize the camera refresh controller
void initialize({required VoidCallback onCamerasUpdated}) {
_cameraProvider = CameraProviderWithCache.instance;
_onCamerasUpdated = onCamerasUpdated;
_cameraProvider.addListener(_onCamerasUpdated!);
/// Initialize the node refresh controller
void initialize({required VoidCallback onNodesUpdated}) {
_nodeProvider = NodeProviderWithCache.instance;
_onNodesUpdated = onNodesUpdated;
_nodeProvider.addListener(_onNodesUpdated!);
}
/// Dispose of resources and listeners
void dispose() {
if (_onCamerasUpdated != null) {
_cameraProvider.removeListener(_onCamerasUpdated!);
if (_onNodesUpdated != null) {
_nodeProvider.removeListener(_onNodesUpdated!);
}
}
/// Check if camera profiles changed and handle cache clearing if needed.
/// Check if node profiles changed and handle cache clearing if needed.
/// Returns true if profiles changed (triggering a refresh).
bool checkAndHandleProfileChanges({
required List<NodeProfile> currentEnabledProfiles,
@@ -42,13 +42,13 @@ class CameraRefreshController {
// Handle profile change with cache clearing and refresh
WidgetsBinding.instance.addPostFrameCallback((_) {
// Clear camera cache to ensure fresh data for new profile combination
_cameraProvider.clearCache();
// Clear node cache to ensure fresh data for new profile combination
_nodeProvider.clearCache();
// Clear pre-fetch area since profiles changed
PrefetchAreaService().clearPreFetchedArea();
// Force display refresh first (for immediate UI update)
_cameraProvider.refreshDisplay();
// Notify that profiles changed (triggers camera refresh)
_nodeProvider.refreshDisplay();
// Notify that profiles changed (triggers node refresh)
onProfilesChanged();
});
@@ -57,8 +57,8 @@ class CameraRefreshController {
return false;
}
/// Refresh cameras from provider for the current map view
void refreshCamerasFromProvider({
/// Refresh nodes from provider for the current map view
void refreshNodesFromProvider({
required AnimatedMapController controller,
required List<NodeProfile> enabledProfiles,
required UploadMode uploadMode,
@@ -85,15 +85,15 @@ class CameraRefreshController {
return;
}
_cameraProvider.fetchAndUpdate(
_nodeProvider.fetchAndUpdate(
bounds: bounds,
profiles: enabledProfiles,
uploadMode: uploadMode,
);
}
/// Get the camera provider instance for external access
CameraProviderWithCache get cameraProvider => _cameraProvider;
/// Get the node provider instance for external access
NodeProviderWithCache get nodeProvider => _nodeProvider;
/// Helper to check if two profile lists are equal by comparing IDs
bool _profileListsEqual(List<NodeProfile> list1, List<NodeProfile> list2) {