Location search starts a new mission; shrink and center header bar
Ortssuche verschob bisher nur die Karte - der HTML-Demonstrator beginnt bei einer Suche immer eine neue, nach dem gefundenen Ort benannte Mission (setMissionFromPlace(), aufgerufen aus doSearch()). Vorherige Aenderungen gehen dabei nicht verloren, da flushPendingAutosave() (hier: CurrentMissionMetaNotifier._flushNow()) zuerst noch ausstehende Autosaves schreibt. Die Nominatim-Suche wurde dafuer aus MapSearchControls in einen eigenstaendigen NominatimService extrahiert (analog WindService): injectable http.Client, damit sich die Suche in Tests ohne echten Netzwerkzugriff ueberschreiben laesst. CurrentMissionMetaNotifier bekam dafuer startNewFromPlace() (startNew() intern darauf umgebaut, um Duplikation zu vermeiden). Kopfleiste von 86%/64% (Plan-/Fly-Modus) auf einheitlich 70% Bildschirmbreite verkleinert - zentriert war sie durch Align(topCenter) + FractionallySizedBox bereits strukturell korrekt, wirkte bei der vollen Breite aber unausgewogen. Verifiziert: flutter analyze (0 issues), flutter test (64/64, davon 4 neue NominatimService-Tests und 1 neuer Widget-Test fuer den Missions-Reset bei Ortssuche), manuell auf Pixel_10a-Emulator - Suche nach "Rotterdam" setzt Fusszeile auf "Mission: Rotterdam" mit 0 Wegpunkten trotz zuvor bestehender Mission mit Wegpunkten. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
aaec7f0f72
commit
926d805156
@@ -0,0 +1,68 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
/// Ergebnis einer Ortssuche: Koordinaten plus ein kompakter Anzeigename,
|
||||
/// der auch als Missionsname dient (siehe MapSearchControls).
|
||||
class GeocodingResult {
|
||||
const GeocodingResult({
|
||||
required this.label,
|
||||
required this.lat,
|
||||
required this.lon,
|
||||
});
|
||||
|
||||
final String label;
|
||||
final double lat;
|
||||
final double lon;
|
||||
}
|
||||
|
||||
/// Geocoding ueber Nominatim (OpenStreetMap) - analog doSearch() im HTML-
|
||||
/// Demonstrator. Injectable http.Client analog WindService, damit dies in
|
||||
/// Tests ohne echten Netzwerkzugriff ueberschrieben werden kann.
|
||||
class NominatimService {
|
||||
NominatimService({http.Client? client}) : _client = client ?? http.Client();
|
||||
|
||||
final http.Client _client;
|
||||
|
||||
Future<GeocodingResult?> search(String query) async {
|
||||
final uri = Uri.https('nominatim.openstreetmap.org', '/search', {
|
||||
'format': 'json',
|
||||
'addressdetails': '1',
|
||||
'accept-language': 'en',
|
||||
'limit': '1',
|
||||
'q': query,
|
||||
});
|
||||
final response = await _client
|
||||
.get(uri, headers: {'User-Agent': 'dmc_app (Drone Mission Control)'});
|
||||
if (response.statusCode != 200) return null;
|
||||
|
||||
final results = jsonDecode(response.body) as List;
|
||||
if (results.isEmpty) return null;
|
||||
|
||||
final first = results.first as Map<String, dynamic>;
|
||||
return GeocodingResult(
|
||||
label: _extractPlaceLabel(first),
|
||||
lat: double.parse(first['lat'] as String),
|
||||
lon: double.parse(first['lon'] as String),
|
||||
);
|
||||
}
|
||||
|
||||
/// Analog extractPlaceLabel() im HTML-Demonstrator: bevorzugt einen
|
||||
/// kompakten Ortsnamen aus den Nominatim-Adressbestandteilen, faellt sonst
|
||||
/// auf den ersten Abschnitt von display_name zurueck.
|
||||
String _extractPlaceLabel(Map<String, dynamic> result) {
|
||||
final address = result['address'] as Map<String, dynamic>?;
|
||||
final label = address?['city'] ??
|
||||
address?['town'] ??
|
||||
address?['village'] ??
|
||||
address?['municipality'] ??
|
||||
address?['suburb'] ??
|
||||
address?['county'];
|
||||
if (label is String && label.isNotEmpty) return label;
|
||||
final displayName = result['display_name'] as String?;
|
||||
if (displayName != null && displayName.isNotEmpty) {
|
||||
return displayName.split(',').first;
|
||||
}
|
||||
return 'Unknown location';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user