eletrotupi / tcc/ frontend/hooks/useNotificationObserver.ts12c613c01bc44da902e59329b5ed93393aa84da7
2.1 KB | 81 lines Raw
1
import { useEffect, useRef } from "react";
2
import * as Notifications from "expo-notifications";
3
import { useRouter, useRootNavigationState } 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 Record<string, any>;
43

44
      if (!screen) return;
45

46
      const payload = { body, title, ...params };
47

48
      if (coldLaunch) {
49
        router.replace({
50
          pathname: screen as any,
51
          params: payload,
52
        });
53
      } else {
54
        router.push({
55
          pathname: screen as any,
56
          params: payload,
57
        });
58
      }
59
    }
60

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

69
    // Warm/foreground
70
    const subscription = Notifications.addNotificationResponseReceivedListener(
71
      (response) => {
72
        handleResponse(response, false);
73
      },
74
    );
75

76
    return () => {
77
      isMounted = false;
78
      subscription.remove();
79
    };
80
  }, [routerReady, router]);
81
}