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 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 _hasPermission() async { var permission = await Geolocator.checkPermission(); if (permission == LocationPermission.denied) { permission = await Geolocator.requestPermission(); } return permission == LocationPermission.whileInUse || permission == LocationPermission.always; } }