feat(sw.js/app.js): Gère les notifications push et l'abonnement

Ajoute la gestion des notifications push avec abonnement via le
service worker et enregistre l'abonnement sur le serveur. Gère
l'affichage d'une bannière pour demander la permission.
```
This commit is contained in:
Serreau Jovann
2025-11-19 13:48:31 +01:00
parent 1d97514c94
commit de9c951eaf
9 changed files with 410 additions and 22 deletions

BIN
public/assets/notif.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -31,24 +31,54 @@ workbox.routing.registerRoute(
})
);
self.addEventListener('fetch', (event) => {
if (event.request.mode === 'navigate') {
event.respondWith((async () => {
try {
const preloadResp = await event.preloadResponse;
// --- GESTION DES NOTIFICATIONS PUSH (Réception) ---
self.addEventListener('push', (event) => {
if (event.data) {
// Assurez-vous que le payload JSON envoyé par votre serveur contient
// 'title', 'message' et 'link'.
const data = event.data.json();
if (preloadResp) {
return preloadResp;
}
const title = data.title || 'Nouvelle Notification';
const message = data.message || 'Contenu mis à jour.';
const link = data.link || '/'; // Lien par défaut vers la racine
const networkResp = await fetch(event.request);
return networkResp;
} catch (error) {
const cache = await caches.open(CACHE);
const cachedResp = await cache.match(offlineFallbackPage);
return cachedResp;
const options = {
body: message,
// PATH MIS À JOUR ICI
icon: data.icon || '/assets/notif.png',
data: {
link: link // On stocke le lien pour le réutiliser au clic
}
})());
};
// Affiche la notification
event.waitUntil(
self.registration.showNotification(title, options)
);
}
});
// --- GESTION DES CLICS SUR LA NOTIFICATION ---
self.addEventListener('notificationclick', (event) => {
// Récupère le lien stocké dans la notification
const urlToOpen = event.notification.data.link || '/';
// Ferme la notification après le clic
event.notification.close();
// Ouvre l'URL associée, soit dans un onglet existant, soit dans un nouvel onglet
event.waitUntil(
clients.matchAll({ type: 'window', includeUncontrolled: true }).then((clientList) => {
// Tente de trouver un client existant pour naviguer
for (const client of clientList) {
if (client.url.endsWith(urlToOpen) && 'focus' in client) {
return client.focus();
}
}
// Sinon, ouvre une nouvelle fenêtre/onglet
return clients.openWindow(urlToOpen);
})
);
});