mirror of
https://github.com/FoggedLens/deflock-app.git
synced 2026-02-12 16:52:51 +00:00
More camera -> node
This commit is contained in:
@@ -10,6 +10,14 @@ Successfully refactored the largest file in the codebase (MapView, 880 lines) by
|
||||
- **Total new code**: 4 new focused manager classes (351 lines total)
|
||||
- **Net complexity reduction**: Converted monolithic widget into clean orchestrator + specialized managers
|
||||
|
||||
### Step 1.5: Terminology Update (Camera → Node)
|
||||
- **Renamed 3 core files** to use "node" instead of "camera" terminology
|
||||
- **Updated all class names** to reflect current multi-device scope (not just cameras)
|
||||
- **Updated all method names** and comments for consistency
|
||||
- **Updated all imports/references** across the entire codebase
|
||||
- **Benefits**: Consistent terminology that reflects the app's expansion beyond just cameras to all surveillance devices
|
||||
=======
|
||||
|
||||
### New Manager Classes Created
|
||||
|
||||
#### 1. MapDataManager (`lib/widgets/map/map_data_manager.dart`) - 92 lines
|
||||
@@ -158,9 +166,20 @@ Expected reduction: ~400-500 lines
|
||||
- `lib/widgets/map/map_interaction_manager.dart`
|
||||
- `lib/widgets/map/marker_layer_builder.dart`
|
||||
- `lib/widgets/map/overlay_layer_builder.dart`
|
||||
- `lib/widgets/node_provider_with_cache.dart` (renamed from camera_provider_with_cache.dart)
|
||||
- `lib/widgets/map/node_refresh_controller.dart` (renamed from camera_refresh_controller.dart)
|
||||
- `lib/widgets/map/node_markers.dart` (renamed from camera_markers.dart)
|
||||
|
||||
### Modified Files
|
||||
- `lib/widgets/map_view.dart` (880 → 572 lines)
|
||||
- `lib/app_state.dart` (updated imports and references)
|
||||
- `lib/state/upload_queue_state.dart` (updated all references)
|
||||
- `lib/services/prefetch_area_service.dart` (updated references)
|
||||
|
||||
### Removed Files
|
||||
- `lib/widgets/camera_provider_with_cache.dart` (renamed to node_provider_with_cache.dart)
|
||||
- `lib/widgets/map/camera_refresh_controller.dart` (renamed to node_refresh_controller.dart)
|
||||
- `lib/widgets/map/camera_markers.dart` (renamed to node_markers.dart)
|
||||
|
||||
### Total Impact
|
||||
- **Lines removed**: 308 from MapView
|
||||
|
||||
@@ -18,7 +18,7 @@ import 'services/node_cache.dart';
|
||||
import 'services/tile_preview_service.dart';
|
||||
import 'services/changelog_service.dart';
|
||||
import 'services/operator_profile_service.dart';
|
||||
import 'widgets/camera_provider_with_cache.dart';
|
||||
import 'widgets/node_provider_with_cache.dart';
|
||||
import 'services/profile_service.dart';
|
||||
import 'widgets/proximity_warning_dialog.dart';
|
||||
import 'widgets/reauth_messages_dialog.dart';
|
||||
@@ -214,7 +214,7 @@ class AppState extends ChangeNotifier {
|
||||
await _authState.init(_settingsState.uploadMode);
|
||||
|
||||
// Set up callback to repopulate pending nodes after cache clears
|
||||
CameraProviderWithCache.instance.setOnCacheClearedCallback(() {
|
||||
NodeProviderWithCache.instance.setOnCacheClearedCallback(() {
|
||||
_uploadQueueState.repopulateCacheFromQueue();
|
||||
});
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import '../dev_config.dart';
|
||||
import 'map_data_submodules/nodes_from_overpass.dart';
|
||||
import 'node_cache.dart';
|
||||
import 'network_status.dart';
|
||||
import '../widgets/camera_provider_with_cache.dart';
|
||||
import '../widgets/node_provider_with_cache.dart';
|
||||
|
||||
/// Manages pre-fetching larger areas to reduce Overpass API calls.
|
||||
/// Uses zoom level 10 areas and automatically splits if hitting node limits.
|
||||
@@ -143,7 +143,7 @@ class PrefetchAreaService {
|
||||
// We just need to handle the successful result here
|
||||
|
||||
// Notify UI that cache has been updated with fresh data
|
||||
CameraProviderWithCache.instance.refreshDisplay();
|
||||
NodeProviderWithCache.instance.refreshDisplay();
|
||||
|
||||
} catch (e) {
|
||||
debugPrint('[PrefetchAreaService] Pre-fetch failed: $e');
|
||||
|
||||
@@ -9,7 +9,7 @@ import '../models/osm_node.dart';
|
||||
import '../models/node_profile.dart';
|
||||
import '../services/node_cache.dart';
|
||||
import '../services/uploader.dart';
|
||||
import '../widgets/camera_provider_with_cache.dart';
|
||||
import '../widgets/node_provider_with_cache.dart';
|
||||
import 'settings_state.dart';
|
||||
import 'session_state.dart';
|
||||
|
||||
@@ -113,7 +113,7 @@ class UploadQueueState extends ChangeNotifier {
|
||||
_saveQueue();
|
||||
|
||||
// Notify node provider to update the map
|
||||
CameraProviderWithCache.instance.notifyListeners();
|
||||
NodeProviderWithCache.instance.notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,7 +150,7 @@ class UploadQueueState extends ChangeNotifier {
|
||||
|
||||
NodeCache.instance.addOrUpdate([tempNode]);
|
||||
// Notify node provider to update the map
|
||||
CameraProviderWithCache.instance.notifyListeners();
|
||||
NodeProviderWithCache.instance.notifyListeners();
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
@@ -238,7 +238,7 @@ class UploadQueueState extends ChangeNotifier {
|
||||
NodeCache.instance.addOrUpdate([originalNode, editedNode]);
|
||||
}
|
||||
// Notify node provider to update the map
|
||||
CameraProviderWithCache.instance.notifyListeners();
|
||||
NodeProviderWithCache.instance.notifyListeners();
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
@@ -269,7 +269,7 @@ class UploadQueueState extends ChangeNotifier {
|
||||
|
||||
NodeCache.instance.addOrUpdate([nodeWithDeletionTag]);
|
||||
// Notify node provider to update the map
|
||||
CameraProviderWithCache.instance.notifyListeners();
|
||||
NodeProviderWithCache.instance.notifyListeners();
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
@@ -284,7 +284,7 @@ class UploadQueueState extends ChangeNotifier {
|
||||
_saveQueue();
|
||||
|
||||
// Notify node provider to update the map
|
||||
CameraProviderWithCache.instance.notifyListeners();
|
||||
NodeProviderWithCache.instance.notifyListeners();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
@@ -296,7 +296,7 @@ class UploadQueueState extends ChangeNotifier {
|
||||
_saveQueue();
|
||||
|
||||
// Notify node provider to update the map
|
||||
CameraProviderWithCache.instance.notifyListeners();
|
||||
NodeProviderWithCache.instance.notifyListeners();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
@@ -665,7 +665,7 @@ class UploadQueueState extends ChangeNotifier {
|
||||
}
|
||||
|
||||
// Notify node provider to update the map
|
||||
CameraProviderWithCache.instance.notifyListeners();
|
||||
NodeProviderWithCache.instance.notifyListeners();
|
||||
}
|
||||
|
||||
// Handle successful deletion by removing the node from cache
|
||||
@@ -675,7 +675,7 @@ class UploadQueueState extends ChangeNotifier {
|
||||
NodeCache.instance.removeNodeById(item.originalNodeId!);
|
||||
|
||||
// Notify node provider to update the map
|
||||
CameraProviderWithCache.instance.notifyListeners();
|
||||
NodeProviderWithCache.instance.notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
@@ -14,11 +14,11 @@ import '../models/suspected_location.dart';
|
||||
import '../models/tile_provider.dart';
|
||||
import '../state/session_state.dart';
|
||||
import 'debouncer.dart';
|
||||
import 'camera_provider_with_cache.dart';
|
||||
import 'node_provider_with_cache.dart';
|
||||
import 'map/map_overlays.dart';
|
||||
import 'map/map_position_manager.dart';
|
||||
import 'map/tile_layer_manager.dart';
|
||||
import 'map/camera_refresh_controller.dart';
|
||||
import 'map/node_refresh_controller.dart';
|
||||
import 'map/gps_controller.dart';
|
||||
import 'map/map_data_manager.dart';
|
||||
import 'map/map_interaction_manager.dart';
|
||||
@@ -69,7 +69,7 @@ class MapViewState extends State<MapView> {
|
||||
|
||||
late final MapPositionManager _positionManager;
|
||||
late final TileLayerManager _tileManager;
|
||||
late final CameraRefreshController _cameraController;
|
||||
late final NodeRefreshController _nodeController;
|
||||
late final GpsController _gpsController;
|
||||
late final MapDataManager _dataManager;
|
||||
late final MapInteractionManager _interactionManager;
|
||||
@@ -93,8 +93,8 @@ class MapViewState extends State<MapView> {
|
||||
_positionManager = MapPositionManager();
|
||||
_tileManager = TileLayerManager();
|
||||
_tileManager.initialize();
|
||||
_cameraController = CameraRefreshController();
|
||||
_cameraController.initialize(onCamerasUpdated: _onNodesUpdated);
|
||||
_nodeController = NodeRefreshController();
|
||||
_nodeController.initialize(onNodesUpdated: _onNodesUpdated);
|
||||
_gpsController = GpsController();
|
||||
_dataManager = MapDataManager();
|
||||
_interactionManager = MapInteractionManager();
|
||||
@@ -167,7 +167,7 @@ class MapViewState extends State<MapView> {
|
||||
return [];
|
||||
}
|
||||
return mapBounds != null
|
||||
? CameraProviderWithCache.instance.getCachedNodesForBounds(mapBounds)
|
||||
? NodeProviderWithCache.instance.getCachedNodesForBounds(mapBounds)
|
||||
: [];
|
||||
} catch (e) {
|
||||
debugPrint('[MapView] Could not get nearby nodes: $e');
|
||||
@@ -209,7 +209,7 @@ class MapViewState extends State<MapView> {
|
||||
_cameraDebounce.dispose();
|
||||
_tileDebounce.dispose();
|
||||
_mapPositionDebounce.dispose();
|
||||
_cameraController.dispose();
|
||||
_nodeController.dispose();
|
||||
_tileManager.dispose();
|
||||
_gpsController.dispose();
|
||||
PrefetchAreaService().dispose();
|
||||
@@ -241,7 +241,7 @@ class MapViewState extends State<MapView> {
|
||||
|
||||
void _refreshNodesFromProvider() {
|
||||
final appState = context.read<AppState>();
|
||||
_cameraController.refreshCamerasFromProvider(
|
||||
_nodeController.refreshNodesFromProvider(
|
||||
controller: _controller,
|
||||
enabledProfiles: appState.enabledProfiles,
|
||||
uploadMode: appState.uploadMode,
|
||||
@@ -273,8 +273,8 @@ class MapViewState extends State<MapView> {
|
||||
final session = appState.session;
|
||||
final editSession = appState.editSession;
|
||||
|
||||
// Check if enabled profiles changed and refresh cameras if needed
|
||||
_cameraController.checkAndHandleProfileChanges(
|
||||
// Check if enabled profiles changed and refresh nodes if needed
|
||||
_nodeController.checkAndHandleProfileChanges(
|
||||
currentEnabledProfiles: appState.enabledProfiles,
|
||||
onProfilesChanged: _refreshNodesFromProvider,
|
||||
);
|
||||
|
||||
@@ -12,10 +12,10 @@ import '../app_state.dart';
|
||||
|
||||
/// Provides surveillance nodes for a map view, using an in-memory cache and optionally
|
||||
/// merging in new results from Overpass via MapDataProvider when not offline.
|
||||
class CameraProviderWithCache extends ChangeNotifier {
|
||||
static final CameraProviderWithCache instance = CameraProviderWithCache._internal();
|
||||
factory CameraProviderWithCache() => instance;
|
||||
CameraProviderWithCache._internal();
|
||||
class NodeProviderWithCache extends ChangeNotifier {
|
||||
static final NodeProviderWithCache instance = NodeProviderWithCache._internal();
|
||||
factory NodeProviderWithCache() => instance;
|
||||
NodeProviderWithCache._internal();
|
||||
|
||||
Timer? _debounceTimer;
|
||||
|
||||
@@ -61,7 +61,7 @@ class CameraProviderWithCache extends ChangeNotifier {
|
||||
notifyListeners();
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint('[CameraProviderWithCache] Node fetch failed: $e');
|
||||
debugPrint('[NodeProviderWithCache] Node fetch failed: $e');
|
||||
// Cache already holds whatever is available for the view
|
||||
}
|
||||
});
|
||||
@@ -114,4 +114,4 @@ class CameraProviderWithCache extends ChangeNotifier {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user