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
This commit is contained in:
dwindown
2026-03-13 15:42:17 +07:00
commit faadc1865d
189 changed files with 23834 additions and 0 deletions

View File

View File

@@ -0,0 +1 @@
// TODO: implement

View File

@@ -0,0 +1,119 @@
import 'package:flutter/foundation.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'models/app_settings.dart';
import 'models/checklist_item.dart';
import 'models/daily_worship_log.dart';
import 'models/dzikir_counter.dart';
import 'models/quran_bookmark.dart';
import 'models/cached_prayer_times.dart';
import 'models/shalat_log.dart';
import 'models/tilawah_log.dart';
import 'models/dzikir_log.dart';
import 'models/puasa_log.dart';
/// Box name constants for Hive.
class HiveBoxes {
HiveBoxes._();
static const String settings = 'settings';
static const String checklistItems = 'checklist_items';
static const String worshipLogs = 'worship_logs';
static const String dzikirCounters = 'dzikir_counters';
static const String bookmarks = 'bookmarks';
static const String cachedPrayerTimes = 'cached_prayer_times';
}
/// Initialize Hive and open all boxes.
Future<void> initHive() async {
await Hive.initFlutter();
// Register adapters
Hive.registerAdapter(AppSettingsAdapter());
Hive.registerAdapter(ChecklistItemAdapter());
Hive.registerAdapter(DailyWorshipLogAdapter());
Hive.registerAdapter(DzikirCounterAdapter());
Hive.registerAdapter(QuranBookmarkAdapter());
Hive.registerAdapter(CachedPrayerTimesAdapter());
Hive.registerAdapter(ShalatLogAdapter());
Hive.registerAdapter(TilawahLogAdapter());
Hive.registerAdapter(DzikirLogAdapter());
Hive.registerAdapter(PuasaLogAdapter());
// Open boxes
try {
await Hive.openBox<AppSettings>(HiveBoxes.settings);
} catch (e) {
debugPrint('Settings box corrupted, resetting: $e');
if (Hive.isBoxOpen(HiveBoxes.settings)) {
await Hive.box<AppSettings>(HiveBoxes.settings).close();
}
await Hive.deleteBoxFromDisk(HiveBoxes.settings);
await Hive.openBox<AppSettings>(HiveBoxes.settings);
}
await Hive.openBox<ChecklistItem>(HiveBoxes.checklistItems);
final worshipBox = await Hive.openBox<DailyWorshipLog>(HiveBoxes.worshipLogs);
await Hive.openBox<DzikirCounter>(HiveBoxes.dzikirCounters);
await Hive.openBox<QuranBookmark>(HiveBoxes.bookmarks);
await Hive.openBox<CachedPrayerTimes>(HiveBoxes.cachedPrayerTimes);
// MIGRATION: Delete legacy logs that crash due to type casts (Map<String, bool> vs Map<String, ShalatLog>)
final keysToDelete = [];
for (final key in worshipBox.keys) {
try {
final log = worshipBox.get(key);
if (log != null) {
log.shalatLogs.values.toList(); // Force evaluation
}
} catch (_) {
keysToDelete.add(key);
}
}
if (keysToDelete.isNotEmpty) {
await worshipBox.deleteAll(keysToDelete);
debugPrint('Deleted ${keysToDelete.length} legacy worship logs.');
}
}
/// Seeds default settings and checklist items on first launch.
Future<void> seedDefaults() async {
// Seed AppSettings
final settingsBox = Hive.box<AppSettings>(HiveBoxes.settings);
if (settingsBox.isEmpty) {
await settingsBox.put('default', AppSettings());
}
// Seed default checklist items
final checklistBox = Hive.box<ChecklistItem>(HiveBoxes.checklistItems);
if (checklistBox.isEmpty) {
final defaults = [
ChecklistItem(
id: 'fajr', title: 'Sholat Fajr', category: 'sholat_fardhu', sortOrder: 0),
ChecklistItem(
id: 'dhuhr', title: 'Sholat Dhuhr', category: 'sholat_fardhu', sortOrder: 1),
ChecklistItem(
id: 'asr', title: 'Sholat Asr', category: 'sholat_fardhu', sortOrder: 2),
ChecklistItem(
id: 'maghrib', title: 'Sholat Maghrib', category: 'sholat_fardhu', sortOrder: 3),
ChecklistItem(
id: 'isha', title: 'Sholat Isha', category: 'sholat_fardhu', sortOrder: 4),
ChecklistItem(
id: 'tilawah', title: 'Tilawah Quran', category: 'tilawah',
subtitle: '1 Juz', sortOrder: 5),
ChecklistItem(
id: 'dzikir_pagi', title: 'Dzikir Pagi', category: 'dzikir',
subtitle: '1 session', sortOrder: 6),
ChecklistItem(
id: 'dzikir_petang', title: 'Dzikir Petang', category: 'dzikir',
subtitle: '1 session', sortOrder: 7),
ChecklistItem(
id: 'rawatib', title: 'Sholat Sunnah Rawatib', category: 'sunnah', sortOrder: 8),
ChecklistItem(
id: 'shodaqoh', title: 'Shodaqoh', category: 'charity', sortOrder: 9),
];
for (final item in defaults) {
await checklistBox.put(item.id, item);
}
}
}

