UX tweaks to attribution, download button, allow search in release builds

This commit is contained in:
stopflock
2025-10-06 10:07:54 -05:00
parent f285a18563
commit f5aeba473b
5 changed files with 47 additions and 69 deletions

View File

@@ -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) {

View File

@@ -345,16 +345,30 @@ class _HomeScreenState extends State<HomeScreen> 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<HomeScreen> 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<HomeScreen> 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<HomeScreen> 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),
),
),
),
),

View File

@@ -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'),
),

View File

@@ -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),
],
],

View File

@@ -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+