@magicbell/react-headless
Version:
Hooks to build a notification inbox
106 lines (92 loc) • 3.22 kB
text/typescript
import { path } from 'ramda';
import { IRemoteConfig } from '../types/index.js';
import { postAPI } from './ajax.js';
function stringToUint8Array(plainString: string) {
const padding = '='.repeat((4 - (plainString.length % 4)) % 4);
const base64 = (plainString + padding).replace(/-/g, '+').replace(/_/g, '/');
const rawData = window.atob(base64);
const outputArray = new Uint8Array(rawData.length);
for (let i = 0; i < rawData.length; ++i) {
outputArray[i] = rawData.charCodeAt(i);
}
return outputArray;
}
/**
* Store a subscription in the backend so we can notify this user later.
*
* @param subscription The push subscription
*/
function storeSubscription(subscription) {
const data = {
web_push_subscription: {
data: subscription,
},
};
return postAPI('/web_push_subscriptions', data);
}
/**
* Request permission to send push notifications.
*
* @param pushManager
* @param publicKey VAPID public key
*/
export function subscribeToPushNotifications(pushManager: PushManager, publicKey: string) {
const applicationServerKey = stringToUint8Array(publicKey);
return pushManager.subscribe({ userVisibleOnly: true, applicationServerKey });
}
/**
* Request permission to send push notifications and store the subscription in
* the backend.
*
* @param pushManager
* @param user
* @param project
*/
export async function createPushSubscription(pushManager: PushManager, config: IRemoteConfig) {
const vapidPublicKey = path(['webPush', 'config', 'vapidAuthentication', 'publicKey'], config.channels) as string;
const subscription = await subscribeToPushNotifications(pushManager, vapidPublicKey);
return storeSubscription(subscription.toJSON());
}
/**
* Request permission to send push notifications in Safari and store the
* subscription in the backend.
*
* @param authenticationToken A string that helps you identify the user
* @param webServiceUrl URL of the Safari web push service
* @param websitePushID Apple identifier of the website push service
*/
export function createSafariPushSubscription(
authenticationToken: string,
webServiceUrl: string,
websitePushID = 'web.com.magicbell-notifications',
) {
const permissionData = window['safari'].pushNotification.permission(websitePushID);
if (permissionData.permission === 'granted') return Promise.resolve(permissionData);
if (permissionData.permission === 'denied') return Promise.reject(false);
return new Promise(function (resolve, reject) {
window['safari'].pushNotification.requestPermission(
webServiceUrl,
websitePushID,
{ authenticationToken },
function (permissionData) {
if (permissionData.deviceToken) {
const subscriptionData = {
endpoint: permissionData.deviceToken,
keys: { websitePushID },
platform: 'safari',
};
storeSubscription(subscriptionData)
.then((subscription) => {
resolve(subscription);
})
.catch((error) => {
reject(error);
});
} else {
const error = new Error('Permission was denied');
reject(error);
}
},
);
});
}