Files
jamshalat-diary/lib/data/services/location_service.dart
dwindown faadc1865d feat: Murattal player enhancements & prayer schedule auto-scroll
- Murattal: Spotify-style 5-button controls [Shuffle, Prev, Play, Next, Playlist]
- Murattal: Animated 7-bar equalizer visualization in player circle
- Murattal: Unsplash API background with frosted glass player overlay
- Murattal: Transparent AppBar with backdrop blur
- Murattal: Surah playlist bottom sheet with full 114 Surah list
- Murattal: Auto-play disabled on screen open, enabled on navigation
- Murattal: Shuffle mode for random Surah playback
- Murattal: Photographer attribution per Unsplash guidelines
- Dashboard: Auto-scroll prayer schedule to next active prayer
- Fix: setState lifecycle errors on Reading & Murattal screens
- Setup: flutter_dotenv, cached_network_image, url_launcher deps
2026-03-13 15:42:17 +07:00

87 lines
2.8 KiB
Dart

import 'package:geolocator/geolocator.dart';
import 'package:geocoding/geocoding.dart' as geocoding;
import 'package:hive_flutter/hive_flutter.dart';
import '../local/hive_boxes.dart';
import '../local/models/app_settings.dart';
/// Location service with GPS + fallback to last known location.
class LocationService {
LocationService._();
static final LocationService instance = LocationService._();
/// Request permission and get current GPS location.
Future<Position?> getCurrentLocation() async {
bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
if (!serviceEnabled) return null;
LocationPermission permission = await Geolocator.checkPermission();
if (permission == LocationPermission.denied) {
permission = await Geolocator.requestPermission();
if (permission == LocationPermission.denied) return null;
}
if (permission == LocationPermission.deniedForever) return null;
try {
final position = await Geolocator.getCurrentPosition(
locationSettings: const LocationSettings(
accuracy: LocationAccuracy.medium,
timeLimit: Duration(seconds: 10),
),
);
// Save to settings for fallback
await _saveLastKnown(position.latitude, position.longitude);
return position;
} catch (_) {
return null;
}
}
/// Get last known location from Hive settings.
({double lat, double lng, String? cityName})? getLastKnownLocation() {
final settingsBox = Hive.box<AppSettings>(HiveBoxes.settings);
final settings = settingsBox.get('default');
if (settings?.lastLat != null && settings?.lastLng != null) {
return (
lat: settings!.lastLat!,
lng: settings.lastLng!,
cityName: settings.lastCityName,
);
}
return null;
}
/// Reverse geocode to get city name from coordinates.
Future<String> getCityName(double lat, double lng) async {
try {
final placemarks = await geocoding.placemarkFromCoordinates(lat, lng);
if (placemarks.isNotEmpty) {
final place = placemarks.first;
final city = place.locality ?? place.subAdministrativeArea ?? 'Unknown';
final country = place.country ?? '';
return '$city, $country';
}
} catch (_) {
// Geocoding may fail offline — return coords
}
return '${lat.toStringAsFixed(2)}, ${lng.toStringAsFixed(2)}';
}
/// Save last known position to Hive.
Future<void> _saveLastKnown(double lat, double lng) async {
final settingsBox = Hive.box<AppSettings>(HiveBoxes.settings);
final settings = settingsBox.get('default');
if (settings != null) {
settings.lastLat = lat;
settings.lastLng = lng;
try {
settings.lastCityName = await getCityName(lat, lng);
} catch (_) {
// Ignore geocoding errors
}
await settings.save();
}
}
}