Created
November 1, 2023 16:51
-
-
Save TheBrotherFromASouthernMother/b1bb1dce3826837a210d940046db9ad7 to your computer and use it in GitHub Desktop.
Push Notification Handler (React Native + Hooks)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useCallback, useContext } from 'react'; | |
import * as Notifications from 'expo-notifications'; | |
import AppContext from 'components/AppContext'; | |
import isNil from 'lodash/isNil'; | |
import isString from 'lodash/isString'; | |
import get from 'lodash/get'; | |
import { safeParseJSON, getLocalStorageItem } from 'lib/util'; | |
import { DEFAULT_UUID_STORAGE_KEY } from 'Authentication/constants'; | |
import useRecordMassPushNotificationOpen from 'Notifications/hooks/useRecordMassPushNotificationOpen'; | |
import useHandlePushNotificationNavigation from 'Notifications/hooks/useHandlePushNotificationNavigation'; | |
import { QUESTION_SCREEN_NAVIGATION_KEY, QUESTION_ID_NAVIGATION_PARAM_NAME } from 'QandA/constants'; | |
// As of this writing, the Expo API may deliver the message data as either an object or as a JSON string :( | |
const getPushNotificationProperty = (notificationData, propertyName) => { | |
if (isString(notificationData)) { | |
return get(safeParseJSON(notificationData), propertyName); | |
} | |
return get(notificationData, propertyName); | |
}; | |
const useHandlePushNotification = () => { | |
const { | |
sentry, | |
trackEvent, | |
getCurrentUser, | |
} = useContext(AppContext); | |
const lastNotificationResponseFromUser = Notifications.useLastNotificationResponse(); | |
const recordMassPushNotificationOpen = useRecordMassPushNotificationOpen(); | |
const handlePushNotificationNavigation = useHandlePushNotificationNavigation(); | |
return useCallback(async ({ isAuthenticated }) => { | |
let messageId = null; | |
let uuid = null; | |
let handlesNavigation = false; | |
try { | |
if (isNil(lastNotificationResponseFromUser)) return handlesNavigation; | |
/* | |
NOTE: Current user may be nullish since this hook handles notifications for both | |
authenticated and non-authenticated users. As such if the user is not logged in, we'll try to attribute their | |
"open" to their defaultUUID. | |
*/ | |
const currentUser = await getCurrentUser(); | |
const userUUID = get(currentUser, 'uuid'); | |
if (isNil(userUUID)) { | |
uuid = await getLocalStorageItem(DEFAULT_UUID_STORAGE_KEY, null); | |
} else { | |
uuid = userUUID; | |
} | |
const notificationActionIdentifier = get(lastNotificationResponseFromUser, 'actionIdentifier'); | |
const notificationData = get(lastNotificationResponseFromUser, 'notification.request.content.data'); | |
messageId = getPushNotificationProperty(notificationData, 'id'); | |
const stack = getPushNotificationProperty(notificationData, 'stack'); | |
const screen = getPushNotificationProperty(notificationData, 'screen'); | |
// tracks analytics on Amplitude | |
trackEvent('push_notification_open_send_attempt', { | |
messageId, | |
actionIdentifier: notificationActionIdentifier, | |
isAuthenticated, | |
}); | |
// Records mass push noficiations for SQL querying on backend (E.g. redash) | |
await recordMassPushNotificationOpen({ | |
messageId, | |
notificationActionIdentifier, | |
uuid, | |
}) | |
if (isAuthenticated) { | |
// If user is not authenticated, delegate navigation back to parent hook | |
const params = {}; | |
if (screen === QUESTION_SCREEN_NAVIGATION_KEY) { | |
const questionId = getPushNotificationProperty(notificationData, QUESTION_ID_NAVIGATION_PARAM_NAME); | |
params.questionId = questionId; | |
} | |
handlesNavigation = await handlePushNotificationNavigation({ stack, screen, params }); | |
} | |
trackEvent( | |
'push_notification_open_send_success', | |
{ | |
messageId, | |
actionIdentifier: notificationActionIdentifier, | |
isAuthenticated, | |
} | |
); | |
return handlesNavigation; | |
} catch (error) { | |
sentry.Native.captureException(error); | |
trackEvent('push_notification_open_send_error', { messageId }); | |
return handlesNavigation; | |
} | |
}, [ | |
sentry, | |
trackEvent, | |
getCurrentUser, | |
lastNotificationResponseFromUser, | |
recordMassPushNotificationOpen, | |
handlePushNotificationNavigation, | |
]); | |
}; | |
export default useHandlePushNotification; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment