| 1 | import { useEffect, useLayoutEffect, useRef } from "react"; |
| 2 | import * as Notifications from "expo-notifications"; |
| 3 | import { useLinkTo } from "@react-navigation/native"; |
| 4 | |
| 5 | import { setAndroidThreadOnScreen } from "./androidNotifications"; |
| 6 | import { foregroundNotificationBehavior } from "./foregroundNotificationBehavior"; |
| 7 | import { routeAgentNotificationResponseOnce, threadDeepLinkOnScreen } from "./notificationPayload"; |
| 8 | import { consumeLastAgentNotificationResponse } from "./notificationResponseConsumer"; |
| 9 | |
| 10 | export function useAgentNotificationNavigation(pathname: string): void { |
| 11 | const linkTo = useLinkTo(); |
| 12 | const handledResponseIds = useRef(new Set<string>()); |
| 13 | // Read through a ref so the native handler registered once below sees the |
| 14 | // current route without re-registering on every navigation. |
| 15 | const deepLinkOnScreen = useRef<string | null>(null); |
| 16 | useLayoutEffect(() => { |
| 17 | const thread = threadDeepLinkOnScreen(pathname); |
| 18 | deepLinkOnScreen.current = thread; |
| 19 | // Android alerts are built natively from FCM data, so update the native |
| 20 | // route at commit time alongside the iOS handler's route reference. |
| 21 | setAndroidThreadOnScreen(thread); |
| 22 | }, [pathname]); |
| 23 | |
| 24 | useEffect(() => { |
| 25 | Notifications.setNotificationHandler({ |
| 26 | handleNotification: (notification) => |
| 27 | Promise.resolve(foregroundNotificationBehavior(notification, deepLinkOnScreen.current)), |
| 28 | }); |
| 29 | return () => { |
| 30 | Notifications.setNotificationHandler(null); |
| 31 | }; |
| 32 | }, []); |
| 33 | |
| 34 | useEffect(() => { |
| 35 | const handleResponse = (response: Notifications.NotificationResponse): void => { |
| 36 | routeAgentNotificationResponseOnce({ |
| 37 | handledResponseIds: handledResponseIds.current, |
| 38 | response, |
| 39 | navigate: linkTo, |
| 40 | }); |
| 41 | }; |
| 42 | |
| 43 | const subscription = Notifications.addNotificationResponseReceivedListener(handleResponse); |
| 44 | void consumeLastAgentNotificationResponse({ |
| 45 | getLastResponse: () => Notifications.getLastNotificationResponseAsync(), |
| 46 | clearLastResponse: () => Notifications.clearLastNotificationResponseAsync(), |
| 47 | handleResponse, |
| 48 | }); |
| 49 | |
| 50 | return () => { |
| 51 | subscription.remove(); |
| 52 | }; |
| 53 | }, [linkTo]); |
| 54 | } |