1import { useEffect, useLayoutEffect, useRef } from "react";
2import * as Notifications from "expo-notifications";
3import { useLinkTo } from "@react-navigation/native";
4
5import { setAndroidThreadOnScreen } from "./androidNotifications";
6import { foregroundNotificationBehavior } from "./foregroundNotificationBehavior";
7import { routeAgentNotificationResponseOnce, threadDeepLinkOnScreen } from "./notificationPayload";
8import { consumeLastAgentNotificationResponse } from "./notificationResponseConsumer";
9
10export 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}