eletrotupi / tcc/ commit / 0decf53

frontend: introduce a notification observer

Pedro Lucas Porcellis porcellis@eletrotupi.com · 4 months ago 0decf53a4abd2e7b11462965b9f7612156f7670a Browse files
Parents cb5d2d5
Changed 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 +
}