From 9a99072108dd9ac0598adb0f3b3f1459d068f9a6 Mon Sep 17 00:00:00 2001 From: Krille Fear Date: Sat, 22 Jan 2022 11:16:40 +0100 Subject: [PATCH] feat: Display room avatar and actions and play sound for linux desktop notifications --- assets/l10n/intl_en.arb | 4 +- .../local_notifications_extension.dart | 91 +++++++++++++++++++ lib/widgets/matrix.dart | 48 +--------- 3 files changed, 97 insertions(+), 46 deletions(-) create mode 100644 lib/widgets/local_notifications_extension.dart diff --git a/assets/l10n/intl_en.arb b/assets/l10n/intl_en.arb index ef4877897..40f0d56ac 100644 --- a/assets/l10n/intl_en.arb +++ b/assets/l10n/intl_en.arb @@ -2706,5 +2706,7 @@ "storyPrivacyWarning": "Please note that people can see and contact each other in your story. Your stories will be visible for 24 hours but there is no guarantee that they will be deleted from all devices and servers.", "@storyPrivacyWarning": {}, "iUnderstand": "I understand", - "@iUnderstand": {} + "@iUnderstand": {}, + "dismiss": "Dismiss", + "markAsRead": "Mark as read" } diff --git a/lib/widgets/local_notifications_extension.dart b/lib/widgets/local_notifications_extension.dart new file mode 100644 index 000000000..e2c20c6e0 --- /dev/null +++ b/lib/widgets/local_notifications_extension.dart @@ -0,0 +1,91 @@ +import 'dart:io'; + +import 'package:flutter/foundation.dart'; + +import 'package:desktop_notifications/desktop_notifications.dart'; +import 'package:flutter_cache_manager/flutter_cache_manager.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; +import 'package:matrix/matrix.dart'; +import 'package:universal_html/html.dart' as html; + +import 'package:fluffychat/config/app_config.dart'; +import 'package:fluffychat/utils/matrix_sdk_extensions.dart/matrix_locals.dart'; +import 'package:fluffychat/widgets/matrix.dart'; + +extension LocalNotificationsExtension on MatrixState { + void showLocalNotification(EventUpdate eventUpdate) async { + final roomId = eventUpdate.roomID; + if (webHasFocus && activeRoomId == roomId) return; + final room = client.getRoomById(roomId); + if (room.notificationCount == 0) return; + final event = Event.fromJson(eventUpdate.content, room); + final title = + room.getLocalizedDisplayname(MatrixLocals(L10n.of(widget.context))); + final body = event.getLocalizedBody( + MatrixLocals(L10n.of(widget.context)), + withSenderNamePrefix: + !room.isDirectChat || room.lastEvent.senderId == client.userID, + plaintextBody: true, + hideReply: true, + hideEdit: true, + ); + final icon = event.sender.avatarUrl?.getThumbnail(client, + width: 64, height: 64, method: ThumbnailMethod.crop) ?? + room.avatar?.getThumbnail(client, + width: 64, height: 64, method: ThumbnailMethod.crop); + if (kIsWeb) { + html.AudioElement() + ..src = 'assets/assets/sounds/notification.wav' + ..autoplay = true + ..load(); + html.Notification( + title, + body: body, + icon: icon.toString(), + ); + } else if (Platform.isLinux) { + final appIconUrl = room.avatar + ?.getThumbnail( + room.client, + width: 56, + height: 56, + ) + .toString(); + final appIconFile = await DefaultCacheManager().getSingleFile(appIconUrl); + final notification = await linuxNotifications.notify( + title, + body: body, + replacesId: linuxNotificationIds[roomId] ?? 0, + appName: AppConfig.applicationName, + appIcon: appIconFile.path, + actions: [ + NotificationAction( + DesktopNotificationActions.dismiss.name, + L10n.of(widget.context).dismiss, + ), + NotificationAction( + DesktopNotificationActions.seen.name, + L10n.of(widget.context).markAsRead, + ), + ], + hints: [ + NotificationHint.soundName('message-new-instant'), + ], + ); + notification.action.then((actionStr) { + final action = DesktopNotificationActions.values + .singleWhere((a) => a.name == actionStr); + switch (action) { + case DesktopNotificationActions.seen: + room.setReadMarker(event.eventId, mRead: event.eventId); + break; + case DesktopNotificationActions.dismiss: + break; + } + }); + linuxNotificationIds[roomId] = notification.id; + } + } +} + +enum DesktopNotificationActions { seen, dismiss } diff --git a/lib/widgets/matrix.dart b/lib/widgets/matrix.dart index 440d06434..be3d46e7a 100644 --- a/lib/widgets/matrix.dart +++ b/lib/widgets/matrix.dart @@ -20,7 +20,6 @@ import 'package:vrouter/vrouter.dart'; import 'package:fluffychat/config/themes.dart'; import 'package:fluffychat/utils/client_manager.dart'; -import 'package:fluffychat/utils/matrix_sdk_extensions.dart/matrix_locals.dart'; import 'package:fluffychat/utils/platform_infos.dart'; import 'package:fluffychat/utils/sentry_controller.dart'; import 'package:fluffychat/utils/uia_request_manager.dart'; @@ -31,6 +30,7 @@ import '../utils/account_bundles.dart'; import '../utils/background_push.dart'; import '../utils/famedlysdk_store.dart'; import '../utils/platform_infos.dart'; +import 'local_notifications_extension.dart'; class Matrix extends StatefulWidget { static const String callNamespace = 'chat.fluffy.jitsi_call'; @@ -226,51 +226,9 @@ class MatrixState extends State with WidgetsBindingObserver { String get activeRoomId => VRouter.of(navigatorContext).pathParameters['roomid']; - void _showLocalNotification(EventUpdate eventUpdate) async { - final roomId = eventUpdate.roomID; - if (webHasFocus && activeRoomId == roomId) return; - final room = client.getRoomById(roomId); - if (room.notificationCount == 0) return; - final event = Event.fromJson(eventUpdate.content, room); - final title = - room.getLocalizedDisplayname(MatrixLocals(L10n.of(widget.context))); - final body = event.getLocalizedBody( - MatrixLocals(L10n.of(widget.context)), - withSenderNamePrefix: - !room.isDirectChat || room.lastEvent.senderId == client.userID, - plaintextBody: true, - hideReply: true, - hideEdit: true, - ); - final icon = event.sender.avatarUrl?.getThumbnail(client, - width: 64, height: 64, method: ThumbnailMethod.crop) ?? - room.avatar?.getThumbnail(client, - width: 64, height: 64, method: ThumbnailMethod.crop); - if (kIsWeb) { - html.AudioElement() - ..src = 'assets/assets/sounds/notification.wav' - ..autoplay = true - ..load(); - html.Notification( - title, - body: body, - icon: icon.toString(), - ); - } else if (Platform.isLinux) { - final notification = await linuxNotifications.notify( - title, - body: body, - replacesId: _linuxNotificationIds[roomId] ?? 0, - appName: AppConfig.applicationName, - appIcon: "im.fluffychat.Fluffychat", - ); - _linuxNotificationIds[roomId] = notification.id; - } - } - final linuxNotifications = PlatformInfos.isLinux ? NotificationsClient() : null; - final Map _linuxNotificationIds = {}; + final Map linuxNotificationIds = {}; @override void initState() { @@ -385,7 +343,7 @@ class MatrixState extends State with WidgetsBindingObserver { [EventTypes.Message, EventTypes.Sticker, EventTypes.Encrypted] .contains(e.content['type']) && e.content['sender'] != c.userID) - .listen(_showLocalNotification); + .listen(showLocalNotification); }); } }