feat: notification actions android

unified push notifications seem to stop after one aciton, this is broken atm
This commit is contained in:
td 2023-02-11 19:22:00 +05:30
parent 78a5206ba7
commit 1ccb1642ac
No known key found for this signature in database
GPG Key ID: F6D9E9BF14C7D103
6 changed files with 120 additions and 38 deletions

View File

@ -2518,5 +2518,7 @@
"enterInviteLinkOrMatrixId": "Enter invite link or Matrix ID...",
"reopenChat": "Reopen chat",
"noBackupWarning": "Warning! Without enabling chat backup, you will lose access to your encrypted messages. It is highly recommended to enable the chat backup first before logging out.",
"noOtherDevicesFound": "No other devices found"
"noOtherDevicesFound": "No other devices found",
"markRead": "Mark read",
"message": "Message"
}

View File

@ -63,6 +63,9 @@ abstract class AppConfig {
'https://github.com/googlefonts/noto-emoji/';
static const double borderRadius = 16.0;
static const double columnWidth = 360.0;
static const String markAsReadAction = 'markAsReadAction';
static const String replyAction = 'replyAction';
static const String notificationIsolate = 'notificationIsolate';
static void loadFromJson(Map<String, dynamic> json) {
if (json['chat_color'] != null) {

View File

@ -20,6 +20,7 @@
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:isolate';
import 'dart:typed_data';
import 'dart:ui';
@ -72,6 +73,16 @@ class BackgroundPush {
bool upAction = false;
BackgroundPush._(this.client) {
IsolateNameServer.removePortNameMapping(AppConfig.notificationIsolate);
final receivePort = ReceivePort();
IsolateNameServer.registerPortWithName(
receivePort.sendPort, AppConfig.notificationIsolate);
final backgroundMessagePort = receivePort.asBroadcastStream();
backgroundMessagePort.listen((event) async {
await notificationActionCallbacks(event);
});
onRoomSync ??= client.onSync.stream
.where((s) => s.hasRoomUpdate)
.listen((s) => _onClearingPush(getFromServer: false));
@ -116,6 +127,29 @@ class BackgroundPush {
}
StreamSubscription<SyncUpdate>? onRoomSync;
Future<void> notificationActionCallbacks(Map response) async {
try {
if (response['payload'] == null) return;
Logs().d('Got response with action: ${response['actionId']}');
final roomId = json.decode(response['payload']!)['roomId'];
final eventId = json.decode(response['payload']!)['eventId'];
if (response['actionId'] == AppConfig.markAsReadAction) {
Logs().d('notification action setting read marker to $eventId');
await client.setReadMarker(roomId, eventId, mRead: eventId);
}
if (response['actionId'] == AppConfig.replyAction) {
Logs().d('notification action replying in room $roomId');
final sentEventId = await client
.getRoomById(roomId)!
.sendTextEvent(response['input'].toString());
if (sentEventId != null) {
await client.setReadMarker(roomId, sentEventId, mRead: sentEventId);
}
}
} catch (e) {
Logs().e('[BackgroundPushPlugin] error in notification actions', e);
}
}
Future<void> setupPusher({
String? gatewayUrl,
@ -282,7 +316,8 @@ class BackgroundPush {
Future<void> goToRoom(NotificationResponse? response) async {
try {
final roomId = response?.payload;
if (response == null || response.payload == null) return;
final roomId = jsonDecode(response.payload!)['roomId'];
Logs().v('[Push] Attempting to go to room $roomId...');
if (router == null || roomId == null) {
return;
@ -369,11 +404,13 @@ class BackgroundPush {
json.decode(utf8.decode(message))['notification']);
// UP may strip the devices list
data['devices'] ??= [];
Logs().e('showingaksdjf');
await pushHelper(
PushNotification.fromJson(data),
client: client,
l10n: l10n,
activeRoomId: router?.currentState?.pathParameters['roomid'],
onSelectNotification: goToRoom,
);
}

View File

@ -15,6 +15,21 @@ import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart';
import 'package:fluffychat/utils/platform_infos.dart';
import 'package:fluffychat/utils/voip/callkeep_manager.dart';
// Is triggered by `onDidReceiveBackgroundNotificationResponse` in a different isolate
// this gets cached btw (until new or uninstall). so even if you disable
// `onDidReceiveBackgroundNotificationResponse` the old `notificationTapBackground` will
// still function until replaced or app is reinstalled
@pragma('vm:entry-point')
void notificationTapBackground(NotificationResponse notificationResponse) {
final sendPort =
IsolateNameServer.lookupPortByName(AppConfig.notificationIsolate);
sendPort!.send({
'payload': notificationResponse.payload,
'actionId': notificationResponse.actionId,
'input': notificationResponse.input,
});
}
Future<void> pushHelper(
PushNotification notification, {
Client? client,
@ -41,7 +56,7 @@ Future<void> pushHelper(
iOS: DarwinInitializationSettings(),
),
onDidReceiveNotificationResponse: onSelectNotification,
onDidReceiveBackgroundNotificationResponse: onSelectNotification,
// onDidReceiveBackgroundNotificationResponse: onSelectNotification,
);
flutterLocalNotificationsPlugin.show(
0,
@ -93,7 +108,7 @@ Future<void> _tryPushHelper(
iOS: DarwinInitializationSettings(),
),
onDidReceiveNotificationResponse: onSelectNotification,
//onDidReceiveBackgroundNotificationResponse: onSelectNotification,
onDidReceiveBackgroundNotificationResponse: notificationTapBackground,
);
client ??= (await ClientManager.getClients(initialize: false)).first;
@ -197,6 +212,29 @@ Future<void> _tryPushHelper(
AppConfig.pushNotificationsChannelName,
channelDescription: AppConfig.pushNotificationsChannelDescription,
number: notification.counts?.unread,
actions: event.room.membership == Membership.join
? [
if (event.room.canSendEvent('m.read') &&
event.room.canSendEvent('m.fully_read'))
AndroidNotificationAction(
AppConfig.markAsReadAction,
l10n.markRead,
showsUserInterface: false,
),
if (event.room.canSendEvent(EventTypes.Message))
AndroidNotificationAction(
AppConfig.replyAction,
l10n.reply,
showsUserInterface: false,
inputs: [
AndroidNotificationActionInput(
label: l10n.message,
allowedMimeTypes: <String>{'text/plain'},
)
],
)
]
: [],
styleInformation: messagingStyleInformation ??
MessagingStyleInformation(
Person(name: event.room.client.userID),
@ -208,7 +246,6 @@ Future<void> _tryPushHelper(
),
ticker: l10n.unreadChats(notification.counts?.unread ?? 1),
importance: Importance.max,
priority: Priority.high,
groupKey: event.room.id,
);
const iOSPlatformChannelSpecifics = DarwinNotificationDetails();
@ -224,7 +261,7 @@ Future<void> _tryPushHelper(
),
body,
platformChannelSpecifics,
payload: event.roomId,
payload: json.encode({'roomId': event.roomId, 'eventId': event.eventId}),
);
Logs().v('Push helper has been completed!');
}

View File

@ -293,10 +293,10 @@ packages:
dependency: transitive
description:
name: dbus
sha256: "4f814fc7e73057f78f307a6c4714fe2ffb4bdb994ab1970540a068ec4d5a45be"
sha256: "6f07cba3f7b3448d42d015bfd3d53fe12e5b36da2423f23838efc1d5fb31a263"
url: "https://pub.dev"
source: hosted
version: "0.7.3"
version: "0.7.8"
desktop_drop:
dependency: "direct main"
description:
@ -614,19 +614,20 @@ packages:
flutter_local_notifications:
dependency: "direct main"
description:
name: flutter_local_notifications
sha256: f222919a34545931e47b06000836b5101baeffb0e6eb5a4691d2d42851740dd9
url: "https://pub.dev"
source: hosted
version: "12.0.4"
path: flutter_local_notifications
ref: "v13.1.0"
resolved-ref: af8082bc65d281e4485b41d0a8b72614627fbb1c
url: "https://gitlab.com/techno_disaster/flutter_local_notifications.git"
source: git
version: "13.1.0"
flutter_local_notifications_linux:
dependency: transitive
description:
name: flutter_local_notifications_linux
sha256: "6af440e3962eeab8459602c309d7d4ab9e62f05d5cfe58195a28f846a0b5d523"
sha256: "8f6c1611e0c4a88a382691a97bb3c3feb24cc0c0b54152b8b5fb7ffb837f7fbf"
url: "https://pub.dev"
source: hosted
version: "1.0.0"
version: "3.0.0"
flutter_local_notifications_platform_interface:
dependency: transitive
description:
@ -649,13 +650,13 @@ packages:
source: hosted
version: "3.1.0"
flutter_math_fork:
dependency: transitive
dependency: "direct overridden"
description:
name: flutter_math_fork
sha256: cfec964c4975c6becc64291eb9b782fe70df5e0c5bfe0763d9e856432fcc6fcd
sha256: fa511bdcb91fc35eac155ec5790883886dd9de6572fea549f1ad4660ef6804e9
url: "https://pub.dev"
source: hosted
version: "0.4.2+2"
version: "0.6.3+1"
flutter_matrix_html:
dependency: "direct main"
description:
@ -668,10 +669,10 @@ packages:
dependency: "direct dev"
description:
name: flutter_native_splash
sha256: bd36d1a7f05ff8378cad17d20c33ca904630bfd3fcf8b15c9e8237efbccfad0a
sha256: "6777a3abb974021a39b5fdd2d46a03ca390e03903b6351f21d10e7ecc969f12d"
url: "https://pub.dev"
source: hosted
version: "2.2.0+1"
version: "2.2.16"
flutter_olm:
dependency: "direct main"
description:
@ -757,10 +758,10 @@ packages:
dependency: transitive
description:
name: flutter_svg
sha256: "9ac1967e2f72a08af11b05b39167920f90d043cf67163d13a544a358c8f31afa"
sha256: "6ff9fa12892ae074092de2fa6a9938fb21dbabfdaa2ff57dc697ff912fc8d4b2"
url: "https://pub.dev"
source: hosted
version: "0.22.0"
version: "1.1.6"
flutter_test:
dependency: "direct dev"
description: flutter
@ -933,10 +934,10 @@ packages:
dependency: "direct main"
description:
name: image
sha256: "02bafd3b4f399bfeb10034deba9753d93b55ce41cd0c4d3d8b355626f80e5b32"
sha256: "8e9d133755c3e84c73288363e6343157c383a0c6c56fc51afcc5d4d7180306d6"
url: "https://pub.dev"
source: hosted
version: "3.1.3"
version: "3.3.0"
image_picker:
dependency: "direct main"
description:
@ -1079,14 +1080,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.8.1"
lint:
dependency: transitive
description:
name: lint
sha256: "4a539aa34ec5721a2c7574ae2ca0336738ea4adc2a34887d54b7596310b33c85"
url: "https://pub.dev"
source: hosted
version: "1.10.0"
lints:
dependency: transitive
description:
@ -1323,18 +1316,18 @@ packages:
dependency: transitive
description:
name: path_drawing
sha256: "3bdd251dae9ffaef944450b73f168610db7e968e7b20daf0c3907f8b4aafc8a2"
sha256: bbb1934c0cbb03091af082a6389ca2080345291ef07a5fa6d6e078ba8682f977
url: "https://pub.dev"
source: hosted
version: "0.5.1+1"
version: "1.0.1"
path_parsing:
dependency: transitive
description:
name: path_parsing
sha256: ee5c47c1058ad66b4a41746ec3996af9593d0858872807bcd64ac118f0700337
sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf
url: "https://pub.dev"
source: hosted
version: "0.2.1"
version: "1.0.1"
path_provider:
dependency: "direct main"
description:
@ -2264,10 +2257,10 @@ packages:
dependency: transitive
description:
name: xml
sha256: "80d494c09849dc3f899d227a78c30c5b949b985ededf884cb3f3bcd39f4b447a"
sha256: "979ee37d622dec6365e2efa4d906c37470995871fe9ae080d967e192d88286b5"
url: "https://pub.dev"
source: hosted
version: "5.4.1"
version: "6.2.2"
yaml:
dependency: transitive
description:

View File

@ -147,6 +147,16 @@ dependency_overrides:
# This otherwise breaks on linux with flutter 3.7.0, let's override it for now.
file_selector: ^0.9.2+2
file_selector_linux: ^0.9.1
# because unified push and flutter isolate both have a flutter engine spawned
# automatically, this fork uses those cached engine for notification actions
# on android
flutter_local_notifications:
git:
url: https://gitlab.com/techno_disaster/flutter_local_notifications.git
path: flutter_local_notifications
ref: v13.1.0
# dependency hell
flutter_math_fork: ^0.6.3+1
# fake secure storage plugin for Windows
# See: https://gitlab.com/gitlab-com/gl-infra/reliability/-/issues/15161
flutter_secure_storage_windows: