From 781415e274d4278f506da8ec8cf75be047e020cc Mon Sep 17 00:00:00 2001 From: provokateurin Date: Thu, 24 Oct 2024 15:07:07 +0200 Subject: [PATCH] fix(neon_framework): Group push notifications on Android Signed-off-by: provokateurin --- .../lib/src/utils/push_utils.dart | 29 +++++++- .../neon_framework/test/push_utils_test.dart | 72 +++++++++++++++++++ 2 files changed, 100 insertions(+), 1 deletion(-) diff --git a/packages/neon_framework/lib/src/utils/push_utils.dart b/packages/neon_framework/lib/src/utils/push_utils.dart index 28c1bbdb0b3..d92a0e5c14b 100644 --- a/packages/neon_framework/lib/src/utils/push_utils.dart +++ b/packages/neon_framework/lib/src/utils/push_utils.dart @@ -1,11 +1,11 @@ import 'dart:async'; import 'dart:convert'; -import 'dart:typed_data'; import 'dart:ui'; import 'package:account_repository/account_repository.dart'; import 'package:built_collection/built_collection.dart'; import 'package:crypto/crypto.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:flutter_svg/flutter_svg.dart' show SvgBytesLoader, vg; @@ -185,6 +185,29 @@ class PushUtils { ), payload: json.encode(pushNotification.toJson()), ); + + // Other platforms don't support grouping, so don't send another notification there. + if (defaultTargetPlatform == TargetPlatform.android) { + // Sine we only support Android SDK 24+, we can just generate an empty summary notification as it will not be shown anyway. + await localNotificationsPlugin.show( + _getGroupSummaryID(accountID, appID), + null, + null, + NotificationDetails( + android: AndroidNotificationDetails( + appID, + appName ?? appID, + groupKey: '${appID}_app', + setAsGroupSummary: true, + styleInformation: InboxStyleInformation( + [], + summaryText: appName ?? appID, + ), + color: NcColors.primary, + ), + ), + ); + } } } } @@ -269,4 +292,8 @@ class PushUtils { static int _getNotificationID(String accountID, PushNotification notification) { return sha256.convert(utf8.encode('$accountID${notification.subject.nid}')).bytes.reduce((a, b) => a + b); } + + static int _getGroupSummaryID(String accountID, String app) { + return sha256.convert(utf8.encode('$accountID$app')).bytes.reduce((a, b) => a + b); + } } diff --git a/packages/neon_framework/test/push_utils_test.dart b/packages/neon_framework/test/push_utils_test.dart index b7b9b1c20e6..3cb31d6efa3 100644 --- a/packages/neon_framework/test/push_utils_test.dart +++ b/packages/neon_framework/test/push_utils_test.dart @@ -302,6 +302,30 @@ void main() { payload: payload, ), ).called(1); + verify( + () => localNotificationsPlatform.show( + 4082, + null, + null, + notificationDetails: any( + named: 'notificationDetails', + that: predicate( + (d) => + d.channelId == 'app' && + d.channelName == 'app' && + d.subText == null && + d.groupKey == 'app_app' && + d.icon == null && + d.largeIcon == null && + d.when == null && + d.color == NcColors.primary && + d.category == null && + d.importance == Importance.defaultImportance && + d.priority == Priority.defaultPriority, + ), + ), + ), + ).called(1); onDidReceiveNotificationResponseCallback( NotificationResponse( @@ -437,6 +461,30 @@ void main() { payload: payload, ), ).called(1); + verify( + () => localNotificationsPlatform.show( + 4405, + null, + null, + notificationDetails: any( + named: 'notificationDetails', + that: predicate( + (d) => + d.channelId == 'files' && + d.channelName == 'Files' && + d.subText == null && + d.groupKey == 'files_app' && + d.icon == null && + d.largeIcon == null && + d.when == null && + d.color == NcColors.primary && + d.category == null && + d.importance == Importance.defaultImportance && + d.priority == Priority.defaultPriority, + ), + ), + ), + ).called(1); verify(() => storage.requestCache).called(1); }); @@ -485,6 +533,30 @@ void main() { payload: payload, ), ).called(1); + verify( + () => localNotificationsPlatform.show( + 4082, + null, + null, + notificationDetails: any( + named: 'notificationDetails', + that: predicate( + (d) => + d.channelId == 'app' && + d.channelName == 'app' && + d.subText == null && + d.groupKey == 'app_app' && + d.icon == null && + d.largeIcon == null && + d.when == null && + d.color == NcColors.primary && + d.category == null && + d.importance == Importance.defaultImportance && + d.priority == Priority.defaultPriority, + ), + ), + ), + ).called(1); }); }); });