Improve notifications, tilawah flow, and dzikir structure
This commit is contained in:
@@ -71,6 +71,13 @@ class _QuranReadingScreenState extends ConsumerState<QuranReadingScreen> {
|
||||
}
|
||||
}
|
||||
|
||||
void _navigateToSurah(int surahNumber, {int? startVerse}) {
|
||||
final base = widget.isSimpleModeTab ? '/quran' : '/tools/quran';
|
||||
final verseQuery =
|
||||
(startVerse != null && startVerse > 0) ? '?startVerse=$startVerse' : '';
|
||||
context.pushReplacement('$base/$surahNumber$verseQuery');
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
@@ -679,6 +686,7 @@ class _QuranReadingScreenState extends ConsumerState<QuranReadingScreen> {
|
||||
TilawahSession session, int endVerseId) async {
|
||||
final endSurahId = _surah!['nomor'] ?? 1;
|
||||
final endSurahName = _surah!['namaLatin'] ?? '';
|
||||
final isLastAyat = endVerseId == _verses.length;
|
||||
|
||||
int calculatedAyat = 0;
|
||||
|
||||
@@ -723,115 +731,155 @@ class _QuranReadingScreenState extends ConsumerState<QuranReadingScreen> {
|
||||
}
|
||||
|
||||
if (!mounted) return;
|
||||
bool saveAsLastRead = true;
|
||||
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (ctx) => AlertDialog(
|
||||
title: const Text('Catat Sesi Tilawah',
|
||||
style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.primary.withValues(alpha: 0.1),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
builder: (ctx) => StatefulBuilder(
|
||||
builder: (context, setModalState) => AlertDialog(
|
||||
title: const Text('Catat Sesi Tilawah',
|
||||
style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.primary.withValues(alpha: 0.1),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Column(children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Text('Mulai:', style: TextStyle(fontSize: 13)),
|
||||
Text(
|
||||
'${session.startSurahName} : ${session.startVerseId}',
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold, fontSize: 13)),
|
||||
]),
|
||||
const Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 4),
|
||||
child: Divider()),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Text('Selesai:',
|
||||
style: TextStyle(fontSize: 13)),
|
||||
Text('$endSurahName : $endVerseId',
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold, fontSize: 13)),
|
||||
]),
|
||||
])),
|
||||
const SizedBox(height: 16),
|
||||
Row(
|
||||
children: [
|
||||
const Icon(LucideIcons.bookOpen,
|
||||
size: 20, color: AppColors.primary),
|
||||
const SizedBox(width: 8),
|
||||
Text('Total Dibaca: $calculatedAyat Ayat',
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold, fontSize: 15)),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
CheckboxListTile(
|
||||
value: saveAsLastRead,
|
||||
onChanged: (value) {
|
||||
setModalState(() => saveAsLastRead = value ?? true);
|
||||
},
|
||||
contentPadding: EdgeInsets.zero,
|
||||
controlAffinity: ListTileControlAffinity.leading,
|
||||
title: const Text(
|
||||
'Simpan juga sebagai Terakhir Dibaca',
|
||||
style: TextStyle(fontSize: 13),
|
||||
),
|
||||
child: Column(children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Text('Mulai:', style: TextStyle(fontSize: 13)),
|
||||
Text(
|
||||
'${session.startSurahName} : ${session.startVerseId}',
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold, fontSize: 13)),
|
||||
]),
|
||||
const Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 4),
|
||||
child: Divider()),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Text('Selesai:', style: TextStyle(fontSize: 13)),
|
||||
Text('$endSurahName : $endVerseId',
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold, fontSize: 13)),
|
||||
]),
|
||||
])),
|
||||
const SizedBox(height: 16),
|
||||
Row(
|
||||
children: [
|
||||
const Icon(LucideIcons.bookOpen,
|
||||
size: 20, color: AppColors.primary),
|
||||
const SizedBox(width: 8),
|
||||
Text('Total Dibaca: $calculatedAyat Ayat',
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold, fontSize: 15)),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
ref.invalidate(tilawahTrackingProvider);
|
||||
Navigator.pop(ctx);
|
||||
},
|
||||
child: const Text('Batal', style: TextStyle(color: Colors.red)),
|
||||
),
|
||||
FilledButton(
|
||||
onPressed: () async {
|
||||
final settingsBox = Hive.box<AppSettings>(HiveBoxes.settings);
|
||||
final settings = settingsBox.get('default') ?? AppSettings();
|
||||
final todayKey =
|
||||
DateFormat('yyyy-MM-dd').format(DateTime.now());
|
||||
final logBox = Hive.box<DailyWorshipLog>(HiveBoxes.worshipLogs);
|
||||
var log = logBox.get(todayKey);
|
||||
|
||||
if (log == null) {
|
||||
log = DailyWorshipLog(
|
||||
date: todayKey,
|
||||
shalatLogs: <String, ShalatLog>{
|
||||
'subuh': ShalatLog(),
|
||||
'dzuhur': ShalatLog(),
|
||||
'ashar': ShalatLog(),
|
||||
'maghrib': ShalatLog(),
|
||||
'isya': ShalatLog(),
|
||||
},
|
||||
);
|
||||
logBox.put(todayKey, log);
|
||||
}
|
||||
|
||||
if (log.tilawahLog == null) {
|
||||
log.tilawahLog = TilawahLog(
|
||||
targetValue: settings.tilawahTargetValue,
|
||||
targetUnit: settings.tilawahTargetUnit,
|
||||
autoSync: _autoSyncEnabled,
|
||||
);
|
||||
}
|
||||
|
||||
log.tilawahLog!.rawAyatRead += calculatedAyat;
|
||||
log.save();
|
||||
|
||||
if (saveAsLastRead) {
|
||||
final verse = _verses.firstWhere(
|
||||
(v) => (v['nomorAyat'] ?? 0) == endVerseId,
|
||||
orElse: () => <String, dynamic>{},
|
||||
);
|
||||
if (verse.isNotEmpty) {
|
||||
await _saveBookmark(
|
||||
endSurahId,
|
||||
endVerseId,
|
||||
verse,
|
||||
isLastRead: true,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('$calculatedAyat Ayat dicatat!'),
|
||||
backgroundColor: AppColors.primary,
|
||||
duration: const Duration(seconds: 2),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
ref.invalidate(tilawahTrackingProvider);
|
||||
Navigator.pop(ctx);
|
||||
|
||||
final isLastSurah = endSurahId >= 114;
|
||||
if (settings.tilawahAutoContinueNextSurah &&
|
||||
isLastAyat &&
|
||||
!isLastSurah) {
|
||||
_navigateToSurah(endSurahId + 1, startVerse: 1);
|
||||
}
|
||||
},
|
||||
child: const Text('Simpan'),
|
||||
),
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
ref.invalidate(tilawahTrackingProvider);
|
||||
Navigator.pop(ctx);
|
||||
},
|
||||
child: const Text('Batal', style: TextStyle(color: Colors.red)),
|
||||
),
|
||||
FilledButton(
|
||||
onPressed: () {
|
||||
final todayKey = DateFormat('yyyy-MM-dd').format(DateTime.now());
|
||||
final logBox = Hive.box<DailyWorshipLog>(HiveBoxes.worshipLogs);
|
||||
var log = logBox.get(todayKey);
|
||||
|
||||
if (log == null) {
|
||||
log = DailyWorshipLog(
|
||||
date: todayKey,
|
||||
shalatLogs: <String, ShalatLog>{
|
||||
'subuh': ShalatLog(),
|
||||
'dzuhur': ShalatLog(),
|
||||
'ashar': ShalatLog(),
|
||||
'maghrib': ShalatLog(),
|
||||
'isya': ShalatLog(),
|
||||
},
|
||||
);
|
||||
logBox.put(todayKey, log);
|
||||
}
|
||||
|
||||
if (log.tilawahLog == null) {
|
||||
final settingsBox = Hive.box<AppSettings>(HiveBoxes.settings);
|
||||
final settings = settingsBox.get('default') ?? AppSettings();
|
||||
log.tilawahLog = TilawahLog(
|
||||
targetValue: settings.tilawahTargetValue,
|
||||
targetUnit: settings.tilawahTargetUnit,
|
||||
autoSync: _autoSyncEnabled,
|
||||
);
|
||||
}
|
||||
|
||||
log.tilawahLog!.rawAyatRead += calculatedAyat;
|
||||
log.save();
|
||||
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('$calculatedAyat Ayat dicatat!'),
|
||||
backgroundColor: AppColors.primary,
|
||||
duration: const Duration(seconds: 2),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
ref.invalidate(tilawahTrackingProvider);
|
||||
Navigator.pop(ctx);
|
||||
},
|
||||
child: const Text('Simpan'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -1156,6 +1204,42 @@ class _QuranReadingScreenState extends ConsumerState<QuranReadingScreen> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildTrackingSessionBanner({
|
||||
required bool isDark,
|
||||
required TilawahSession session,
|
||||
}) {
|
||||
final currentSurah = _surah?['namaLatin']?.toString() ?? widget.surahId;
|
||||
return Container(
|
||||
margin: const EdgeInsets.fromLTRB(16, 12, 16, 4),
|
||||
padding: const EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.primary.withValues(alpha: isDark ? 0.16 : 0.1),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
border: Border.all(
|
||||
color: AppColors.primary.withValues(alpha: 0.25),
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(LucideIcons.flag, size: 16, color: AppColors.primary),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Text(
|
||||
'Sesi aktif: ${session.startSurahName}:${session.startVerseId} -> $currentSurah',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: isDark
|
||||
? AppColors.textPrimaryDark
|
||||
: AppColors.textPrimaryLight,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final trackingSession = ref.watch(tilawahTrackingProvider);
|
||||
@@ -1271,6 +1355,11 @@ class _QuranReadingScreenState extends ConsumerState<QuranReadingScreen> {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
if (trackingSession != null)
|
||||
_buildTrackingSessionBanner(
|
||||
isDark: isDark,
|
||||
session: trackingSession,
|
||||
),
|
||||
if (showBismillah) ...[
|
||||
_buildBismillahSection(isDark: isDark),
|
||||
const SizedBox(height: 8),
|
||||
@@ -1292,6 +1381,25 @@ class _QuranReadingScreenState extends ConsumerState<QuranReadingScreen> {
|
||||
),
|
||||
),
|
||||
],
|
||||
if ((_surah?['nomor'] as int? ?? 1) < 114)
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(
|
||||
16, 18, 16, 0),
|
||||
child: FilledButton.icon(
|
||||
onPressed: () {
|
||||
final nextSurah =
|
||||
(_surah?['nomor'] as int? ?? 1) +
|
||||
1;
|
||||
_navigateToSurah(nextSurah,
|
||||
startVerse: 1);
|
||||
},
|
||||
icon:
|
||||
const Icon(LucideIcons.arrowRight),
|
||||
label: Text(trackingSession == null
|
||||
? 'Lanjut ke Surah Berikutnya'
|
||||
: 'Lanjut Surah (Sesi Tetap Aktif)'),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user