View File

@@ -0,0 +1,101 @@
import 'package:hive_flutter/hive_flutter.dart';
part 'app_settings.g.dart';
/// User settings stored in Hive.
@HiveType(typeId: 0)
class AppSettings extends HiveObject {
@HiveField(0)
String userName;
@HiveField(1)
String userEmail;
@HiveField(2)
int themeModeIndex; // 0=system, 1=light, 2=dark
@HiveField(3)
double arabicFontSize;
@HiveField(4)
String uiLanguage; // 'id' or 'en'
@HiveField(5)
Map<String, bool> adhanEnabled;
@HiveField(6)
Map<String, int> iqamahOffset; // minutes
@HiveField(7)
String? checklistReminderTime; // HH:mm format
@HiveField(8)
double? lastLat;
@HiveField(9)
double? lastLng;
@HiveField(10)
String? lastCityName;
@HiveField(11)
int rawatibLevel; // 0 = Off, 1 = Muakkad Only, 2 = Full
@HiveField(12)
int tilawahTargetValue;
@HiveField(13)
String tilawahTargetUnit; // 'Juz', 'Halaman', 'Ayat'
@HiveField(14)
bool tilawahAutoSync;
@HiveField(15)
bool trackDzikir;
@HiveField(16)
bool trackPuasa;
@HiveField(17)
bool showLatin;
@HiveField(18)
bool showTerjemahan;
AppSettings({
this.userName = 'User',
this.userEmail = '',
this.themeModeIndex = 0,
this.arabicFontSize = 24.0,
this.uiLanguage = 'id',
Map<String, bool>? adhanEnabled,
Map<String, int>? iqamahOffset,
this.checklistReminderTime = '09:00',
this.lastLat,
this.lastLng,
this.lastCityName,
this.rawatibLevel = 1, // Default to Muakkad
this.tilawahTargetValue = 1,
this.tilawahTargetUnit = 'Juz',
this.tilawahAutoSync = false,
this.trackDzikir = true,
this.trackPuasa = false,
this.showLatin = true,
this.showTerjemahan = true,
}) : adhanEnabled = adhanEnabled ??
{
'fajr': true,
'dhuhr': true,
'asr': true,
'maghrib': true,
'isha': true,
},
iqamahOffset = iqamahOffset ??
{
'fajr': 15,
'dhuhr': 10,
'asr': 10,
'maghrib': 5,
'isha': 10,
};
}

View File

