From 160bc8f9f2d5a84adc78ab4f7637c09a9fa38523 Mon Sep 17 00:00:00 2001 From: stopflock Date: Sun, 10 Aug 2025 23:31:17 -0500 Subject: [PATCH] add dev_config to centralize hardcoded stuff into one place. --- lib/dev_config.dart | 25 +++++++++++++++++++ lib/screens/home_screen.dart | 4 +-- .../map_data_submodules/tiles_from_osm.dart | 9 ++++--- lib/services/offline_area_service.dart | 5 ++-- lib/widgets/map_view.dart | 12 +++++---- 5 files changed, 42 insertions(+), 13 deletions(-) diff --git a/lib/dev_config.dart b/lib/dev_config.dart index e69de29..31f73ce 100644 --- a/lib/dev_config.dart +++ b/lib/dev_config.dart @@ -0,0 +1,25 @@ +// lib/dev_config.dart +/// Developer/build-time configuration for global/non-user-tunable constants. +const int kWorldMinZoom = 1; +const int kWorldMaxZoom = 4; + +// Example: Default tile storage estimate (KB per tile), for size estimates +const double kTileEstimateKb = 25.0; + +// Direction cone for map view +const double kDirectionConeHalfAngle = 15.0; // degrees +const double kDirectionConeBaseLength = 0.0012; // multiplier + +// Marker/camera interaction +const Duration kMarkerTapTimeout = Duration(milliseconds: 250); +const Duration kDebounceCameraRefresh = Duration(milliseconds: 500); +const Duration kDebounceTileLayerUpdate = Duration(milliseconds: 50); + +// Tile/Network fetch retry parameters (for tunable dev backoff) +const int kTileFetchMaxAttempts = 3; +const int kTileFetchInitialDelayMs = 4000; +const int kTileFetchJitter1Ms = 1000; +const int kTileFetchSecondDelayMs = 15000; +const int kTileFetchJitter2Ms = 4000; +const int kTileFetchThirdDelayMs = 60000; +const int kTileFetchJitter3Ms = 5000; diff --git a/lib/screens/home_screen.dart b/lib/screens/home_screen.dart index 999cf0f..ae30e45 100644 --- a/lib/screens/home_screen.dart +++ b/lib/screens/home_screen.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:latlong2/latlong.dart'; +import 'package:flock_map_app/dev_config.dart'; import '../app_state.dart'; import '../widgets/map_view.dart'; import 'package:flutter_map/flutter_map.dart'; @@ -133,8 +134,7 @@ class _DownloadAreaDialogState extends State { final minZoom = findDynamicMinZoom(bounds); final maxZoom = _zoom.toInt(); final nTiles = computeTileList(bounds, minZoom, maxZoom).length; - const kbPerTile = 25.0; // Empirically ~6.5kB average for OSM tiles at z=1-19 - final totalMb = (nTiles * kbPerTile) / 1024.0; + final totalMb = (nTiles * kTileEstimateKb) / 1024.0; setState(() { _minZoom = minZoom; _tileCount = nTiles; diff --git a/lib/services/map_data_submodules/tiles_from_osm.dart b/lib/services/map_data_submodules/tiles_from_osm.dart index 67dfa7d..d5870a1 100644 --- a/lib/services/map_data_submodules/tiles_from_osm.dart +++ b/lib/services/map_data_submodules/tiles_from_osm.dart @@ -3,6 +3,7 @@ import 'dart:io'; import 'dart:async'; import 'package:http/http.dart' as http; import 'package:flutter/foundation.dart'; +import 'package:flock_map_app/dev_config.dart'; /// Global semaphore to limit simultaneous tile fetches final _tileFetchSemaphore = _SimpleSemaphore(4); // Max 4 concurrent @@ -15,13 +16,13 @@ Future> fetchOSMTile({ required int y, }) async { final url = 'https://tile.openstreetmap.org/$z/$x/$y.png'; - const int maxAttempts = 3; + const int maxAttempts = kTileFetchMaxAttempts; int attempt = 0; final random = Random(); final delays = [ - 4000 + random.nextInt(1000), // 4-5s after 1st failure - 15000 + random.nextInt(4000), // 15-19s after 2nd - 60000 + random.nextInt(5000), // 60-65s after 3rd + kTileFetchInitialDelayMs + random.nextInt(kTileFetchJitter1Ms), + kTileFetchSecondDelayMs + random.nextInt(kTileFetchJitter2Ms), + kTileFetchThirdDelayMs + random.nextInt(kTileFetchJitter3Ms), ]; while (true) { await _tileFetchSemaphore.acquire(); diff --git a/lib/services/offline_area_service.dart b/lib/services/offline_area_service.dart index 72bad86..72c4754 100644 --- a/lib/services/offline_area_service.dart +++ b/lib/services/offline_area_service.dart @@ -11,6 +11,7 @@ import '../models/osm_camera_node.dart'; import '../app_state.dart'; import 'map_data_provider.dart'; import 'map_data_submodules/cameras_from_overpass.dart'; +import 'package:flock_map_app/dev_config.dart'; /// Service for managing download, storage, and retrieval of offline map areas and cameras. class OfflineAreaService { @@ -98,7 +99,7 @@ class OfflineAreaService { for (final a in _areas) { if (a.isPermanent) { world = a; break; } } - final Set> expectedTiles = computeTileList(worldBounds, 1, 4); + final Set> expectedTiles = computeTileList(worldBounds, kWorldMinZoom, kWorldMaxZoom); if (world != null) { int filesFound = 0; List> missingTiles = []; @@ -198,7 +199,7 @@ class OfflineAreaService { try { Set> allTiles; if (area.isPermanent) { - allTiles = computeTileList(globalWorldBounds(), 1, 4); + allTiles = computeTileList(globalWorldBounds(), kWorldMinZoom, kWorldMaxZoom); } else { allTiles = computeTileList(bounds, minZoom, maxZoom); } diff --git a/lib/widgets/map_view.dart b/lib/widgets/map_view.dart index 04817a8..f24f8bd 100644 --- a/lib/widgets/map_view.dart +++ b/lib/widgets/map_view.dart @@ -20,6 +20,7 @@ import '../models/osm_camera_node.dart'; import 'debouncer.dart'; import 'camera_tag_sheet.dart'; import 'tile_provider_with_cache.dart'; +import 'package:flock_map_app/dev_config.dart'; // --- Smart marker widget for camera with single/double tap distinction class _CameraMapMarker extends StatefulWidget { @@ -33,7 +34,8 @@ class _CameraMapMarker extends StatefulWidget { class _CameraMapMarkerState extends State<_CameraMapMarker> { Timer? _tapTimer; - static const Duration tapTimeout = Duration(milliseconds: 250); + // From dev_config.dart for build-time parameters + static const Duration tapTimeout = kMarkerTapTimeout; void _onTap() { _tapTimer = Timer(tapTimeout, () { @@ -85,7 +87,7 @@ class MapView extends StatefulWidget { class _MapViewState extends State { late final MapController _controller; final MapDataProvider _mapDataProvider = MapDataProvider(); - final Debouncer _debounce = Debouncer(const Duration(milliseconds: 500)); + final Debouncer _debounce = Debouncer(kDebounceCameraRefresh); Debouncer? _debounceTileLayerUpdate; StreamSubscription? _positionSub; @@ -113,7 +115,7 @@ class _MapViewState extends State { @override void initState() { super.initState(); - _debounceTileLayerUpdate = Debouncer(const Duration(milliseconds: 50),); + _debounceTileLayerUpdate = Debouncer(kDebounceTileLayerUpdate); // Kick off offline area loading as soon as map loads OfflineAreaService(); _controller = widget.controller; @@ -391,8 +393,8 @@ class _MapViewState extends State { } Polygon _buildCone(LatLng origin, double bearingDeg, double zoom) { - const halfAngle = 15.0; - final length = 0.0012 * math.pow(2, 15 - zoom); + final halfAngle = kDirectionConeHalfAngle; + final length = kDirectionConeBaseLength * math.pow(2, 15 - zoom); LatLng _project(double deg) { final rad = deg * math.pi / 180;