diff --git a/ephios/core/context.py b/ephios/core/context.py index 7182ed67f..090bb255e 100644 --- a/ephios/core/context.py +++ b/ephios/core/context.py @@ -42,6 +42,7 @@ def ephios_base_context(request): "ephios_version": settings.EPHIOS_VERSION, "PWA_APP_ICONS": get_pwa_app_icons(), "PWA_APP_SPLASH_SCREEN": [], + "VAPID_PUBLIC_KEY": settings.WEBPUSH_SETTINGS.get("VAPID_PUBLIC_KEY", ""), "DEBUG": settings.DEBUG, "organization_name": global_preferences_registry.manager()["general__organization_name"], "platform_name": dynamic_settings.PLATFORM_NAME, diff --git a/ephios/core/templates/core/settings/settings_notifications.html b/ephios/core/templates/core/settings/settings_notifications.html index de4ff3195..2b93a0706 100644 --- a/ephios/core/templates/core/settings/settings_notifications.html +++ b/ephios/core/templates/core/settings/settings_notifications.html @@ -2,11 +2,6 @@ {% load crispy_forms_filters %} {% load utils %} {% load i18n %} -{% load webpush_notifications %} - -{% block html_head %} - {% webpush_header %} -{% endblock %} {% block settings_content %}

{% translate "Notifications" %}

diff --git a/ephios/locale/de/LC_MESSAGES/django.po b/ephios/locale/de/LC_MESSAGES/django.po index af1bf4355..a0fdab3cb 100644 --- a/ephios/locale/de/LC_MESSAGES/django.po +++ b/ephios/locale/de/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-09-11 23:54+0200\n" +"POT-Creation-Date: 2026-01-11 17:22+0100\n" "PO-Revision-Date: 2025-09-04 22:35+0200\n" "Last-Translator: Felix Rindt \n" "Language-Team: German rememberDismissed("pwaPrompt")); + + // Get reference to apple (non-installable) prompt offcanvas + const pwaAppleOffcanvas = document.getElementById('pwaAppleOffcanvas'); + const pwaAppleBsOffcanvas = new bootstrap.Offcanvas('#pwaAppleOffcanvas') + pwaAppleOffcanvas.addEventListener('hide.bs.offcanvas', _ => rememberDismissed("pwaPrompt")); + + // Get reference to notification subscription prompt offcanvas + const notificationOffcanvas = document.getElementById("notificationOffcanvas"); + const notificationBsOffcanvas = new bootstrap.Offcanvas('#notificationOffcanvas'); + notificationOffcanvas.addEventListener("hide.bs.offcanvas", _ => rememberDismissed("notificationPrompt")) + + let deferredInstallPrompt; + + // The browser fires the beforeinstallprompt event when the PWA can be installed. + // We need to store the prompt to be able to show the install button later on. + // We show the prompt to the user if they did not decline in the last month and are logged in + window.addEventListener('beforeinstallprompt', (e) => { + e.preventDefault(); + deferredInstallPrompt = e; + if (!getCookie("pwaPrompt") && document.body.dataset.userIsAuthenticated === "True") { + pwaAndroidBsOffcanvas.show(); + } + }); + + // The browser fires the appinstalled event after the PWA has been installed. + // We use this opportunity to ask the user if they want to receive notifications + window.addEventListener('appinstalled', () => { + pwaAndroidBsOffcanvas.hide(); + // isPushEnabled is set by webpush.js from django-webpush + if (typeof isPushEnabled !== undefined && !isPushEnabled) { + notificationBsOffcanvas.show(); + document.getElementById("webpush-subscribe-button") + .addEventListener("click", _ => notificationBsOffcanvas.hide()) + } + deferredInstallPrompt = null; + }); + + // When the user clicks on the install button in our PWA install prompt, we can used the saved prompt + // from the browser event to actually trigger the installation + const buttonInstall = document.getElementById("pwaInstall"); + buttonInstall.addEventListener('click', async () => { + deferredInstallPrompt.prompt(); + await deferredInstallPrompt.userChoice; + pwaAndroidBsOffcanvas.hide(); + deferredInstallPrompt = null; + }); + + // iOS does not support programmatic installation, so we show an offcanvas with instructions instead + if (/iPad|iPhone|iPod/.test(navigator.userAgent) && !getCookie("pwaPrompt") && document.body.dataset.userIsAuthenticated === "True") { + pwaAppleBsOffcanvas.show(); + } + + setTimeout(() => { + // Only show this prompt inside of the PWA (with display-mode: standalone) for logged in user that did not decline in the last month + // isPushEnabled is set by webpush.js from django-webpush + if ((window.matchMedia('(display-mode: standalone)').matches || navigator.standalone) && typeof isPushEnabled !== undefined && !isPushEnabled && !getCookie("notificationPrompt")) { + document.getElementById("webpush-subscribe-button") + .addEventListener("click", _ => notificationBsOffcanvas.hide()) + notificationBsOffcanvas.show(); + } + }, 2000); // isPushEnabled is only set to true after a request to the backend, so it takes some time + }) +function rememberDismissed(key) { + const date = new Date(); + date.setDate(date.getDate() + 30); + document.cookie = key + "=hidden;expires=" + date.toUTCString(); +} + function getCookie(name) { let cookieValue = null; if (document.cookie && document.cookie !== '') { diff --git a/ephios/templates/base.html b/ephios/templates/base.html index 912fca584..3ba734af1 100644 --- a/ephios/templates/base.html +++ b/ephios/templates/base.html @@ -1,3 +1,4 @@ +{% load webpush_notifications %} {% load signal_extras %} {% load settings_extras %} {% load statici18n %} @@ -14,6 +15,9 @@ + + + @@ -56,6 +60,7 @@ {% else %} {% endif %} + @@ -71,7 +76,7 @@ {% endblock %} - +