Use MyQuran Hijri calendar API for displayed date

This commit is contained in:
dwindown
2026-03-30 21:42:42 +07:00
parent ad33b01231
commit 33810bb4bd
5 changed files with 113 additions and 5 deletions

View File

@@ -0,0 +1,68 @@
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:intl/intl.dart';
import '../../core/hijri_date.dart';
class HijriCalendarService {
HijriCalendarService._({http.Client? client})
: _client = client ?? http.Client();
static final HijriCalendarService instance = HijriCalendarService._();
static const String _baseUrl = 'https://api.myquran.com/v3/cal/hijr';
final http.Client _client;
final Map<String, String> _cache = {};
Future<String> getHijriLabel(DateTime date) async {
final dateOnly = DateTime(date.year, date.month, date.day);
final dateKey = DateFormat('yyyy-MM-dd').format(dateOnly);
final cached = _cache[dateKey];
if (cached != null) return cached;
try {
final response = await _client.get(Uri.parse('$_baseUrl/$dateKey'));
if (response.statusCode == 200) {
final payload = json.decode(response.body) as Map<String, dynamic>;
final label = parseHijriLabel(payload);
if (label != null) {
_cache[dateKey] = label;
return label;
}
}
} catch (_) {
// Keep UI usable when the device is offline.
}
final fallback = HijriDateFormatter.format(dateOnly);
_cache[dateKey] = fallback;
return fallback;
}
static String? parseHijriLabel(Map<String, dynamic> payload) {
if (payload['status'] != true) return null;
final data = payload['data'];
if (data is! Map) return null;
final hijr = data['hijr'];
if (hijr is! Map) return null;
final today = hijr['today']?.toString().trim();
if (today != null && today.isNotEmpty) {
final parts = today.split(',');
return parts.length > 1 ? parts.last.trim() : today;
}
final day = hijr['day'];
final monthName = hijr['monthName']?.toString().trim();
final year = hijr['year'];
if (day != null && monthName != null && monthName.isNotEmpty && year != null) {
return '$day $monthName $year H';
}
return null;
}
}

View File

@@ -31,7 +31,8 @@ class JumatScreen extends ConsumerWidget {
final timeStr = DateFormat('HH:mm').format(clock);
final secStr = DateFormat(':ss').format(clock);
final dateGregorian = DateFormat('EEEE, d MMMM yyyy', 'en').format(clock);
final dateHijri = HijriDateFormatter.format(clock);
final dateHijri =
ref.watch(hijriDateProvider).valueOrNull ?? HijriDateFormatter.format(clock);
final durToKhutbah = screenData.timeUntilNext ?? const Duration(minutes: 0);
final minToKhutbah = durToKhutbah.inMinutes;

View File

@@ -39,6 +39,8 @@ class MainScreen extends ConsumerWidget {
final timeStr = DateFormat('HH:mm').format(clock);
final secStr = DateFormat(':ss').format(clock);
final dateGregorian = DateFormat('EEEE, d MMMM yyyy', 'id').format(clock);
final dateHijri =
ref.watch(hijriDateProvider).valueOrNull ?? HijriDateFormatter.format(clock);
return Container(
color: SacredColors.background,
@@ -98,7 +100,7 @@ class MainScreen extends ConsumerWidget {
child: Column(
children: [
// ── HEADER ──
_buildHeader(context, s, fs, settings, dateGregorian),
_buildHeader(context, s, fs, settings, dateGregorian, dateHijri),
// ── CENTER: Clock + Countdown ──
Expanded(
@@ -211,9 +213,14 @@ class MainScreen extends ConsumerWidget {
);
}
Widget _buildHeader(BuildContext context, double s, double fs, AppSettings settings, String dateGregorian) {
final dateHijri = HijriDateFormatter.format(DateTime.now());
Widget _buildHeader(
BuildContext context,
double s,
double fs,
AppSettings settings,
String dateGregorian,
String dateHijri,
) {
return Padding(
padding: EdgeInsets.only(top: 24 * s, bottom: 8 * s),
child: Row(

View File

@@ -3,7 +3,9 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'core/enums.dart';
import 'core/hijri_date.dart';
import 'data/local/models.dart';
import 'data/services/hijri_service.dart';
import 'data/services/sync_service.dart';
// ──────────────────────────────────────────────
@@ -75,6 +77,17 @@ final todayScheduleProvider = Provider<DailyPrayerSchedule?>((ref) {
return SyncService.instance.getTodaySchedule(clock);
});
final hijriDateProvider = FutureProvider<String>((ref) async {
final clock = ref.watch(clockProvider).valueOrNull ?? DateTime.now();
final dateOnly = DateTime(clock.year, clock.month, clock.day);
try {
return await HijriCalendarService.instance.getHijriLabel(dateOnly);
} catch (_) {
return HijriDateFormatter.format(dateOnly);
}
});
// ──────────────────────────────────────────────
// SCREEN STATE MACHINE PROVIDER
// ──────────────────────────────────────────────