import 'dart:async'; import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import '../Entities/drift_database.dart'; import '../Repositories/transaction_repository.dart'; import '../Services/date_service.dart'; import '../Services/initializer.dart'; import '../Services/transaction_service.dart'; import 'port_controller.dart'; import 'transaction_controller.dart'; /// Kümmert sich um die Verwendung von Benachrichtigungen auf verschiedenen /// Plattformen class LocalNotifications { /// Gibt die aktuell gültige Instanz dieser Klasse zurück factory LocalNotifications() => _instance; LocalNotifications._internal() { unawaited(_initialise()); } static final _instance = LocalNotifications._internal(); final FlutterLocalNotificationsPlugin _localNotificationsPlugin = FlutterLocalNotificationsPlugin(); final Initializer _initializer = Initializer(); Future _initialise() async { if (_initializer.initialized) { return; } await _localNotificationsPlugin .resolvePlatformSpecificImplementation< AndroidFlutterLocalNotificationsPlugin >() ?.requestNotificationsPermission(); const AndroidInitializationSettings androidInitializationSettings = AndroidInitializationSettings('app_icon'); const LinuxInitializationSettings linuxInitializationSettings = LinuxInitializationSettings(defaultActionName: 'Öffnen'); const InitializationSettings initializationSettings = InitializationSettings( android: androidInitializationSettings, linux: linuxInitializationSettings, ); await _localNotificationsPlugin.initialize( initializationSettings, onDidReceiveNotificationResponse: _onDidReceiveNotificationResponse, onDidReceiveBackgroundNotificationResponse: notificationTapBackground, ); if (!kIsWeb && !Platform.isLinux) { final NotificationAppLaunchDetails? notificationAppLaunchDetails = await _localNotificationsPlugin.getNotificationAppLaunchDetails(); if (notificationAppLaunchDetails?.didNotificationLaunchApp ?? false) { _onDidReceiveNotificationResponse( NotificationResponse( notificationResponseType: NotificationResponseType.selectedNotification, payload: notificationAppLaunchDetails!.notificationResponse?.payload, ), ); } } _initializer.setInitialized(); } /// Zeigt eine Benachrichtigung an, die einen dazu auffordert, /// automatisch generierte Transaktionen zu überprüfen Future showTransactionsToCheckNotification( final List transactions, ) async { await _initializer.waitUntilInitialized(); const AndroidNotificationDetails androidNotificationDetails = AndroidNotificationDetails( 'transactions_to_check', 'Transaktionen zu prüfen', channelDescription: 'Zeigt an, dass es zu prüfende Transaktionen gibt', actions: [ AndroidNotificationAction('mark_checked', 'Als geprüft markieren'), AndroidNotificationAction( 'show_transactions', 'Anzeigen', showsUserInterface: true, ), // TODO: Prüfen, ob die App geöffnet wird ], ); const LinuxNotificationDetails linuxNotificationDetails = LinuxNotificationDetails( actions: [ LinuxNotificationAction( key: 'mark_checked', label: 'Als geprüft markieren', ), LinuxNotificationAction( key: 'show_transactions', label: 'Anzeigen', ), ], ); const NotificationDetails notificationDetails = NotificationDetails( android: androidNotificationDetails, linux: linuxNotificationDetails, ); final String title; final String body; if (transactions.length == 1) { title = 'Transaktion prüfen'; body = 'Es wurde eine neue Transaktion anhand einer ' 'wiederkehrenden Transaktion erstellt:\n' '${transactions[0].name} - ' '${DateService.dateFormat.format(transactions[0].date!)} - ' '${transactions[0].amount} €\n\n' 'Diese muss überprüft werden!'; } else { int counter = 0; final List transactionsToShow = []; for (final Transaction transaction in transactions) { if (counter >= 10) { break; } transactionsToShow.add( '${transaction.name} - ' '${DateService.dateFormat.format(transaction.date!)} - ' '${transaction.amount}', ); counter++; } title = 'Transaktionen prüfen'; body = 'Es wurden neue Transaktionen anhand ' 'wiederkehrender Transaktionen erstellt:\n' '${transactionsToShow.join('\n')}\n\n' 'Diese müssen überprüft werden!'; } await _localNotificationsPlugin.show( 0, title, body, notificationDetails, payload: TransactionService.transactionsToString(transactions), ); } void _onDidReceiveNotificationResponse( final NotificationResponse notificationResponse, ) { if (notificationResponse.actionId == 'mark_checked') { TransactionRepository().markTransactionsAsChecked( TransactionService.transactionsFromString(notificationResponse.payload), ); if (kIsWeb) { unawaited(TransactionController().updateTransactions()); } else { PortController().getPort('update-transactions')?.send('ready'); } } else { if (kIsWeb) { TransactionController().goToTransactions( transactions: TransactionService.transactionsFromString( notificationResponse.payload, ), ); } else { PortController() .getPort('go-to-transactions') ?.send(notificationResponse.payload); } } } /// Wird von den LocalNotifications aufgerufen, /// wenn eine Aktion im Hintergrund abgehandelt werden soll @pragma('vm:entry-point') static void notificationTapBackground( final NotificationResponse notificationResponse, ) { if (notificationResponse.actionId == 'mark_checked') { TransactionRepository().markTransactionsAsChecked( TransactionService.transactionsFromString(notificationResponse.payload), ); } } }