odoo_loyalty_app/lib/services/background_service.dart

86 lines
3.1 KiB
Dart

import 'dart:convert';
import 'package:workmanager/workmanager.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:odoo_rpc/odoo_rpc.dart';
import 'notification_service.dart';
// NOTE: This key tracks what IDs have been shown as device tray notifications.
// It is separate from 'last_seen_notification_id' (which tracks what the user READ in-app).
const String _kLastDeviceNotifiedId = 'last_device_notified_id';
@pragma('vm:entry-point')
void callbackDispatcher() {
Workmanager().executeTask((task, inputData) async {
try {
final prefs = await SharedPreferences.getInstance();
final url = prefs.getString('odoo_url');
final sessionStr = prefs.getString('odoo_session');
if (url == null || sessionStr == null) {
return Future.value(true); // Not logged in, nothing to do
}
final lastDeviceNotifiedId = prefs.getInt(_kLastDeviceNotifiedId) ?? 0;
final sessionArgs = json.decode(sessionStr);
final session = OdooSession.fromJson(
Map<String, dynamic>.from(sessionArgs as Map));
final client = OdooClient(url, sessionId: session);
final response = await client.callRPC(
'/api/loyalty/fetch_notifications',
'call',
{'last_id': 0},
);
client.close();
if (response != null && response['status'] == 'success') {
final List<dynamic> notifications =
List<dynamic>.from(response['data'] ?? []);
// Filter to only truly new ones not yet shown on device tray
final newNotifs = notifications
.where((n) => (n['id'] as int? ?? 0) > lastDeviceNotifiedId)
.toList();
final notifService = NotificationService();
await notifService.initialize();
if (newNotifs.isNotEmpty) {
int highestId = lastDeviceNotifiedId;
for (final notif in newNotifs) {
final int notifId = notif['id'] as int? ?? 0;
if (notifId > highestId) highestId = notifId;
await notifService.showNotification(
id: notifId,
title: notif['title'] as String? ?? 'Mie Mapan',
body: notif['body'] as String? ?? '',
);
}
await prefs.setInt(_kLastDeviceNotifiedId, highestId);
}
// Always compute badge count based on read_notification_ids
final readIds = prefs.getStringList('read_notification_ids');
if (readIds == null) {
// Initialize read list with all currently fetched notifications on first install/run
final initialRead = notifications.map((n) => (n['id'] as int? ?? 0).toString()).toList();
await prefs.setStringList('read_notification_ids', initialRead);
await notifService.setBadge(0);
} else {
final unreadCount = notifications
.where((n) => !readIds.contains((n['id'] as int? ?? 0).toString()))
.length;
await notifService.setBadge(unreadCount);
}
}
} catch (_) {
// Silently swallow — background isolate must never crash
}
return Future.value(true);
});
}