diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 167602f73..f7688fc0e 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -135,6 +135,9 @@
+
+
+
notificationTap(
+ response,
+ client: client,
+ router: FluffyChatApp.router,
+ ),
+ onDidReceiveBackgroundNotificationResponse: notificationTapBackground,
);
Logs().v('Flutter Local Notifications initialized');
//firebase.setListeners(
@@ -278,7 +284,14 @@ class BackgroundPush {
return;
}
_wentToRoomOnStartup = true;
- goToRoom(details.notificationResponse);
+ final response = details.notificationResponse;
+ if (response != null) {
+ notificationTap(
+ response,
+ client: client,
+ router: FluffyChatApp.router,
+ );
+ }
});
}
@@ -323,30 +336,6 @@ class BackgroundPush {
);
}
- Future goToRoom(NotificationResponse? response) async {
- try {
- final roomId = response?.payload;
- Logs().v('[Push] Attempting to go to room $roomId...');
- if (roomId == null) {
- return;
- }
- await client.roomsLoading;
- await client.accountDataLoading;
- if (client.getRoomById(roomId) == null) {
- await client
- .waitForRoomInSync(roomId)
- .timeout(const Duration(seconds: 30));
- }
- FluffyChatApp.router.go(
- client.getRoomById(roomId)?.membership == Membership.invite
- ? '/rooms'
- : '/rooms/$roomId',
- );
- } catch (e, s) {
- Logs().e('[Push] Failed to open room', e, s);
- }
- }
-
Future setupUp() async {
await UnifiedPushUi(matrix!.context, ["default"], UPFunctions())
.registerAppWithDialog();
diff --git a/lib/utils/notification_background_handler.dart b/lib/utils/notification_background_handler.dart
new file mode 100644
index 000000000..e604ddcad
--- /dev/null
+++ b/lib/utils/notification_background_handler.dart
@@ -0,0 +1,80 @@
+import 'package:collection/collection.dart';
+import 'package:flutter_local_notifications/flutter_local_notifications.dart';
+import 'package:go_router/go_router.dart';
+import 'package:matrix/matrix.dart';
+import 'package:shared_preferences/shared_preferences.dart';
+
+import 'package:fluffychat/utils/client_manager.dart';
+
+@pragma('vm:entry-point')
+void notificationTapBackground(
+ NotificationResponse notificationResponse,
+) async {
+ final client = (await ClientManager.getClients(
+ initialize: false,
+ store: await SharedPreferences.getInstance(),
+ ))
+ .first;
+ notificationTap(notificationResponse, client: client);
+}
+
+void notificationTap(
+ NotificationResponse notificationResponse, {
+ GoRouter? router,
+ required Client client,
+}) async {
+ switch (notificationResponse.notificationResponseType) {
+ case NotificationResponseType.selectedNotification:
+ final roomId = notificationResponse.payload;
+ if (roomId == null) return;
+
+ if (router == null) {
+ Logs().v('Ignore select notification action in background mode');
+ return;
+ }
+ Logs().v('Open room from notification tap', roomId);
+ await client.roomsLoading;
+ await client.accountDataLoading;
+ if (client.getRoomById(roomId) == null) {
+ await client
+ .waitForRoomInSync(roomId)
+ .timeout(const Duration(seconds: 30));
+ }
+ router.go(
+ client.getRoomById(roomId)?.membership == Membership.invite
+ ? '/rooms'
+ : '/rooms/$roomId',
+ );
+ case NotificationResponseType.selectedNotificationAction:
+ final actionType = FluffyChatNotificationActions.values.singleWhereOrNull(
+ (action) => action.name == notificationResponse.actionId,
+ );
+ if (actionType == null) {
+ throw Exception('Selected notification with action but no action ID');
+ }
+ final roomId = notificationResponse.payload;
+ if (roomId == null) {
+ throw Exception('Selected notification with action but no payload');
+ }
+ final room = client.getRoomById(roomId);
+ if (room == null) {
+ throw Exception(
+ 'Selected notification with action but unknown room $roomId',
+ );
+ }
+ switch (actionType) {
+ case FluffyChatNotificationActions.markAsRead:
+ await room.setReadMarker(room.lastEvent!.eventId);
+ case FluffyChatNotificationActions.reply:
+ final input = notificationResponse.input;
+ if (input == null || input.isEmpty) {
+ throw Exception(
+ 'Selected notification with reply action but without input',
+ );
+ }
+ await room.sendTextEvent(input);
+ }
+ }
+}
+
+enum FluffyChatNotificationActions { markAsRead, reply }
diff --git a/lib/utils/push_helper.dart b/lib/utils/push_helper.dart
index 39f6bd90f..078746c61 100644
--- a/lib/utils/push_helper.dart
+++ b/lib/utils/push_helper.dart
@@ -15,6 +15,7 @@ import 'package:fluffychat/l10n/l10n.dart';
import 'package:fluffychat/utils/client_download_content_extension.dart';
import 'package:fluffychat/utils/client_manager.dart';
import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart';
+import 'package:fluffychat/utils/notification_background_handler.dart';
import 'package:fluffychat/utils/platform_infos.dart';
const notificationAvatarDimension = 128;
@@ -277,6 +278,19 @@ Future _tryPushHelper(
importance: Importance.high,
priority: Priority.max,
groupKey: event.room.spaceParents.firstOrNull?.roomId ?? 'rooms',
+ actions: [
+ AndroidNotificationAction(
+ FluffyChatNotificationActions.markAsRead.name,
+ l10n.markAsRead,
+ ),
+ AndroidNotificationAction(
+ FluffyChatNotificationActions.reply.name,
+ l10n.reply,
+ inputs: [
+ const AndroidNotificationActionInput(),
+ ],
+ ),
+ ],
);
const iOSPlatformChannelSpecifics = DarwinNotificationDetails();
final platformChannelSpecifics = NotificationDetails(