gửi thông báo với Reactjs and firebase
phinv54 ✍︎︎ 05-09-2020
b1: enable service worker trong file index.js
import * as serviceWorker from './serviceWorker'
....
serviceWorker.register();
b2: tạo custom hook để đăng ký service worker
import {useEffect} from "react";
import {
askUserPermission,
createNotificationSubscription,
getUserSubscription,
isPushNotificationSupported,
registerServiceWorker,
subscriptionToDb
} from "../notifications/push-notifications";
const pushNotificationSupported = isPushNotificationSupported();
export default function usePushNotifications(user) {
useEffect(() => {
if (pushNotificationSupported && user.user_id) {
onRegisterPubSub(user)
}
}, [user]);
const onRegisterPubSub = async (user) => {
try {
// đăng ký calendar service worker
await registerServiceWorker()
// xin quyen tu user
const consent = await askUserPermission()
if (consent === "granted") {
// neu dong y
// kiem tra thong tin cu da co
let subscription = await getUserSubscription();
if (!subscription) {
subscription = await createNotificationSubscription()
}
await subscriptionToDb(JSON.parse(JSON.stringify(subscription)), user.user_id)
}
} catch (e) {
console.log(e);
}
}
}
file push-notifications.js:
import {db} from '../firebaseConfig'
import {CALENDAR_COLLECTION} from "../config/constants";
import firebase from "firebase/app";
const pushServerPublicKey = "your key";
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;
}
function isPushNotificationSupported() {
return "serviceWorker" in navigator && "PushManager" in window;
}
async function askUserPermission() {
return await Notification.requestPermission();
}
function registerServiceWorker() {
return navigator.serviceWorker.register("/calendar-service-worker.js");
}
/**
*
* using the registered service worker creates a push notification subscription and returns it
*
*/
async function createNotificationSubscription() {
//wait for service worker installation to be ready
const serviceWorker = await navigator.serviceWorker.ready;
// subscribe and return the subscription
return await serviceWorker.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array(pushServerPublicKey)
});
}
function getUserSubscription() {
//wait for service worker installation to be ready, and then
return navigator.serviceWorker.ready
.then(function (serviceWorker) {
return serviceWorker.pushManager.getSubscription();
})
.then(function (pushSubscription) {
return pushSubscription;
});
}
async function subscriptionToDb(sub, userId) {
const userRef = db.doc(`${CALENDAR_COLLECTION}/${userId}`)
await userRef.set({
subscriptions: firebase.firestore.FieldValue.arrayUnion(sub)
}, {merge: true})
}
async function subscribeUserToPush(user) {
try {
const registration = await navigator.serviceWorker.register('/calendar-service-worker.js')
let sub = await registration.pushManager.getSubscription()
} catch (e) {
}
}
export {
isPushNotificationSupported,
askUserPermission,
registerServiceWorker,
createNotificationSubscription,
getUserSubscription,
subscriptionToDb,
subscribeUserToPush
};
b3: tạo file service work trong thư mục public:
function receivePushNotification(event) {
console.log("[Service Worker] Push Received.");
const {image, tag, url, title, text} = event.data.json();
const options = {
data: url,
body: text,
// icon: image,
vibrate: [200, 100, 200],
// tag: tag,
// image: image,
badge: "https://calendar.geniam.com/favicon.ico",
};
event.waitUntil(self.registration.showNotification(title, options));
}
function openPushNotification(event) {
event.notification.close();
event.waitUntil(clients.openWindow(event.notification.data));
}
self.addEventListener("push", receivePushNotification);
self.addEventListener("notificationclick", openPushNotification);
b4: gọi hook vừa tạo trong file app.js
usePushNotifications(user);