@knocklabs/expo 0.7.0-rc.0 → 0.7.0

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,51 @@
1
1
  # @knocklabs/expo
2
2
 
3
+ ## 0.7.0
4
+
5
+ ### Minor Changes
6
+
7
+ - e8567eb: Add an `enabled` prop to `KnockProvider` (and an `enabled` option to `useAuthenticatedKnockClient`).
8
+
9
+ When `enabled` is `false`, the provider still renders its children but the Knock client sits idle: no identify call, no API requests, no websocket. Set it to `true` and it connects like a login; set it back to `false` and it disconnects and clears its data like a logout. It defaults to `true`, so existing code is unaffected.
10
+
11
+ Use this instead of conditionally mounting `KnockProvider`, for example to wait for a user token that loads asynchronously:
12
+
13
+ ```tsx
14
+ <KnockProvider
15
+ apiKey={apiKey}
16
+ user={{ id: userId }}
17
+ userToken={userToken}
18
+ enabled={Boolean(userId && userToken)}
19
+ />
20
+ ```
21
+
22
+ Also fixed:
23
+
24
+ - `useFeedSettings` no longer calls `GET /v1/users/undefined/feeds/.../settings` when there's no user.
25
+ - `KnockProvider` now disconnects its client (websocket, token-refresh timer, listener) when it unmounts, instead of leaving them running.
26
+
27
+ - e8567eb: Add `useKnockAuthState()` and make Slack, MS Teams, and Expo respond to sign-in changes.
28
+
29
+ - New `useKnockAuthState(knock)` hook re-renders when the user signs in, signs out, or switches.
30
+ - Slack and MS Teams connection status now re-checks when the user changes, instead of checking once and sticking with that result.
31
+ - Expo waits for a signed-in user before registering for push notifications, so logged-out users don't see the OS permission prompt. A notification tapped while logged out no longer tries to update its status.
32
+
33
+ ### Patch Changes
34
+
35
+ - e8567eb: Fix Expo push auto-registration not re-running when the signed-in user changes in place. The auto-register effect now depends on the authenticated `userId`, so switching users on the same `KnockProvider` (where `isAuthenticated` never flips) re-registers the device token against the new user's channel data.
36
+ - Updated dependencies [e8567eb]
37
+ - Updated dependencies [e8567eb]
38
+ - Updated dependencies [e8567eb]
39
+ - @knocklabs/client@0.22.0
40
+ - @knocklabs/react-core@0.14.0
41
+ - @knocklabs/react-native@0.10.0
42
+
43
+ ## 0.7.0-rc.1
44
+
45
+ ### Patch Changes
46
+
47
+ - 6414414: Fix Expo push auto-registration not re-running when the signed-in user changes in place. The auto-register effect now depends on the authenticated `userId`, so switching users on the same `KnockProvider` (where `isAuthenticated` never flips) re-registers the device token against the new user's channel data.
48
+
3
49
  ## 0.7.0-rc.0
4
50
 
