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>
65 lines
2.2 KiB
Dart
65 lines
2.2 KiB
Dart
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;
|
||
}
|
||
}
|