Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(ios)!: duplicate notification presentation on iOS 18.0 #303

Merged
merged 1 commit into from
Nov 18, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions src/ios/PushPlugin.m
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ @interface PushPlugin ()
@property (nonatomic, strong) NSDictionary *launchNotification;
@property (nonatomic, strong) NSDictionary *notificationMessage;
@property (nonatomic, strong) NSMutableDictionary *handlerObj;
@property (nonatomic, strong) UNNotification *previousNotification;

@property (nonatomic, assign) BOOL isInline;
@property (nonatomic, assign) BOOL clearBadge;
Expand Down Expand Up @@ -357,6 +358,30 @@ - (void)willPresentNotification:(NSNotification *)notification {

void (^completionHandler)(UNNotificationPresentationOptions) = notification.userInfo[@"completionHandler"];

if (@available(iOS 18.0, *)) {
if (@available(iOS 18.1, *)) {
// Do nothing for iOS 18.1 and higher.
} else {
// Note: In iOS 18.0, there is a known issue where "willPresentNotification" is triggered twice for a single payload.
// The "willPresentNotification" method is normally triggered when a notification is received while the app is in the
// foreground. Due to this bug, the notification payload is delivered twice, causing the front-end to process the
// notification event twice as well. This behavior is unintended, so this block of code checks if the payload is a
// duplicate by comparing the payload content and the timestamp of when it was received.
NSLog(@"[PushPlugin] Checking for duplicate notification presentation.");
if ([self isDuplicateNotification:originalNotification]) {
NSLog(@"[PushPlugin] Duplicate notification detected; processing will be skipped.");
if (completionHandler) {
completionHandler(UNNotificationPresentationOptionNone);
}
// Cleanup to remove previous notification to remove leaks
self.previousNotification = nil;
return;
}
// If it was not duplicate, we will store it to check for the potential second notification
self.previousNotification = originalNotification;
}
}

self.notificationMessage = modifiedUserInfo;
self.isInline = YES;
[self notificationReceived];
Expand Down Expand Up @@ -763,7 +788,26 @@ - (void)checkUserHasRemoteNotificationsEnabledWithCompletionHandler:(nonnull voi
}];
}

- (BOOL)isDuplicateNotification:(UNNotification *)notification {
BOOL isDuplicate = NO;
if (self.previousNotification) {
// Extract relevant data from the current notification
NSDate *currentNotificationDate = notification.date;
NSDictionary *currentPayload = notification.request.content.userInfo;
// Extract relevant data from the previous notification
NSDate *previousNotificationDate = self.previousNotification.date;
NSDictionary *previousPayload = self.previousNotification.request.content.userInfo;
// Compare the date timestamp
BOOL isSameDate = [currentNotificationDate isEqualToDate:previousNotificationDate];
// Compare the payload content
BOOL isSamePayload = [currentPayload isEqualToDictionary:previousPayload];
isDuplicate = isSameDate && isSamePayload;
}
return isDuplicate;
}

- (void)dealloc {
self.previousNotification = nil;
self.launchNotification = nil;
self.coldstart = nil;
}
Expand Down
Loading