@@ -0,0 +1,95 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'app_settings.dart';
// **************************************************************************
// TypeAdapterGenerator
// **************************************************************************
class AppSettingsAdapter extends TypeAdapter<AppSettings> {
@override
final int typeId = 0;
@override
AppSettings read(BinaryReader reader) {
final numOfFields = reader.readByte();
final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return AppSettings(
userName: fields.containsKey(0) ? fields[0] as String? ?? '' : '',
userEmail: fields.containsKey(1) ? fields[1] as String? ?? '' : '',
themeModeIndex: fields.containsKey(2) ? fields[2] as int? ?? 0 : 0,
arabicFontSize: fields.containsKey(3) ? fields[3] as double? ?? 26.0 : 26.0,
uiLanguage: fields.containsKey(4) ? fields[4] as String? ?? 'id' : 'id',
adhanEnabled: fields.containsKey(5) ? (fields[5] as Map?)?.cast<String, bool>() : null,
iqamahOffset: fields.containsKey(6) ? (fields[6] as Map?)?.cast<String, int>() : null,
checklistReminderTime: fields.containsKey(7) ? fields[7] as String? : null,
lastLat: fields.containsKey(8) ? fields[8] as double? : null,
lastLng: fields.containsKey(9) ? fields[9] as double? : null,
lastCityName: fields.containsKey(10) ? fields[10] as String? : null,
rawatibLevel: fields.containsKey(11) ? fields[11] as int? ?? 1 : 1,
tilawahTargetValue: fields.containsKey(12) ? fields[12] as int? ?? 1 : 1,
tilawahTargetUnit: fields.containsKey(13) ? fields[13] as String? ?? 'Juz' : 'Juz',
tilawahAutoSync: fields.containsKey(14) ? fields[14] as bool? ?? false : false,
trackDzikir: fields.containsKey(15) ? fields[15] as bool? ?? true : true,
trackPuasa: fields.containsKey(16) ? fields[16] as bool? ?? false : false,
showLatin: fields.containsKey(17) ? fields[17] as bool? ?? true : true,
showTerjemahan: fields.containsKey(18) ? fields[18] as bool? ?? true : true,
);
}
@override
void write(BinaryWriter writer, AppSettings obj) {
writer
..writeByte(19)
..writeByte(0)
..write(obj.userName)
..writeByte(1)
..write(obj.userEmail)
..writeByte(2)
..write(obj.themeModeIndex)
..writeByte(3)
..write(obj.arabicFontSize)
..writeByte(4)
..write(obj.uiLanguage)
..writeByte(5)
..write(obj.adhanEnabled)
..writeByte(6)
..write(obj.iqamahOffset)
..writeByte(7)
..write(obj.checklistReminderTime)
..writeByte(8)
..write(obj.lastLat)
..writeByte(9)
..write(obj.lastLng)
..writeByte(10)
..write(obj.lastCityName)
..writeByte(11)
..write(obj.rawatibLevel)
..writeByte(12)
..write(obj.tilawahTargetValue)
..writeByte(13)
..write(obj.tilawahTargetUnit)
..writeByte(14)
..write(obj.tilawahAutoSync)
..writeByte(15)
..write(obj.trackDzikir)
..writeByte(16)
..write(obj.trackPuasa)
..writeByte(17)
..write(obj.showLatin)
..writeByte(18)
..write(obj.showTerjemahan);
}
@override
int get hashCode => typeId.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is AppSettingsAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}

View File

@@ -0,0 +1,50 @@
import 'package:hive_flutter/hive_flutter.dart';
part 'cached_prayer_times.g.dart';
/// Cached prayer times for a specific location + date.
@HiveType(typeId: 5)
class CachedPrayerTimes extends HiveObject {
@HiveField(0)
String key; // 'lat_lng_yyyy-MM-dd'
@HiveField(1)
double lat;
@HiveField(2)
double lng;
@HiveField(3)
String date;
@HiveField(4)
DateTime fajr;
@HiveField(5)
DateTime sunrise;
@HiveField(6)
DateTime dhuhr;
@HiveField(7)
DateTime asr;
@HiveField(8)
DateTime maghrib;
@HiveField(9)
DateTime isha;
CachedPrayerTimes({
required this.key,
required this.lat,
required this.lng,
required this.date,
required this.fajr,
required this.sunrise,
required this.dhuhr,
required this.asr,
required this.maghrib,
required this.isha,
});
}

