import 'dart:async'; import 'package:flutter/foundation.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; const String aiDigestNotificationPayload = 'ai_digest_review_inbox'; final Provider aiDigestNotificationIntentBusProvider = Provider( (Ref ref) { final AiDigestNotificationIntentBus bus = AiDigestNotificationIntentBus(); ref.onDispose(() { unawaited(bus.close()); }); return bus; }, ); class AiDigestNotificationIntentBus { final StreamController _controller = StreamController.broadcast(); Stream get intents => _controller.stream; void emitTap(String payload) { if (!_controller.isClosed) { _controller.add(payload); } } Future close() => _controller.close(); } abstract interface class AiDigestNotifier { Future showDigestReady(int count); } class LocalAiDigestNotifier implements AiDigestNotifier { LocalAiDigestNotifier({ FlutterLocalNotificationsPlugin? plugin, void Function(String payload)? onTapPayload, }) : _plugin = plugin ?? FlutterLocalNotificationsPlugin(), _onTapPayload = onTapPayload; final FlutterLocalNotificationsPlugin _plugin; final void Function(String payload)? _onTapPayload; Future? _initializeFuture; @override Future showDigestReady(int count) async { if (!_supportsNotifications()) { return; } await _ensureInitialized(); await _plugin.show( id: 8124, title: 'Relationship digest ready', body: '$count private ${count == 1 ? 'suggestion is' : 'suggestions are'} ready to review.', notificationDetails: const NotificationDetails( android: AndroidNotificationDetails( 'relationship_saver_ai_digest', 'Relationship Digest', channelDescription: 'Private AI digest suggestions ready for review', importance: Importance.defaultImportance, priority: Priority.defaultPriority, ), iOS: DarwinNotificationDetails(), macOS: DarwinNotificationDetails(), ), payload: aiDigestNotificationPayload, ); } Future _ensureInitialized() { return _initializeFuture ??= _plugin.initialize( settings: const InitializationSettings( android: AndroidInitializationSettings('@mipmap/ic_launcher'), iOS: DarwinInitializationSettings(), macOS: DarwinInitializationSettings(), ), onDidReceiveNotificationResponse: (NotificationResponse response) { final String? payload = response.payload; if (payload != null && payload.isNotEmpty) { _onTapPayload?.call(payload); } }, ); } bool _supportsNotifications() { if (kIsWeb) { return false; } return defaultTargetPlatform != TargetPlatform.linux; } } final Provider aiDigestNotifierProvider = Provider((Ref ref) { return LocalAiDigestNotifier( onTapPayload: ref.watch(aiDigestNotificationIntentBusProvider).emitTap, ); });