Untitled

 avatar
unknown
typescript
9 months ago
5.0 kB
7
Indexable
import notifee, {
  AndroidImportance,
  AndroidVisibility,
} from '@notifee/react-native';
import firebase from '@react-native-firebase/app';
import {useQueryClient} from '@tanstack/react-query';
import {PropsWithChildren, useEffect} from 'react';
import {
  RESULTS,
  checkNotifications,
  requestNotifications,
} from 'react-native-permissions';
import {QUERY_KEY} from './constants';
import {FCMResponse, useSaveFcmTokenMutation} from './services/fcm-token';
import {
  useGameStore,
  useGuestStore,
  useNotificationPermissionStore,
} from './store';

type Props = PropsWithChildren<{}>;

const AppProvider = ({children}: Props) => {
  const saveFcmTokenMutation = useSaveFcmTokenMutation();
  const {updatePendingGameResult} = useGameStore();
  const {updatePendingPredictionResult, isGuest, setCanViewLatestPrediction} =
    useGuestStore();
  const {
    setAllNotification,
    clearNotification,
    game,
    prediction,
    promotion,
    system,
    setGranted,
    isGranted,
  } = useNotificationPermissionStore();

  const permissions = {game, prediction, promotion, system};
  const granted = permissions.system;
  // Object.values(permissions).some(p => p);

  const queryClient = useQueryClient();

  const onDisplayNotification = async (d: FCMResponse) => {
    if (!granted) {
      return;
    }

    // Request permissions (required for iOS)
    await notifee.requestPermission({
      alert: true,
      sound: true,
    });

    // Create a channel (required for Android)
    const channelId = await notifee.createChannel({
      id: 'default',
      name: 'Default Channel',
      sound: 'default',
      vibration: true,
      vibrationPattern: [300, 500],
      visibility: AndroidVisibility.PUBLIC,
      importance: AndroidImportance.HIGH,
    });

    // Display a notification
    await notifee
      .displayNotification({
        title: d.notification.title,
        body: d.notification.body,
        data: d.data,
        android: {
          channelId,
          smallIcon: 'ic_notification', // optional, defaults to 'ic_launcher'.
          color: '#3438CD',
          // pressAction is needed if you want the notification to open the app when pressed
          pressAction: {
            id: 'default',
            launchActivity: 'default',
          },
          importance: AndroidImportance.HIGH,
          visibility: AndroidVisibility.PUBLIC,
          sound: 'default',
          showTimestamp: true,
          vibrationPattern: [300, 100, 100, 100],
        },
        ios: {
          sound: 'default',
        },
      })
      .catch(console.log);
  };

  useEffect(() => {
    (async () => {
      const {status: checkStatus} = await checkNotifications();
      if (checkStatus !== RESULTS.GRANTED && checkStatus !== RESULTS.LIMITED) {
        const {status: grantStatus} = await requestNotifications([
          'sound',
          'alert',
        ]);
        if (
          grantStatus !== RESULTS.GRANTED &&
          grantStatus !== RESULTS.LIMITED
        ) {
          clearNotification();
          return;
        }
      }
      setGranted(true);
      !isGranted && setAllNotification(true);
    })();

    return () => {};
  }, [clearNotification, setAllNotification, isGranted, setGranted]);

  useEffect(() => {
    if (!granted) {
      return;
    }
    if (!firebase.messaging().isDeviceRegisteredForRemoteMessages) {
      firebase.messaging().registerDeviceForRemoteMessages().catch(console.log);
    }
    firebase
      .messaging()
      .getToken()
      .then(token => {
        saveFcmTokenMutation.mutate(token, {
          onError: error => {
            console.log(error);
          },
          onSuccess: () => {},
        });
      })
      .catch(console.log);

    const unsubscribe = firebase.messaging().onMessage(async remoteMessage => {
      if (!granted) {
        return;
      }
      const d = {
        notification: remoteMessage.notification,
        data: remoteMessage.data,
      } as FCMResponse;
      await onDisplayNotification(d).catch(console.log);
      if (!remoteMessage.data?.result) {
        return;
      }
      // process data
      const drawResult = JSON.parse(remoteMessage.data?.result as string);
      updatePendingGameResult(drawResult);
      setCanViewLatestPrediction(false);

      await queryClient
        .refetchQueries({
          queryKey: [QUERY_KEY.PREDICT.GET_SYSTEM_PREDICTIONS],
        })
        .catch(console.log);
      await queryClient
        .refetchQueries({
          queryKey: [QUERY_KEY.PREDICT.GET_LATEST_PREDICTION],
        })
        .catch(console.log);
      if (isGuest) {
        updatePendingPredictionResult(drawResult);
      } else {
        await queryClient.refetchQueries({
          queryKey: [QUERY_KEY.PREDICT.GET_MY_PREDICTIONS],
        });
      }
    });

    return () => {
      unsubscribe();
    };
  }, [isGuest, granted]);

  return children;
};

export default AppProvider;
Editor is loading...
Leave a Comment