Add a button for enabling push notifications

pull/158/head
borntolurk 2023-06-28 02:39:48 +02:00
parent b7929df032
commit 4861136380
5 changed files with 71 additions and 71 deletions

View File

@ -234,3 +234,10 @@ for (const input of inputs) {
if (parseInt(input.value) > parseInt(input.max)) input.value = input.max;
};
}
if (!('serviceWorker' in navigator && 'PushManager' in window)) {
let e = document.getElementById("enable-push-nav-item").style = "display: none";
if (e) {
e.style = "display: none"
}
}

View File

@ -605,3 +605,51 @@ document.querySelectorAll('form').forEach(form => {
form.classList.add('is-submitting');
});
});
function urlB64ToUint8Array(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 updateSubscriptionOnServer(subscription, apiEndpoint) {
const formData = new FormData();
formData.append("subscription_json", JSON.stringify(subscription));
const xhr = createXhrWithFormKey(
apiEndpoint,
'POST',
formData
);
xhr[0].send(xhr[1]);
}
function enablePushNotifications() {
if (!('serviceWorker' in navigator && 'PushManager' in window)) return;
let publicKeyElement = document.getElementById('VAPID_PUBLIC_KEY');
if (!publicKeyElement) return;
let publicKey = urlB64ToUint8Array(publicKeyElement.value);
navigator.serviceWorker.getRegistration("/assets/js/service_worker.js").then((reg) => {
return reg.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: publicKey,
})
}).then((subscription) => {
updateSubscriptionOnServer(subscription, "/push_subscribe")
alert("Push notifications are enabled!")
}).catch((e) => {
alert("Failed to enable push notifications :marseyill:")
console.log(e)
})
}

View File

@ -1,76 +1,11 @@
'use strict';
function urlB64ToUint8Array(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 updateSubscriptionOnServer(subscription, apiEndpoint) {
const formData = new FormData();
formData.append("subscription_json", JSON.stringify(subscription));
const xhr = createXhrWithFormKey(
apiEndpoint,
'POST',
formData
);
xhr[0].send(xhr[1]);
}
function subscribeUser(swRegistration, applicationServerPublicKey, apiEndpoint) {
const applicationServerKey = urlB64ToUint8Array(applicationServerPublicKey);
swRegistration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: applicationServerKey
})
.then(function(subscription) {
return updateSubscriptionOnServer(subscription, apiEndpoint);
})
.then(function(response) {
if (!response.ok) {
throw new Error('Bad status code from server.');
}
return response.json();
})
.then(function(responseData) {
if (responseData.status!=="success") {
throw new Error('Bad response from server.');
}
})
.catch(function() {
});
}
function registerServiceWorker(serviceWorkerUrl, applicationServerPublicKey, apiEndpoint){
let swRegistration = null;
function registerServiceWorker(serviceWorkerUrl){
if ('serviceWorker' in navigator && 'PushManager' in window) {
navigator.serviceWorker.register(serviceWorkerUrl)
.then(function(swReg) {
subscribeUser(swReg, applicationServerPublicKey, apiEndpoint);
swRegistration = swReg;
})
.catch(function() {
});
} else {
navigator.serviceWorker.register(serviceWorkerUrl);
}
return swRegistration;
}
registerServiceWorker(
"/assets/js/service_worker.js",
document.getElementById('VAPID_PUBLIC_KEY').value,
"/push_subscribe"
"/assets/js/service_worker.js"
)

View File

@ -254,7 +254,9 @@
<a class="dropdown-item" href="{{v.url}}"><i class="fas fa-user-circle fa-fw mr-3"></i>My profile</a>
<a class="dropdown-item" href="/settings/personal"><i class="fas fa-cog fa-fw mr-3"></i>Settings</a>
<a class="dropdown-item" href="/app"><i class="fas fa-mobile fa-fw mr-3"></i>Mobile app</a>
{% if g.browser != 'webview' %}
<a class="dropdown-item" href="/app"><i class="fas fa-mobile fa-fw mr-3"></i>Mobile app</a>
{% endif %}
<a class="dropdown-item donate-link" rel="nofollow noopener" href="/donate"><i class="fas fa-dollar-sign fa-fw mr-3"></i>Donate</a>
@ -310,7 +312,12 @@
<a class="nav-link" href="/settings/personal"><i class="fas fa-cog fa-fw mr-3"></i>Settings</a>
</li>
<a class="nav-item nav-link" href="/app"><i class="fas fa-mobile fa-fw mr-3"></i>Mobile app</a>
{% if g.browser == 'webview' %}
<a class="nav-item nav-link" href="/app" id="mobile-app-nav-item"><i class="fas fa-mobile fa-fw mr-3"></i>Mobile app</a>
{% endif %}
<a class="nav-item nav-link" href="#" id="enable-push-nav-item" data-nonce="{{g.nonce}}" data-nonce="{{g.nonce}}" data-onclick="enablePushNotifications()"><i class="fas fa-bell fa-fw mr-3"></i>Enable push notifications</a>
<a class="nav-item nav-link donate-link" rel="nofollow noopener" href="/donate"><i class="fas fa-dollar-sign fa-fw mr-3"></i>Donate</a>

View File

@ -160,7 +160,10 @@
{% if request.path == '/' and v %}
<script defer src="{{'js/register_service_worker.js' | asset}}"></script>
<input hidden id="VAPID_PUBLIC_KEY" value="{{VAPID_PUBLIC_KEY}}">
{% endif %}
{% if v %}
<input hidden id="VAPID_PUBLIC_KEY" value="{{VAPID_PUBLIC_KEY}}">
{% endif %}
{% if False and request.path == '/' and g.browser != 'webview' and time.time() > session.get('tooltip_dismissed',0)+86400*30 %}