notification support

This commit is contained in:
Karl 2025-07-17 15:41:16 +01:00
parent 1fc2fc46e0
commit 3e1e7a5ce2
3 changed files with 70 additions and 3 deletions

2
app.py
View File

@ -58,7 +58,7 @@ def get_version() -> str:
@app.context_processor
def inject_version() -> Dict[str, str]:
"""Injects the version into all templates."""
return dict(version=get_version())
return dict(version=get_version(), config=app.config, session=session)
@app.before_request
def make_session_permanent() -> None:

View File

@ -21,6 +21,19 @@ self.addEventListener('install', function(event) {
);
});
self.addEventListener('push', function(event) {
const data = event.data.json();
const options = {
body: data.body,
icon: '/static/web-app-manifest-192x192.png',
badge: '/static/favicon-96x96.png'
};
event.waitUntil(
self.registration.showNotification(data.title, options)
);
});
self.addEventListener('fetch', function(event) {
event.respondWith(
caches.match(event.request)

View File

@ -54,8 +54,62 @@
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
{% block scripts %}{% endblock %}
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('{{ url_for("static", filename="service-worker.js") }}')
if ('serviceWorker' in navigator && 'PushManager' in window) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('{{ url_for("static", filename="service-worker.js") }}').then(function(registration) {
console.log('ServiceWorker registration successful with scope: ', registration.scope);
askPermission(registration);
}, function(err) {
console.log('ServiceWorker registration failed: ', err);
});
});
}
function askPermission(registration) {
Notification.requestPermission().then(function(result) {
if (result === 'granted') {
subscribeUser(registration);
}
});
}
function subscribeUser(registration) {
const applicationServerKey = urlB64ToUint8Array('{{ config.VAPID_PUBLIC_KEY }}');
registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: applicationServerKey
}).then(function(subscription) {
console.log('User is subscribed.');
saveSubscription(subscription);
}).catch(function(err) {
console.log('Failed to subscribe the user: ', err);
});
}
function saveSubscription(subscription) {
fetch('/save-subscription', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Basic {{ session.auth_credentials }}'
},
body: JSON.stringify(subscription)
});
}
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;
}
</script>
</body>