View File

@@ -0,0 +1,68 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'cached_prayer_times.dart';
// **************************************************************************
// TypeAdapterGenerator
// **************************************************************************
class CachedPrayerTimesAdapter extends TypeAdapter<CachedPrayerTimes> {
@override
final int typeId = 5;
@override
CachedPrayerTimes read(BinaryReader reader) {
final numOfFields = reader.readByte();
final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return CachedPrayerTimes(
key: fields[0] as String,
lat: fields[1] as double,
lng: fields[2] as double,
date: fields[3] as String,
fajr: fields[4] as DateTime,
sunrise: fields[5] as DateTime,
dhuhr: fields[6] as DateTime,
asr: fields[7] as DateTime,
maghrib: fields[8] as DateTime,
isha: fields[9] as DateTime,
);
}
@override
void write(BinaryWriter writer, CachedPrayerTimes obj) {
writer
..writeByte(10)
..writeByte(0)
..write(obj.key)
..writeByte(1)
..write(obj.lat)
..writeByte(2)
..write(obj.lng)
..writeByte(3)
..write(obj.date)
..writeByte(4)
..write(obj.fajr)
..writeByte(5)
..write(obj.sunrise)
..writeByte(6)
..write(obj.dhuhr)
..writeByte(7)
..write(obj.asr)
..writeByte(8)
..write(obj.maghrib)
..writeByte(9)
..write(obj.isha);
}
@override
int get hashCode => typeId.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is CachedPrayerTimesAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}

View File

@@ -0,0 +1,34 @@
import 'package:hive_flutter/hive_flutter.dart';
part 'checklist_item.g.dart';
/// A single checklist item definition (template, not daily state).
@HiveType(typeId: 1)
class ChecklistItem extends HiveObject {
@HiveField(0)
String id;
@HiveField(1)
String title;
@HiveField(2)
String category;
@HiveField(3)
String? subtitle;
@HiveField(4)
int sortOrder;
@HiveField(5)
bool isCustom;
ChecklistItem({
required this.id,
required this.title,
required this.category,
this.subtitle,
required this.sortOrder,
this.isCustom = false,
});
}

View File

@@ -0,0 +1,56 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'checklist_item.dart';
// **************************************************************************
// TypeAdapterGenerator
// **************************************************************************
class ChecklistItemAdapter extends TypeAdapter<ChecklistItem> {
@override
final int typeId = 1;
@override
ChecklistItem read(BinaryReader reader) {
final numOfFields = reader.readByte();
final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return ChecklistItem(
id: fields[0] as String,
title: fields[1] as String,
category: fields[2] as String,
subtitle: fields[3] as String?,
sortOrder: fields[4] as int,
isCustom: fields[5] as bool,
);
}
@override
void write(BinaryWriter writer, ChecklistItem obj) {
writer
..writeByte(6)
..writeByte(0)
..write(obj.id)
..writeByte(1)
..write(obj.title)
..writeByte(2)
..write(obj.category)
..writeByte(3)
..write(obj.subtitle)
..writeByte(4)
..write(obj.sortOrder)
..writeByte(5)
..write(obj.isCustom);
}
@override
int get hashCode => typeId.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is ChecklistItemAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}

View File

