Implementiert den kompletten Kern-Flow der Emergency App gemäß docs/plan.md: - Notrufnummern-Datenbasis für 199 Länder + Modelle/Repository (AP1) - DialerService für tel:-Notrufe ohne Auto-Dial (AP2) - Statisches UI mit Panik-Button-Fallback (AP3) - Priorisierte Ländererkennung: SIM/Netz -> GPS/Geocoding -> Cache (AP4) - EmergencyProvider verdrahtet Repository/LocationService mit der UI (AP5) - Manuelle Länderauswahl als Fallback samt eigener Priorität (AP6) - UI-Lokalisierung (de/en/fr/es), an erkanntes Land gekoppelt (AP7) Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
71 lines
2.9 KiB
Dart
71 lines
2.9 KiB
Dart
import 'country_code_sources/cached_country_code_source.dart';
|
||
import 'country_code_sources/country_code_source.dart';
|
||
import 'country_code_sources/gps_country_code_source.dart';
|
||
import 'country_code_sources/manual_country_code_source.dart';
|
||
import 'country_code_sources/sim_country_code_source.dart';
|
||
|
||
/// Orchestriert die priorisierte Ermittlungskette für den aktuellen
|
||
/// Ländercode (`docs/plan.md`, Abschnitt 6 + 8, AP4 + AP6):
|
||
///
|
||
/// 0. manuelle Auswahl des Nutzers (`shared_preferences`, übersteuert alles)
|
||
/// 1. SIM/Netz-Ländercode (offline, primär)
|
||
/// 2. GPS + Reverse-Geocoding (Fallback, ggf. Netz nötig)
|
||
/// 3. zuletzt gespeicherter Code (`shared_preferences`)
|
||
///
|
||
/// Die erste Quelle, die einen nicht-`null`-Wert liefert, gewinnt; die
|
||
/// übrigen Quellen werden dann nicht mehr angefragt. Nach einem Treffer über
|
||
/// SIM oder GPS wird der Cache best-effort aktualisiert (Fehler dabei
|
||
/// beeinflussen die Rückgabe nicht), damit ein späterer Aufruf ohne
|
||
/// Netz/GPS/SIM trotzdem einen aktuellen Wert liefern kann. Die manuelle
|
||
/// Auswahl (Stufe 0) wird bewusst **nicht** in diesen automatischen Cache
|
||
/// (Stufe 3) geschrieben – beides sind getrennte Mechanismen mit eigenem
|
||
/// `shared_preferences`-Key, siehe `ManualCountryCodeSource` und
|
||
/// `CachedCountryCodeSource`.
|
||
///
|
||
/// `null` wird nur zurückgegeben, wenn wirklich alle Quellen fehlschlagen –
|
||
/// die UI (AP5+) muss diesen Fall (`status = countryUnknown`) explizit
|
||
/// behandeln.
|
||
class LocationService {
|
||
LocationService({
|
||
CountryCodeSource? simSource,
|
||
CountryCodeSource? gpsSource,
|
||
CountryCodeCache? cacheSource,
|
||
ManualCountryCodeStore? manualSource,
|
||
}) : _simSource = simSource ?? const SimCountryCodeSource(),
|
||
_gpsSource = gpsSource ?? GpsCountryCodeSource(),
|
||
_cacheSource = cacheSource ?? const CachedCountryCodeSource(),
|
||
_manualSource = manualSource ?? const ManualCountryCodeSource();
|
||
|
||
final CountryCodeSource _simSource;
|
||
final CountryCodeSource _gpsSource;
|
||
final CountryCodeCache _cacheSource;
|
||
final ManualCountryCodeStore _manualSource;
|
||
|
||
Future<String?> resolveCountryCode() async {
|
||
final manualResult = await _manualSource.resolve();
|
||
if (manualResult != null) {
|
||
return manualResult;
|
||
}
|
||
|
||
final simResult = await _simSource.resolve();
|
||
if (simResult != null) {
|
||
await _cacheSource.save(simResult);
|
||
return simResult;
|
||
}
|
||
|
||
final gpsResult = await _gpsSource.resolve();
|
||
if (gpsResult != null) {
|
||
await _cacheSource.save(gpsResult);
|
||
return gpsResult;
|
||
}
|
||
|
||
return _cacheSource.resolve();
|
||
}
|
||
|
||
/// Setzt oder löscht die manuelle Länderauswahl (`docs/plan.md`,
|
||
/// Abschnitt 8, AP6). `isoCode == null` löscht eine zuvor gesetzte Auswahl
|
||
/// wieder, sodass der nächste [resolveCountryCode]-Aufruf wieder auf die
|
||
/// automatische Kette (SIM → GPS → Cache) zurückfällt.
|
||
Future<void> setManualCountryCode(String? isoCode) => _manualSource.save(isoCode);
|
||
}
|