frontend: introduce a notification observer
Pedro Lucas Porcellis porcellis@eletrotupi.com · 4 months ago
0decf53a4abd2e7b11462965b9f7612156f7670a Browse filesParents
cb5d2d5Changed files
1
Additions
+72
Deletions
0
/dev/null → frontend/hooks/useNotificationObserver.ts
1 +
import { useEffect, useRef } from "react";
2 +
import * as Notifications from "expo-notifications";
3 +
import { useRouter, useRootNavigationState } from "expo-router";
4 +
5 +
export function useNotificationObserver() {
6 +
const router = useRouter();
7 +
const rootNavState = useRootNavigationState();
8 +
const routerReady = !!rootNavState?.key;
9 +
const handled = useRef(false);
10 +
const lastHandledId = useRef<string | null>(null);
11 +
12 +
useEffect(() => {
13 +
if (!routerReady) return;
14 +
if (handled.current) return;
15 +
16 +
let isMounted = true;
17 +
18 +
function handleResponse(
19 +
response: Notifications.NotificationResponse | null,
20 +
coldLaunch: boolean,
21 +
) {
22 +
if (!response || !isMounted) return;
23 +
24 +
const id = response.notification.request.identifier;
25 +
const { request } = response.notification;
26 +
const { content } = request;
27 +
const { title, body, subtitle, data } = content;
28 +
29 +
if (lastHandledId.current === id) return;
30 +
lastHandledId.current = id;
31 +
32 +
// XXX: Looks so dumb, actually
33 +
const { screen, ...params } = (data ?? {}) as Record<string, any>;
34 +
35 +
if (!screen) return;
36 +
37 +
const payload = { body, title, ...params };
38 +
39 +
if (coldLaunch) {
40 +
router.replace({
41 +
pathname: screen as any,
42 +
params: payload,
43 +
});
44 +
} else {
45 +
router.push({
46 +
pathname: screen as any,
47 +
params: payload,
48 +
});
49 +
}
50 +
}
51 +
52 +
// Cold launch
53 +
Notifications.getLastNotificationResponseAsync().then((response) => {
54 +
if (!handled.current) {
55 +
handled.current = true;
56 +
handleResponse(response, true);
57 +
}
58 +
});
59 +
60 +
// Warm/foreground
61 +
const subscription = Notifications.addNotificationResponseReceivedListener(
62 +
(response) => {
63 +
handleResponse(response, false);
64 +
},
65 +
);
66 +
67 +
return () => {
68 +
isMounted = false;
69 +
subscription.remove();
70 +
};
71 +
}, [routerReady, router]);
72 +
}