diff --git a/lib/services/simple_tile_service.dart b/lib/services/simple_tile_service.dart index 9cc3aa2..b1f3254 100644 --- a/lib/services/simple_tile_service.dart +++ b/lib/services/simple_tile_service.dart @@ -40,31 +40,39 @@ class SimpleTileHttpClient extends http.BaseClient { } Future _getTile(int z, int x, int y) async { + // Only serve from offline if available - otherwise let flutter_map handle directly try { - // Use centralized tile fetching from MapDataProvider - final tileBytes = await _mapDataProvider.getTile(z: z, x: x, y: y); - debugPrint('[SimpleTileService] Serving tile $z/$x/$y via MapDataProvider'); + // Check if we have this tile offline (without fetching) + final localTileBytes = await _mapDataProvider.getTile(z: z, x: x, y: y, source: MapSource.local); + debugPrint('[SimpleTileService] Serving tile $z/$x/$y from offline storage'); + + // Serve offline tile with proper cache headers return http.StreamedResponse( - Stream.value(tileBytes), + Stream.value(localTileBytes), 200, headers: { 'Content-Type': 'image/png', - 'Cache-Control': 'public, max-age=604800', // 1 week cache + 'Cache-Control': 'public, max-age=604800', 'Expires': _httpDateFormat(DateTime.now().add(Duration(days: 7))), 'Last-Modified': _httpDateFormat(DateTime.now().subtract(Duration(hours: 1))), }, ); } catch (e) { - debugPrint('[SimpleTileService] Tile fetch failed for $z/$x/$y: $e'); - - // Return 404 for any failure - let flutter_map handle gracefully - return http.StreamedResponse( - Stream.value([]), - 404, - reasonPhrase: 'Tile not available: $e', - ); + // No offline tile - try OSM with proper error handling + debugPrint('[SimpleTileService] No offline tile for $z/$x/$y - trying OSM'); + try { + return await _inner.send(http.Request('GET', Uri.parse('https://tile.openstreetmap.org/$z/$x/$y.png'))); + } catch (networkError) { + debugPrint('[SimpleTileService] OSM request failed for $z/$x/$y: $networkError'); + // Return 404 instead of throwing - let flutter_map handle gracefully + return http.StreamedResponse( + Stream.value([]), + 404, + reasonPhrase: 'Network tile unavailable: $networkError', + ); + } } } diff --git a/lib/widgets/map_view.dart b/lib/widgets/map_view.dart index f4a4335..508aa1a 100644 --- a/lib/widgets/map_view.dart +++ b/lib/widgets/map_view.dart @@ -1,5 +1,4 @@ import 'dart:async'; -import 'dart:math' as math; import 'package:flutter/material.dart'; import 'package:flutter_map/flutter_map.dart'; import 'package:latlong2/latlong.dart'; @@ -50,9 +49,8 @@ class _MapViewState extends State { // Track profile changes to trigger camera refresh List? _lastEnabledProfiles; - // Track map position to only clear queue on significant changes + // Track zoom to clear queue on zoom changes double? _lastZoom; - LatLng? _lastCenter; @override void initState() { @@ -164,18 +162,7 @@ class _MapViewState extends State { return ids1.length == ids2.length && ids1.containsAll(ids2); } - /// Calculate approximate distance between two LatLng points in meters - double _distanceInMeters(LatLng point1, LatLng point2) { - const double earthRadius = 6371000; // Earth radius in meters - final dLat = (point2.latitude - point1.latitude) * (3.14159 / 180); - final dLon = (point2.longitude - point1.longitude) * (3.14159 / 180); - final a = math.sin(dLat / 2) * math.sin(dLat / 2) + - math.cos(point1.latitude * (3.14159 / 180)) * - math.cos(point2.latitude * (3.14159 / 180)) * - math.sin(dLon / 2) * math.sin(dLon / 2); - final c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a)); - return earthRadius * c; - } + @override Widget build(BuildContext context) { @@ -257,25 +244,17 @@ class _MapViewState extends State { appState.updateSession(target: pos.center); } - // TODO: Re-enable smart queue clearing once we debug tile loading issues - // For now, let flutter_map handle its own request management - /* - // Only clear tile queue on significant movement changes + // Only clear tile queue on significant ZOOM changes (not panning) final currentZoom = pos.zoom; - final currentCenter = pos.center; - final zoomChanged = _lastZoom == null || (currentZoom - _lastZoom!).abs() > 0.1; - final centerChanged = _lastCenter == null || - _distanceInMeters(_lastCenter!, currentCenter) > 100; // 100m threshold + final zoomChanged = _lastZoom != null && (currentZoom - _lastZoom!).abs() > 0.5; - if (zoomChanged || centerChanged) { + if (zoomChanged) { _tileDebounce(() { - debugPrint('[MapView] Significant map change - clearing stale tile requests'); + debugPrint('[MapView] Zoom change detected - clearing stale tile requests'); _tileHttpClient.clearTileQueue(); }); - _lastZoom = currentZoom; - _lastCenter = currentCenter; } - */ + _lastZoom = currentZoom; // Request more cameras on any map movement/zoom at valid zoom level (slower debounce) if (pos.zoom >= 10) {