eletrotupi / tcc/ frontend/hooks/useNotificationObserver.tsc941890054e469bdf624c967e653c5c48b4fb80f
2.1 KB | 84 lines Raw
1
import { useEffect, useRef } from "react";
2
import * as Notifications from "expo-notifications";
3
import { useRouter, useRootNavigationState, type Href } from "expo-router";
4

5
Notifications.setNotificationHandler({
6
  handleNotification: async () => ({
7
    shouldPlaySound: true,
8
    shouldSetBadge: false,
9
    shouldShowBanner: true,
10
    shouldShowList: true,
11
  }),
12
});
13

14
export function useNotificationObserver() {
15
  const router = useRouter();
16
  const rootNavState = useRootNavigationState();
17
  const routerReady = !!rootNavState?.key;
18
  const handled = useRef(false);
19
  const lastHandledId = useRef<string | null>(null);
20

21
  useEffect(() => {
22
    if (!routerReady) return;
23
    if (handled.current) return;
24

25
    let isMounted = true;
26

27
    function handleResponse(
28
      response: Notifications.NotificationResponse | null,
29
      coldLaunch: boolean,
30
    ) {
31
      if (!response || !isMounted) return;
32

33
      const id = response.notification.request.identifier;
34
      const { request } = response.notification;
35
      const { content } = request;
36
      const { title, body, subtitle, data } = content;
37

38
      if (lastHandledId.current === id) return;
39
      lastHandledId.current = id;
40

41
      // XXX: Looks so dumb, actually
42
      const { screen, ...params } = (data ?? {}) as {
43
        screen?: string;
44
        [key: string]: string | undefined;
45
      };
46

47
      if (!screen) return;
48

49
      const payload = { body, title, ...params };
50

51
      if (coldLaunch) {
52
        router.replace({
53
          pathname: screen,
54
          params: payload,
55
        } as Href);
56
      } else {
57
        router.push({
58
          pathname: screen,
59
          params: payload,
60
        } as Href);
61
      }
62
    }
63

64
    // Cold launch
65
    Notifications.getLastNotificationResponseAsync().then((response) => {
66
      if (!handled.current) {
67
        handled.current = true;
68
        handleResponse(response, true);
69
      }
70
    });
71

72
    // Warm/foreground
73
    const subscription = Notifications.addNotificationResponseReceivedListener(
74
      (response) => {
75
        handleResponse(response, false);
76
      },
77
    );
78

79
    return () => {
80
      isMounted = false;
81
      subscription.remove();
82
    };
83
  }, [routerReady, router]);
84
}