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
@@ -1,13 +1,13 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_map/flutter_map.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:latlong2/latlong.dart';
|
||||
|
||||
import '../providers/current_mission_provider.dart';
|
||||
import '../providers/geocoding_provider.dart';
|
||||
import '../providers/map_controller_provider.dart';
|
||||
import '../providers/mission_meta_provider.dart';
|
||||
import '../providers/wind_provider.dart';
|
||||
|
||||
/// Ortssuche (Nominatim) + Home-/Fit-Buttons, eingebettet als Mittelteil
|
||||
/// der Plan/Fly-Kopfleiste (HTML-Demonstrator: #searchWrap/#homeBtn/
|
||||
@@ -40,24 +40,21 @@ class _MapSearchControlsState extends ConsumerState<MapSearchControls> {
|
||||
|
||||
final messenger = ScaffoldMessenger.of(context);
|
||||
try {
|
||||
final uri = Uri.https('nominatim.openstreetmap.org', '/search', {
|
||||
'format': 'json',
|
||||
'addressdetails': '1',
|
||||
'accept-language': 'en',
|
||||
'limit': '1',
|
||||
'q': query,
|
||||
});
|
||||
final response = await http
|
||||
.get(uri, headers: {'User-Agent': 'dmc_app (Drone Mission Control)'});
|
||||
final results = jsonDecode(response.body) as List;
|
||||
if (results.isEmpty) {
|
||||
final result = await ref.read(nominatimServiceProvider).search(query);
|
||||
if (result == null) {
|
||||
messenger.showSnackBar(const SnackBar(content: Text('Location not found')));
|
||||
return;
|
||||
}
|
||||
final first = results.first as Map<String, dynamic>;
|
||||
final lat = double.parse(first['lat'] as String);
|
||||
final lon = double.parse(first['lon'] as String);
|
||||
ref.read(mapControllerProvider).move(LatLng(lat, lon), 15);
|
||||
ref.read(mapControllerProvider).move(LatLng(result.lat, result.lon), 15);
|
||||
|
||||
// Eine Ortssuche beginnt immer eine neue, nach dem Ort benannte
|
||||
// Mission statt nur die Karte zu verschieben (HTML-Demonstrator:
|
||||
// setMissionFromPlace(), aufgerufen aus doSearch()) - vorherige
|
||||
// Aenderungen werden dabei zuerst autosaved, gehen also nicht verloren.
|
||||
await ref
|
||||
.read(currentMissionMetaProvider.notifier)
|
||||
.startNewFromPlace(result.label);
|
||||
await ref.read(headerWindProvider.notifier).refresh();
|
||||
} catch (_) {
|
||||
messenger.showSnackBar(const SnackBar(content: Text('Search failed')));
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ class TopModeBar extends StatelessWidget {
|
||||
return SafeArea(
|
||||
bottom: false,
|
||||
child: FractionallySizedBox(
|
||||
widthFactor: isFly ? 0.64 : 0.86,
|
||||
widthFactor: 0.70,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
|
||||
decoration: BoxDecoration(
|
||||
|
||||
Reference in New Issue
Block a user