forked from Nexus/nexus
refactor and improve notification handling
This commit is contained in:
parent
9cf16db669
commit
765e96cce4
2 changed files with 91 additions and 63 deletions
|
|
@ -10,8 +10,16 @@ import "package:nexus/main.dart";
|
||||||
import "package:flutter_local_notifications/flutter_local_notifications.dart";
|
import "package:flutter_local_notifications/flutter_local_notifications.dart";
|
||||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||||
import "package:nexus/controllers/notification_request.dart";
|
import "package:nexus/controllers/notification_request.dart";
|
||||||
|
import "package:nexus/models/push_notification.dart";
|
||||||
import "package:xdg_desktop_portal/xdg_desktop_portal.dart";
|
import "package:xdg_desktop_portal/xdg_desktop_portal.dart";
|
||||||
|
|
||||||
|
typedef NotificationMessage = ({
|
||||||
|
NotificationUser sender,
|
||||||
|
NotificationUser self,
|
||||||
|
File? senderAvatar,
|
||||||
|
bool isDm,
|
||||||
|
});
|
||||||
|
|
||||||
class NotificationController
|
class NotificationController
|
||||||
extends AsyncNotifier<FlutterLocalNotificationsPlugin> {
|
extends AsyncNotifier<FlutterLocalNotificationsPlugin> {
|
||||||
@override
|
@override
|
||||||
|
|
@ -140,24 +148,24 @@ class NotificationController
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Passing [message] shows it as a chat message in the conversation for
|
||||||
|
/// [threadId], naming the sender in group chats.
|
||||||
Future<void> send({
|
Future<void> send({
|
||||||
required int id,
|
required int id,
|
||||||
required String title,
|
required String title,
|
||||||
String? body,
|
required String body,
|
||||||
File? icon,
|
|
||||||
String? payload,
|
String? payload,
|
||||||
String? senderName,
|
|
||||||
File? senderAvatar,
|
|
||||||
String? selfName,
|
|
||||||
bool isGroup = false,
|
|
||||||
bool sound = true,
|
|
||||||
DateTime? timestamp,
|
|
||||||
String? threadId,
|
String? threadId,
|
||||||
|
DateTime? timestamp,
|
||||||
|
File? icon,
|
||||||
|
bool sound = true,
|
||||||
|
NotificationMessage? message,
|
||||||
}) async {
|
}) async {
|
||||||
debugPrint("Sending notification for $id");
|
debugPrint("Sending notification for $id");
|
||||||
|
|
||||||
// In DMs the title is already the sender, so only prefix in groups
|
// In DMs the title is already the sender
|
||||||
final prefix = isGroup ? senderName : null;
|
final sender = message == null || message.isDm ? null : message.sender;
|
||||||
|
final prefixedBody = sender == null ? body : "${sender.name}: $body";
|
||||||
|
|
||||||
if (Platform.isLinux) {
|
if (Platform.isLinux) {
|
||||||
final portal = await ref.read(PortalController.provider.future);
|
final portal = await ref.read(PortalController.provider.future);
|
||||||
|
|
@ -166,14 +174,14 @@ class NotificationController
|
||||||
await portal.notification.addNotification(
|
await portal.notification.addNotification(
|
||||||
id.toString(),
|
id.toString(),
|
||||||
title: title,
|
title: title,
|
||||||
body: prefix == null || body == null ? body : "$prefix: $body",
|
body: prefixedBody,
|
||||||
markupBody: prefix == null || body == null
|
markupBody: sender == null
|
||||||
? null
|
? null
|
||||||
: "<b>${escape.convert(prefix)}</b>: ${escape.convert(body)}",
|
: "<b>${escape.convert(sender.name)}</b>: ${escape.convert(body)}",
|
||||||
defaultAction: "app.event",
|
defaultAction: "app.event",
|
||||||
defaultActionTarget: payload,
|
defaultActionTarget: payload,
|
||||||
sound: sound ? null : const XdgNotificationSoundSilent(),
|
sound: sound ? null : const XdgNotificationSoundSilent(),
|
||||||
category: XdgNotificationCategory.imReceived,
|
category: message == null ? null : XdgNotificationCategory.imReceived,
|
||||||
priority: .normal,
|
priority: .normal,
|
||||||
buttons: [
|
buttons: [
|
||||||
// TODO: Impl when notif daemons actualy support imReplyWithText
|
// TODO: Impl when notif daemons actualy support imReplyWithText
|
||||||
|
|
@ -184,11 +192,13 @@ class NotificationController
|
||||||
// ),
|
// ),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
} else {
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
final controller = await future;
|
final controller = await future;
|
||||||
|
|
||||||
// Append to the conversation already shown under this id, if any
|
// Append to the conversation already shown under this id, if any
|
||||||
final existingStyle = Platform.isAndroid
|
final existingStyle = Platform.isAndroid && message != null
|
||||||
? await controller
|
? await controller
|
||||||
.resolvePlatformSpecificImplementation<
|
.resolvePlatformSpecificImplementation<
|
||||||
AndroidFlutterLocalNotificationsPlugin
|
AndroidFlutterLocalNotificationsPlugin
|
||||||
|
|
@ -201,28 +211,50 @@ class NotificationController
|
||||||
presentSound: sound,
|
presentSound: sound,
|
||||||
threadIdentifier: threadId,
|
threadIdentifier: threadId,
|
||||||
);
|
);
|
||||||
final notificationDetails = NotificationDetails(
|
|
||||||
android: .new(
|
await controller.show(
|
||||||
|
id: id,
|
||||||
|
title: title,
|
||||||
|
body: prefixedBody,
|
||||||
|
payload: payload,
|
||||||
|
notificationDetails: .new(
|
||||||
|
android: message == null
|
||||||
|
? .new(
|
||||||
|
"general",
|
||||||
|
"General",
|
||||||
|
silent: !sound,
|
||||||
|
when: timestamp?.millisecondsSinceEpoch,
|
||||||
|
largeIcon: icon == null
|
||||||
|
? null
|
||||||
|
: FilePathAndroidBitmap(icon.path),
|
||||||
|
styleInformation: BigTextStyleInformation(body),
|
||||||
|
)
|
||||||
|
: .new(
|
||||||
"messages",
|
"messages",
|
||||||
"Messages",
|
"Messages",
|
||||||
silent: !sound,
|
silent: !sound,
|
||||||
largeIcon: icon == null ? null : FilePathAndroidBitmap(icon.path),
|
when: timestamp?.millisecondsSinceEpoch,
|
||||||
styleInformation: senderName == null || body == null
|
category: .message,
|
||||||
|
largeIcon: icon == null
|
||||||
? null
|
? null
|
||||||
: MessagingStyleInformation(
|
: FilePathAndroidBitmap(icon.path),
|
||||||
.new(name: selfName ?? "You"),
|
styleInformation: MessagingStyleInformation(
|
||||||
conversationTitle: isGroup ? title : null,
|
.new(key: message.self.id, name: message.self.name),
|
||||||
groupConversation: isGroup,
|
conversationTitle: message.isDm ? null : title,
|
||||||
|
groupConversation: !message.isDm,
|
||||||
messages: [
|
messages: [
|
||||||
...?existingStyle?.messages,
|
...?existingStyle?.messages,
|
||||||
.new(
|
.new(
|
||||||
body,
|
body,
|
||||||
timestamp ?? .now(),
|
timestamp ?? .now(),
|
||||||
.new(
|
.new(
|
||||||
name: senderName,
|
key: message.sender.id,
|
||||||
icon: senderAvatar == null
|
name: message.sender.name,
|
||||||
|
icon: message.senderAvatar == null
|
||||||
? null
|
? null
|
||||||
: BitmapFilePathAndroidIcon(senderAvatar.path),
|
: BitmapFilePathAndroidIcon(
|
||||||
|
message.senderAvatar!.path,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
@ -237,16 +269,8 @@ class NotificationController
|
||||||
? null
|
? null
|
||||||
: .new(id: threadId, title: title, arguments: payload ?? ""),
|
: .new(id: threadId, title: title, arguments: payload ?? ""),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
await controller.show(
|
|
||||||
id: id,
|
|
||||||
title: title,
|
|
||||||
body: prefix == null || body == null ? body : "$prefix: $body",
|
|
||||||
notificationDetails: notificationDetails,
|
|
||||||
payload: payload,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static final provider =
|
static final provider =
|
||||||
|
|
|
||||||
|
|
@ -122,17 +122,21 @@ class UnifiedPushController extends AsyncNotifier<String?> {
|
||||||
: notification.eventId)
|
: notification.eventId)
|
||||||
.hashCode &
|
.hashCode &
|
||||||
0x7fffffff,
|
0x7fffffff,
|
||||||
title: notification.roomName,
|
|
||||||
icon: icon,
|
|
||||||
payload: notification.eventRowId.toString(),
|
|
||||||
body: notification.text,
|
|
||||||
senderName: pmp?.name ?? notification.sender.name,
|
|
||||||
senderAvatar: senderAvatar,
|
|
||||||
selfName: notification.self.name,
|
|
||||||
isGroup: !notification.isDm,
|
|
||||||
sound: notification.sound,
|
|
||||||
timestamp: notification.timestamp,
|
|
||||||
threadId: notification.roomId,
|
threadId: notification.roomId,
|
||||||
|
title: notification.roomName,
|
||||||
|
body: notification.text,
|
||||||
|
payload: notification.eventRowId.toString(),
|
||||||
|
timestamp: notification.timestamp,
|
||||||
|
icon: icon,
|
||||||
|
sound: notification.sound,
|
||||||
|
message: (
|
||||||
|
sender: pmp == null
|
||||||
|
? notification.sender
|
||||||
|
: pmp.copyWith(id: "${notification.sender.id}/${pmp.id}"),
|
||||||
|
self: notification.self,
|
||||||
|
senderAvatar: senderAvatar,
|
||||||
|
isDm: notification.isDm,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (isInBackground) exit(0);
|
if (isInBackground) exit(0);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue