-
Notifications
You must be signed in to change notification settings - Fork 4.7k
/
getDevicePushTokenAsync.web.js
79 lines (79 loc) · 4.25 KB
/
getDevicePushTokenAsync.web.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
import { CodedError, Platform, SyntheticPlatformEmitter } from '@unimodules/core';
import Constants from 'expo-constants';
export default async function getDevicePushTokenAsync() {
const data = await _subscribeDeviceToPushNotificationsAsync();
SyntheticPlatformEmitter.emit('onDevicePushToken', { devicePushToken: data });
return { type: Platform.OS, data };
}
function guardPermission() {
if (!('Notification' in window)) {
throw new CodedError('ERR_UNAVAILABLE', 'The Web Notifications API is not available on this device.');
}
if (!navigator.serviceWorker) {
throw new CodedError('ERR_UNAVAILABLE', 'Notifications cannot be used because the service worker API is not supported on this device. This might also happen because your web page does not support HTTPS.');
}
if (Notification.permission !== 'granted') {
throw new CodedError('ERR_NOTIFICATIONS_PERMISSION_DENIED', `Cannot use web notifications without permissions granted. Request permissions with "expo-permissions".`);
}
}
async function _subscribeDeviceToPushNotificationsAsync() {
if (!Constants.manifest.notification?.vapidPublicKey) {
throw new CodedError('ERR_NOTIFICATIONS_PUSH_WEB_MISSING_CONFIG', 'You must provide `notification.vapidPublicKey` in `app.json` to use push notifications on web. Learn more: https://docs.expo.io/versions/latest/guides/using-vapid/.');
}
if (!Constants.manifest.notification?.serviceWorkerPath) {
throw new CodedError('ERR_NOTIFICATIONS_PUSH_MISSING_CONFIGURATION', 'You must specify `notification.serviceWorkerPath` in `app.json` to use push notifications on the web. Please provide the path to the service worker that will handle notifications.');
}
guardPermission();
let registration = null;
try {
registration = await navigator.serviceWorker.register(Constants.manifest.notification.serviceWorkerPath);
}
catch (error) {
throw new CodedError('ERR_NOTIFICATIONS_PUSH_REGISTRATION_FAILED', `Could not register this device for push notifications because the service worker (${Constants.manifest.notification.serviceWorkerPath}) could not be registered: ${error}`);
}
await navigator.serviceWorker.ready;
if (!registration.active) {
throw new CodedError('ERR_NOTIFICATIONS_PUSH_REGISTRATION_FAILED', 'Could not register this device for push notifications because the service worker is not active.');
}
const subscribeOptions = {
userVisibleOnly: true,
applicationServerKey: _urlBase64ToUint8Array(Constants.manifest.notification.vapidPublicKey),
};
let pushSubscription = null;
try {
pushSubscription = await registration.pushManager.subscribe(subscribeOptions);
}
catch (error) {
throw new CodedError('ERR_NOTIFICATIONS_PUSH_REGISTRATION_FAILED', 'The device was unable to register for remote notifications with the browser endpoint. (' +
error +
')');
}
const pushSubscriptionJson = pushSubscription.toJSON();
const subscriptionObject = {
endpoint: pushSubscriptionJson.endpoint,
keys: {
p256dh: pushSubscriptionJson.keys.p256dh,
auth: pushSubscriptionJson.keys.auth,
},
};
// Store notification icon string in service worker.
// This message is received by `/expo-service-worker.js`.
// We wrap it with `fromExpoWebClient` to make sure other message
// will not override content such as `notificationIcon`.
// https://stackoverflow.com/a/35729334/2603230
let notificationIcon = (Constants.manifest.notification || {}).icon;
await registration.active.postMessage(JSON.stringify({ fromExpoWebClient: { notificationIcon } }));
return subscriptionObject;
}
// https://github.com/web-push-libs/web-push#using-vapid-key-for-applicationserverkey
function _urlBase64ToUint8Array(base64String) {
const padding = '='.repeat((4 - (base64String.length % 4)) % 4);
const base64 = (base64String + 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;
}
//# sourceMappingURL=getDevicePushTokenAsync.web.js.map