From 111bdc4254dfd15edcd36ea621ce3bd9adace9a9 Mon Sep 17 00:00:00 2001 From: stopflock Date: Sun, 5 Oct 2025 16:48:25 -0500 Subject: [PATCH] Fix opentopomap x/y, allow searching in release when not offline --- README.md | 2 -- lib/dev_config.dart | 18 ++++++++++ lib/models/tile_provider.dart | 2 +- lib/screens/home_screen.dart | 6 ++-- lib/widgets/map/map_overlays.dart | 58 ++++++++++++++++++++++++------- lib/widgets/navigation_sheet.dart | 46 +++++++++++++----------- 6 files changed, 93 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index d2bca4a..01e37f0 100644 --- a/README.md +++ b/README.md @@ -79,8 +79,6 @@ cp lib/keys.dart.example lib/keys.dart ## Roadmap ### Needed Bugfixes -- No seach or navigation while offline (the thing we do now) -- Let user search in release builds, just not navigate - Swap in tsbichof avoidance routing API ### Current Development diff --git a/lib/dev_config.dart b/lib/dev_config.dart index 9b37dec..f4a3c4d 100644 --- a/lib/dev_config.dart +++ b/lib/dev_config.dart @@ -43,6 +43,24 @@ const bool kEnableDevelopmentModes = false; // Set to false to hide sandbox/simu // Navigation features - set to false to hide navigation UI elements while in development const bool kEnableNavigationFeatures = kEnableDevelopmentModes; // Hide navigation until fully implemented +/// Search availability: dev builds always, release builds only when online +bool enableSearchFeatures({required bool offlineMode}) { + if (kEnableDevelopmentModes) { + return true; // Dev builds: always allow search + } else { + return !offlineMode; // Release builds: only when online + } +} + +/// Navigation availability: only dev builds, and only when online +bool enableNavigationFeatures({required bool offlineMode}) { + if (!kEnableDevelopmentModes) { + return false; // Release builds: never allow navigation + } else { + return !offlineMode; // Dev builds: only when online + } +} + // Marker/node interaction const int kCameraMinZoomLevel = 10; // Minimum zoom to show nodes (Overpass) const int kOsmApiMinZoomLevel = 13; // Minimum zoom for OSM API bbox queries (sandbox mode) diff --git a/lib/models/tile_provider.dart b/lib/models/tile_provider.dart index c772512..cdcb92d 100644 --- a/lib/models/tile_provider.dart +++ b/lib/models/tile_provider.dart @@ -186,7 +186,7 @@ class DefaultTileProviders { TileType( id: 'opentopomap_topo', name: 'Topographic', - urlTemplate: 'https://tile.memomaps.de/tilegen/{z}/{y}/{x}.png', + urlTemplate: 'https://tile.memomaps.de/tilegen/{z}/{x}/{y}.png', attribution: 'Kartendaten: © OpenStreetMap-Mitwirkende, SRTM | Kartendarstellung: © OpenTopoMap (CC-BY-SA)', maxZoom: 18, ), diff --git a/lib/screens/home_screen.dart b/lib/screens/home_screen.dart index d7d3dd3..19b7652 100644 --- a/lib/screens/home_screen.dart +++ b/lib/screens/home_screen.dart @@ -522,15 +522,15 @@ class _HomeScreenState extends State with TickerProviderStateMixin { sheetHeight: activeSheetHeight, selectedNodeId: _selectedNodeId, onNodeTap: openNodeTagSheet, - onSearchPressed: kEnableNavigationFeatures ? _onNavigationButtonPressed : null, + onSearchPressed: (enableSearchFeatures(offlineMode: appState.offlineMode) || enableNavigationFeatures(offlineMode: appState.offlineMode)) ? _onNavigationButtonPressed : null, onUserGesture: () { if (appState.followMeMode != FollowMeMode.off) { appState.setFollowMeMode(FollowMeMode.off); } }, ), - // Search bar (slides in when in search mode) - only in dev mode - if (kEnableNavigationFeatures && appState.isInSearchMode) + // Search bar (slides in when in search mode) - available based on feature flags + if (enableSearchFeatures(offlineMode: appState.offlineMode) && appState.isInSearchMode) Positioned( top: 0, left: 0, diff --git a/lib/widgets/map/map_overlays.dart b/lib/widgets/map/map_overlays.dart index f22d8e1..5f7ab96 100644 --- a/lib/widgets/map/map_overlays.dart +++ b/lib/widgets/map/map_overlays.dart @@ -148,18 +148,52 @@ class MapOverlays extends StatelessWidget { builder: (context, appState, child) { return Column( children: [ - // Navigation button - simplified logic (only show in dev mode) - if (kEnableNavigationFeatures && onSearchPressed != null && (appState.showSearchButton || appState.showRouteButton)) ...[ - FloatingActionButton( - mini: true, - heroTag: "search_nav", - onPressed: onSearchPressed, - tooltip: appState.showRouteButton - ? LocalizationService.instance.t('navigation.routeOverview') - : LocalizationService.instance.t('navigation.searchLocation'), - child: Icon(appState.showRouteButton ? Icons.route : Icons.search), - ), - const SizedBox(height: 8), + // Search/Navigation button - show based on new feature flags + if (onSearchPressed != null) ...[ + // Show search button if search is available OR if showing route button + if ((enableSearchFeatures(offlineMode: appState.offlineMode) && appState.showSearchButton) || + (enableNavigationFeatures(offlineMode: appState.offlineMode) && appState.showRouteButton)) ...[ + FloatingActionButton( + mini: true, + heroTag: "search_nav", + onPressed: () { + // If offline and trying to search, show snackbar + if (appState.showSearchButton && appState.offlineMode && !kEnableDevelopmentModes) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text('Search not available offline'), + duration: Duration(seconds: 2), + ), + ); + } else { + onSearchPressed?.call(); + } + }, + tooltip: appState.showRouteButton + ? LocalizationService.instance.t('navigation.routeOverview') + : LocalizationService.instance.t('navigation.searchLocation'), + child: Icon(appState.showRouteButton ? Icons.route : Icons.search), + ), + const SizedBox(height: 8), + ] + // Show disabled search button with snackbar in release builds when offline + else if (appState.showSearchButton && !kEnableDevelopmentModes) ...[ + FloatingActionButton( + mini: true, + heroTag: "search_nav", + onPressed: () { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text('Search not available offline'), + duration: Duration(seconds: 2), + ), + ); + }, + tooltip: LocalizationService.instance.t('navigation.searchLocation'), + child: Icon(Icons.search), + ), + const SizedBox(height: 8), + ], ], // Layer selector button diff --git a/lib/widgets/navigation_sheet.dart b/lib/widgets/navigation_sheet.dart index dd948cc..d47ee37 100644 --- a/lib/widgets/navigation_sheet.dart +++ b/lib/widgets/navigation_sheet.dart @@ -4,6 +4,7 @@ import 'package:provider/provider.dart'; import 'package:latlong2/latlong.dart'; import '../app_state.dart'; +import '../dev_config.dart'; import '../services/localization_service.dart'; class NavigationSheet extends StatelessWidget { @@ -100,29 +101,32 @@ class NavigationSheet extends StatelessWidget { address: provisionalAddress, ), const SizedBox(height: 16), - Row( - children: [ - Expanded( - child: ElevatedButton.icon( - icon: const Icon(Icons.directions), - label: Text(LocalizationService.instance.t('navigation.routeTo')), - onPressed: () { - appState.startRoutePlanning(thisLocationIsStart: false); - }, + // Only show routing buttons if navigation features are enabled + if (enableNavigationFeatures(offlineMode: appState.offlineMode)) ...[ + Row( + children: [ + Expanded( + child: ElevatedButton.icon( + icon: const Icon(Icons.directions), + label: Text(LocalizationService.instance.t('navigation.routeTo')), + onPressed: () { + appState.startRoutePlanning(thisLocationIsStart: false); + }, + ), ), - ), - const SizedBox(width: 12), - Expanded( - child: ElevatedButton.icon( - icon: const Icon(Icons.my_location), - label: Text(LocalizationService.instance.t('navigation.routeFrom')), - onPressed: () { - appState.startRoutePlanning(thisLocationIsStart: true); - }, + const SizedBox(width: 12), + Expanded( + child: ElevatedButton.icon( + icon: const Icon(Icons.my_location), + label: Text(LocalizationService.instance.t('navigation.routeFrom')), + onPressed: () { + appState.startRoutePlanning(thisLocationIsStart: true); + }, + ), ), - ), - ], - ), + ], + ), + ], ], // SETTING SECOND POINT: Show both points and select button