@kode-frontend/react-native-push-notification
Version:
Push notification service for React Native apps
282 lines (251 loc) • 6.5 kB
text/typescript
import notifee, {
AndroidBigPictureStyle,
AndroidStyle,
AuthorizationStatus,
IOSNotificationAttachment,
InitialNotification,
TriggerNotification,
} from '@notifee/react-native'
import messaging, {
FirebaseMessagingTypes,
} from '@react-native-firebase/messaging'
import { Image, Linking, Platform } from 'react-native'
import { TFirebaseRemoteMessage, TPushNotificationBody } from './types'
import { isPermisionsGrantedByDefault } from '../model/constanst'
let initialRemotePushWasGetting = false
let initialLocalPushWasGetting = false
const isPermitted = (authorizationStatus: AuthorizationStatus) => {
return (
authorizationStatus === AuthorizationStatus.AUTHORIZED ||
authorizationStatus === AuthorizationStatus.PROVISIONAL
)
}
/**
* Checks for permissions to send notifications
*/
export async function hasPermission() {
const status = await notifee.getNotificationSettings()
return isPermitted(status.authorizationStatus)
}
/**
* Request permissions to receive push notifications
*/
export async function requestPermission() {
const status = await notifee.requestPermission()
return isPermitted(status.authorizationStatus)
}
/**
* Checks and request permissions to receive push notifications
*/
export async function checkPermission() {
const enabledNotifications = await hasPermission()
if (!enabledNotifications && !isPermisionsGrantedByDefault) {
return await requestPermission()
}
return enabledNotifications
}
/**
* Generating message id
*/
const createUUIDService = () => {
let id = 0
return {
getUuid: () => {
return String(++id)
},
}
}
const UUIDService = createUUIDService()
/**
* Receives scheduled local push notifications
*/
export function getScheduledLocalNotifications(): Promise<
TriggerNotification[]
> {
return new Promise((resolve, reject) => {
try {
const notifications = notifee.getTriggerNotifications()
resolve(notifications)
} catch (e) {
reject(e)
}
})
}
/**
* Cancels all local pushes
*/
export function cancelAllNotifications(): Promise<void> {
return new Promise(async (resolve, reject) => {
try {
const notifications = await getScheduledLocalNotifications()
const notificationIds = notifications.map(
item => item.notification.id ?? '',
)
resolve(notifee.cancelAllNotifications(notificationIds))
} catch (e) {
reject(e)
}
})
}
/**
* Cancels local push by id
*/
export function cancelNotification(notificationId: string): Promise<void> {
return new Promise((resolve, reject) => {
try {
resolve(notifee.cancelNotification(notificationId))
} catch (e) {
reject(e)
}
})
}
/**
* Gets the initial remote push (from Firebase)
*/
export function getInitialPush(): Promise<FirebaseMessagingTypes.RemoteMessage | null> {
return new Promise((resolve, reject) => {
try {
if (initialRemotePushWasGetting) {
return resolve(null)
}
const initialPush = messaging().getInitialNotification()
resolve(initialPush)
initialRemotePushWasGetting = true
} catch (e) {
reject(e)
}
})
}
/**
* Gets the initial local push
*/
export function getInitialLocalPush(): Promise<InitialNotification | null> {
return new Promise((resolve, reject) => {
try {
if (initialLocalPushWasGetting) {
return resolve(null)
}
const initialPush = notifee.getInitialNotification()
resolve(initialPush)
initialLocalPushWasGetting = true
} catch (e) {
reject(e)
}
})
}
/**
* Gets the Firebase FCM-token for push notifications
*/
export const getToken = async () => {
try {
const enabledNotifications = await checkPermission()
if (!enabledNotifications) {
return null
}
} catch (e) {
return null
}
let fcmToken = null
try {
fcmToken = await messaging().getToken()
return fcmToken
} catch (e) {}
return fcmToken
}
/**
* Removes the FCM-token in Firebase. The device will not be able to receive push notifications
*/
export const removeToken = async () => {
await messaging().deleteToken()
}
/**
* Go to notification settings
*/
export const openSettings = Platform.select({
ios: Linking.openSettings,
android: notifee.openNotificationSettings,
})!
/**
* Set the number on the badge (iOS)
*/
export const setApplicationIconBadgeNumber = (number: number) => {
try {
notifee.setBadgeCount(number)
} catch (e) {}
}
/**
* Increases the number on the badge (iOS)
*/
export const incrementApplicationIconBadgeNumber = () => {
try {
notifee.incrementBadgeCount()
} catch (e) {}
}
/**
* Decreases the number on the badge (iOS)
*/
export const decrementApplicationIconBadgeNumber = () => {
try {
notifee.decrementBadgeCount()
} catch (e) {}
}
/**
* Retrieves attachment on iOS from remoteMessage
*/
export const getIosAttachment = async (message: TFirebaseRemoteMessage) => {
if (message.data?.fcm_options?.image) {
try {
/**
* Let's make sure the attachment is available on iOS
*/
await Image.prefetch(message.data.fcm_options.image)
} catch (e) {
delete message.data.fcm_options.image
}
}
const attachment: IOSNotificationAttachment[] = message.data?.fcm_options
?.image
? [
{
url: message.data.fcm_options.image,
},
]
: []
return attachment
}
/**
* Retrieves attachment on Android from remoteMessage
*/
export const getAndroidAttachment = async (
message: FirebaseMessagingTypes.RemoteMessage,
) => {
if (message.notification?.android?.imageUrl) {
try {
/**
* Let's make sure the attachment is available on Android
*/
await Image.prefetch(message.notification.android.imageUrl)
} catch (e) {
delete message.notification.android.imageUrl
}
}
const attachment: AndroidBigPictureStyle | undefined = message.notification
?.android?.imageUrl
? {
type: AndroidStyle.BIGPICTURE,
picture: message.notification.android.imageUrl,
}
: undefined
return attachment
}
export const mapRemotePushToLocalPush = (
remotePush: FirebaseMessagingTypes.RemoteMessage,
) => {
const pushNotification: TPushNotificationBody = {
id: UUIDService.getUuid(),
title: remotePush.notification?.title ?? '',
body: remotePush.notification?.body ?? '',
data: remotePush.data,
}
return pushNotification
}