import React, { useEffect, useState, useContext, createContext } from 'react'; import * as Notifications from 'expo-notifications'; import { storage, StoreType } from 'src/storage'; import { Linking, Platform } from 'react-native'; import { CommonActions, useNavigation } from '@react-navigation/native'; import { NAVIGATION_PAGES } from 'src/types'; import { usePostSetSettingsMutation } from '@api/notifications'; const PushNotificationContext = createContext<{ isSubscribed: boolean; toggleSubscription: () => Promise; }>({ isSubscribed: false, toggleSubscription: async () => {} }); export const usePushNotification = () => useContext(PushNotificationContext); export const PushNotificationProvider = ({ children }: { children: React.ReactNode }) => { const token = storage.get('token', StoreType.STRING) as string; const [isSubscribed, setIsSubscribed] = useState( (storage.get('subscribed', StoreType.BOOLEAN) as boolean) ?? false ); const { mutateAsync: setNotificationsSettings } = usePostSetSettingsMutation(); const navigation = useNavigation(); const lastNotificationResponse = Notifications.useLastNotificationResponse(); useEffect(() => { if (lastNotificationResponse && Platform.OS === 'android') { console.log( 'lastNotificationResponse', lastNotificationResponse.notification.request.content.data ); const data = lastNotificationResponse.notification.request.content.data; if (data?.screen && data?.parentScreen) { if (data?.params) { const parsedParams = JSON.parse(data.params) ?? {}; navigation.dispatch( CommonActions.reset({ index: 1, routes: [ { name: 'DrawerApp', state: { routes: [ { name: data.parentScreen, state: { routes: [ { name: NAVIGATION_PAGES.MAP_TAB }, { name: data.screen, params: parsedParams } ] } } ] } } ] }) ); } else { navigation.dispatch( CommonActions.reset({ index: 1, routes: [ { name: 'DrawerApp', state: { routes: [ { name: data.parentScreen, state: { routes: [ { name: NAVIGATION_PAGES.MAP_TAB }, { name: data.screen } ] } } ] } } ] }) ); } } if (data?.url) { Linking.openURL(data.url); } } }, [lastNotificationResponse]); useEffect(() => { if (isSubscribed) { Notifications.setNotificationHandler({ handleNotification: async () => ({ shouldShowAlert: true, shouldPlaySound: false, shouldSetBadge: false }) }); const notificationListener = Notifications.addNotificationReceivedListener((notification) => { console.log('Notification received'); }); const responseListener = Notifications.addNotificationResponseReceivedListener((response) => { console.log('Notification response received'); let screenName; let url; let parentScreen; let params; if (Platform.OS === 'ios') { parentScreen = ( response.notification.request.trigger as Notifications.PushNotificationTrigger )?.payload?.parentScreen; screenName = ( response.notification.request.trigger as Notifications.PushNotificationTrigger )?.payload?.screen; params = (response.notification.request.trigger as Notifications.PushNotificationTrigger) ?.payload?.params; url = (response.notification.request.trigger as Notifications.PushNotificationTrigger) ?.payload?.url; } if (screenName && parentScreen) { if (params) { const parsedParams = JSON.parse(params as string) ?? {}; navigation.dispatch( CommonActions.reset({ index: 1, routes: [ { name: 'DrawerApp', state: { routes: [ { name: parentScreen as string, state: { routes: [ { name: NAVIGATION_PAGES.MAP_TAB }, { name: screenName as string, params: parsedParams } ] } } ] } } ] }) ); } else { navigation.dispatch( CommonActions.reset({ index: 1, routes: [ { name: 'DrawerApp', state: { routes: [ { name: parentScreen as string, state: { routes: [ { name: NAVIGATION_PAGES.MAP_TAB }, { name: screenName as string } ] } } ] } } ] }) ); } } if (url) { Linking.openURL(url as string); } }); return () => { notificationListener.remove(); responseListener.remove(); }; } }, [isSubscribed]); const subscribeToNotifications = async () => { storage.set('subscribed', true); setIsSubscribed(true); }; const unsubscribeFromNotifications = async () => { const settings = { 'app-ios': 0, 'app-android': 0, 'app-friends': 0, 'email-friends': 0 }; await setNotificationsSettings({ token, settings: JSON.stringify(settings) }); storage.remove('deviceToken'); storage.set('subscribed', false); setIsSubscribed(false); }; const toggleSubscription = async () => { if (isSubscribed) { await unsubscribeFromNotifications(); } else { await subscribeToNotifications(); } }; return ( {children} ); };