@@ -0,0 +1,86 @@
import 'package:hive_flutter/hive_flutter.dart';
import 'shalat_log.dart';
import 'tilawah_log.dart';
import 'dzikir_log.dart';
import 'puasa_log.dart';
part 'daily_worship_log.g.dart';
/// Daily worship completion log, keyed by date string 'yyyy-MM-dd'.
@HiveType(typeId: 2)
class DailyWorshipLog extends HiveObject {
@HiveField(0)
String date;
@HiveField(1)
Map<String, ShalatLog> shalatLogs; // e.g., 'subuh' -> ShalatLog
@HiveField(5)
TilawahLog? tilawahLog;
@HiveField(6)
DzikirLog? dzikirLog;
@HiveField(7)
PuasaLog? puasaLog;
@HiveField(2)
int totalItems;
@HiveField(3)
int completedCount;
@HiveField(4)
double completionPercent;
DailyWorshipLog({
required this.date,
Map<String, ShalatLog>? shalatLogs,
this.tilawahLog,
this.dzikirLog,
this.puasaLog,
this.totalItems = 0,
this.completedCount = 0,
this.completionPercent = 0.0,
}) : shalatLogs = shalatLogs ?? {};
/// Dynamically calculates the "Poin Ibadah" for this day.
int get totalPoints {
int points = 0;
// 1. Shalat Fardhu
for (final sLog in shalatLogs.values) {
if (sLog.completed) {
if (sLog.location == 'Masjid') {
points += 25;
} else {
points += 10;
}
}
if (sLog.qabliyah == true) points += 5;
if (sLog.badiyah == true) points += 5;
}
// 2. Tilawah
if (tilawahLog != null) {
// 1 point per Ayat read
points += tilawahLog!.rawAyatRead;
// Bonus 20 points for completing daily target
if (tilawahLog!.isCompleted) {
points += 20;
}
}
// 3. Dzikir & Puasa
if (dzikirLog != null) {
if (dzikirLog!.pagi) points += 10;
if (dzikirLog!.petang) points += 10;
}
if (puasaLog != null && puasaLog!.completed) {
points += 30;
}
return points;
}
}

View File

@@ -0,0 +1,70 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'daily_worship_log.dart';
// **************************************************************************
// TypeAdapterGenerator
// **************************************************************************
class DailyWorshipLogAdapter extends TypeAdapter<DailyWorshipLog> {
@override
final int typeId = 2;
@override
DailyWorshipLog read(BinaryReader reader) {
final numOfFields = reader.readByte();
final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
Map<String, ShalatLog>? parsedShalatLogs;
try {
parsedShalatLogs = (fields[1] as Map?)?.cast<String, ShalatLog>();
} catch (_) {
// If casting fails (e.g. it was the old Map<String, bool>), ignore it.
parsedShalatLogs = {};
}
return DailyWorshipLog(
date: fields[0] as String,
shalatLogs: parsedShalatLogs,
tilawahLog: fields[5] as TilawahLog?,
dzikirLog: fields[6] as DzikirLog?,
puasaLog: fields[7] as PuasaLog?,
totalItems: fields[2] as int,
completedCount: fields[3] as int,
completionPercent: fields[4] as double,
);
}
@override
void write(BinaryWriter writer, DailyWorshipLog obj) {
writer
..writeByte(8)
..writeByte(0)
..write(obj.date)
..writeByte(1)
..write(obj.shalatLogs)
..writeByte(5)
..write(obj.tilawahLog)
..writeByte(6)
..write(obj.dzikirLog)
..writeByte(7)
..write(obj.puasaLog)
..writeByte(2)
..write(obj.totalItems)
..writeByte(3)
..write(obj.completedCount)
..writeByte(4)
..write(obj.completionPercent);
}
@override
int get hashCode => typeId.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is DailyWorshipLogAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}

View File

@@ -0,0 +1,26 @@
import 'package:hive_flutter/hive_flutter.dart';
part 'dzikir_counter.g.dart';
/// Counter for a single dzikir item on a specific date.
@HiveType(typeId: 3)
class DzikirCounter extends HiveObject {
@HiveField(0)
String dzikirId;
@HiveField(1)
String date;
@HiveField(2)
int count;
@HiveField(3)
int target;
DzikirCounter({
required this.dzikirId,
required this.date,
this.count = 0,
required this.target,
});
}

View File

@@ -0,0 +1,50 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'dzikir_counter.dart';
// **************************************************************************
// TypeAdapterGenerator
// **************************************************************************
class DzikirCounterAdapter extends TypeAdapter<DzikirCounter> {
@override
final int typeId = 3;
@override
DzikirCounter read(BinaryReader reader) {
final numOfFields = reader.readByte();
final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return DzikirCounter(
dzikirId: fields[0] as String,
date: fields[1] as String,
count: fields[2] as int,
target: fields[3] as int,
);
}
@override
void write(BinaryWriter writer, DzikirCounter obj) {
writer
..writeByte(4)
..writeByte(0)
..write(obj.dzikirId)
..writeByte(1)
..write(obj.date)
..writeByte(2)
..write(obj.count)
..writeByte(3)
..write(obj.target);
}
@override
int get hashCode => typeId.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is DzikirCounterAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}

