- 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
127 lines
3.4 KiB
Dart
127 lines
3.4 KiB
Dart
import 'package:adhan/adhan.dart' as adhan;
|
|
import 'package:hive_flutter/hive_flutter.dart';
|
|
import '../local/hive_boxes.dart';
|
|
import '../local/models/cached_prayer_times.dart';
|
|
import 'package:intl/intl.dart';
|
|
|
|
/// Result object for prayer times.
|
|
class PrayerTimesResult {
|
|
final DateTime fajr;
|
|
final DateTime sunrise;
|
|
final DateTime dhuhr;
|
|
final DateTime asr;
|
|
final DateTime maghrib;
|
|
final DateTime isha;
|
|
|
|
PrayerTimesResult({
|
|
required this.fajr,
|
|
required this.sunrise,
|
|
required this.dhuhr,
|
|
required this.asr,
|
|
required this.maghrib,
|
|
required this.isha,
|
|
});
|
|
}
|
|
|
|
/// Prayer time calculation service using the adhan package.
|
|
class PrayerService {
|
|
PrayerService._();
|
|
static final PrayerService instance = PrayerService._();
|
|
|
|
/// Calculate prayer times for a given location and date.
|
|
/// Uses cache if available; writes to cache after calculation.
|
|
PrayerTimesResult getPrayerTimes(double lat, double lng, DateTime date) {
|
|
final dateKey = DateFormat('yyyy-MM-dd').format(date);
|
|
final cacheKey = '${lat.toStringAsFixed(4)}_${lng.toStringAsFixed(4)}_$dateKey';
|
|
|
|
// Check cache
|
|
final cacheBox = Hive.box<CachedPrayerTimes>(HiveBoxes.cachedPrayerTimes);
|
|
final cached = cacheBox.get(cacheKey);
|
|
if (cached != null) {
|
|
return PrayerTimesResult(
|
|
fajr: cached.fajr,
|
|
sunrise: cached.sunrise,
|
|
dhuhr: cached.dhuhr,
|
|
asr: cached.asr,
|
|
maghrib: cached.maghrib,
|
|
isha: cached.isha,
|
|
);
|
|
}
|
|
|
|
// Calculate using adhan package
|
|
final coordinates = adhan.Coordinates(lat, lng);
|
|
final dateComponents = adhan.DateComponents(date.year, date.month, date.day);
|
|
final params = adhan.CalculationMethod.muslim_world_league.getParameters();
|
|
params.madhab = adhan.Madhab.shafi;
|
|
|
|
final prayerTimes = adhan.PrayerTimes(coordinates, dateComponents, params);
|
|
|
|
final result = PrayerTimesResult(
|
|
fajr: prayerTimes.fajr!,
|
|
sunrise: prayerTimes.sunrise!,
|
|
dhuhr: prayerTimes.dhuhr!,
|
|
asr: prayerTimes.asr!,
|
|
maghrib: prayerTimes.maghrib!,
|
|
isha: prayerTimes.isha!,
|
|
);
|
|
|
|
// Cache result
|
|
cacheBox.put(
|
|
cacheKey,
|
|
CachedPrayerTimes(
|
|
key: cacheKey,
|
|
lat: lat,
|
|
lng: lng,
|
|
date: dateKey,
|
|
fajr: result.fajr,
|
|
sunrise: result.sunrise,
|
|
dhuhr: result.dhuhr,
|
|
asr: result.asr,
|
|
maghrib: result.maghrib,
|
|
isha: result.isha,
|
|
),
|
|
);
|
|
|
|
return result;
|
|
}
|
|
|
|
/// Get the next prayer name and time from now.
|
|
MapEntry<String, DateTime>? getNextPrayer(PrayerTimesResult times) {
|
|
final now = DateTime.now();
|
|
final entries = {
|
|
'Fajr': times.fajr,
|
|
'Dhuhr': times.dhuhr,
|
|
'Asr': times.asr,
|
|
'Maghrib': times.maghrib,
|
|
'Isha': times.isha,
|
|
};
|
|
|
|
for (final entry in entries.entries) {
|
|
if (entry.value.isAfter(now)) {
|
|
return entry;
|
|
}
|
|
}
|
|
return null; // All prayers passed for today
|
|
}
|
|
|
|
/// Get the current active prayer (the last prayer whose time has passed).
|
|
String? getCurrentPrayer(PrayerTimesResult times) {
|
|
final now = DateTime.now();
|
|
String? current;
|
|
|
|
if (now.isAfter(times.isha)) {
|
|
current = 'Isha';
|
|
} else if (now.isAfter(times.maghrib)) {
|
|
current = 'Maghrib';
|
|
} else if (now.isAfter(times.asr)) {
|
|
current = 'Asr';
|
|
} else if (now.isAfter(times.dhuhr)) {
|
|
current = 'Dhuhr';
|
|
} else if (now.isAfter(times.fajr)) {
|
|
current = 'Fajr';
|
|
}
|
|
|
|
return current;
|
|
}
|
|
}
|