Feat: Fügt Benachrichtigungen für nicht überprüfte Transaktionen hinzu
This commit is contained in:
@@ -5,8 +5,8 @@ import 'package:flutter/foundation.dart';
|
||||
import 'package:isolate_manager/isolate_manager.dart';
|
||||
import 'package:workmanager/workmanager.dart';
|
||||
|
||||
import '../Tasks/workers.dart';
|
||||
import '../Tasks/workmanager_workers.dart';
|
||||
import '../Tasks/BackgroundHandler/workers.dart';
|
||||
import '../Tasks/BackgroundHandler/workmanager_workers.dart';
|
||||
|
||||
/// Erstellt Hintergrundtasks und führt diese aus
|
||||
class BackgroundTaskController {
|
||||
@@ -22,6 +22,14 @@ class BackgroundTaskController {
|
||||
initialDelay: const Duration(minutes: 1),
|
||||
),
|
||||
);
|
||||
unawaited(
|
||||
Workmanager().registerPeriodicTask(
|
||||
'show-notifications',
|
||||
'show_notifications',
|
||||
frequency: const Duration(minutes: 120),
|
||||
initialDelay: const Duration(minutes: 5),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
unawaited(
|
||||
IsolateManager.runFunction(runTask, {
|
||||
@@ -30,6 +38,16 @@ class BackgroundTaskController {
|
||||
'frequencyMinutes': 30,
|
||||
}),
|
||||
);
|
||||
|
||||
if (!kIsWeb) {
|
||||
unawaited(
|
||||
IsolateManager.runFunction(runTask, {
|
||||
'taskName': 'show_notifications',
|
||||
'initialDelayMinutes': 5,
|
||||
'frequencyMinutes': 120,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
204
lib/Controller/local_notifications.dart
Normal file
204
lib/Controller/local_notifications.dart
Normal file
@@ -0,0 +1,204 @@
|
||||
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<void> _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<void> showTransactionsToCheckNotification(
|
||||
final List<Transaction> 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>[
|
||||
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<String> 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),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import 'package:drift/drift.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:logger/logger.dart';
|
||||
import 'package:routemaster/routemaster.dart';
|
||||
|
||||
import '../Entities/drift_database.dart';
|
||||
import '../Pages/Dialog/dialog_action.dart';
|
||||
@@ -13,6 +14,8 @@ import '../Pages/Dialog/dialog_input_field_type_enum.dart';
|
||||
import '../Pages/Dialog/dialog_type_enum.dart';
|
||||
import '../Pages/Dialog/dynamic_dialog.dart';
|
||||
import '../Repositories/transaction_repository.dart';
|
||||
import '../Services/navigation_service.dart';
|
||||
import '../Services/transaction_service.dart';
|
||||
import 'account_controller.dart';
|
||||
import 'port_controller.dart';
|
||||
|
||||
@@ -72,13 +75,31 @@ class TransactionController {
|
||||
});
|
||||
|
||||
if (!kIsWeb) {
|
||||
final ReceivePort receivePort = ReceivePort()
|
||||
final ReceivePort updateTransactionsReceivePort = ReceivePort()
|
||||
..listen((_) {
|
||||
Logger().i('Received update-transactions signal');
|
||||
unawaited(updateTransactions());
|
||||
});
|
||||
|
||||
PortController().addPort(receivePort.sendPort, 'update-transactions');
|
||||
PortController().addPort(
|
||||
updateTransactionsReceivePort.sendPort,
|
||||
'update-transactions',
|
||||
);
|
||||
|
||||
final ReceivePort gotToTransactionsReceivePort = ReceivePort()
|
||||
..listen((final value) {
|
||||
Logger().i('Received go-to-transactions signal');
|
||||
|
||||
final List<Transaction> transactions =
|
||||
TransactionService.transactionsFromString(value);
|
||||
|
||||
goToTransactions(transactions: transactions);
|
||||
});
|
||||
|
||||
PortController().addPort(
|
||||
gotToTransactionsReceivePort.sendPort,
|
||||
'go-to-transactions',
|
||||
);
|
||||
}
|
||||
|
||||
unawaited(updateTransactions());
|
||||
@@ -121,6 +142,21 @@ class TransactionController {
|
||||
}
|
||||
}
|
||||
|
||||
/// Wechselt zur Übersicht über die Transaktionen
|
||||
void goToTransactions({final List<Transaction>? transactions}) {
|
||||
final BuildContext? context = NavigationService.getCurrentBuildContext();
|
||||
|
||||
if (context != null && transactions != null) {
|
||||
if (transactions.length == 1) {
|
||||
Routemaster.of(
|
||||
context,
|
||||
).push('/trend', queryParameters: {'name': transactions.first.name});
|
||||
}
|
||||
|
||||
Routemaster.of(context).replace('/trend');
|
||||
}
|
||||
}
|
||||
|
||||
/// Startet den Prozess, um eine neue Transaktion anzulegen
|
||||
void newTransactionHandler() {
|
||||
unawaited(_newTransactionDialog?.show());
|
||||
|
||||
Reference in New Issue
Block a user