import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../../../core/config/app_config.dart'; import '../../../../core/services/notification_service.dart'; import '../../domain/entities/app_notification.dart'; import '../../data/in_site_notification.dart'; import '../../data/in_site_notification_repository.dart'; /// Global local notifications plugin instance (initialized in main.dart). final localNotificationsPluginProvider = Provider((ref) { return FlutterLocalNotificationsPlugin(); }); /// Notification service singleton. final notificationServiceProvider = Provider((ref) { final config = ref.watch(appConfigProvider); final plugin = ref.watch(localNotificationsPluginProvider); return NotificationService( baseUrl: config.apiBaseUrl, localNotifications: plugin, ); }); /// Accumulated push notification list (local/realtime). class NotificationListNotifier extends StateNotifier> { NotificationListNotifier() : super([]); void add(AppNotification notification) { state = [notification, ...state]; } void markRead(String id) { state = state.map((n) { if (n.id == id) return n.copyWith(isRead: true); return n; }).toList(); } void markAllRead() { state = state.map((n) => n.copyWith(isRead: true)).toList(); } void clear() { state = []; } } final notificationListProvider = StateNotifierProvider>( (ref) { return NotificationListNotifier(); }); /// Local push notification unread count. final unreadNotificationCountProvider = Provider((ref) { final notifications = ref.watch(notificationListProvider); return notifications.where((n) => !n.isRead).length; }); // ── In-site (站内消息) notification providers ────────────────────────────── /// Polls the backend every 30s for the unread in-site notification count. final inSiteUnreadCountProvider = StreamProvider((ref) async* { final repo = ref.watch(inSiteNotificationRepositoryProvider); Future fetch() async { try { return await repo.getUnreadCount(); } catch (_) { return 0; } } // Emit immediately on first build yield await fetch(); // Then poll every 30s await for (final _ in Stream.periodic(const Duration(seconds: 30))) { yield await fetch(); } }); /// Fetches the full in-site notification list (on demand, refreshed when invalidated). final inSiteNotificationsProvider = FutureProvider>((ref) async { final repo = ref.watch(inSiteNotificationRepositoryProvider); final result = await repo.getMyNotifications(limit: 100); return result.items; });