mirror of
https://github.com/FoggedLens/deflock-app.git
synced 2026-02-12 16:52:51 +00:00
106 lines
3.7 KiB
Dart
106 lines
3.7 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_map_animations/flutter_map_animations.dart';
|
|
import 'package:flutter_map/flutter_map.dart';
|
|
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 '../../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;
|
|
List<NodeProfile>? _lastEnabledProfiles;
|
|
VoidCallback? _onCamerasUpdated;
|
|
|
|
/// Initialize the camera refresh controller
|
|
void initialize({required VoidCallback onCamerasUpdated}) {
|
|
_cameraProvider = CameraProviderWithCache.instance;
|
|
_onCamerasUpdated = onCamerasUpdated;
|
|
_cameraProvider.addListener(_onCamerasUpdated!);
|
|
}
|
|
|
|
/// Dispose of resources and listeners
|
|
void dispose() {
|
|
if (_onCamerasUpdated != null) {
|
|
_cameraProvider.removeListener(_onCamerasUpdated!);
|
|
}
|
|
}
|
|
|
|
/// Check if camera profiles changed and handle cache clearing if needed.
|
|
/// Returns true if profiles changed (triggering a refresh).
|
|
bool checkAndHandleProfileChanges({
|
|
required List<NodeProfile> currentEnabledProfiles,
|
|
required VoidCallback onProfilesChanged,
|
|
}) {
|
|
if (_lastEnabledProfiles == null ||
|
|
!_profileListsEqual(_lastEnabledProfiles!, currentEnabledProfiles)) {
|
|
_lastEnabledProfiles = List.from(currentEnabledProfiles);
|
|
|
|
// 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 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)
|
|
onProfilesChanged();
|
|
});
|
|
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/// Refresh cameras from provider for the current map view
|
|
void refreshCamerasFromProvider({
|
|
required AnimatedMapController controller,
|
|
required List<NodeProfile> enabledProfiles,
|
|
required UploadMode uploadMode,
|
|
required BuildContext context,
|
|
}) {
|
|
LatLngBounds? bounds;
|
|
try {
|
|
bounds = controller.mapController.camera.visibleBounds;
|
|
} catch (_) {
|
|
return;
|
|
}
|
|
|
|
final zoom = controller.mapController.camera.zoom;
|
|
if (zoom < dev.kNodeMinZoomLevel) {
|
|
// Show a snackbar-style bubble warning
|
|
if (context.mounted) {
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
SnackBar(
|
|
content: Text('Nodes not drawn below zoom level $dev.kNodeMinZoomLevel'),
|
|
duration: const Duration(seconds: 2),
|
|
),
|
|
);
|
|
}
|
|
return;
|
|
}
|
|
|
|
_cameraProvider.fetchAndUpdate(
|
|
bounds: bounds,
|
|
profiles: enabledProfiles,
|
|
uploadMode: uploadMode,
|
|
);
|
|
}
|
|
|
|
/// Get the camera provider instance for external access
|
|
CameraProviderWithCache get cameraProvider => _cameraProvider;
|
|
|
|
/// Helper to check if two profile lists are equal by comparing IDs
|
|
bool _profileListsEqual(List<NodeProfile> list1, List<NodeProfile> list2) {
|
|
if (list1.length != list2.length) return false;
|
|
// Compare by profile IDs since profiles are value objects
|
|
final ids1 = list1.map((p) => p.id).toSet();
|
|
final ids2 = list2.map((p) => p.id).toSet();
|
|
return ids1.length == ids2.length && ids1.containsAll(ids2);
|
|
}
|
|
} |