@loyalytics/swan-react-native-sdk 2.5.1-beta.3 → 2.5.1-beta.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -146,6 +146,7 @@ export function _resetClickDedup() {
146
146
  export default class SwanSDK {
147
147
  listeners = {};
148
148
  coldStartCheckDone = false;
149
+ pendingNotificationPayload = null;
149
150
  SDK_VERSION = PACKAGE_VERSION;
150
151
  isProduction = 'STAGE';
151
152
  appId = '';
@@ -620,6 +621,15 @@ export default class SwanSDK {
620
621
  this.coldStartCheckDone = true;
621
622
  // Defer to next microtask so the listener is fully registered before events emit
622
623
  Promise.resolve().then(() => {
624
+ // Deliver buffered standard/image push notification (one-shot APIs like
625
+ // getInitialNotification() can't be re-read — data was buffered in emitNotificationOpened).
626
+ // Skip carousel notifications — checkPendingCarouselClick() handles those with per-item routes.
627
+ const payload = this.pendingNotificationPayload;
628
+ this.pendingNotificationPayload = null;
629
+ if (payload && payload.notificationType !== 'carousel') {
630
+ this.emitNotificationOpened(payload);
631
+ }
632
+ // Check for pending carousel click (native side holds data until consumed)
623
633
  this.checkPendingCarouselClick();
624
634
  });
625
635
  }
@@ -649,6 +659,15 @@ export default class SwanSDK {
649
659
  * @internal - Used by module-level notification handlers
650
660
  */
651
661
  emitNotificationOpened(payload) {
662
+ const listeners = this.listeners[SwanSDK.EVENTS.NOTIFICATION_OPENED];
663
+ if ((!listeners || listeners.length === 0) && !this.coldStartCheckDone) {
664
+ // Cold start: buffer for delivery when first listener registers.
665
+ // One-shot APIs like getInitialNotification() won't have this data later.
666
+ Logger.log('[SwanSDK] Buffering notification payload for deferred delivery');
667
+ this.pendingNotificationPayload = payload;
668
+ return;
669
+ }
670
+ this.pendingNotificationPayload = null;
652
671
  this.emit(SwanSDK.EVENTS.NOTIFICATION_OPENED, payload);
653
672
  // Also emit unified deep link event for push source
654
673
  this.emitDeepLinkOpened({
@@ -2863,10 +2882,13 @@ export default class SwanSDK {
2863
2882
  // similar to how Firebase requires onMessage() at module level.
2864
2883
 
2865
2884
  // Check if app was opened by tapping a Notifee-displayed notification (data-only architecture)
2885
+ // Notifee's getInitialNotification() returns { notification, pressAction }.
2886
+ // The FCM data we stored via displayNotification({ data: {...} }) lives at
2887
+ // notification.data — NOT at the top-level .data (which doesn't exist).
2866
2888
  const initialNotification = await notifee.getInitialNotification();
2867
2889
  if (initialNotification && !this.initialNotificationHandled) {
2868
2890
  const messageId = initialNotification?.notification?.id;
2869
- const notificationData = initialNotification.data || {};
2891
+ const notificationData = initialNotification.notification?.data || {};
2870
2892
  if (messageId && markClickProcessed(messageId)) {
2871
2893
  Logger.log('[SwanSDK] App opened from Notifee notification tap:', messageId);
2872
2894
  this.initialNotificationHandled = true;