Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TheBrotherFromASouthernMother/b1bb1dce3826837a210d940046db9ad7 to your computer and use it in GitHub Desktop.
Save TheBrotherFromASouthernMother/b1bb1dce3826837a210d940046db9ad7 to your computer and use it in GitHub Desktop.
Push Notification Handler (React Native + Hooks)
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