diff --git a/components/main/MainContent.vue b/components/main/MainContent.vue index c6a0bc0f..9e5804e4 100644 --- a/components/main/MainContent.vue +++ b/components/main/MainContent.vue @@ -42,6 +42,7 @@ const wideLayout = computed(() => route.meta.wideLayout ?? false) -
+
diff --git a/layouts/default.vue b/layouts/default.vue index 06fed06e..aca1daa1 100644 --- a/layouts/default.vue +++ b/layouts/default.vue @@ -65,6 +65,7 @@ const isGrayscale = usePreferences('grayscaleMode')
+ diff --git a/locales/en.json b/locales/en.json index a2f79959..6b028be7 100644 --- a/locales/en.json +++ b/locales/en.json @@ -248,6 +248,8 @@ }, "pwa": { "dismiss": "Dismiss", + "install": "Install", + "install_title": "Install Elk", "title": "New Elk update available!", "update": "Update", "update_available_short": "Update Elk", diff --git a/locales/es.json b/locales/es.json index ee7cc2fd..a73d615d 100644 --- a/locales/es.json +++ b/locales/es.json @@ -204,6 +204,8 @@ }, "pwa": { "dismiss": "Descartar", + "install": "Instalar", + "install_title": "Instalar Elk", "title": "Nueva versión de Elk disponible", "update": "Actualizar", "update_available_short": "Actualiza Elk", diff --git a/locales/fr-FR.json b/locales/fr-FR.json index 09be1fa5..3418d1fe 100644 --- a/locales/fr-FR.json +++ b/locales/fr-FR.json @@ -253,6 +253,8 @@ }, "pwa": { "dismiss": "Fermer", + "install": "Installer", + "install_title": "Installer Elk", "title": "Nouvelle mise à jour Elk disponible !", "update": "Mettre à jour", "update_available_short": "Mettre à jour Elk", diff --git a/plugins/pwa.client.ts b/plugins/pwa.client.ts index dfa60334..79e8c776 100644 --- a/plugins/pwa.client.ts +++ b/plugins/pwa.client.ts @@ -4,6 +4,7 @@ export default defineNuxtPlugin(() => { const online = useOnline() const registrationError = ref(false) const swActivated = ref(false) + const showInstallPrompt = ref(false) // https://thomashunter.name/posts/2021-12-11-detecting-if-pwa-twa-is-installed const ua = navigator.userAgent @@ -57,10 +58,51 @@ export default defineNuxtPlugin(() => { needRefresh.value = false } + type InstallPromptEvent = Event & { + prompt: () => void + userChoice: Promise<{ outcome: 'dismissed' | 'accepted' }> + } + + let deferredPrompt: InstallPromptEvent | undefined + + const beforeInstallPrompt = (e: Event) => { + e.preventDefault() + deferredPrompt = e as InstallPromptEvent + showInstallPrompt.value = true + } + window.addEventListener('beforeinstallprompt', beforeInstallPrompt) + window.addEventListener('appinstalled', () => { + deferredPrompt = undefined + showInstallPrompt.value = false + }) + + const cancelInstall = () => { + deferredPrompt = undefined + showInstallPrompt.value = false + window.removeEventListener('beforeinstallprompt', beforeInstallPrompt) + } + + const install = async () => { + if (!showInstallPrompt.value || !deferredPrompt) { + showInstallPrompt.value = false + return + } + + showInstallPrompt.value = false + await nextTick() + deferredPrompt.prompt() + const { outcome } = await deferredPrompt.userChoice + if (outcome === 'dismissed') + cancelInstall() + } + return { provide: { pwa: reactive({ isInstalled, + showInstallPrompt, + cancelInstall, + install, swActivated, registrationError, needRefresh,