Files
jamshalat-diary/lib/data/services/equran_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

109 lines
3.2 KiB
Dart

import 'dart:convert';
import 'package:http/http.dart' as http;
/// Service for EQuran.id v2 API.
/// Provides complete Quran data: Arabic, Indonesian translation,
/// tafsir, and audio from 6 qari.
class EQuranService {
static const String _baseUrl = 'https://equran.id/api/v2';
static final EQuranService instance = EQuranService._();
EQuranService._();
// In-memory cache
List<Map<String, dynamic>>? _surahListCache;
/// Get list of all 114 surahs.
Future<List<Map<String, dynamic>>> getAllSurahs() async {
if (_surahListCache != null) return _surahListCache!;
try {
final response = await http.get(Uri.parse('$_baseUrl/surat'));
if (response.statusCode == 200) {
final data = json.decode(response.body);
if (data['code'] == 200) {
_surahListCache =
List<Map<String, dynamic>>.from(data['data']);
return _surahListCache!;
}
}
} catch (e) {
// silent fallback
}
return [];
}
/// Get full surah with all ayat, audio, etc.
/// Returns the full surah data object.
Future<Map<String, dynamic>?> getSurah(int number) async {
try {
final response =
await http.get(Uri.parse('$_baseUrl/surat/$number'));
if (response.statusCode == 200) {
final data = json.decode(response.body);
if (data['code'] == 200) {
return Map<String, dynamic>.from(data['data']);
}
}
} catch (e) {
// silent fallback
}
return null;
}
/// Get tafsir for a surah.
Future<Map<String, dynamic>?> getTafsir(int number) async {
try {
final response =
await http.get(Uri.parse('$_baseUrl/tafsir/$number'));
if (response.statusCode == 200) {
final data = json.decode(response.body);
if (data['code'] == 200) {
return Map<String, dynamic>.from(data['data']);
}
}
} catch (e) {
// silent fallback
}
return null;
}
/// Get deterministic daily ayat from API
Future<Map<String, dynamic>?> getDailyAyat() async {
try {
final now = DateTime.now();
final dayOfYear = int.parse(now.difference(DateTime(now.year, 1, 1)).inDays.toString());
// Pick surah 1-114
int surahId = (dayOfYear % 114) + 1;
final surahData = await getSurah(surahId);
if (surahData != null && surahData['ayat'] != null) {
int totalAyat = surahData['jumlahAyat'] ?? 1;
int ayatIndex = dayOfYear % totalAyat;
final targetAyat = surahData['ayat'][ayatIndex];
return {
'surahName': surahData['namaLatin'],
'nomorSurah': surahId,
'nomorAyat': targetAyat['nomorAyat'],
'teksArab': targetAyat['teksArab'],
'teksIndonesia': targetAyat['teksIndonesia'],
};
}
} catch (e) {
// silent fallback
}
return null;
}
/// Available qari names mapped to audio key index.
static const Map<String, String> qariNames = {
'01': 'Abdullah Al-Juhany',
'02': 'Abdul Muhsin Al-Qasim',
'03': 'Abdurrahman As-Sudais',
'04': 'Ibrahim Al-Dossari',
'05': 'Misyari Rasyid Al-Afasi',
'06': 'Yasser Al-Dosari',
};
}