View File

@@ -0,0 +1,17 @@
import 'package:hive/hive.dart';
part 'dzikir_log.g.dart';
@HiveType(typeId: 9)
class DzikirLog {
@HiveField(0)
bool pagi;
@HiveField(1)
bool petang;
DzikirLog({
this.pagi = false,
this.petang = false,
});
}

View File

@@ -0,0 +1,44 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'dzikir_log.dart';
// **************************************************************************
// TypeAdapterGenerator
// **************************************************************************
class DzikirLogAdapter extends TypeAdapter<DzikirLog> {
@override
final int typeId = 9;
@override
DzikirLog read(BinaryReader reader) {
final numOfFields = reader.readByte();
final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return DzikirLog(
pagi: fields[0] as bool,
petang: fields[1] as bool,
);
}
@override
void write(BinaryWriter writer, DzikirLog obj) {
writer
..writeByte(2)
..writeByte(0)
..write(obj.pagi)
..writeByte(1)
..write(obj.petang);
}
@override
int get hashCode => typeId.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is DzikirLogAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}

View File

@@ -0,0 +1,17 @@
import 'package:hive/hive.dart';
part 'puasa_log.g.dart';
@HiveType(typeId: 10)
class PuasaLog {
@HiveField(0)
String? jenisPuasa; // 'Senin', 'Kamis', 'Ayyamul Bidh', 'Daud', etc.
@HiveField(1)
bool completed;
PuasaLog({
this.jenisPuasa,
this.completed = false,
});
}

View File

@@ -0,0 +1,44 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'puasa_log.dart';
// **************************************************************************
// TypeAdapterGenerator
// **************************************************************************
class PuasaLogAdapter extends TypeAdapter<PuasaLog> {
@override
final int typeId = 10;
@override
PuasaLog read(BinaryReader reader) {
final numOfFields = reader.readByte();
final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return PuasaLog(
jenisPuasa: fields[0] as String?,
completed: fields[1] as bool,
);
}
@override
void write(BinaryWriter writer, PuasaLog obj) {
writer
..writeByte(2)
..writeByte(0)
..write(obj.jenisPuasa)
..writeByte(1)
..write(obj.completed);
}
@override
int get hashCode => typeId.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is PuasaLogAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}

View File

@@ -0,0 +1,42 @@
import 'package:hive_flutter/hive_flutter.dart';
part 'quran_bookmark.g.dart';
/// A bookmarked Quran verse.
@HiveType(typeId: 4)
class QuranBookmark extends HiveObject {
@HiveField(0)
int surahId;
@HiveField(1)
int verseId;
@HiveField(2)
String surahName;
@HiveField(3)
String verseText; // Arabic snippet
@HiveField(4)
DateTime savedAt;
@HiveField(5)
bool isLastRead;
@HiveField(6)
String? verseLatin;
@HiveField(7)
String? verseTranslation;
QuranBookmark({
required this.surahId,
required this.verseId,
required this.surahName,
required this.verseText,
required this.savedAt,
this.isLastRead = false,
this.verseLatin,
this.verseTranslation,
});
}

View File

