diff --git a/lib/controllers/notifications.dart b/lib/controllers/notifications.dart index 2109cb7..d9bcd8f 100644 --- a/lib/controllers/notifications.dart +++ b/lib/controllers/notifications.dart @@ -1,9 +1,11 @@ +import "dart:convert"; import "dart:io"; import "package:flutter_local_notifications/flutter_local_notifications.dart"; // ignore: implementation_imports import "package:flutter_local_notifications_linux/src/model/hint.dart"; import "package:flutter_riverpod/flutter_riverpod.dart"; +import "package:nexus/controllers/event.dart"; class NotificationsController extends AsyncNotifier { @@ -26,7 +28,11 @@ class NotificationsController linux: .new(defaultActionName: "Open"), ), onDidReceiveNotificationResponse: (details) { - print(details.data); + if (details.payload case final payload?) { + final event = ref.watch( + EventController.provider(.fromJson(json.decode(payload))), + ); + } }, ); @@ -75,8 +81,6 @@ class NotificationsController "Messages", largeIcon: icon == null ? null : FilePathAndroidBitmap(icon.path), ), - iOS: .new(), - macOS: .new(), linux: .new( customHints: icon == null ? null @@ -87,6 +91,9 @@ class NotificationsController ), ], ), + // TODO: See if icons can be added to iOS, macOS, and Windows notifications (#68) + iOS: .new(), + macOS: .new(), windows: .new(), ); diff --git a/lib/controllers/unified_push.dart b/lib/controllers/unified_push.dart index 0698bda..1e90114 100644 --- a/lib/controllers/unified_push.dart +++ b/lib/controllers/unified_push.dart @@ -3,15 +3,19 @@ import "dart:io"; import "package:flutter_riverpod/flutter_riverpod.dart"; import "package:intl/intl.dart"; +import "package:nexus/controllers/key.dart"; import "package:nexus/controllers/notifications.dart"; import "package:nexus/controllers/rooms.dart"; import "package:nexus/main.dart"; import "package:nexus/controllers/client.dart"; import "package:nexus/controllers/client_state.dart"; import "package:nexus/models/content/message.dart"; +import "package:nexus/models/content/sticker.dart"; +import "package:nexus/models/requests/get_event.dart"; import "package:nexus/models/requests/register_pusher.dart"; import "package:unifiedpush/unifiedpush.dart"; import "package:unifiedpush_storage_shared_preferences/storage.dart"; +import "package:window_manager/window_manager.dart"; class UnifiedPushController extends AsyncNotifier { @override @@ -23,32 +27,39 @@ class UnifiedPushController extends AsyncNotifier { storage: UnifiedPushStorageSharedPreferences(), background: isInBackground, ), - onNewEndpoint: (endpoint, instance) async { - await client.registerPusher( - .new( - appDisplayName: "Nexus", - appId: "nexus.federated.nexus", - data: PusherData.webPush( - url: Uri.parse(endpoint.url), - auth: endpoint.pubKeySet!.auth, - ), - deviceDisplayName: - "Nexus on ${toBeginningOfSentenceCase(Platform.operatingSystem)}", - kind: .webPush, - lang: "en", - pushKey: endpoint.pubKeySet!.pubKey, + onNewEndpoint: (endpoint, instance) => client.registerPusher( + .new( + appDisplayName: "Nexus", + appId: "nexus.federated.nexus", + data: PusherData.webPush( + url: Uri.parse(endpoint.url), + auth: endpoint.pubKeySet!.auth, ), - ); - }, + deviceDisplayName: + "Nexus on ${toBeginningOfSentenceCase(Platform.operatingSystem)}", + kind: .webPush, + lang: "en", + pushKey: endpoint.pubKeySet!.pubKey, + ), + ), onMessage: (message, instance) async { if (message.decrypted == false) { - // TODO: Handle more gracefully, show option to re-register pusher - throw Exception("Failed to decrypt notification"); + throw Exception( + "Failed to decrypt notification. Try toggling off and on UnifiedPush in settings.", + ); } final event = await client.handlePush( json.decode(String.fromCharCodes(message.content)), ); + if (event.unreadType?.shouldNotify != true || + (!isInBackground && + await windowManager.isFocused() && + ref.watch(KeyController.provider(KeyController.roomKey)) == + event.roomId)) { + return; + } + final room = ref.read( RoomsController.provider.select((rooms) => rooms[event.roomId]), ); @@ -64,14 +75,19 @@ class UnifiedPushController extends AsyncNotifier { .read(NotificationsController.provider.notifier) .send( id: event.eventId.hashCode & 0x7fffffff, - title: room?.metadata?.name ?? "New Message", + title: room?.metadata?.name ?? "New Event", icon: icon, + payload: json.encode( + GetEventRequest(eventId: event.eventId, roomId: event.roomId), + ), body: switch (event.content) { - MessageContent(:final body) => body, - // TODO: Handle more types + MessageContent(:final body?) || + StickerContent(:final body) => body, _ => null, }, ); + + if (isInBackground) exit(0); }, onRegistrationFailed: (error, instance) => throw error, onUnregistered: (instance) => ref.invalidateSelf(),