5
51
  ### Minor Changes
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const l=require("react/jsx-runtime"),P=require("@knocklabs/react-core"),K=require("@knocklabs/react-native"),o=require("react"),v=require("./getNotificationsModule.js"),d=require("./utils.js"),x=o.createContext(void 0);function M(){const r=o.useContext(x);if(r===void 0)throw new Error("[Knock] useExpoPushNotifications must be used within a KnockExpoPushNotificationProvider");return r}const m=({knockExpoChannelId:r,customNotificationHandler:c,setupAndroidNotificationChannel:h=d.setupDefaultAndroidChannel,children:E,autoRegister:k=!0})=>{const e=P.useKnockClient(),{status:C}=P.useKnockAuthState(e),g=C==="authenticated",{registerPushTokenToChannel:u,unregisterPushTokenFromChannel:R}=K.usePushNotifications(),[S,T]=o.useState(null),p=o.useRef(()=>{}),N=o.useRef(()=>{}),b=o.useCallback(t=>{p.current=t},[]),w=o.useCallback(t=>{N.current=t},[]),a=o.useCallback(async()=>{try{e.log("[Knock] Registering for push notifications");const t=await d.registerForPushNotifications(h);return t?(e.log(`[Knock] Push token received: ${t}`),T(t),t):null}catch(t){return console.error("[Knock] Error registering for push notifications:",t),null}},[e,h]),f=o.useCallback(async(t,s)=>{var i;const n=(i=t.request.content.data)==null?void 0:i.knock_message_id;if(!n){e.log("[Knock] Skipping status update for non-Knock notification");return}if(!e.isAuthenticated()){e.log("[Knock] Skipping status update; user is not authenticated");return}return e.messages.updateStatus(n,s)},[e]);o.useEffect(()=>{const t=v.getNotificationsModule();if(!t)return;const s=c||(async()=>d.DEFAULT_NOTIFICATION_BEHAVIOR);t.setNotificationHandler({handleNotification:s})},[c]),o.useEffect(()=>{if(!k||!g)return;let t=!0;return(async()=>{try{const n=await a();n&&t&&(await u(n,r),e.log("[Knock] Push token registered with Knock channel"))}catch(n){console.error("[Knock] Error during auto-registration:",n)}})(),()=>{t=!1}},[k,g,r,a,u,e]),o.useEffect(()=>{const t=v.getNotificationsModule();if(!t)return;const s=t.addNotificationReceivedListener(i=>{e.log("[Knock] Notification received in foreground"),f(i,"interacted"),p.current(i)}),n=t.addNotificationResponseReceivedListener(i=>{e.log("[Knock] Notification was tapped"),f(i.notification,"interacted"),N.current(i)});return()=>{s.remove(),n.remove()}},[e,f]);const y={expoPushToken:S,registerForPushNotifications:a,registerPushTokenToChannel:u,unregisterPushTokenFromChannel:R,onNotificationReceived:b,onNotificationTapped:w};return l.jsx(x.Provider,{value:y,children:E})},q=r=>l.jsx(K.KnockPushNotificationProvider,{children:l.jsx(m,{...r})});exports.KnockExpoPushNotificationProvider=q;exports.useExpoPushNotifications=M;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const l=require("react/jsx-runtime"),P=require("@knocklabs/react-core"),K=require("@knocklabs/react-native"),o=require("react"),v=require("./getNotificationsModule.js"),d=require("./utils.js"),x=o.createContext(void 0);function m(){const r=o.useContext(x);if(r===void 0)throw new Error("[Knock] useExpoPushNotifications must be used within a KnockExpoPushNotificationProvider");return r}const q=({knockExpoChannelId:r,customNotificationHandler:c,setupAndroidNotificationChannel:h=d.setupDefaultAndroidChannel,children:E,autoRegister:k=!0})=>{const e=P.useKnockClient(),{status:C,userId:R}=P.useKnockAuthState(e),g=C==="authenticated",{registerPushTokenToChannel:u,unregisterPushTokenFromChannel:S}=K.usePushNotifications(),[T,b]=o.useState(null),p=o.useRef(()=>{}),N=o.useRef(()=>{}),w=o.useCallback(t=>{p.current=t},[]),y=o.useCallback(t=>{N.current=t},[]),a=o.useCallback(async()=>{try{e.log("[Knock] Registering for push notifications");const t=await d.registerForPushNotifications(h);return t?(e.log(`[Knock] Push token received: ${t}`),b(t),t):null}catch(t){return console.error("[Knock] Error registering for push notifications:",t),null}},[e,h]),f=o.useCallback(async(t,s)=>{var i;const n=(i=t.request.content.data)==null?void 0:i.knock_message_id;if(!n){e.log("[Knock] Skipping status update for non-Knock notification");return}if(!e.isAuthenticated()){e.log("[Knock] Skipping status update; user is not authenticated");return}return e.messages.updateStatus(n,s)},[e]);o.useEffect(()=>{const t=v.getNotificationsModule();if(!t)return;const s=c||(async()=>d.DEFAULT_NOTIFICATION_BEHAVIOR);t.setNotificationHandler({handleNotification:s})},[c]),o.useEffect(()=>{if(!k||!g)return;let t=!0;return(async()=>{try{const n=await a();n&&t&&(await u(n,r),e.log("[Knock] Push token registered with Knock channel"))}catch(n){console.error("[Knock] Error during auto-registration:",n)}})(),()=>{t=!1}},[k,g,R,r,a,u,e]),o.useEffect(()=>{const t=v.getNotificationsModule();if(!t)return;const s=t.addNotificationReceivedListener(i=>{e.log("[Knock] Notification received in foreground"),f(i,"interacted"),p.current(i)}),n=t.addNotificationResponseReceivedListener(i=>{e.log("[Knock] Notification was tapped"),f(i.notification,"interacted"),N.current(i)});return()=>{s.remove(),n.remove()}},[e,f]);const M={expoPushToken:T,registerForPushNotifications:a,registerPushTokenToChannel:u,unregisterPushTokenFromChannel:S,onNotificationReceived:w,onNotificationTapped:y};return l.jsx(x.Provider,{value:M,children:E})},A=r=>l.jsx(K.KnockPushNotificationProvider,{children:l.jsx(q,{...r})});exports.KnockExpoPushNotificationProvider=A;exports.useExpoPushNotifications=m;
2
2
  //# sourceMappingURL=KnockExpoPushNotificationProvider.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"KnockExpoPushNotificationProvider.js","sources":["../../../../src/modules/push/KnockExpoPushNotificationProvider.tsx"],"sourcesContent":["import { Message, MessageEngagementStatus } from \"@knocklabs/client\";\nimport { useKnockAuthState, useKnockClient } from \"@knocklabs/react-core\";\nimport {\n KnockPushNotificationProvider,\n usePushNotifications,\n} from \"@knocklabs/react-native\";\nimport React, {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useRef,\n useState,\n} from \"react\";\n\nimport {\n type Notification,\n type NotificationResponse,\n getNotificationsModule,\n} from \"./getNotificationsModule\";\nimport type {\n KnockExpoPushNotificationContextType,\n KnockExpoPushNotificationProviderProps,\n} from \"./types\";\nimport {\n DEFAULT_NOTIFICATION_BEHAVIOR,\n registerForPushNotifications as registerForPushNotificationsUtil,\n setupDefaultAndroidChannel,\n} from \"./utils\";\n\n// Re-export types for consumers\nexport type {\n KnockExpoPushNotificationContextType,\n KnockExpoPushNotificationProviderProps,\n} from \"./types\";\n\nconst KnockExpoPushNotificationContext = createContext<\n KnockExpoPushNotificationContextType | undefined\n>(undefined);\n\n/**\n * Hook to access push notification functionality within a KnockExpoPushNotificationProvider.\n * @throws Error if used outside of a KnockExpoPushNotificationProvider\n */\nexport function useExpoPushNotifications(): KnockExpoPushNotificationContextType {\n const context = useContext(KnockExpoPushNotificationContext);\n\n if (context === undefined) {\n throw new Error(\n \"[Knock] useExpoPushNotifications must be used within a KnockExpoPushNotificationProvider\",\n );\n }\n\n return context;\n}\n\n/**\n * Internal provider component that handles all the Expo push notification logic.\n */\nconst InternalExpoPushNotificationProvider: React.FC<\n KnockExpoPushNotificationProviderProps\n> = ({\n knockExpoChannelId,\n customNotificationHandler,\n setupAndroidNotificationChannel = setupDefaultAndroidChannel,\n children,\n autoRegister = true,\n}) => {\n const knockClient = useKnockClient();\n const { status: authStatus } = useKnockAuthState(knockClient);\n const isAuthenticated = authStatus === \"authenticated\";\n const { registerPushTokenToChannel, unregisterPushTokenFromChannel } =\n usePushNotifications();\n\n const [expoPushToken, setExpoPushToken] = useState<string | null>(null);\n\n // Use refs for handlers to avoid re-running effects when handlers change\n const notificationReceivedHandlerRef = useRef<\n (notification: Notification) => void\n >(() => {});\n\n const notificationTappedHandlerRef = useRef<\n (response: NotificationResponse) => void\n >(() => {});\n\n /**\n * Register a handler to be called when a notification is received in the foreground.\n */\n const onNotificationReceived = useCallback(\n (handler: (notification: Notification) => void) => {\n notificationReceivedHandlerRef.current = handler;\n },\n [],\n );\n\n /**\n * Register a handler to be called when a notification is tapped.\n */\n const onNotificationTapped = useCallback(\n (handler: (response: NotificationResponse) => void) => {\n notificationTappedHandlerRef.current = handler;\n },\n [],\n );\n\n /**\n * Manually trigger push notification registration.\n * Returns the push token if successful, or null if registration failed.\n */\n const registerForPushNotifications = useCallback(async (): Promise<\n string | null\n > => {\n try {\n knockClient.log(\"[Knock] Registering for push notifications\");\n\n const token = await registerForPushNotificationsUtil(\n setupAndroidNotificationChannel,\n );\n\n if (token) {\n knockClient.log(`[Knock] Push token received: ${token}`);\n setExpoPushToken(token);\n return token;\n }\n\n return null;\n } catch (error) {\n console.error(\"[Knock] Error registering for push notifications:\", error);\n return null;\n }\n }, [knockClient, setupAndroidNotificationChannel]);\n\n /**\n * Update the Knock message status when a notification is received or interacted with.\n * Only updates status for notifications that originated from Knock (have a knock_message_id).\n */\n const updateMessageStatus = useCallback(\n async (\n notification: Notification,\n status: MessageEngagementStatus,\n ): Promise<Message | void> => {\n const messageId = notification.request.content.data?.[\n \"knock_message_id\"\n ] as string | undefined;\n\n // Skip status update if this isn't a Knock notification\n // Fixes issue: https://github.com/knocklabs/javascript/issues/589\n if (!messageId) {\n knockClient.log(\n \"[Knock] Skipping status update for non-Knock notification\",\n );\n return;\n }\n\n // Skip when there's no authenticated user (e.g. a notification tapped\n // after logout) — otherwise this fires a messages request with no user.\n if (!knockClient.isAuthenticated()) {\n knockClient.log(\n \"[Knock] Skipping status update; user is not authenticated\",\n );\n return;\n }\n\n return knockClient.messages.updateStatus(messageId, status);\n },\n [knockClient],\n );\n\n // Set up the notification handler for foreground notifications\n useEffect(() => {\n const NotificationsModule = getNotificationsModule();\n if (!NotificationsModule) return;\n\n const handleNotification = customNotificationHandler\n ? customNotificationHandler\n : async () => DEFAULT_NOTIFICATION_BEHAVIOR;\n\n NotificationsModule.setNotificationHandler({ handleNotification });\n }, [customNotificationHandler]);\n\n // Auto-register for push notifications once there is an authenticated user.\n // Gating on auth defers the OS permission prompt (prompting a logged-out user\n // is hostile) and avoids registering a token against no user. Because\n // `isAuthenticated` is a dependency, enabling auth later re-runs registration.\n useEffect(() => {\n if (!autoRegister || !isAuthenticated) {\n return;\n }\n\n let isMounted = true;\n\n const register = async () => {\n try {\n const token = await registerForPushNotifications();\n\n if (token && isMounted) {\n await registerPushTokenToChannel(token, knockExpoChannelId);\n knockClient.log(\"[Knock] Push token registered with Knock channel\");\n }\n } catch (error) {\n console.error(\"[Knock] Error during auto-registration:\", error);\n }\n };\n\n register();\n\n return () => {\n isMounted = false;\n };\n }, [\n autoRegister,\n isAuthenticated,\n knockExpoChannelId,\n registerForPushNotifications,\n registerPushTokenToChannel,\n knockClient,\n ]);\n\n // Set up notification listeners for received and tapped notifications\n useEffect(() => {\n const NotificationsModule = getNotificationsModule();\n if (!NotificationsModule) return;\n\n const receivedSubscription =\n NotificationsModule.addNotificationReceivedListener((notification) => {\n knockClient.log(\"[Knock] Notification received in foreground\");\n updateMessageStatus(notification, \"interacted\");\n notificationReceivedHandlerRef.current(notification);\n });\n\n const responseSubscription =\n NotificationsModule.addNotificationResponseReceivedListener(\n (response) => {\n knockClient.log(\"[Knock] Notification was tapped\");\n updateMessageStatus(response.notification, \"interacted\");\n notificationTappedHandlerRef.current(response);\n },\n );\n\n return () => {\n receivedSubscription.remove();\n responseSubscription.remove();\n };\n }, [knockClient, updateMessageStatus]);\n\n const contextValue: KnockExpoPushNotificationContextType = {\n expoPushToken,\n registerForPushNotifications,\n registerPushTokenToChannel,\n unregisterPushTokenFromChannel,\n onNotificationReceived,\n onNotificationTapped,\n };\n\n return (\n <KnockExpoPushNotificationContext.Provider value={contextValue}>\n {children}\n </KnockExpoPushNotificationContext.Provider>\n );\n};\n\n/**\n * Provider component for Expo push notifications with Knock.\n *\n * Wraps the internal provider with the base KnockPushNotificationProvider\n * to provide full push notification functionality.\n *\n * @example\n * ```tsx\n * <KnockProvider apiKey=\"your-api-key\" userId=\"user-id\">\n * <KnockExpoPushNotificationProvider knockExpoChannelId=\"your-channel-id\">\n * <App />\n * </KnockExpoPushNotificationProvider>\n * </KnockProvider>\n * ```\n */\nexport const KnockExpoPushNotificationProvider: React.FC<\n KnockExpoPushNotificationProviderProps\n> = (props) => {\n return (\n <KnockPushNotificationProvider>\n <InternalExpoPushNotificationProvider {...props} />\n </KnockPushNotificationProvider>\n );\n};\n"],"names":["KnockExpoPushNotificationContext","createContext","useExpoPushNotifications","context","useContext","InternalExpoPushNotificationProvider","knockExpoChannelId","customNotificationHandler","setupAndroidNotificationChannel","setupDefaultAndroidChannel","children","autoRegister","knockClient","useKnockClient","authStatus","useKnockAuthState","isAuthenticated","registerPushTokenToChannel","unregisterPushTokenFromChannel","usePushNotifications","expoPushToken","setExpoPushToken","useState","notificationReceivedHandlerRef","useRef","notificationTappedHandlerRef","onNotificationReceived","useCallback","handler","onNotificationTapped","registerForPushNotifications","token","registerForPushNotificationsUtil","error","updateMessageStatus","notification","status","messageId","_a","useEffect","NotificationsModule","getNotificationsModule","handleNotification","DEFAULT_NOTIFICATION_BEHAVIOR","isMounted","receivedSubscription","responseSubscription","response","contextValue","KnockExpoPushNotificationProvider","props","KnockPushNotificationProvider","jsx"],"mappings":"iRAoCMA,EAAmCC,gBAEvC,MAAS,EAMJ,SAASC,GAAiE,CACzE,MAAAC,EAAUC,aAAWJ,CAAgC,EAE3D,GAAIG,IAAY,OACd,MAAM,IAAI,MACR,0FACF,EAGK,OAAAA,CACT,CAKA,MAAME,EAEF,CAAC,CACH,mBAAAC,EACA,0BAAAC,EACA,gCAAAC,EAAkCC,EAAA,2BAClC,SAAAC,EACA,aAAAC,EAAe,EACjB,IAAM,CACJ,MAAMC,EAAcC,EAAAA,eAAe,EAC7B,CAAE,OAAQC,GAAeC,EAAAA,kBAAkBH,CAAW,EACtDI,EAAkBF,IAAe,gBACjC,CAAE,2BAAAG,EAA4B,+BAAAC,CAA+B,EACjEC,uBAAqB,EAEjB,CAACC,EAAeC,CAAgB,EAAIC,EAAAA,SAAwB,IAAI,EAGhEC,EAAiCC,EAAAA,OAErC,IAAM,CAAA,CAAE,EAEJC,EAA+BD,EAAAA,OAEnC,IAAM,CAAA,CAAE,EAKJE,EAAyBC,EAAA,YAC5BC,GAAkD,CACjDL,EAA+B,QAAUK,CAC3C,EACA,CAAA,CACF,EAKMC,EAAuBF,EAAA,YAC1BC,GAAsD,CACrDH,EAA6B,QAAUG,CACzC,EACA,CAAA,CACF,EAMME,EAA+BH,EAAAA,YAAY,SAE5C,CACC,GAAA,CACFf,EAAY,IAAI,4CAA4C,EAE5D,MAAMmB,EAAQ,MAAMC,EAAA,6BAClBxB,CACF,EAEA,OAAIuB,GACUnB,EAAA,IAAI,gCAAgCmB,CAAK,EAAE,EACvDV,EAAiBU,CAAK,EACfA,GAGF,WACAE,EAAO,CACN,eAAA,MAAM,oDAAqDA,CAAK,EACjE,IAAA,CACT,EACC,CAACrB,EAAaJ,CAA+B,CAAC,EAM3C0B,EAAsBP,EAAA,YAC1B,MACEQ,EACAC,IAC4B,OAC5B,MAAMC,GAAYC,EAAAH,EAAa,QAAQ,QAAQ,OAA7B,YAAAG,EAChB,iBAKF,GAAI,CAACD,EAAW,CACFzB,EAAA,IACV,2DACF,EACA,MAAA,CAKE,GAAA,CAACA,EAAY,kBAAmB,CACtBA,EAAA,IACV,2DACF,EACA,MAAA,CAGF,OAAOA,EAAY,SAAS,aAAayB,EAAWD,CAAM,CAC5D,EACA,CAACxB,CAAW,CACd,EAGA2B,EAAAA,UAAU,IAAM,CACd,MAAMC,EAAsBC,EAAAA,uBAAuB,EACnD,GAAI,CAACD,EAAqB,OAEpB,MAAAE,EAAqBnC,IAEvB,SAAYoC,EAAA,+BAEIH,EAAA,uBAAuB,CAAE,mBAAAE,EAAoB,CAAA,EAChE,CAACnC,CAAyB,CAAC,EAM9BgC,EAAAA,UAAU,IAAM,CACV,GAAA,CAAC5B,GAAgB,CAACK,EACpB,OAGF,IAAI4B,EAAY,GAeP,OAbQ,SAAY,CACvB,GAAA,CACI,MAAAb,EAAQ,MAAMD,EAA6B,EAE7CC,GAASa,IACL,MAAA3B,EAA2Bc,EAAOzB,CAAkB,EAC1DM,EAAY,IAAI,kDAAkD,SAE7DqB,EAAO,CACN,QAAA,MAAM,0CAA2CA,CAAK,CAAA,CAElE,GAES,EAEF,IAAM,CACCW,EAAA,EACd,CAAA,EACC,CACDjC,EACAK,EACAV,EACAwB,EACAb,EACAL,CAAA,CACD,EAGD2B,EAAAA,UAAU,IAAM,CACd,MAAMC,EAAsBC,EAAAA,uBAAuB,EACnD,GAAI,CAACD,EAAqB,OAE1B,MAAMK,EACJL,EAAoB,gCAAiCL,GAAiB,CACpEvB,EAAY,IAAI,6CAA6C,EAC7DsB,EAAoBC,EAAc,YAAY,EAC9CZ,EAA+B,QAAQY,CAAY,CAAA,CACpD,EAEGW,EACJN,EAAoB,wCACjBO,GAAa,CACZnC,EAAY,IAAI,iCAAiC,EAC7BsB,EAAAa,EAAS,aAAc,YAAY,EACvDtB,EAA6B,QAAQsB,CAAQ,CAAA,CAEjD,EAEF,MAAO,IAAM,CACXF,EAAqB,OAAO,EAC5BC,EAAqB,OAAO,CAC9B,CAAA,EACC,CAAClC,EAAasB,CAAmB,CAAC,EAErC,MAAMc,EAAqD,CACzD,cAAA5B,EACA,6BAAAU,EACA,2BAAAb,EACA,+BAAAC,EACA,uBAAAQ,EACA,qBAAAG,CACF,EAEA,aACG7B,EAAiC,SAAjC,CAA0C,MAAOgD,EAC/C,SAAAtC,EACH,CAEJ,EAiBauC,EAERC,SAEAC,gCACC,CAAA,SAAAC,EAAAA,IAAC/C,EAAsC,CAAA,GAAG6C,CAAO,CAAA,EACnD"}
