Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save efstathiosntonas/0c4fcd97360fb8f0a20fe43f0963b0b1 to your computer and use it in GitHub Desktop.
Save efstathiosntonas/0c4fcd97360fb8f0a20fe43f0963b0b1 to your computer and use it in GitHub Desktop.
OneSignal React Native Notifications Handler and AsyncStorage
import AsyncStorage from '@react-native-community/async-storage';
import {Navigation} from 'react-native-navigation';
import {uniqBy} from 'lodash';
// using uuid/v4 to generate unique keys for each notification for FlatList etc.
import uuidv4 from 'uuid/v4';
// AsyncStorage.clear();
export const handleNotifications = async (notification, condition, ref) => {
console.log('COMING FROM ', ref);
// Delete a single Notification
if (condition === 'delete') {
let notifs = await getNotificationsFromStorage('delete');
const index = notifs.findIndex(
item =>
item.payload.notificationID === notification.payload.notificationID
);
if (index > -1) {
notifs.splice(index, 1);
}
await saveNotificationsToStorage(notifs, 'delete single notification');
await setTabBadgeCounter(notifs);
}
// Mark single Notification as seen
if (condition === 'seen') {
let notifs = await getNotificationsFromStorage('seen');
const index = notifs.findIndex(
item =>
item.payload.notificationID === notification.payload.notificationID
);
notifs[index].seen = true;
await saveNotificationsToStorage(notifs, 'seen single notification');
await setTabBadgeCounter(notifs);
}
// Mark Notification as visited
if (condition === 'visited') {
const notifications = await getNotificationsFromStorage('visited');
const index = notifications.findIndex(
/* notification._id is coming from mongo database, it has nothing to do with OneSignal,
we check if the notification is been seen/opened by user in notifications view screen */
item => item.payload.additionalData.id === notification._id
);
if (index > -1) {
console.log('found visited', notification);
notifications[index].seen = true;
notifications[index].key = uuidv4();
await saveNotificationsToStorage(
notifications,
'mark notification visited'
);
await setTabBadgeCounter(notifications);
}
}
let notifications = await getNotificationsFromStorage(
'if all conditions fails, we reach normal notification procedure'
);
// We already have notifs in storage
if (notifications !== null) {
await setTabBadgeCounter(notifications);
notification.key = uuidv4();
if (condition === 'open') {
const {notification: extractedNotification} = notification;
if (!extractedNotification.isAppInFocus) {
extractedNotification.key = uuidv4();
await setNotificationNotOpened(
extractedNotification,
'opened & extracted, not in focus, we have notifications in storage'
);
}
await goToNotificationView(
extractedNotification,
'going to notification view, opened & extracted, we have notifications in storage'
);
} else if (condition === 'receive') {
notification.seen = false;
const storedNotifications = await unshiftNotificationInStorage(
notification,
'receive, storage has notifs'
);
await setTabBadgeCounter(storedNotifications);
}
} else {
// We don't have notifs in storage
if (condition === 'open') {
/* when opening notification from `opened` OneSignal event it has different
format than the `receive` OneSignal event */
const {notification: extractedNotification} = notification;
/* set notification as seen since we are going directly
in notification view screen, not in notification list view */
extractedNotification.seen = true;
extractedNotification.key = uuidv4();
if (!extractedNotification.isAppInFocus) {
await setNotificationNotOpened(
extractedNotification,
'opened & extracted, app NOT focused, we dont have notifications in storage'
);
}
const storedNotifications = await pushNotificationInStorage(
extractedNotification,
'opened & extracted, app IN focus, we dont have notifications in storage'
);
await setTabBadgeCounter(storedNotifications);
await goToNotificationView(extractedNotification);
} else if (condition === 'receive') {
notification.seen = false;
notification.key = uuidv4();
const storedNotifications = await pushNotificationInStorage(
notification,
'receive, we dont have notifications in storage'
);
await setTabBadgeCounter(storedNotifications);
}
}
};
/* Helpers for managing notifications */
export const setTabBadgeCounter = async notifications => {
const unseenNotifications = notifications.reduce((sum, item) => {
if (item.seen === false) {
return sum + 1;
} else {
return sum;
}
}, 0);
// using wix's react native navigation v3
Navigation.mergeOptions('NotificationsScreen', {
bottomTab: {
badge: unseenNotifications === 0 ? '' : unseenNotifications.toString(),
badgeColor: 'red'
}
});
};
export const goToNotificationView = async (notification, ref) => {
/*
using wix's react native navigation v3
first we need to navigate to Notification tab, in my case it was fourth in my tabs so index is 3
then we push to the notification view/screen passing the notification data as props
*/
console.log('GOING TO NOTIFICATION VIEW ', ref);
Navigation.mergeOptions('notificationStack', {
bottomTabs: {
currentTabIndex: 3
}
});
await Navigation.push('notificationStack', {
component: {
name: 'NotificationScreen',
passProps: {
item: notification,
mode: 'notifications',
id: notification.payload.additionalData.id
}
}
});
};
export const unshiftNotificationInStorage = async (notification, ref) => {
console.log('UNSHIFT NOTIFICATION FROM STORAGE ', ref);
const parsedNotifications = await getNotificationsFromStorage();
parsedNotifications.unshift(notification);
/*
check if we have duplicate notifications
and remove them from notification array by checking notificationID
from notification's payload
*/
const uniqueNotifications = uniqBy(
parsedNotifications,
'payload.notificationID'
);
await saveNotificationsToStorage(
uniqueNotifications,
'unshift notification and save'
);
console.log('RESULT - UNSHIFT NOTIFICATION ', ref, uniqueNotifications);
return uniqueNotifications;
};
export const pushNotificationInStorage = async (notification, ref) => {
console.log('PUSHING NOTIFICATION TO STORAGE ', ref);
let parsedNotifications = await getNotificationsFromStorage();
if (parsedNotifications) {
parsedNotifications.push(notification);
} else {
parsedNotifications = [];
parsedNotifications.push(notification);
}
await saveNotificationsToStorage(
parsedNotifications,
'push notification and save'
);
console.log('RESULT - PUSHING NOTIFICATION ', ref, parsedNotifications);
return parsedNotifications;
};
/*
the following 2 functions are almost a hack, set notification in localStorage as not opened
so when app is killed and opened, navigate to notification view screen.
In my case i have 2 navigation roots, 1 root is splash screen and the other root is bottom Tabs,
when my app loads for first time (from killed state) when a user taps the notification shadow then
navigator cannot 'see' Tabs root. In my Home screen i have this in order to send user to notification screen:
const fromNotificationOpen = await AsyncStorage.getItem('notificationNotOpened');
if (fromNotificationOpen) {
await goToNotificationView(JSON.parse(fromNotificationOpen));
}
After visiting the notification view, in componentDidMount simply call await AsyncStorage.removeItem('notificationNotOpened')
to get rid of the unopened notification,
*/
export const setNotificationNotOpened = async (notification, ref) => {
console.log('EXTRACTED & NOT OPENED BUT COMING FROM OPENED EVENT ', ref);
await AsyncStorage.setItem(
'notificationNotOpened',
JSON.stringify(notification)
);
const result = await AsyncStorage.getItem('notificationNotOpened');
console.log(
'RESULT - EXTRACTED & NOT OPENED BUT COMING FROM OPENED EVENT ',
ref,
JSON.parse(result)
);
};
export const getNotificationsFromStorage = async ref => {
console.log('GETTING NOTIFICATION FROM STORAGE ', ref);
const notifications = await AsyncStorage.getItem('notifications');
console.log(
'RESULT - GETTING NOTIFICATION FROM STORAGE ',
ref,
notifications
? JSON.parse(notifications)
: ', STORAGE HAS NO NOTIFICATIONS OR WHATSSOEVER'
);
return JSON.parse(notifications);
};
export const saveNotificationsToStorage = async (notifications, ref) => {
console.log('SAVING NOTIFICATION TO STORAGE ', ref);
await AsyncStorage.setItem('notifications', JSON.stringify(notifications));
const storedNotifications = await AsyncStorage.getItem('notifications');
console.log(
'RESULT - SAVING NOTIFICATION TO STORAGE ',
ref,
JSON.parse(storedNotifications)
);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment