Files
jamshalat-diary/lib/data/services/background_sync_service.dart
2026-05-20 19:52:15 +07:00

118 lines
3.9 KiB
Dart

import 'dart:async';
import 'package:flutter/widgets.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:intl/intl.dart';
import 'package:workmanager/workmanager.dart';
import '../local/hive_boxes.dart';
import '../local/models/app_settings.dart';
import 'myquran_sholat_service.dart';
import 'notification_orchestrator_service.dart';
import 'notification_service.dart';
class BackgroundSyncService {
BackgroundSyncService._();
static final BackgroundSyncService instance = BackgroundSyncService._();
static const String periodicTaskName = 'jamshalat_periodic_sync';
static const String periodicUniqueName = 'jamshalat_periodic_sync_unique';
Future<void> init() async {
await Workmanager().initialize(_workmanagerCallbackDispatcher);
}
Future<void> registerPeriodicSync() async {
await Workmanager().registerPeriodicTask(
periodicUniqueName,
periodicTaskName,
existingWorkPolicy: ExistingPeriodicWorkPolicy.update,
frequency: const Duration(hours: 6),
initialDelay: const Duration(minutes: 15),
constraints: Constraints(
networkType: NetworkType.connected,
),
backoffPolicy: BackoffPolicy.exponential,
backoffPolicyDelay: const Duration(minutes: 10),
);
}
static Future<void> runSyncPass() async {
WidgetsFlutterBinding.ensureInitialized();
await initHive();
final settingsBox = Hive.box<AppSettings>(HiveBoxes.settings);
final settings = settingsBox.get('default') ?? AppSettings();
final cityId = _resolveCityId(settings);
final schedulesByDate = await _buildWindowSchedules(cityId);
if (schedulesByDate.isNotEmpty) {
await NotificationService.instance.syncPrayerNotifications(
cityId: cityId,
adhanEnabled: settings.adhanEnabled,
iqamahOffset: settings.iqamahOffset,
schedulesByDate: schedulesByDate,
reportReminderEnabled: settings.shalatReportReminderEnabled,
reportReminderDelayMinutes: settings.shalatReportReminderDelayMinutes,
reportReminderRepeatCount: settings.shalatReportReminderRepeatCount,
reportReminderRepeatIntervalMinutes:
settings.shalatReportReminderRepeatIntervalMinutes,
);
}
await NotificationService.instance.syncHabitNotifications(
settings: settings,
);
await NotificationOrchestratorService.instance.runPassivePass(
settings: settings,
);
}
static Future<Map<String, Map<String, String>>> _buildWindowSchedules(
String cityId) async {
final now = DateTime.now();
final startDate = DateTime(now.year, now.month, now.day);
final endDate = startDate.add(const Duration(days: 35));
final monthKeys = <String>{
DateFormat('yyyy-MM').format(startDate),
DateFormat('yyyy-MM').format(endDate),
};
final schedulesByDate = <String, Map<String, String>>{};
for (final monthKey in monthKeys) {
final monthly = await MyQuranSholatService.instance
.getMonthlySchedule(cityId, monthKey);
for (final entry in monthly.entries) {
final date = DateTime.tryParse(entry.key);
if (date == null) continue;
final normalized = DateTime(date.year, date.month, date.day);
if (normalized.isBefore(startDate) || normalized.isAfter(endDate)) {
continue;
}
schedulesByDate[entry.key] = entry.value;
}
}
return schedulesByDate;
}
static String _resolveCityId(AppSettings settings) {
final stored = settings.lastCityName ?? '';
if (stored.contains('|')) {
return stored.split('|').last;
}
return '58a2fc6ed39fd083f55d4182bf88826d';
}
}
@pragma('vm:entry-point')
void _workmanagerCallbackDispatcher() {
Workmanager().executeTask((task, inputData) async {
if (task == BackgroundSyncService.periodicTaskName) {
await BackgroundSyncService.runSyncPass();
return true;
}
return true;
});
}