1
+ {"version":3,"file":"KnockExpoPushNotificationProvider.js","sources":["../../../../src/modules/push/KnockExpoPushNotificationProvider.tsx"],"sourcesContent":["import { Message, MessageEngagementStatus } from \"@knocklabs/client\";\nimport { useKnockAuthState, useKnockClient } from \"@knocklabs/react-core\";\nimport {\n KnockPushNotificationProvider,\n usePushNotifications,\n} from \"@knocklabs/react-native\";\nimport React, {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useRef,\n useState,\n} from \"react\";\n\nimport {\n type Notification,\n type NotificationResponse,\n getNotificationsModule,\n} from \"./getNotificationsModule\";\nimport type {\n KnockExpoPushNotificationContextType,\n KnockExpoPushNotificationProviderProps,\n} from \"./types\";\nimport {\n DEFAULT_NOTIFICATION_BEHAVIOR,\n registerForPushNotifications as registerForPushNotificationsUtil,\n setupDefaultAndroidChannel,\n} from \"./utils\";\n\n// Re-export types for consumers\nexport type {\n KnockExpoPushNotificationContextType,\n KnockExpoPushNotificationProviderProps,\n} from \"./types\";\n\nconst KnockExpoPushNotificationContext = createContext<\n KnockExpoPushNotificationContextType | undefined\n>(undefined);\n\n/**\n * Hook to access push notification functionality within a KnockExpoPushNotificationProvider.\n * @throws Error if used outside of a KnockExpoPushNotificationProvider\n */\nexport function useExpoPushNotifications(): KnockExpoPushNotificationContextType {\n const context = useContext(KnockExpoPushNotificationContext);\n\n if (context === undefined) {\n throw new Error(\n \"[Knock] useExpoPushNotifications must be used within a KnockExpoPushNotificationProvider\",\n );\n }\n\n return context;\n}\n\n/**\n * Internal provider component that handles all the Expo push notification logic.\n */\nconst InternalExpoPushNotificationProvider: React.FC<\n KnockExpoPushNotificationProviderProps\n> = ({\n knockExpoChannelId,\n customNotificationHandler,\n setupAndroidNotificationChannel = setupDefaultAndroidChannel,\n children,\n autoRegister = true,\n}) => {\n const knockClient = useKnockClient();\n const { status: authStatus, userId } = useKnockAuthState(knockClient);\n const isAuthenticated = authStatus === \"authenticated\";\n const { registerPushTokenToChannel, unregisterPushTokenFromChannel } =\n usePushNotifications();\n\n const [expoPushToken, setExpoPushToken] = useState<string | null>(null);\n\n // Use refs for handlers to avoid re-running effects when handlers change\n const notificationReceivedHandlerRef = useRef<\n (notification: Notification) => void\n >(() => {});\n\n const notificationTappedHandlerRef = useRef<\n (response: NotificationResponse) => void\n >(() => {});\n\n /**\n * Register a handler to be called when a notification is received in the foreground.\n */\n const onNotificationReceived = useCallback(\n (handler: (notification: Notification) => void) => {\n notificationReceivedHandlerRef.current = handler;\n },\n [],\n );\n\n /**\n * Register a handler to be called when a notification is tapped.\n */\n const onNotificationTapped = useCallback(\n (handler: (response: NotificationResponse) => void) => {\n notificationTappedHandlerRef.current = handler;\n },\n [],\n );\n\n /**\n * Manually trigger push notification registration.\n * Returns the push token if successful, or null if registration failed.\n */\n const registerForPushNotifications = useCallback(async (): Promise<\n string | null\n > => {\n try {\n knockClient.log(\"[Knock] Registering for push notifications\");\n\n const token = await registerForPushNotificationsUtil(\n setupAndroidNotificationChannel,\n );\n\n if (token) {\n knockClient.log(`[Knock] Push token received: ${token}`);\n setExpoPushToken(token);\n return token;\n }\n\n return null;\n } catch (error) {\n console.error(\"[Knock] Error registering for push notifications:\", error);\n return null;\n }\n }, [knockClient, setupAndroidNotificationChannel]);\n\n /**\n * Update the Knock message status when a notification is received or interacted with.\n * Only updates status for notifications that originated from Knock (have a knock_message_id).\n */\n const updateMessageStatus = useCallback(\n async (\n notification: Notification,\n status: MessageEngagementStatus,\n ): Promise<Message | void> => {\n const messageId = notification.request.content.data?.[\n \"knock_message_id\"\n ] as string | undefined;\n\n // Skip status update if this isn't a Knock notification\n // Fixes issue: https://github.com/knocklabs/javascript/issues/589\n if (!messageId) {\n knockClient.log(\n \"[Knock] Skipping status update for non-Knock notification\",\n );\n return;\n }\n\n // Skip when there's no authenticated user (e.g. a notification tapped\n // after logout) — otherwise this fires a messages request with no user.\n if (!knockClient.isAuthenticated()) {\n knockClient.log(\n \"[Knock] Skipping status update; user is not authenticated\",\n );\n return;\n }\n\n return knockClient.messages.updateStatus(messageId, status);\n },\n [knockClient],\n );\n\n // Set up the notification handler for foreground notifications\n useEffect(() => {\n const NotificationsModule = getNotificationsModule();\n if (!NotificationsModule) return;\n\n const handleNotification = customNotificationHandler\n ? customNotificationHandler\n : async () => DEFAULT_NOTIFICATION_BEHAVIOR;\n\n NotificationsModule.setNotificationHandler({ handleNotification });\n }, [customNotificationHandler]);\n\n // Auto-register for push notifications once there is an authenticated user.\n // Gating on auth defers the OS permission prompt (prompting a logged-out user\n // is hostile) and avoids registering a token against no user. Because\n // `isAuthenticated` is a dependency, enabling auth later re-runs registration.\n // `userId` is also a dependency so that an in-place user switch (same Knock\n // instance re-authenticated as a different user, where `isAuthenticated` never\n // flips) re-registers the device token against the new user's channel data.\n useEffect(() => {\n if (!autoRegister || !isAuthenticated) {\n return;\n }\n\n let isMounted = true;\n\n const register = async () => {\n try {\n const token = await registerForPushNotifications();\n\n if (token && isMounted) {\n await registerPushTokenToChannel(token, knockExpoChannelId);\n knockClient.log(\"[Knock] Push token registered with Knock channel\");\n }\n } catch (error) {\n console.error(\"[Knock] Error during auto-registration:\", error);\n }\n };\n\n register();\n\n return () => {\n isMounted = false;\n };\n }, [\n autoRegister,\n isAuthenticated,\n userId,\n knockExpoChannelId,\n registerForPushNotifications,\n registerPushTokenToChannel,\n knockClient,\n ]);\n\n // Set up notification listeners for received and tapped notifications\n useEffect(() => {\n const NotificationsModule = getNotificationsModule();\n if (!NotificationsModule) return;\n\n const receivedSubscription =\n NotificationsModule.addNotificationReceivedListener((notification) => {\n knockClient.log(\"[Knock] Notification received in foreground\");\n updateMessageStatus(notification, \"interacted\");\n notificationReceivedHandlerRef.current(notification);\n });\n\n const responseSubscription =\n NotificationsModule.addNotificationResponseReceivedListener(\n (response) => {\n knockClient.log(\"[Knock] Notification was tapped\");\n updateMessageStatus(response.notification, \"interacted\");\n notificationTappedHandlerRef.current(response);\n },\n );\n\n return () => {\n receivedSubscription.remove();\n responseSubscription.remove();\n };\n }, [knockClient, updateMessageStatus]);\n\n const contextValue: KnockExpoPushNotificationContextType = {\n expoPushToken,\n registerForPushNotifications,\n registerPushTokenToChannel,\n unregisterPushTokenFromChannel,\n onNotificationReceived,\n onNotificationTapped,\n };\n\n return (\n <KnockExpoPushNotificationContext.Provider value={contextValue}>\n {children}\n </KnockExpoPushNotificationContext.Provider>\n );\n};\n\n/**\n * Provider component for Expo push notifications with Knock.\n *\n * Wraps the internal provider with the base KnockPushNotificationProvider\n * to provide full push notification functionality.\n *\n * @example\n * ```tsx\n * <KnockProvider apiKey=\"your-api-key\" userId=\"user-id\">\n * <KnockExpoPushNotificationProvider knockExpoChannelId=\"your-channel-id\">\n * <App />\n * </KnockExpoPushNotificationProvider>\n * </KnockProvider>\n * ```\n */\nexport const KnockExpoPushNotificationProvider: React.FC<\n KnockExpoPushNotificationProviderProps\n> = (props) => {\n return (\n <KnockPushNotificationProvider>\n <InternalExpoPushNotificationProvider {...props} />\n </KnockPushNotificationProvider>\n );\n};\n"],"names":["KnockExpoPushNotificationContext","createContext","useExpoPushNotifications","context","useContext","InternalExpoPushNotificationProvider","knockExpoChannelId","customNotificationHandler","setupAndroidNotificationChannel","setupDefaultAndroidChannel","children","autoRegister","knockClient","useKnockClient","authStatus","userId","useKnockAuthState","isAuthenticated","registerPushTokenToChannel","unregisterPushTokenFromChannel","usePushNotifications","expoPushToken","setExpoPushToken","useState","notificationReceivedHandlerRef","useRef","notificationTappedHandlerRef","onNotificationReceived","useCallback","handler","onNotificationTapped","registerForPushNotifications","token","registerForPushNotificationsUtil","error","updateMessageStatus","notification","status","messageId","_a","useEffect","NotificationsModule","getNotificationsModule","handleNotification","DEFAULT_NOTIFICATION_BEHAVIOR","isMounted","receivedSubscription","responseSubscription","response","contextValue","KnockExpoPushNotificationProvider","props","KnockPushNotificationProvider","jsx"],"mappings":"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"}
@@ -1,44 +1,44 @@
1
1
  import { jsx as h } from "react/jsx-runtime";
