diff --git a/packages/neon_framework/lib/src/utils/push_utils.dart b/packages/neon_framework/lib/src/utils/push_utils.dart index 6b85faa0509..fb0142b467d 100644 --- a/packages/neon_framework/lib/src/utils/push_utils.dart +++ b/packages/neon_framework/lib/src/utils/push_utils.dart @@ -125,6 +125,29 @@ class PushUtils { } else { _log.fine('Got unknown background notification ${json.encode(pushNotification.toJson())}'); } + + if (defaultTargetPlatform == TargetPlatform.android) { + final groups = >{}; + + // Count how many notifications per group still exist. + final activeNotifications = await localNotificationsPlugin.getActiveNotifications(); + for (final activeNotification in activeNotifications) { + final id = activeNotification.id; + final groupKey = activeNotification.groupKey; + if (id != null && groupKey != null) { + groups[groupKey] ??= []; + groups[groupKey]!.add(id); + } + } + + for (final entry in groups.entries) { + // If there is only one notification left it has to be the summary, + // because the child notifications are automatically canceled when the user cancels the summary notification. + if (entry.value.length == 1) { + await localNotificationsPlugin.cancel(getGroupSummaryID(accountID, entry.key)); + } + } + } } else { packageInfo ??= await PackageInfo.fromPlatform(); accountStorage ??= AccountStorage( diff --git a/packages/neon_framework/test/push_utils_test.dart b/packages/neon_framework/test/push_utils_test.dart index 77e1fc44991..6b8a9a19481 100644 --- a/packages/neon_framework/test/push_utils_test.dart +++ b/packages/neon_framework/test/push_utils_test.dart @@ -142,6 +142,7 @@ void main() { ).thenAnswer((_) async {}); when(() => localNotificationsPlatform.cancel(any(), tag: any(named: 'tag'))).thenAnswer((_) async {}); when(() => localNotificationsPlatform.cancelAll()).thenAnswer((_) async {}); + when(() => localNotificationsPlatform.getActiveNotifications()).thenAnswer((_) async => []); keypair = RSAKeypair.fromRandom(); @@ -205,6 +206,7 @@ void main() { await PushUtils.onMessage(_encryptPushNotifications(keypair, [payload]), account.id); verify(() => localNotificationsPlatform.cancel(PushUtils.getNotificationID(account.id, 1))).called(1); + verify(() => localNotificationsPlatform.getActiveNotifications()).called(1); }); test('Delete multiple', () async { @@ -221,6 +223,7 @@ void main() { verify(() => localNotificationsPlatform.cancel(PushUtils.getNotificationID(account.id, 1))).called(1); verify(() => localNotificationsPlatform.cancel(PushUtils.getNotificationID(account.id, 2))).called(1); + verify(() => localNotificationsPlatform.getActiveNotifications()).called(1); }); test('Delete all', () async { @@ -235,6 +238,7 @@ void main() { await PushUtils.onMessage(_encryptPushNotifications(keypair, [payload]), account.id); verify(() => localNotificationsPlatform.cancelAll()).called(1); + verify(() => localNotificationsPlatform.getActiveNotifications()).called(1); }); test('Background', () async { @@ -245,6 +249,41 @@ void main() { }; await PushUtils.onMessage(_encryptPushNotifications(keypair, [payload]), account.id); + verify(() => localNotificationsPlatform.getActiveNotifications()).called(1); + }); + + test('Cancel summary notification', () async { + when(() => localNotificationsPlatform.getActiveNotifications()).thenAnswer( + (_) async => [ + const ActiveNotification( + id: 123, + groupKey: 'app1', + ), + const ActiveNotification( + id: 456, + groupKey: 'app2', + ), + const ActiveNotification( + id: 789, + groupKey: 'app2', + ), + ], + ); + + final payload = { + 'priority': '', + 'type': 'background', + 'subject': { + 'nid': 1, + 'delete': true, + }, + }; + + await PushUtils.onMessage(_encryptPushNotifications(keypair, [payload]), account.id); + + verify(() => localNotificationsPlatform.cancel(PushUtils.getNotificationID(account.id, 1))).called(1); + verify(() => localNotificationsPlatform.getActiveNotifications()).called(1); + verify(() => localNotificationsPlatform.cancel(PushUtils.getGroupSummaryID(account.id, 'app1'))).called(1); }); group('Message', () {