Add JS for subscribing to and receiving push notifications
This commit is contained in:
parent
8b98c278da
commit
2da4767623
|
@ -15,6 +15,7 @@ import initModeration from 'retrospring/features/moderation';
|
|||
import initMemes from 'retrospring/features/memes';
|
||||
import initLocales from 'retrospring/features/locales';
|
||||
import initFront from 'retrospring/features/front';
|
||||
import initWebpush from 'retrospring/features/webpush';
|
||||
|
||||
start();
|
||||
document.addEventListener('DOMContentLoaded', initAnswerbox);
|
||||
|
@ -28,6 +29,7 @@ document.addEventListener('DOMContentLoaded', initModeration);
|
|||
document.addEventListener('DOMContentLoaded', initMemes);
|
||||
document.addEventListener('turbo:load', initLocales);
|
||||
document.addEventListener('turbo:load', initFront);
|
||||
document.addEventListener('DOMContentLoaded', initWebpush);
|
||||
|
||||
window['Stimulus'] = Application.start();
|
||||
const context = require.context('../retrospring/controllers', true, /\.ts$/);
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
export function dismissHandler (event: Event): void {
|
||||
event.preventDefault();
|
||||
|
||||
const sender: HTMLButtonElement = event.target as HTMLButtonElement;
|
||||
sender.closest<HTMLDivElement>('.push-settings').classList.add('d-none');
|
||||
localStorage.setItem('dismiss-push-settings-prompt', 'true');
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
import { get, post } from '@rails/request.js';
|
||||
import I18n from "retrospring/i18n";
|
||||
import { showNotification } from "utilities/notifications";
|
||||
|
||||
export function enableHandler (event: Event): void {
|
||||
event.preventDefault();
|
||||
|
||||
try {
|
||||
installServiceWorker()
|
||||
.then(subscribe)
|
||||
.then(async subscription => {
|
||||
return Notification.requestPermission().then(permission => {
|
||||
if (permission != "granted") {
|
||||
return;
|
||||
}
|
||||
|
||||
post('/ajax/web_push', {
|
||||
body: {
|
||||
subscription
|
||||
},
|
||||
contentType: 'application/json'
|
||||
}).then(async response => {
|
||||
const data = await response.json;
|
||||
|
||||
if (data.success) {
|
||||
new Notification(I18n.translate("frontend.push_notifications.subscribe.success.title"), {
|
||||
body: I18n.translate("frontend.push_notifications.subscribe.success.body")
|
||||
});
|
||||
} else {
|
||||
new Notification(I18n.translate("frontend.push_notifications.fail.title"), {
|
||||
body: I18n.translate("frontend.push_notifications.fail.body")
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Failed to set up push notifications", error);
|
||||
showNotification(I18n.translate("frontend.push_notifications.setup_fail"));
|
||||
}
|
||||
}
|
||||
|
||||
async function installServiceWorker(): Promise<ServiceWorkerRegistration> {
|
||||
return navigator.serviceWorker.register("/service_worker.js", { scope: "/" });
|
||||
}
|
||||
|
||||
async function getServerKey(): Promise<Buffer> {
|
||||
const response = await get("/ajax/webpush/key");
|
||||
const data = await response.json;
|
||||
return Buffer.from(data.key, 'base64');
|
||||
}
|
||||
|
||||
async function subscribe(registration: ServiceWorkerRegistration): Promise<PushSubscription> {
|
||||
const key = await getServerKey();
|
||||
return await registration.pushManager.subscribe({
|
||||
userVisibleOnly: true,
|
||||
applicationServerKey: key
|
||||
});
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
import registerEvents from 'retrospring/utilities/registerEvents';
|
||||
import { enableHandler } from './enable';
|
||||
import { dismissHandler } from "./dismiss";
|
||||
|
||||
export default (): void => {
|
||||
const swCapable = 'serviceWorker' in navigator;
|
||||
if (swCapable) {
|
||||
document.body.classList.add('cap-service-worker');
|
||||
}
|
||||
|
||||
const notificationCapable = 'Notification' in window;
|
||||
if (notificationCapable) {
|
||||
document.body.classList.add('cap-notification');
|
||||
}
|
||||
|
||||
if (swCapable && notificationCapable) {
|
||||
navigator.serviceWorker.getRegistration().then(registration => {
|
||||
if (!registration && localStorage.getItem('dismiss-push-settings-prompt') == null) {
|
||||
document.querySelector('.push-settings').classList.remove('d-none');
|
||||
}
|
||||
})
|
||||
|
||||
registerEvents([
|
||||
{type: 'click', target: '[data-action="push-enable"]', handler: enableHandler, global: true},
|
||||
{type: 'click', target: '[data-action="push-dismiss"]', handler: dismissHandler, global: true},
|
||||
]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
.card.push-settings.d-none
|
||||
.card-body
|
||||
= t(".description")
|
||||
%button.btn.btn-primary{ data: { action: "push-enable" } }= t("voc.y")
|
||||
%button.btn{ data: { action: "push-dismiss" } }= t("voc.n")
|
|
@ -2,6 +2,7 @@
|
|||
.row
|
||||
.col-sm-10.col-md-10.col-lg-9.mx-auto
|
||||
= render 'inbox/actions', delete_id: @delete_id, disabled: @disabled, inbox_count: @inbox_count
|
||||
= render 'inbox/push_settings'
|
||||
= render 'layouts/messages'
|
||||
= yield
|
||||
|
||||
|
|
|
@ -49,6 +49,15 @@ en:
|
|||
confirm:
|
||||
title: "Are you sure?"
|
||||
text: "This will mute this user for everyone."
|
||||
push_notifications:
|
||||
subscribe:
|
||||
success:
|
||||
title: Push notifications enabled!
|
||||
body: You will now receive push notifications for new questions on this device.
|
||||
fail:
|
||||
title: Failed to subscribe to push notifications
|
||||
body: Please try again later
|
||||
setup_fail: Failed to set up push notifications. Please try again later.
|
||||
report:
|
||||
confirm:
|
||||
title: "Are you sure you want to report this %{type}?"
|
||||
|
|
|
@ -231,6 +231,8 @@ en:
|
|||
share:
|
||||
heading: "Share"
|
||||
button: "Share on %{service}"
|
||||
push_settings:
|
||||
description: "Want to receive push notifications for new questions on your device?"
|
||||
layouts:
|
||||
feedback:
|
||||
heading: "Feedback"
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
self.addEventListener('push', function (event) {
|
||||
if (event.data) {
|
||||
const notification = event.data.json();
|
||||
console.log(event.data);
|
||||
|
||||
event.waitUntil(self.registration.showNotification(notification.title, {
|
||||
body: notification.body
|
||||
}));
|
||||
} else {
|
||||
console.error("Push event received, but it didn't contain any data.", event);
|
||||
}
|
||||
});
|
Loading…
Reference in New Issue