Files
jamshalat-masjid-screen/lib/data/local/models.dart

421 lines
13 KiB
Dart

import 'package:hive_flutter/hive_flutter.dart';
/// Hive type adapter IDs and box names.
class HiveBoxes {
HiveBoxes._();
static const String settings = 'app_settings';
static const String prayerSchedule = 'prayer_schedule';
}
/// AppSettings stored in Hive.
@HiveType(typeId: 0)
class AppSettings extends HiveObject {
@HiveField(0)
String masjidName;
@HiveField(1)
String masjidAddress;
@HiveField(2)
String cityIdApi; // myQuran city hash ID
@HiveField(3)
String cityDisplayName;
@HiveField(4)
bool showImsak;
@HiveField(5)
bool showTerbit;
// Iqomah durations in minutes
@HiveField(6)
int iqomahSubuh;
@HiveField(7)
int iqomahDzuhur;
@HiveField(8)
int iqomahAshar;
@HiveField(9)
int iqomahMaghrib;
@HiveField(10)
int iqomahIsya;
// Pre-Adzan lead time (minutes before adzan to lock main screen)
@HiveField(11)
int preAdzanLead;
// Blank screen durations
@HiveField(12)
int blankScreenNormal; // minutes
@HiveField(13)
int blankScreenJumat; // minutes
// Running text items
@HiveField(14)
List<String> runningTexts;
// Friday officers
@HiveField(15)
String khatibName;
@HiveField(16)
String imamName;
// Rotation settings
@HiveField(17)
int mainScreenDurationSec;
@HiveField(18)
int slideDurationSec;
// Last sync timestamp
@HiveField(19)
String? lastSyncDate;
// Slideshow image paths (local)
@HiveField(20)
List<String> slideshowImages;
// Text scaling (0=Small, 1=Medium, 2=Large)
@HiveField(21)
int textScaleIndex;
// Unsplash Background configs
@HiveField(22)
bool useUnsplashBackground;
@HiveField(23)
String unsplashKeyword;
@HiveField(24)
int unsplashRotationHours;
// Branded background image (local file path set by admin)
@HiveField(25)
String? brandedBgImage;
// Per-item duration for running texts (seconds each)
@HiveField(26)
List<int> runningTextDurations;
// Running text animation type: 'marquee' or 'fade'
@HiveField(27)
String marqueeAnimType;
// Granular text group scales (independent of textScaleIndex)
// Group: Prayer card label (e.g. "SUBUH", "DZUHUR")
@HiveField(28)
double scaleCardLabel;
// Group: Prayer card body (time + iqomah text)
@HiveField(29)
double scaleCardBody;
// Group: Running text ticker at bottom
@HiveField(30)
double scaleRunningText;
AppSettings({
this.masjidName = 'Masjid Al-Ikhlas',
this.masjidAddress = 'Jl. Kebaikan No. 1',
this.cityIdApi = '1218', // Default: Yogyakarta
this.cityDisplayName = 'Kota Yogyakarta',
this.showImsak = true,
this.showTerbit = true,
this.iqomahSubuh = 15,
this.iqomahDzuhur = 10,
this.iqomahAshar = 10,
this.iqomahMaghrib = 7,
this.iqomahIsya = 10,
this.preAdzanLead = 10,
this.blankScreenNormal = 15,
this.blankScreenJumat = 45,
this.runningTexts = const [
'Mohon luruskan dan rapatkan shaf',
'Kajian rutin setiap Ahad pagi',
],
this.khatibName = 'Ust. Fulan, S.Ag',
this.imamName = 'Ust. Alan, Lc',
this.mainScreenDurationSec = 15,
this.slideDurationSec = 10,
this.lastSyncDate,
this.slideshowImages = const [],
this.textScaleIndex = 1,
this.useUnsplashBackground = false,
this.unsplashKeyword = 'mosque',
this.unsplashRotationHours = 6,
this.brandedBgImage,
this.runningTextDurations = const [],
this.marqueeAnimType = 'marquee',
this.scaleCardLabel = 1.0,
this.scaleCardBody = 1.0,
this.scaleRunningText = 1.0,
});
AppSettings copyWith({
String? masjidName,
String? masjidAddress,
String? cityIdApi,
String? cityDisplayName,
bool? showImsak,
bool? showTerbit,
int? iqomahSubuh,
int? iqomahDzuhur,
int? iqomahAshar,
int? iqomahMaghrib,
int? iqomahIsya,
int? preAdzanLead,
int? blankScreenNormal,
int? blankScreenJumat,
List<String>? runningTexts,
String? khatibName,
String? imamName,
int? mainScreenDurationSec,
int? slideDurationSec,
String? lastSyncDate,
List<String>? slideshowImages,
int? textScaleIndex,
bool? useUnsplashBackground,
String? unsplashKeyword,
int? unsplashRotationHours,
String? brandedBgImage,
List<int>? runningTextDurations,
String? marqueeAnimType,
double? scaleCardLabel,
double? scaleCardBody,
double? scaleRunningText,
}) {
return AppSettings(
masjidName: masjidName ?? this.masjidName,
masjidAddress: masjidAddress ?? this.masjidAddress,
cityIdApi: cityIdApi ?? this.cityIdApi,
cityDisplayName: cityDisplayName ?? this.cityDisplayName,
showImsak: showImsak ?? this.showImsak,
showTerbit: showTerbit ?? this.showTerbit,
iqomahSubuh: iqomahSubuh ?? this.iqomahSubuh,
iqomahDzuhur: iqomahDzuhur ?? this.iqomahDzuhur,
iqomahAshar: iqomahAshar ?? this.iqomahAshar,
iqomahMaghrib: iqomahMaghrib ?? this.iqomahMaghrib,
iqomahIsya: iqomahIsya ?? this.iqomahIsya,
preAdzanLead: preAdzanLead ?? this.preAdzanLead,
blankScreenNormal: blankScreenNormal ?? this.blankScreenNormal,
blankScreenJumat: blankScreenJumat ?? this.blankScreenJumat,
runningTexts: runningTexts ?? this.runningTexts,
khatibName: khatibName ?? this.khatibName,
imamName: imamName ?? this.imamName,
mainScreenDurationSec: mainScreenDurationSec ?? this.mainScreenDurationSec,
slideDurationSec: slideDurationSec ?? this.slideDurationSec,
lastSyncDate: lastSyncDate ?? this.lastSyncDate,
slideshowImages: slideshowImages ?? this.slideshowImages,
textScaleIndex: textScaleIndex ?? this.textScaleIndex,
useUnsplashBackground: useUnsplashBackground ?? this.useUnsplashBackground,
unsplashKeyword: unsplashKeyword ?? this.unsplashKeyword,
unsplashRotationHours: unsplashRotationHours ?? this.unsplashRotationHours,
brandedBgImage: brandedBgImage ?? this.brandedBgImage,
runningTextDurations: runningTextDurations ?? this.runningTextDurations,
marqueeAnimType: marqueeAnimType ?? this.marqueeAnimType,
scaleCardLabel: scaleCardLabel ?? this.scaleCardLabel,
scaleCardBody: scaleCardBody ?? this.scaleCardBody,
scaleRunningText: scaleRunningText ?? this.scaleRunningText,
);
}
}
/// Adapter for AppSettings — hand-written to avoid code generation.
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++) {
fields[reader.readByte()] = reader.read();
}
return AppSettings(
masjidName: fields[0] as String? ?? 'Masjid Al-Ikhlas',
masjidAddress: fields[1] as String? ?? 'Jl. Kebaikan No. 1',
cityIdApi: fields[2] as String? ?? '1218',
cityDisplayName: fields[3] as String? ?? 'Kota Yogyakarta',
showImsak: fields[4] as bool? ?? true,
showTerbit: fields[5] as bool? ?? true,
iqomahSubuh: fields[6] as int? ?? 15,
iqomahDzuhur: fields[7] as int? ?? 10,
iqomahAshar: fields[8] as int? ?? 10,
iqomahMaghrib: fields[9] as int? ?? 7,
iqomahIsya: fields[10] as int? ?? 10,
preAdzanLead: fields[11] as int? ?? 10,
blankScreenNormal: fields[12] as int? ?? 15,
blankScreenJumat: fields[13] as int? ?? 45,
runningTexts: (fields[14] as List?)?.cast<String>() ?? const [],
khatibName: fields[15] as String? ?? '',
imamName: fields[16] as String? ?? '',
mainScreenDurationSec: fields[17] as int? ?? 15,
slideDurationSec: fields[18] as int? ?? 10,
lastSyncDate: fields[19] as String?,
slideshowImages: (fields[20] as List?)?.cast<String>() ?? const [],
textScaleIndex: fields[21] as int? ?? 1,
useUnsplashBackground: fields[22] as bool? ?? false,
unsplashKeyword: fields[23] as String? ?? 'mosque',
unsplashRotationHours: fields[24] as int? ?? 6,
brandedBgImage: fields[25] as String?,
runningTextDurations: (fields[26] as List?)?.cast<int>() ?? const [],
marqueeAnimType: fields[27] as String? ?? 'marquee',
scaleCardLabel: (fields[28] as num?)?.toDouble() ?? 1.0,
scaleCardBody: (fields[29] as num?)?.toDouble() ?? 1.0,
scaleRunningText: (fields[30] as num?)?.toDouble() ?? 1.0,
);
}
@override
void write(BinaryWriter writer, AppSettings obj) {
writer
..writeByte(31)
..writeByte(0)..write(obj.masjidName)
..writeByte(1)..write(obj.masjidAddress)
..writeByte(2)..write(obj.cityIdApi)
..writeByte(3)..write(obj.cityDisplayName)
..writeByte(4)..write(obj.showImsak)
..writeByte(5)..write(obj.showTerbit)
..writeByte(6)..write(obj.iqomahSubuh)
..writeByte(7)..write(obj.iqomahDzuhur)
..writeByte(8)..write(obj.iqomahAshar)
..writeByte(9)..write(obj.iqomahMaghrib)
..writeByte(10)..write(obj.iqomahIsya)
..writeByte(11)..write(obj.preAdzanLead)
..writeByte(12)..write(obj.blankScreenNormal)
..writeByte(13)..write(obj.blankScreenJumat)
..writeByte(14)..write(obj.runningTexts)
..writeByte(15)..write(obj.khatibName)
..writeByte(16)..write(obj.imamName)
..writeByte(17)..write(obj.mainScreenDurationSec)
..writeByte(18)..write(obj.slideDurationSec)
..writeByte(19)..write(obj.lastSyncDate)
..writeByte(20)..write(obj.slideshowImages)
..writeByte(21)..write(obj.textScaleIndex)
..writeByte(22)..write(obj.useUnsplashBackground)
..writeByte(23)..write(obj.unsplashKeyword)
..writeByte(24)..write(obj.unsplashRotationHours)
..writeByte(25)..write(obj.brandedBgImage)
..writeByte(26)..write(obj.runningTextDurations)
..writeByte(27)..write(obj.marqueeAnimType)
..writeByte(28)..write(obj.scaleCardLabel)
..writeByte(29)..write(obj.scaleCardBody)
..writeByte(30)..write(obj.scaleRunningText);
}
}
/// Daily prayer schedule row cached from the MyQuran API.
@HiveType(typeId: 1)
class DailyPrayerSchedule extends HiveObject {
@HiveField(0)
String date; // yyyy-MM-dd
@HiveField(1)
String imsak;
@HiveField(2)
String subuh;
@HiveField(3)
String terbit;
@HiveField(4)
String dhuha;
@HiveField(5)
String dzuhur;
@HiveField(6)
String ashar;
@HiveField(7)
String maghrib;
@HiveField(8)
String isya;
DailyPrayerSchedule({
required this.date,
required this.imsak,
required this.subuh,
required this.terbit,
required this.dhuha,
required this.dzuhur,
required this.ashar,
required this.maghrib,
required this.isya,
});
/// Parse time string "HH:mm" to a DateTime on the given date.
DateTime timeToDateTime(String time, DateTime refDate) {
final parts = time.split(':');
return DateTime(
refDate.year,
refDate.month,
refDate.day,
int.parse(parts[0]),
int.parse(parts[1]),
);
}
/// Get all prayer times as DateTime map for a given reference date.
Map<String, DateTime> toDateTimeMap(DateTime refDate) => {
'imsak': timeToDateTime(imsak, refDate),
'subuh': timeToDateTime(subuh, refDate),
'terbit': timeToDateTime(terbit, refDate),
'dhuha': timeToDateTime(dhuha, refDate),
'dzuhur': timeToDateTime(dzuhur, refDate),
'ashar': timeToDateTime(ashar, refDate),
'maghrib': timeToDateTime(maghrib, refDate),
'isya': timeToDateTime(isya, refDate),
};
}
/// Adapter for DailyPrayerSchedule.
class DailyPrayerScheduleAdapter extends TypeAdapter<DailyPrayerSchedule> {
@override
final int typeId = 1;
@override
DailyPrayerSchedule read(BinaryReader reader) {
final numOfFields = reader.readByte();
final fields = <int, dynamic>{};
for (int i = 0; i < numOfFields; i++) {
fields[reader.readByte()] = reader.read();
}
return DailyPrayerSchedule(
date: fields[0] as String? ?? '',
imsak: fields[1] as String? ?? '00:00',
subuh: fields[2] as String? ?? '00:00',
terbit: fields[3] as String? ?? '00:00',
dhuha: fields[4] as String? ?? '00:00',
dzuhur: fields[5] as String? ?? '00:00',
ashar: fields[6] as String? ?? '00:00',
maghrib: fields[7] as String? ?? '00:00',
isya: fields[8] as String? ?? '00:00',
);
}
@override
void write(BinaryWriter writer, DailyPrayerSchedule obj) {
writer
..writeByte(9)
..writeByte(0)..write(obj.date)
..writeByte(1)..write(obj.imsak)
..writeByte(2)..write(obj.subuh)
..writeByte(3)..write(obj.terbit)
..writeByte(4)..write(obj.dhuha)
..writeByte(5)..write(obj.dzuhur)
..writeByte(6)..write(obj.ashar)
..writeByte(7)..write(obj.maghrib)
..writeByte(8)..write(obj.isya);
}
}