@knocklabs/expo 0.7.0-rc.0 → 0.7.0-rc.1

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,11 @@
1
1
  # @knocklabs/expo
2
2
 
3
+ ## 0.7.0-rc.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 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.
8
+
3
9
  ## 0.7.0-rc.0
4
10
 
5
11
  ### 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":"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"}
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":";;;;;;AAoCA,MAAMA,IAAmCC,EAEvC,MAAS;AAMJ,SAASC,IAAiE;AACzE,QAAAC,IAAUC,EAAWJ,CAAgC;AAE3D,MAAIG,MAAY;AACd,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAGK,SAAAA;AACT;AAKA,MAAME,IAEF,CAAC;AAAA,EACH,oBAAAC;AAAA,EACA,2BAAAC;AAAA,EACA,iCAAAC,IAAkCC;AAAA,EAClC,UAAAC;AAAA,EACA,cAAAC,IAAe;AACjB,MAAM;AACJ,QAAMC,IAAcC,EAAe,GAC7B,EAAE,QAAQC,MAAeC,EAAkBH,CAAW,GACtDI,IAAkBF,MAAe,iBACjC,EAAE,4BAAAG,GAA4B,gCAAAC,EAA+B,IACjEC,EAAqB,GAEjB,CAACC,GAAeC,CAAgB,IAAIC,EAAwB,IAAI,GAGhEC,IAAiCC,EAErC,MAAM;AAAA,EAAA,CAAE,GAEJC,IAA+BD,EAEnC,MAAM;AAAA,EAAA,CAAE,GAKJE,IAAyBC;AAAA,IAC7B,CAACC,MAAkD;AACjD,MAAAL,EAA+B,UAAUK;AAAA,IAC3C;AAAA,IACA,CAAA;AAAA,EACF,GAKMC,IAAuBF;AAAA,IAC3B,CAACC,MAAsD;AACrD,MAAAH,EAA6B,UAAUG;AAAA,IACzC;AAAA,IACA,CAAA;AAAA,EACF,GAMME,IAA+BH,EAAY,YAE5C;AACC,QAAA;AACF,MAAAf,EAAY,IAAI,4CAA4C;AAE5D,YAAMmB,IAAQ,MAAMC;AAAAA,QAClBxB;AAAA,MACF;AAEA,aAAIuB,KACUnB,EAAA,IAAI,gCAAgCmB,CAAK,EAAE,GACvDV,EAAiBU,CAAK,GACfA,KAGF;AAAA,aACAE,GAAO;AACN,qBAAA,MAAM,qDAAqDA,CAAK,GACjE;AAAA,IAAA;AAAA,EACT,GACC,CAACrB,GAAaJ,CAA+B,CAAC,GAM3C0B,IAAsBP;AAAA,IAC1B,OACEQ,GACAC,MAC4B;;AAC5B,YAAMC,KAAYC,IAAAH,EAAa,QAAQ,QAAQ,SAA7B,gBAAAG,EAChB;AAKF,UAAI,CAACD,GAAW;AACF,QAAAzB,EAAA;AAAA,UACV;AAAA,QACF;AACA;AAAA,MAAA;AAKE,UAAA,CAACA,EAAY,mBAAmB;AACtB,QAAAA,EAAA;AAAA,UACV;AAAA,QACF;AACA;AAAA,MAAA;AAGF,aAAOA,EAAY,SAAS,aAAayB,GAAWD,CAAM;AAAA,IAC5D;AAAA,IACA,CAACxB,CAAW;AAAA,EACd;AAGA,EAAA2B,EAAU,MAAM;AACd,UAAMC,IAAsBC,EAAuB;AACnD,QAAI,CAACD,EAAqB;AAEpB,UAAAE,IAAqBnC,MAEvB,YAAYoC;AAEI,IAAAH,EAAA,uBAAuB,EAAE,oBAAAE,GAAoB;AAAA,EAAA,GAChE,CAACnC,CAAyB,CAAC,GAM9BgC,EAAU,MAAM;AACV,QAAA,CAAC5B,KAAgB,CAACK;AACpB;AAGF,QAAI4B,IAAY;AAeP,YAbQ,YAAY;AACvB,UAAA;AACI,cAAAb,IAAQ,MAAMD,EAA6B;AAEjD,QAAIC,KAASa,MACL,MAAA3B,EAA2Bc,GAAOzB,CAAkB,GAC1DM,EAAY,IAAI,kDAAkD;AAAA,eAE7DqB,GAAO;AACN,gBAAA,MAAM,2CAA2CA,CAAK;AAAA,MAAA;AAAA,IAElE,GAES,GAEF,MAAM;AACC,MAAAW,IAAA;AAAA,IACd;AAAA,EAAA,GACC;AAAA,IACDjC;AAAA,IACAK;AAAA,IACAV;AAAA,IACAwB;AAAAA,IACAb;AAAA,IACAL;AAAA,EAAA,CACD,GAGD2B,EAAU,MAAM;AACd,UAAMC,IAAsBC,EAAuB;AACnD,QAAI,CAACD,EAAqB;AAE1B,UAAMK,IACJL,EAAoB,gCAAgC,CAACL,MAAiB;AACpE,MAAAvB,EAAY,IAAI,6CAA6C,GAC7DsB,EAAoBC,GAAc,YAAY,GAC9CZ,EAA+B,QAAQY,CAAY;AAAA,IAAA,CACpD,GAEGW,IACJN,EAAoB;AAAA,MAClB,CAACO,MAAa;AACZ,QAAAnC,EAAY,IAAI,iCAAiC,GAC7BsB,EAAAa,EAAS,cAAc,YAAY,GACvDtB,EAA6B,QAAQsB,CAAQ;AAAA,MAAA;AAAA,IAEjD;AAEF,WAAO,MAAM;AACX,MAAAF,EAAqB,OAAO,GAC5BC,EAAqB,OAAO;AAAA,IAC9B;AAAA,EAAA,GACC,CAAClC,GAAasB,CAAmB,CAAC;AAErC,QAAMc,IAAqD;AAAA,IACzD,eAAA5B;AAAA,IAAA,8BACAU;AAAAA,IACA,4BAAAb;AAAA,IACA,gCAAAC;AAAA,IACA,wBAAAQ;AAAA,IACA,sBAAAG;AAAA,EACF;AAEA,2BACG7B,EAAiC,UAAjC,EAA0C,OAAOgD,GAC/C,UAAAtC,GACH;AAEJ,GAiBauC,IAET,CAACC,wBAEAC,GACC,EAAA,UAAA,gBAAAC,EAAC/C,GAAsC,EAAA,GAAG6C,EAAO,CAAA,GACnD;"}
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-rc.1",
4
4
  "author": "@knocklabs",
5
5
  "license": "MIT",
6
6
  "main": "dist/cjs/index.js",
@@ -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,