@@ -0,0 +1,62 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'quran_bookmark.dart';
// **************************************************************************
// TypeAdapterGenerator
// **************************************************************************
class QuranBookmarkAdapter extends TypeAdapter<QuranBookmark> {
@override
final int typeId = 4;
@override
QuranBookmark read(BinaryReader reader) {
final numOfFields = reader.readByte();
final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return QuranBookmark(
surahId: fields[0] as int,
verseId: fields[1] as int,
surahName: fields[2] as String,
verseText: fields[3] as String,
savedAt: fields[4] as DateTime,
isLastRead: fields[5] as bool? ?? false,
verseLatin: fields[6] as String?,
verseTranslation: fields[7] as String?,
);
}
@override
void write(BinaryWriter writer, QuranBookmark obj) {
writer
..writeByte(8)
..writeByte(0)
..write(obj.surahId)
..writeByte(1)
..write(obj.verseId)
..writeByte(2)
..write(obj.surahName)
..writeByte(3)
..write(obj.verseText)
..writeByte(4)
..write(obj.savedAt)
..writeByte(5)
..write(obj.isLastRead)
..writeByte(6)
..write(obj.verseLatin)
..writeByte(7)
..write(obj.verseTranslation);
}
@override
int get hashCode => typeId.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is QuranBookmarkAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}

View File

@@ -0,0 +1,25 @@
import 'package:hive/hive.dart';
part 'shalat_log.g.dart';
@HiveType(typeId: 7)
class ShalatLog {
@HiveField(0)
bool completed;
@HiveField(1)
String? location; // 'Rumah' or 'Masjid'
@HiveField(2)
bool? qabliyah;
@HiveField(3)
bool? badiyah;
ShalatLog({
this.completed = false,
this.location,
this.qabliyah,
this.badiyah,
});
}

View File

@@ -0,0 +1,50 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'shalat_log.dart';
// **************************************************************************
// TypeAdapterGenerator
// **************************************************************************
class ShalatLogAdapter extends TypeAdapter<ShalatLog> {
@override
final int typeId = 7;
@override
ShalatLog read(BinaryReader reader) {
final numOfFields = reader.readByte();
final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return ShalatLog(
completed: fields[0] as bool,
location: fields[1] as String?,
qabliyah: fields[2] as bool?,
badiyah: fields[3] as bool?,
);
}
@override
void write(BinaryWriter writer, ShalatLog obj) {
writer
..writeByte(4)
..writeByte(0)
..write(obj.completed)
..writeByte(1)
..write(obj.location)
..writeByte(2)
..write(obj.qabliyah)
..writeByte(3)
..write(obj.badiyah);
}
@override
int get hashCode => typeId.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is ShalatLogAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}

View File

@@ -0,0 +1,35 @@
import 'package:hive/hive.dart';
part 'tilawah_log.g.dart';
@HiveType(typeId: 8)
class TilawahLog {
@HiveField(0)
int targetValue;
@HiveField(1)
String targetUnit; // 'Juz', 'Halaman', 'Ayat'
@HiveField(2)
int currentProgress;
@HiveField(3)
bool autoSync;
@HiveField(4)
int rawAyatRead;
@HiveField(5)
bool targetCompleted;
TilawahLog({
this.targetValue = 1,
this.targetUnit = 'Juz',
this.currentProgress = 0,
this.autoSync = false,
this.rawAyatRead = 0,
this.targetCompleted = false,
});
bool get isCompleted => targetCompleted;
}

View File

@@ -0,0 +1,56 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'tilawah_log.dart';
// **************************************************************************
// TypeAdapterGenerator
// **************************************************************************
class TilawahLogAdapter extends TypeAdapter<TilawahLog> {
@override
final int typeId = 8;
@override
TilawahLog read(BinaryReader reader) {
final numOfFields = reader.readByte();
final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return TilawahLog(
targetValue: fields[0] as int,
targetUnit: fields[1] as String,
currentProgress: fields[2] as int,
autoSync: fields[3] as bool,
rawAyatRead: fields[4] as int? ?? 0,
targetCompleted: fields[5] as bool? ?? false,
);
}
@override
void write(BinaryWriter writer, TilawahLog obj) {
writer
..writeByte(6)
..writeByte(0)
..write(obj.targetValue)
..writeByte(1)
..write(obj.targetUnit)
..writeByte(2)
..write(obj.currentProgress)
..writeByte(3)
..write(obj.autoSync)
..writeByte(4)
..write(obj.rawAyatRead)
..writeByte(5)
..write(obj.targetCompleted);
}
@override
int get hashCode => typeId.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is TilawahLogAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}