2
- import { useKnockClient as y, useKnockAuthState as A } from "@knocklabs/react-core";
3
- import { KnockPushNotificationProvider as F, usePushNotifications as I } from "@knocklabs/react-native";
4
- import { createContext as M, useContext as b, useState as _, useRef as N, useCallback as s, useEffect as d } from "react";
2
+ import { useKnockClient as A, useKnockAuthState as F } from "@knocklabs/react-core";
3
+ import { KnockPushNotificationProvider as I, usePushNotifications as M } from "@knocklabs/react-native";
4
+ import { createContext as b, useContext as _, useState as L, useRef as N, useCallback as s, useEffect as d } from "react";
5
5
  import { getNotificationsModule as K } from "./getNotificationsModule.mjs";
6
- import { registerForPushNotifications as L, setupDefaultAndroidChannel as O, DEFAULT_NOTIFICATION_BEHAVIOR as D } from "./utils.mjs";
7
- const m = M(void 0);
8
- function z() {
9
- const i = b(m);
6
+ import { registerForPushNotifications as O, setupDefaultAndroidChannel as D, DEFAULT_NOTIFICATION_BEHAVIOR as H } from "./utils.mjs";
7
+ const m = b(void 0);
8
+ function G() {
9
+ const i = _(m);
10
10
  if (i === void 0)
11
11
  throw new Error(
12
12
  "[Knock] useExpoPushNotifications must be used within a KnockExpoPushNotificationProvider"
13
13
  );
14
14
  return i;
15
15
  }
16
- const H = ({
16
+ const V = ({
17
17
  knockExpoChannelId: i,
18
18
  customNotificationHandler: c,
19
- setupAndroidNotificationChannel: l = O,
19
+ setupAndroidNotificationChannel: l = D,
20
20
  children: v,
21
21
  autoRegister: p = !0
22
22
  }) => {
23
- const o = y(), { status: x } = A(o), k = x === "authenticated", { registerPushTokenToChannel: a, unregisterPushTokenFromChannel: E } = I(), [T, R] = _(null), g = N(() => {
23
+ const o = A(), { status: x, userId: E } = F(o), k = x === "authenticated", { registerPushTokenToChannel: u, unregisterPushTokenFromChannel: T } = M(), [R, S] = L(null), g = N(() => {
24
24
  }), P = N(() => {
25
- }), S = s(
25
+ }), w = s(
26
26
  (t) => {
27
27
  g.current = t;
28
28
  },
29
29
  []
30
- ), w = s(
30
+ ), C = s(
31
31
  (t) => {
32
32
  P.current = t;
33
33
  },
34
34
  []
35
- ), u = s(async () => {
35
+ ), a = s(async () => {
36
36
  try {
37
37
  o.log("[Knock] Registering for push notifications");
38
- const t = await L(
38
+ const t = await O(
39
39
  l
40
40
  );
41
- return t ? (o.log(`[Knock] Push token received: ${t}`), R(t), t) : null;
41
+ return t ? (o.log(`[Knock] Push token received: ${t}`), S(t), t) : null;
42
42
  } catch (t) {
43
43
  return console.error("[Knock] Error registering for push notifications:", t), null;
44
44
  }
@@ -65,7 +65,7 @@ const H = ({
65
65
  d(() => {
66
66
  const t = K();
67
67
  if (!t) return;
68
- const r = c || (async () => D);
68
+ const r = c || (async () => H);
69
69
  t.setNotificationHandler({ handleNotification: r });
70
70
  }, [c]), d(() => {
71
71
  if (!p || !k)
@@ -73,8 +73,8 @@ const H = ({
73
73
  let t = !0;
74
74
  return (async () => {
75
75
  try {
76
- const e = await u();
77
- e && t && (await a(e, i), o.log("[Knock] Push token registered with Knock channel"));
76
+ const e = await a();
77
+ e && t && (await u(e, i), o.log("[Knock] Push token registered with Knock channel"));
78
78
  } catch (e) {
79
79
  console.error("[Knock] Error during auto-registration:", e);
80
80
  }
@@ -84,9 +84,10 @@ const H = ({
84
84
  }, [
85
85
  p,
86
86
  k,
87
+ E,
87
88
  i,
88
- u,
89
89
  a,
90
+ u,
90
91
  o
91
92
  ]), d(() => {
92
93
  const t = K();
@@ -102,18 +103,18 @@ const H = ({
102
103
  r.remove(), e.remove();
103
104
  };
104
105
  }, [o, f]);
105
- const C = {
106
- expoPushToken: T,
107
- registerForPushNotifications: u,
108
- registerPushTokenToChannel: a,
109
- unregisterPushTokenFromChannel: E,
110
- onNotificationReceived: S,
111
- onNotificationTapped: w
106
+ const y = {
107
+ expoPushToken: R,
108
+ registerForPushNotifications: a,
109
+ registerPushTokenToChannel: u,
110
+ unregisterPushTokenFromChannel: T,
111
+ onNotificationReceived: w,
112
+ onNotificationTapped: C
112
113
  };
113
- return /* @__PURE__ */ h(m.Provider, { value: C, children: v });
114
- }, G = (i) => /* @__PURE__ */ h(F, { children: /* @__PURE__ */ h(H, { ...i }) });
114
+ return /* @__PURE__ */ h(m.Provider, { value: y, children: v });
115
+ }, J = (i) => /* @__PURE__ */ h(I, { children: /* @__PURE__ */ h(V, { ...i }) });
115
116
  export {
116
- G as KnockExpoPushNotificationProvider,
117
- z as useExpoPushNotifications
117
+ J as KnockExpoPushNotificationProvider,
118
+ G as useExpoPushNotifications
118
119
  };
119
120
  //# sourceMappingURL=KnockExpoPushNotificationProvider.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"KnockExpoPushNotificationProvider.mjs","sources":["../../../../src/modules/push/KnockExpoPushNotificationProvider.tsx"],"sourcesContent":["import { Message, MessageEngagementStatus } from \"@knocklabs/client\";\nimport { useKnockAuthState, useKnockClient } from \"@knocklabs/react-core\";\nimport {\n KnockPushNotificationProvider,\n usePushNotifications,\n} from \"@knocklabs/react-native\";\nimport React, {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useRef,\n useState,\n} from \"react\";\n\nimport {\n type Notification,\n type NotificationResponse,\n getNotificationsModule,\n} from \"./getNotificationsModule\";\nimport type {\n KnockExpoPushNotificationContextType,\n KnockExpoPushNotificationProviderProps,\n} from \"./types\";\nimport {\n DEFAULT_NOTIFICATION_BEHAVIOR,\n registerForPushNotifications as registerForPushNotificationsUtil,\n setupDefaultAndroidChannel,\n} from \"./utils\";\n\n// Re-export types for consumers\nexport type {\n KnockExpoPushNotificationContextType,\n KnockExpoPushNotificationProviderProps,\n} from \"./types\";\n\nconst KnockExpoPushNotificationContext = createContext<\n KnockExpoPushNotificationContextType | undefined\n>(undefined);\n\n/**\n * Hook to access push notification functionality within a KnockExpoPushNotificationProvider.\n * @throws Error if used outside of a KnockExpoPushNotificationProvider\n */\nexport function useExpoPushNotifications(): KnockExpoPushNotificationContextType {\n const context = useContext(KnockExpoPushNotificationContext);\n\n if (context === undefined) {\n throw new Error(\n \"[Knock] useExpoPushNotifications must be used within a KnockExpoPushNotificationProvider\",\n );\n }\n\n return context;\n}\n\n/**\n * Internal provider component that handles all the Expo push notification logic.\n */\nconst InternalExpoPushNotificationProvider: React.FC<\n KnockExpoPushNotificationProviderProps\n> = ({\n knockExpoChannelId,\n customNotificationHandler,\n setupAndroidNotificationChannel = setupDefaultAndroidChannel,\n children,\n autoRegister = true,\n}) => {\n const knockClient = useKnockClient();\n const { status: authStatus } = useKnockAuthState(knockClient);\n const isAuthenticated = authStatus === \"authenticated\";\n const { registerPushTokenToChannel, unregisterPushTokenFromChannel } =\n usePushNotifications();\n\n const [expoPushToken, setExpoPushToken] = useState<string | null>(null);\n\n // Use refs for handlers to avoid re-running effects when handlers change\n const notificationReceivedHandlerRef = useRef<\n (notification: Notification) => void\n >(() => {});\n\n const notificationTappedHandlerRef = useRef<\n (response: NotificationResponse) => void\n >(() => {});\n\n /**\n * Register a handler to be called when a notification is received in the foreground.\n */\n const onNotificationReceived = useCallback(\n (handler: (notification: Notification) => void) => {\n notificationReceivedHandlerRef.current = handler;\n },\n [],\n );\n\n /**\n * Register a handler to be called when a notification is tapped.\n */\n const onNotificationTapped = useCallback(\n (handler: (response: NotificationResponse) => void) => {\n notificationTappedHandlerRef.current = handler;\n },\n [],\n );\n\n /**\n * Manually trigger push notification registration.\n * Returns the push token if successful, or null if registration failed.\n */\n const registerForPushNotifications = useCallback(async (): Promise<\n string | null\n > => {\n try {\n knockClient.log(\"[Knock] Registering for push notifications\");\n\n const token = await registerForPushNotificationsUtil(\n setupAndroidNotificationChannel,\n );\n\n if (token) {\n knockClient.log(`[Knock] Push token received: ${token}`);\n setExpoPushToken(token);\n return token;\n }\n\n return null;\n } catch (error) {\n console.error(\"[Knock] Error registering for push notifications:\", error);\n return null;\n }\n }, [knockClient, setupAndroidNotificationChannel]);\n\n /**\n * Update the Knock message status when a notification is received or interacted with.\n * Only updates status for notifications that originated from Knock (have a knock_message_id).\n */\n const updateMessageStatus = useCallback(\n async (\n notification: Notification,\n status: MessageEngagementStatus,\n ): Promise<Message | void> => {\n const messageId = notification.request.content.data?.[\n \"knock_message_id\"\n ] as string | undefined;\n\n // Skip status update if this isn't a Knock notification\n // Fixes issue: https://github.com/knocklabs/javascript/issues/589\n if (!messageId) {\n knockClient.log(\n \"[Knock] Skipping status update for non-Knock notification\",\n );\n return;\n }\n\n // Skip when there's no authenticated user (e.g. a notification tapped\n // after logout) — otherwise this fires a messages request with no user.\n if (!knockClient.isAuthenticated()) {\n knockClient.log(\n \"[Knock] Skipping status update; user is not authenticated\",\n );\n return;\n }\n\n return knockClient.messages.updateStatus(messageId, status);\n },\n [knockClient],\n );\n\n // Set up the notification handler for foreground notifications\n useEffect(() => {\n const NotificationsModule = getNotificationsModule();\n if (!NotificationsModule) return;\n\n const handleNotification = customNotificationHandler\n ? customNotificationHandler\n : async () => DEFAULT_NOTIFICATION_BEHAVIOR;\n\n NotificationsModule.setNotificationHandler({ handleNotification });\n }, [customNotificationHandler]);\n\n // Auto-register for push notifications once there is an authenticated user.\n // Gating on auth defers the OS permission prompt (prompting a logged-out user\n // is hostile) and avoids registering a token against no user. Because\n // `isAuthenticated` is a dependency, enabling auth later re-runs registration.\n useEffect(() => {\n if (!autoRegister || !isAuthenticated) {\n return;\n }\n\n let isMounted = true;\n\n const register = async () => {\n try {\n const token = await registerForPushNotifications();\n\n if (token && isMounted) {\n await registerPushTokenToChannel(token, knockExpoChannelId);\n knockClient.log(\"[Knock] Push token registered with Knock channel\");\n }\n } catch (error) {\n console.error(\"[Knock] Error during auto-registration:\", error);\n }\n };\n\n register();\n\n return () => {\n isMounted = false;\n };\n }, [\n autoRegister,\n isAuthenticated,\n knockExpoChannelId,\n registerForPushNotifications,\n registerPushTokenToChannel,\n knockClient,\n ]);\n\n // Set up notification listeners for received and tapped notifications\n useEffect(() => {\n const NotificationsModule = getNotificationsModule();\n if (!NotificationsModule) return;\n\n const receivedSubscription =\n NotificationsModule.addNotificationReceivedListener((notification) => {\n knockClient.log(\"[Knock] Notification received in foreground\");\n updateMessageStatus(notification, \"interacted\");\n notificationReceivedHandlerRef.current(notification);\n });\n\n const responseSubscription =\n NotificationsModule.addNotificationResponseReceivedListener(\n (response) => {\n knockClient.log(\"[Knock] Notification was tapped\");\n updateMessageStatus(response.notification, \"interacted\");\n notificationTappedHandlerRef.current(response);\n },\n );\n\n return () => {\n receivedSubscription.remove();\n responseSubscription.remove();\n };\n }, [knockClient, updateMessageStatus]);\n\n const contextValue: KnockExpoPushNotificationContextType = {\n expoPushToken,\n registerForPushNotifications,\n registerPushTokenToChannel,\n unregisterPushTokenFromChannel,\n onNotificationReceived,\n onNotificationTapped,\n };\n\n return (\n <KnockExpoPushNotificationContext.Provider value={contextValue}>\n {children}\n </KnockExpoPushNotificationContext.Provider>\n );\n};\n\n/**\n * Provider component for Expo push notifications with Knock.\n *\n * Wraps the internal provider with the base KnockPushNotificationProvider\n * to provide full push notification functionality.\n *\n * @example\n * ```tsx\n * <KnockProvider apiKey=\"your-api-key\" userId=\"user-id\">\n * <KnockExpoPushNotificationProvider knockExpoChannelId=\"your-channel-id\">\n * <App />\n * </KnockExpoPushNotificationProvider>\n * </KnockProvider>\n * ```\n */\nexport const KnockExpoPushNotificationProvider: React.FC<\n KnockExpoPushNotificationProviderProps\n> = (props) => {\n return (\n <KnockPushNotificationProvider>\n <InternalExpoPushNotificationProvider {...props} />\n </KnockPushNotificationProvider>\n );\n};\n"],"names":["KnockExpoPushNotificationContext","createContext","useExpoPushNotifications","context","useContext","InternalExpoPushNotificationProvider","knockExpoChannelId","customNotificationHandler","setupAndroidNotificationChannel","setupDefaultAndroidChannel","children","autoRegister","knockClient","useKnockClient","authStatus","useKnockAuthState","isAuthenticated","registerPushTokenToChannel","unregisterPushTokenFromChannel","usePushNotifications","expoPushToken","setExpoPushToken","useState","notificationReceivedHandlerRef","useRef","notificationTappedHandlerRef","onNotificationReceived","useCallback","handler","onNotificationTapped","registerForPushNotifications","token","registerForPushNotificationsUtil","error","updateMessageStatus","notification","status","messageId","_a","useEffect","NotificationsModule","getNotificationsModule","handleNotification","DEFAULT_NOTIFICATION_BEHAVIOR","isMounted","receivedSubscription","responseSubscription","response","contextValue","KnockExpoPushNotificationProvider","props","KnockPushNotificationProvider","jsx"],"mappings":"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"}
1
+ {"version":3,"file":"KnockExpoPushNotificationProvider.mjs","sources":["../../../../src/modules/push/KnockExpoPushNotificationProvider.tsx"],"sourcesContent":["import { Message, MessageEngagementStatus } from \"@knocklabs/client\";\nimport { useKnockAuthState, useKnockClient } from \"@knocklabs/react-core\";\nimport {\n KnockPushNotificationProvider,\n usePushNotifications,\n} from \"@knocklabs/react-native\";\nimport React, {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useRef,\n useState,\n} from \"react\";\n\nimport {\n type Notification,\n type NotificationResponse,\n getNotificationsModule,\n} from \"./getNotificationsModule\";\nimport type {\n KnockExpoPushNotificationContextType,\n KnockExpoPushNotificationProviderProps,\n} from \"./types\";\nimport {\n DEFAULT_NOTIFICATION_BEHAVIOR,\n registerForPushNotifications as registerForPushNotificationsUtil,\n setupDefaultAndroidChannel,\n} from \"./utils\";\n\n// Re-export types for consumers\nexport type {\n KnockExpoPushNotificationContextType,\n KnockExpoPushNotificationProviderProps,\n} from \"./types\";\n\nconst KnockExpoPushNotificationContext = createContext<\n KnockExpoPushNotificationContextType | undefined\n>(undefined);\n\n/**\n * Hook to access push notification functionality within a KnockExpoPushNotificationProvider.\n * @throws Error if used outside of a KnockExpoPushNotificationProvider\n */\nexport function useExpoPushNotifications(): KnockExpoPushNotificationContextType {\n const context = useContext(KnockExpoPushNotificationContext);\n\n if (context === undefined) {\n throw new Error(\n \"[Knock] useExpoPushNotifications must be used within a KnockExpoPushNotificationProvider\",\n );\n }\n\n return context;\n}\n\n/**\n * Internal provider component that handles all the Expo push notification logic.\n */\nconst InternalExpoPushNotificationProvider: React.FC<\n KnockExpoPushNotificationProviderProps\n> = ({\n knockExpoChannelId,\n customNotificationHandler,\n setupAndroidNotificationChannel = setupDefaultAndroidChannel,\n children,\n autoRegister = true,\n}) => {\n const knockClient = useKnockClient();\n const { status: authStatus, userId } = useKnockAuthState(knockClient);\n const isAuthenticated = authStatus === \"authenticated\";\n const { registerPushTokenToChannel, unregisterPushTokenFromChannel } =\n usePushNotifications();\n\n const [expoPushToken, setExpoPushToken] = useState<string | null>(null);\n\n // Use refs for handlers to avoid re-running effects when handlers change\n const notificationReceivedHandlerRef = useRef<\n (notification: Notification) => void\n >(() => {});\n\n const notificationTappedHandlerRef = useRef<\n (response: NotificationResponse) => void\n >(() => {});\n\n /**\n * Register a handler to be called when a notification is received in the foreground.\n */\n const onNotificationReceived = useCallback(\n (handler: (notification: Notification) => void) => {\n notificationReceivedHandlerRef.current = handler;\n },\n [],\n );\n\n /**\n * Register a handler to be called when a notification is tapped.\n */\n const onNotificationTapped = useCallback(\n (handler: (response: NotificationResponse) => void) => {\n notificationTappedHandlerRef.current = handler;\n },\n [],\n );\n\n /**\n * Manually trigger push notification registration.\n * Returns the push token if successful, or null if registration failed.\n */\n const registerForPushNotifications = useCallback(async (): Promise<\n string | null\n > => {\n try {\n knockClient.log(\"[Knock] Registering for push notifications\");\n\n const token = await registerForPushNotificationsUtil(\n setupAndroidNotificationChannel,\n );\n\n if (token) {\n knockClient.log(`[Knock] Push token received: ${token}`);\n setExpoPushToken(token);\n return token;\n }\n\n return null;\n } catch (error) {\n console.error(\"[Knock] Error registering for push notifications:\", error);\n return null;\n }\n }, [knockClient, setupAndroidNotificationChannel]);\n\n /**\n * Update the Knock message status when a notification is received or interacted with.\n * Only updates status for notifications that originated from Knock (have a knock_message_id).\n */\n const updateMessageStatus = useCallback(\n async (\n notification: Notification,\n status: MessageEngagementStatus,\n ): Promise<Message | void> => {\n const messageId = notification.request.content.data?.[\n \"knock_message_id\"\n ] as string | undefined;\n\n // Skip status update if this isn't a Knock notification\n // Fixes issue: https://github.com/knocklabs/javascript/issues/589\n if (!messageId) {\n knockClient.log(\n \"[Knock] Skipping status update for non-Knock notification\",\n );\n return;\n }\n\n // Skip when there's no authenticated user (e.g. a notification tapped\n // after logout) — otherwise this fires a messages request with no user.\n if (!knockClient.isAuthenticated()) {\n knockClient.log(\n \"[Knock] Skipping status update; user is not authenticated\",\n );\n return;\n }\n\n return knockClient.messages.updateStatus(messageId, status);\n },\n [knockClient],\n );\n\n // Set up the notification handler for foreground notifications\n useEffect(() => {\n const NotificationsModule = getNotificationsModule();\n if (!NotificationsModule) return;\n\n const handleNotification = customNotificationHandler\n ? customNotificationHandler\n : async () => DEFAULT_NOTIFICATION_BEHAVIOR;\n\n NotificationsModule.setNotificationHandler({ handleNotification });\n }, [customNotificationHandler]);\n\n // Auto-register for push notifications once there is an authenticated user.\n // Gating on auth defers the OS permission prompt (prompting a logged-out user\n // is hostile) and avoids registering a token against no user. Because\n // `isAuthenticated` is a dependency, enabling auth later re-runs registration.\n // `userId` is also a dependency so that an in-place user switch (same Knock\n // instance re-authenticated as a different user, where `isAuthenticated` never\n // flips) re-registers the device token against the new user's channel data.\n useEffect(() => {\n if (!autoRegister || !isAuthenticated) {\n return;\n }\n\n let isMounted = true;\n\n const register = async () => {\n try {\n const token = await registerForPushNotifications();\n\n if (token && isMounted) {\n await registerPushTokenToChannel(token, knockExpoChannelId);\n knockClient.log(\"[Knock] Push token registered with Knock channel\");\n }\n } catch (error) {\n console.error(\"[Knock] Error during auto-registration:\", error);\n }\n };\n\n register();\n\n return () => {\n isMounted = false;\n };\n }, [\n autoRegister,\n isAuthenticated,\n userId,\n knockExpoChannelId,\n registerForPushNotifications,\n registerPushTokenToChannel,\n knockClient,\n ]);\n\n // Set up notification listeners for received and tapped notifications\n useEffect(() => {\n const NotificationsModule = getNotificationsModule();\n if (!NotificationsModule) return;\n\n const receivedSubscription =\n NotificationsModule.addNotificationReceivedListener((notification) => {\n knockClient.log(\"[Knock] Notification received in foreground\");\n updateMessageStatus(notification, \"interacted\");\n notificationReceivedHandlerRef.current(notification);\n });\n\n const responseSubscription =\n NotificationsModule.addNotificationResponseReceivedListener(\n (response) => {\n knockClient.log(\"[Knock] Notification was tapped\");\n updateMessageStatus(response.notification, \"interacted\");\n notificationTappedHandlerRef.current(response);\n },\n );\n\n return () => {\n receivedSubscription.remove();\n responseSubscription.remove();\n };\n }, [knockClient, updateMessageStatus]);\n\n const contextValue: KnockExpoPushNotificationContextType = {\n expoPushToken,\n registerForPushNotifications,\n registerPushTokenToChannel,\n unregisterPushTokenFromChannel,\n onNotificationReceived,\n onNotificationTapped,\n };\n\n return (\n <KnockExpoPushNotificationContext.Provider value={contextValue}>\n {children}\n </KnockExpoPushNotificationContext.Provider>\n );\n};\n\n/**\n * Provider component for Expo push notifications with Knock.\n *\n * Wraps the internal provider with the base KnockPushNotificationProvider\n * to provide full push notification functionality.\n *\n * @example\n * ```tsx\n * <KnockProvider apiKey=\"your-api-key\" userId=\"user-id\">\n * <KnockExpoPushNotificationProvider knockExpoChannelId=\"your-channel-id\">\n * <App />\n * </KnockExpoPushNotificationProvider>\n * </KnockProvider>\n * ```\n */\nexport const KnockExpoPushNotificationProvider: React.FC<\n KnockExpoPushNotificationProviderProps\n> = (props) => {\n return (\n <KnockPushNotificationProvider>\n <InternalExpoPushNotificationProvider {...props} />\n </KnockPushNotificationProvider>\n );\n};\n"],"names":["KnockExpoPushNotificationContext","createContext","useExpoPushNotifications","context","useContext","InternalExpoPushNotificationProvider","knockExpoChannelId","customNotificationHandler","setupAndroidNotificationChannel","setupDefaultAndroidChannel","children","autoRegister","knockClient","useKnockClient","authStatus","userId","useKnockAuthState","isAuthenticated","registerPushTokenToChannel","unregisterPushTokenFromChannel","usePushNotifications","expoPushToken","setExpoPushToken","useState","notificationReceivedHandlerRef","useRef","notificationTappedHandlerRef","onNotificationReceived","useCallback","handler","onNotificationTapped","registerForPushNotifications","token","registerForPushNotificationsUtil","error","updateMessageStatus","notification","status","messageId","_a","useEffect","NotificationsModule","getNotificationsModule","handleNotification","DEFAULT_NOTIFICATION_BEHAVIOR","isMounted","receivedSubscription","responseSubscription","response","contextValue","KnockExpoPushNotificationProvider","props","KnockPushNotificationProvider","jsx"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"KnockExpoPushNotificationProvider.d.ts","sourceRoot":"","sources":["../../../../src/modules/push/KnockExpoPushNotificationProvider.tsx"],"names":[],"mappings":"AAMA,OAAO,KAON,MAAM,OAAO,CAAC;AAOf,OAAO,KAAK,EACV,oCAAoC,EACpC,sCAAsC,EACvC,MAAM,SAAS,CAAC;AAQjB,YAAY,EACV,oCAAoC,EACpC,sCAAsC,GACvC,MAAM,SAAS,CAAC;AAMjB;;;GAGG;AACH,wBAAgB,wBAAwB,IAAI,oCAAoC,CAU/E;AA+MD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,iCAAiC,EAAE,KAAK,CAAC,EAAE,CACtD,sCAAsC,CAOvC,CAAC"}
1
+ {"version":3,"file":"KnockExpoPushNotificationProvider.d.ts","sourceRoot":"","sources":["../../../../src/modules/push/KnockExpoPushNotificationProvider.tsx"],"names":[],"mappings":"AAMA,OAAO,KAON,MAAM,OAAO,CAAC;AAOf,OAAO,KAAK,EACV,oCAAoC,EACpC,sCAAsC,EACvC,MAAM,SAAS,CAAC;AAQjB,YAAY,EACV,oCAAoC,EACpC,sCAAsC,GACvC,MAAM,SAAS,CAAC;AAMjB;;;GAGG;AACH,wBAAgB,wBAAwB,IAAI,oCAAoC,CAU/E;AAmND;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,iCAAiC,EAAE,KAAK,CAAC,EAAE,CACtD,sCAAsC,CAOvC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@knocklabs/expo",
3
- "version": "0.7.0-rc.0",
3
+ "version": "0.7.0",
4
4
  "author": "@knocklabs",
5
5
  "license": "MIT",
6
6
  "main": "dist/cjs/index.js",
@@ -53,9 +53,9 @@
53
53
  "react-native-gesture-handler": ">=2.0.0"
54
54
  },
55
55
  "dependencies": {
56
- "@knocklabs/client": "^0.22.0-rc.0",
57
- "@knocklabs/react-core": "^0.14.0-rc.0",
58
- "@knocklabs/react-native": "^0.10.0-rc.0",
56
+ "@knocklabs/client": "^0.22.0",
57
+ "@knocklabs/react-core": "^0.14.0",
58
+ "@knocklabs/react-native": "^0.10.0",
59
59
  "react-native-render-html": "^6.3.4",
60
60
  "react-native-svg": "~15.15.3"
61
61
  },
@@ -67,7 +67,7 @@ const InternalExpoPushNotificationProvider: React.FC<
67
67
  autoRegister = true,
68
68
  }) => {
69
69
  const knockClient = useKnockClient();
70
- const { status: authStatus } = useKnockAuthState(knockClient);
70
+ const { status: authStatus, userId } = useKnockAuthState(knockClient);
71
71
  const isAuthenticated = authStatus === "authenticated";
72
72
  const { registerPushTokenToChannel, unregisterPushTokenFromChannel } =
73
73
  usePushNotifications();
@@ -182,6 +182,9 @@ const InternalExpoPushNotificationProvider: React.FC<
182
182
  // Gating on auth defers the OS permission prompt (prompting a logged-out user
183
183
  // is hostile) and avoids registering a token against no user. Because
184
184
  // `isAuthenticated` is a dependency, enabling auth later re-runs registration.
185
+ // `userId` is also a dependency so that an in-place user switch (same Knock
186
+ // instance re-authenticated as a different user, where `isAuthenticated` never
187
+ // flips) re-registers the device token against the new user's channel data.
185
188
  useEffect(() => {
186
189
  if (!autoRegister || !isAuthenticated) {
187
190
  return;
@@ -210,6 +213,7 @@ const InternalExpoPushNotificationProvider: React.FC<
210
213
  }, [
211
214
  autoRegister,
212
215
  isAuthenticated,
216
+ userId,
213
217
  knockExpoChannelId,
214
218
  registerForPushNotifications,
215
219
  registerPushTokenToChannel,