eletrotupi / tcc/ frontend/hooks/useNotificationObserver.tsfc5b05d922d3301294cc7a1b3ed53dc3ed4db0bf
1.9 KB | 72 lines Raw
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
}