From f5aeba473bf6899dafe657779f868264b0cce991 Mon Sep 17 00:00:00 2001 From: stopflock Date: Mon, 6 Oct 2025 10:07:54 -0500 Subject: [PATCH] UX tweaks to attribution, download button, allow search in release builds --- lib/dev_config.dart | 9 ----- lib/screens/home_screen.dart | 65 ++++++++++++++++++++----------- lib/screens/settings_screen.dart | 2 +- lib/widgets/map/map_overlays.dart | 38 ++---------------- pubspec.yaml | 2 +- 5 files changed, 47 insertions(+), 69 deletions(-) diff --git a/lib/dev_config.dart b/lib/dev_config.dart index a8ca756..1cd92d3 100644 --- a/lib/dev_config.dart +++ b/lib/dev_config.dart @@ -43,15 +43,6 @@ 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) { diff --git a/lib/screens/home_screen.dart b/lib/screens/home_screen.dart index 19b7652..7a49cf2 100644 --- a/lib/screens/home_screen.dart +++ b/lib/screens/home_screen.dart @@ -345,16 +345,30 @@ class _HomeScreenState extends State with TickerProviderStateMixin { // Zoom out a bit to show the full route when viewing overview _zoomToShowFullRoute(appState); } else { - // Search button - enter search mode - debugPrint('[HomeScreen] Entering search mode'); - try { - final mapCenter = _mapController.mapController.camera.center; - debugPrint('[HomeScreen] Map center: $mapCenter'); - appState.enterSearchMode(mapCenter); - } catch (e) { - // Controller not ready, use fallback location - debugPrint('[HomeScreen] Map controller not ready: $e, using fallback'); - appState.enterSearchMode(LatLng(37.7749, -122.4194)); + // Search button + if (appState.offlineMode) { + // Show offline snackbar instead of entering search mode + debugPrint('[HomeScreen] Search disabled - offline mode'); + ScaffoldMessenger.of(context).clearSnackBars(); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text('Search not available while offline'), + duration: const Duration(seconds: 3), + behavior: SnackBarBehavior.floating, + ), + ); + } else { + // Enter search mode normally + debugPrint('[HomeScreen] Entering search mode'); + try { + final mapCenter = _mapController.mapController.camera.center; + debugPrint('[HomeScreen] Map center: $mapCenter'); + appState.enterSearchMode(mapCenter); + } catch (e) { + // Controller not ready, use fallback location + debugPrint('[HomeScreen] Map controller not ready: $e, using fallback'); + appState.enterSearchMode(LatLng(37.7749, -122.4194)); + } } } } @@ -522,15 +536,15 @@ class _HomeScreenState extends State with TickerProviderStateMixin { sheetHeight: activeSheetHeight, selectedNodeId: _selectedNodeId, onNodeTap: openNodeTagSheet, - onSearchPressed: (enableSearchFeatures(offlineMode: appState.offlineMode) || enableNavigationFeatures(offlineMode: appState.offlineMode)) ? _onNavigationButtonPressed : null, + onSearchPressed: _onNavigationButtonPressed, onUserGesture: () { if (appState.followMeMode != FollowMeMode.off) { appState.setFollowMeMode(FollowMeMode.off); } }, ), - // Search bar (slides in when in search mode) - available based on feature flags - if (enableSearchFeatures(offlineMode: appState.offlineMode) && appState.isInSearchMode) + // Search bar (slides in when in search mode) - only online since search doesn't work offline + if (!appState.offlineMode && appState.isInSearchMode) Positioned( top: 0, left: 0, @@ -568,6 +582,7 @@ class _HomeScreenState extends State with TickerProviderStateMixin { child: Row( children: [ Expanded( + flex: 7, // 70% for primary action child: AnimatedBuilder( animation: LocalizationService.instance, builder: (context, child) => ElevatedButton.icon( @@ -583,18 +598,22 @@ class _HomeScreenState extends State with TickerProviderStateMixin { ), SizedBox(width: 12), Expanded( + flex: 3, // 30% for secondary action child: AnimatedBuilder( animation: LocalizationService.instance, - builder: (context, child) => ElevatedButton.icon( - icon: Icon(Icons.download_for_offline), - label: Text(LocalizationService.instance.download), - onPressed: () => showDialog( - context: context, - builder: (ctx) => DownloadAreaDialog(controller: _mapController.mapController), - ), - style: ElevatedButton.styleFrom( - minimumSize: Size(0, 48), - textStyle: TextStyle(fontSize: 16), + builder: (context, child) => FittedBox( + fit: BoxFit.scaleDown, + child: ElevatedButton.icon( + icon: Icon(Icons.download_for_offline), + label: Text(LocalizationService.instance.download), + onPressed: () => showDialog( + context: context, + builder: (ctx) => DownloadAreaDialog(controller: _mapController.mapController), + ), + style: ElevatedButton.styleFrom( + minimumSize: Size(0, 48), + textStyle: TextStyle(fontSize: 16), + ), ), ), ), diff --git a/lib/screens/settings_screen.dart b/lib/screens/settings_screen.dart index 504f338..e2a0301 100644 --- a/lib/screens/settings_screen.dart +++ b/lib/screens/settings_screen.dart @@ -73,7 +73,7 @@ class SettingsScreen extends StatelessWidget { _buildNavigationTile( context, icon: Icons.language, - title: '🌎 ${locService.t('settings.language')}', + title: locService.t('settings.language'), subtitle: locService.t('settings.languageSubtitle'), onTap: () => Navigator.pushNamed(context, '/settings/language'), ), diff --git a/lib/widgets/map/map_overlays.dart b/lib/widgets/map/map_overlays.dart index 5f7ab96..db5dc64 100644 --- a/lib/widgets/map/map_overlays.dart +++ b/lib/widgets/map/map_overlays.dart @@ -148,51 +148,19 @@ class MapOverlays extends StatelessWidget { builder: (context, appState, child) { return Column( children: [ - // Search/Navigation button - show based on new feature flags + // Search/Navigation button - show search button always, show route button only in dev mode when online 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)) ...[ + if (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(); - } - }, + 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), - ] - // 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), ], ], diff --git a/pubspec.yaml b/pubspec.yaml index badc5c7..4f56e0f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: deflockapp description: Map public surveillance infrastructure with OpenStreetMap publish_to: "none" -version: 1.0.9 +version: 1.0.10 environment: sdk: ">=3.5.0 <4.0.0" # oauth2_client 4.x needs Dart 3.5+