Navigation start+end too close warning

This commit is contained in:
stopflock
2025-12-02 15:02:49 -06:00
parent 0d13fdee37
commit 31f6960d44
10 changed files with 52 additions and 3 deletions

View File

@@ -107,7 +107,6 @@ cp lib/keys.dart.example lib/keys.dart
- Manual cleanup (cognitive load for users)
- Delete the old one (also wrong answer unless user chooses intentionally)
- Give multiple of these options??
- Nav start+end too close together error (warning + disable submit button?)
- Persistent cache for MY submissions: assume submissions worked, cache,clean up when we see that node appear in overpass/OSM results or when older than 24h
- Dropdown on "refine tags" page to select acceptable options for camera:mount= (is this a boolean property of a profile?)
- Option to pull in profiles from NSI (man_made=surveillance only?)

View File

@@ -2,7 +2,9 @@
"1.5.4": {
"content": [
"• FIXED: Download area max zoom level is now limited to the currently selected tile provider's maximum zoom level (e.g., OpenTopoMap limited to Z18, Bing Maps to Z20)",
"• IMPROVED: Download area dialog properly respects tile provider capabilities and prevents downloading tiles beyond what the provider supports"
"• IMPROVED: Download area dialog properly respects tile provider capabilities and prevents downloading tiles beyond what the provider supports",
"• NEW: Navigation route planning now prevents selecting start and end locations that are too close together (configurable minimum distance)",
"• IMPROVED: 'Select Location' button is disabled and shows warning message when route points are closer than 100 meters apart"
]
},
"1.5.3": {

View File

@@ -112,6 +112,7 @@ class AppState extends ChangeNotifier {
double? get routeDistance => _navigationState.routeDistance;
bool get settingRouteStart => _navigationState.settingRouteStart;
bool get isSettingSecondPoint => _navigationState.isSettingSecondPoint;
bool get areRoutePointsTooClose => _navigationState.areRoutePointsTooClose;
bool get isCalculating => _navigationState.isCalculating;
bool get showingOverview => _navigationState.showingOverview;
String? get routingError => _navigationState.routingError;

View File

@@ -124,6 +124,9 @@ const Duration kProximityAlertCooldown = Duration(minutes: 10); // Cooldown betw
// Node proximity warning configuration (for new/edited nodes that are too close to existing ones)
const double kNodeProximityWarningDistance = 15.0; // meters - distance threshold to show warning
// Navigation route planning configuration
const double kNavigationMinRouteDistance = 100.0; // meters - minimum distance between start and end points
// Map interaction configuration
const double kNodeDoubleTapZoomDelta = 1.0; // How much to zoom in when double-tapping nodes (was 1.0)
const double kScrollWheelVelocity = 0.01; // Mouse scroll wheel zoom speed (default 0.005)

View File

@@ -460,6 +460,7 @@
"endSelect": "Ende (auswählen)",
"distance": "Entfernung: {} km",
"routeActive": "Route aktiv",
"locationsTooClose": "Start- und Endpositionen sind zu nah beieinander",
"navigationSettings": "Navigation",
"navigationSettingsSubtitle": "Routenplanung und Vermeidungseinstellungen",
"avoidanceDistance": "Vermeidungsabstand",

View File

@@ -460,6 +460,7 @@
"endSelect": "End (select)",
"distance": "Distance: {} km",
"routeActive": "Route active",
"locationsTooClose": "Start and end locations are too close together",
"navigationSettings": "Navigation",
"navigationSettingsSubtitle": "Route planning and avoidance settings",
"avoidanceDistance": "Avoidance Distance",

View File

@@ -460,6 +460,7 @@
"endSelect": "Fin (seleccionar)",
"distance": "Distancia: {} km",
"routeActive": "Ruta activa",
"locationsTooClose": "Las ubicaciones de inicio y fin están demasiado cerca",
"navigationSettings": "Navegación",
"navigationSettingsSubtitle": "Configuración de planificación de rutas y evitación",
"avoidanceDistance": "Distancia de evitación",

View File

@@ -460,6 +460,7 @@
"endSelect": "Fin (sélectionner)",
"distance": "Distance: {} km",
"routeActive": "Itinéraire actif",
"locationsTooClose": "Les emplacements de départ et d'arrivée sont trop proches",
"navigationSettings": "Navigation",
"navigationSettingsSubtitle": "Paramètres de planification d'itinéraire et d'évitement",
"avoidanceDistance": "Distance d'évitement",

View File

@@ -4,6 +4,7 @@ import 'package:latlong2/latlong.dart';
import '../models/search_result.dart';
import '../services/search_service.dart';
import '../services/routing_service.dart';
import '../dev_config.dart';
/// Simplified navigation modes - brutalist approach
enum AppNavigationMode {
@@ -75,6 +76,17 @@ class NavigationState extends ChangeNotifier {
bool get showSearchButton => _mode == AppNavigationMode.normal;
bool get showRouteButton => _mode == AppNavigationMode.routeActive;
/// Check if the start and end locations are too close together
bool get areRoutePointsTooClose {
if (!_isSettingSecondPoint || _provisionalPinLocation == null) return false;
final firstPoint = _nextPointIsStart ? _routeEnd : _routeStart;
if (firstPoint == null) return false;
final distance = const Distance().as(LengthUnit.Meter, firstPoint, _provisionalPinLocation!);
return distance < kNavigationMinRouteDistance;
}
/// BRUTALIST: Single entry point to search mode
void enterSearchMode(LatLng mapCenter) {
debugPrint('[NavigationState] enterSearchMode - current mode: $_mode');

View File

@@ -159,10 +159,38 @@ class NavigationSheet extends StatelessWidget {
),
const SizedBox(height: 16),
// Show warning message if locations are too close
if (appState.areRoutePointsTooClose) ...[
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.orange.withOpacity(0.1),
borderRadius: BorderRadius.circular(8),
border: Border.all(color: Colors.orange.withOpacity(0.3)),
),
child: Row(
children: [
Icon(Icons.warning, color: Colors.orange[700], size: 20),
const SizedBox(width: 8),
Expanded(
child: Text(
LocalizationService.instance.t('navigation.locationsTooClose'),
style: TextStyle(
fontSize: 14,
color: Colors.orange[700],
),
),
),
],
),
),
const SizedBox(height: 16),
],
ElevatedButton.icon(
icon: const Icon(Icons.check),
label: Text(LocalizationService.instance.t('navigation.selectLocation')),
onPressed: () {
onPressed: appState.areRoutePointsTooClose ? null : () {
debugPrint('[NavigationSheet] Select Location button pressed');
appState.selectSecondRoutePoint();
},