From f3d5142b5535147c70bba1e922b336ea53fdf92b Mon Sep 17 00:00:00 2001 From: Mritunjay Date: Sat, 28 Mar 2026 17:06:30 +0530 Subject: [PATCH 1/5] fix(messaging,ios): emit messaging_notification_opened only for default notification action Ensure messaging_notification_opened is emitted only when the UNNotificationDefaultActionIdentifier is triggered. This prevents onNotificationOpened from being invoked for custom notification actions. --- .../RNFBMessaging+UNUserNotificationCenter.m | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/packages/messaging/ios/RNFBMessaging/RNFBMessaging+UNUserNotificationCenter.m b/packages/messaging/ios/RNFBMessaging/RNFBMessaging+UNUserNotificationCenter.m index 4e98d2f176..2ebc1f0ab9 100644 --- a/packages/messaging/ios/RNFBMessaging/RNFBMessaging+UNUserNotificationCenter.m +++ b/packages/messaging/ios/RNFBMessaging/RNFBMessaging+UNUserNotificationCenter.m @@ -151,6 +151,16 @@ - (void)userNotificationCenter:(UNUserNotificationCenter *)center - (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler { + if (![[response actionIdentifier] isEqualToString:UNNotificationDefaultActionIdentifier]){ + if (_originalDelegate != nil && originalDelegateRespondsTo.didReceiveNotificationResponse) { + [_originalDelegate userNotificationCenter:center + didReceiveNotificationResponse:response + withCompletionHandler:completionHandler]; + } else { + completionHandler(); + } + return; + } NSDictionary *remoteNotification = response.notification.request.content.userInfo; if (remoteNotification[@"gcm.message_id"]) { NSDictionary *notificationDict = From 9c2b9722b5f3bf7c1e2fe9f337c46d87bce8b4d6 Mon Sep 17 00:00:00 2001 From: Mritunjay Date: Sat, 28 Mar 2026 17:17:29 +0530 Subject: [PATCH 2/5] fix(messaging,ios) avoiding code duplication --- .../RNFBMessaging+UNUserNotificationCenter.m | 24 +++++++------------ 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/packages/messaging/ios/RNFBMessaging/RNFBMessaging+UNUserNotificationCenter.m b/packages/messaging/ios/RNFBMessaging/RNFBMessaging+UNUserNotificationCenter.m index 2ebc1f0ab9..3aff050f2a 100644 --- a/packages/messaging/ios/RNFBMessaging/RNFBMessaging+UNUserNotificationCenter.m +++ b/packages/messaging/ios/RNFBMessaging/RNFBMessaging+UNUserNotificationCenter.m @@ -151,23 +151,15 @@ - (void)userNotificationCenter:(UNUserNotificationCenter *)center - (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler { - if (![[response actionIdentifier] isEqualToString:UNNotificationDefaultActionIdentifier]){ - if (_originalDelegate != nil && originalDelegateRespondsTo.didReceiveNotificationResponse) { - [_originalDelegate userNotificationCenter:center - didReceiveNotificationResponse:response - withCompletionHandler:completionHandler]; - } else { - completionHandler(); + if ([[response actionIdentifier] isEqualToString:UNNotificationDefaultActionIdentifier]) { + NSDictionary *remoteNotification = response.notification.request.content.userInfo; + if (remoteNotification[@"gcm.message_id"]) { + NSDictionary *notificationDict = + [RNFBMessagingSerializer remoteMessageUserInfoToDict:remoteNotification]; + [[RNFBRCTEventEmitter shared] sendEventWithName:@"messaging_notification_opened" + body:notificationDict]; + _initialNotification = notificationDict; } - return; - } - NSDictionary *remoteNotification = response.notification.request.content.userInfo; - if (remoteNotification[@"gcm.message_id"]) { - NSDictionary *notificationDict = - [RNFBMessagingSerializer remoteMessageUserInfoToDict:remoteNotification]; - [[RNFBRCTEventEmitter shared] sendEventWithName:@"messaging_notification_opened" - body:notificationDict]; - _initialNotification = notificationDict; } if (_originalDelegate != nil && originalDelegateRespondsTo.didReceiveNotificationResponse) { From 83a5535b5aabef1959223558876c183f85974a30 Mon Sep 17 00:00:00 2001 From: Mritunjay Date: Sat, 28 Mar 2026 19:56:02 +0530 Subject: [PATCH 3/5] combining if statements --- .../RNFBMessaging+UNUserNotificationCenter.m | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/packages/messaging/ios/RNFBMessaging/RNFBMessaging+UNUserNotificationCenter.m b/packages/messaging/ios/RNFBMessaging/RNFBMessaging+UNUserNotificationCenter.m index 3aff050f2a..2ad62e54f7 100644 --- a/packages/messaging/ios/RNFBMessaging/RNFBMessaging+UNUserNotificationCenter.m +++ b/packages/messaging/ios/RNFBMessaging/RNFBMessaging+UNUserNotificationCenter.m @@ -151,17 +151,16 @@ - (void)userNotificationCenter:(UNUserNotificationCenter *)center - (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler { - if ([[response actionIdentifier] isEqualToString:UNNotificationDefaultActionIdentifier]) { - NSDictionary *remoteNotification = response.notification.request.content.userInfo; - if (remoteNotification[@"gcm.message_id"]) { - NSDictionary *notificationDict = - [RNFBMessagingSerializer remoteMessageUserInfoToDict:remoteNotification]; - [[RNFBRCTEventEmitter shared] sendEventWithName:@"messaging_notification_opened" - body:notificationDict]; - _initialNotification = notificationDict; - } + NSDictionary *remoteNotification = response.notification.request.content.userInfo; + if ([[response actionIdentifier] isEqualToString:UNNotificationDefaultActionIdentifier] && remoteNotification[@"gcm.message_id"]) { + NSDictionary *notificationDict = + [RNFBMessagingSerializer remoteMessageUserInfoToDict:remoteNotification]; + [[RNFBRCTEventEmitter shared] sendEventWithName:@"messaging_notification_opened" + body:notificationDict]; + _initialNotification = notificationDict; } + if (_originalDelegate != nil && originalDelegateRespondsTo.didReceiveNotificationResponse) { [_originalDelegate userNotificationCenter:center didReceiveNotificationResponse:response From c6911714eb8f3e0fe7fabf5f107c25774ff50639 Mon Sep 17 00:00:00 2001 From: Mritunjay Date: Sat, 28 Mar 2026 19:56:44 +0530 Subject: [PATCH 4/5] removing white space --- .../ios/RNFBMessaging/RNFBMessaging+UNUserNotificationCenter.m | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/messaging/ios/RNFBMessaging/RNFBMessaging+UNUserNotificationCenter.m b/packages/messaging/ios/RNFBMessaging/RNFBMessaging+UNUserNotificationCenter.m index 2ad62e54f7..c36fcd6819 100644 --- a/packages/messaging/ios/RNFBMessaging/RNFBMessaging+UNUserNotificationCenter.m +++ b/packages/messaging/ios/RNFBMessaging/RNFBMessaging+UNUserNotificationCenter.m @@ -160,7 +160,6 @@ - (void)userNotificationCenter:(UNUserNotificationCenter *)center _initialNotification = notificationDict; } - if (_originalDelegate != nil && originalDelegateRespondsTo.didReceiveNotificationResponse) { [_originalDelegate userNotificationCenter:center didReceiveNotificationResponse:response From df9e00dc0de04a0e8cd2ac44016f84bb1ec8f99e Mon Sep 17 00:00:00 2001 From: Mike Hardy Date: Fri, 24 Jul 2026 14:40:45 -0500 Subject: [PATCH 5/5] fix(messaging,ios): harden delegate forwarding for #8945 P0 Capture a strong local for weak _originalDelegate in didReceiveNotificationResponse and openSettingsForNotification (same pattern as willPresent). Note in docs that opened/initial APIs are default body-tap only. Keep clang-format wrap; drop temporary plan (lives on Linear CP-263). --- docs/messaging/notifications.mdx | 4 ++++ .../RNFBMessaging+UNUserNotificationCenter.m | 19 ++++++++++++------- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/docs/messaging/notifications.mdx b/docs/messaging/notifications.mdx index 1d76291dbe..b2bab82188 100644 --- a/docs/messaging/notifications.mdx +++ b/docs/messaging/notifications.mdx @@ -107,6 +107,10 @@ could open a specific screen for example). The API provides two APIs for handlin - `getInitialNotification`: When the application is opened from a quit state. - `onNotificationOpenedApp`: When the application is running, but in the background. +These fire for the **default notification open** (user taps the notification body). They do **not** fire for +custom notification-category actions or dismiss; those interactions need a dedicated response API (tracked +internally — do not route custom-action navigation through opened/initial). + To handle both scenarios, the code can be executed during setup. For example, using [React Navigation](https://reactnavigation.org/) we can set an initial route when the app is opened from a quit state, and push to a new screen when the app is in a background state: diff --git a/packages/messaging/ios/RNFBMessaging/RNFBMessaging+UNUserNotificationCenter.m b/packages/messaging/ios/RNFBMessaging/RNFBMessaging+UNUserNotificationCenter.m index c36fcd6819..cf9301ebbc 100644 --- a/packages/messaging/ios/RNFBMessaging/RNFBMessaging+UNUserNotificationCenter.m +++ b/packages/messaging/ios/RNFBMessaging/RNFBMessaging+UNUserNotificationCenter.m @@ -152,7 +152,8 @@ - (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler { NSDictionary *remoteNotification = response.notification.request.content.userInfo; - if ([[response actionIdentifier] isEqualToString:UNNotificationDefaultActionIdentifier] && remoteNotification[@"gcm.message_id"]) { + if ([[response actionIdentifier] isEqualToString:UNNotificationDefaultActionIdentifier] && + remoteNotification[@"gcm.message_id"]) { NSDictionary *notificationDict = [RNFBMessagingSerializer remoteMessageUserInfoToDict:remoteNotification]; [[RNFBRCTEventEmitter shared] sendEventWithName:@"messaging_notification_opened" @@ -160,10 +161,13 @@ - (void)userNotificationCenter:(UNUserNotificationCenter *)center _initialNotification = notificationDict; } - if (_originalDelegate != nil && originalDelegateRespondsTo.didReceiveNotificationResponse) { - [_originalDelegate userNotificationCenter:center - didReceiveNotificationResponse:response - withCompletionHandler:completionHandler]; + // _originalDelegate is weak — capture strong local before nil-check + message + // (same race as willPresent; otherwise completionHandler may never run). + id strongOriginalDelegate = _originalDelegate; + if (strongOriginalDelegate != nil && originalDelegateRespondsTo.didReceiveNotificationResponse) { + [strongOriginalDelegate userNotificationCenter:center + didReceiveNotificationResponse:response + withCompletionHandler:completionHandler]; } else { completionHandler(); } @@ -171,8 +175,9 @@ - (void)userNotificationCenter:(UNUserNotificationCenter *)center - (void)userNotificationCenter:(UNUserNotificationCenter *)center openSettingsForNotification:(nullable UNNotification *)notification { - if (_originalDelegate != nil && originalDelegateRespondsTo.openSettingsForNotification) { - [_originalDelegate userNotificationCenter:center openSettingsForNotification:notification]; + id strongOriginalDelegate = _originalDelegate; + if (strongOriginalDelegate != nil && originalDelegateRespondsTo.openSettingsForNotification) { + [strongOriginalDelegate userNotificationCenter:center openSettingsForNotification:notification]; } else { NSDictionary *notificationDict = [RNFBMessagingSerializer notificationToDict:notification]; [[RNFBRCTEventEmitter shared] sendEventWithName:@"messaging_settings_for_notification_opened"