Notrufnummern-Datenbasis, Ländererkennung, State-Management und Lokalisierung (AP1-AP7)
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>
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
import 'package:geocoding/geocoding.dart';
|
||||
import 'package:geolocator/geolocator.dart';
|
||||
|
||||
import 'country_code_source.dart';
|
||||
|
||||
/// Ermittelt den ISO-Ländercode per GPS-Position + Reverse-Geocoding
|
||||
/// (`docs/plan.md`, Abschnitt 6, Fallback-Quelle Nr. 2 – insbesondere auf
|
||||
/// iOS 16+ wichtig, da die SIM-Quelle dort eingeschränkt ist, siehe
|
||||
/// Abschnitt 9).
|
||||
///
|
||||
/// Nutzt bewusst nur die in `geolocator` eingebaute Berechtigungs-API
|
||||
/// (`checkPermission()` / `requestPermission()`) – ein zusätzlicher Einsatz
|
||||
/// von `permission_handler` wäre redundant (AP4-Vorgabe).
|
||||
///
|
||||
/// Liefert `null`, sobald irgendein Schritt scheitert: verweigerte/dauerhaft
|
||||
/// verweigerte Berechtigung, deaktivierte Standortdienste, kein GPS-Fix
|
||||
/// innerhalb des Zeitlimits, oder ein Netzwerkfehler beim Reverse-Geocoding
|
||||
/// (`placemarkFromCoordinates` braucht ggf. Netz). Wirft dabei nie eine
|
||||
/// Exception – das ist im Plan als Edge Case vorgesehen (Abschnitt 7): Die
|
||||
/// Kette fällt dann weiter auf den Cache zurück.
|
||||
class GpsCountryCodeSource implements CountryCodeSource {
|
||||
GpsCountryCodeSource({Geocoding? geocoding}) : _geocoding = geocoding ?? Geocoding();
|
||||
|
||||
final Geocoding _geocoding;
|
||||
|
||||
static const _timeout = Duration(seconds: 10);
|
||||
|
||||
@override
|
||||
Future<String?> resolve() async {
|
||||
try {
|
||||
if (!await _hasPermission()) return null;
|
||||
|
||||
final position = await Geolocator.getCurrentPosition(
|
||||
locationSettings: const LocationSettings(
|
||||
accuracy: LocationAccuracy.low,
|
||||
timeLimit: _timeout,
|
||||
),
|
||||
);
|
||||
|
||||
final placemarks = await _geocoding.placemarkFromCoordinates(
|
||||
position.latitude,
|
||||
position.longitude,
|
||||
);
|
||||
|
||||
for (final placemark in placemarks) {
|
||||
final code = placemark.isoCountryCode?.trim();
|
||||
if (code != null && code.isNotEmpty) {
|
||||
return code.toUpperCase();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
} catch (_) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> _hasPermission() async {
|
||||
var permission = await Geolocator.checkPermission();
|
||||
if (permission == LocationPermission.denied) {
|
||||
permission = await Geolocator.requestPermission();
|
||||
}
|
||||
return permission == LocationPermission.whileInUse || permission == LocationPermission.always;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user