Compare commits

...

4 commits

Author SHA1 Message Date
Michel EDIGHOFFER
2cb0561baf
feat: add french translation 2023-01-20 15:18:49 +01:00
userquin
c416f892ba Merge branch 'main' into userquin/feat-pwa-install-banner
# Conflicts:
#	layouts/default.vue
2023-01-20 15:02:53 +01:00
userquin
0ce69d5399 chore: refactor cancel install logic 2023-01-18 21:01:45 +01:00
userquin
b1876bc160 feat(pwa): installable pwa widget 2023-01-18 20:45:00 +01:00
8 changed files with 74 additions and 0 deletions

View file

@ -38,6 +38,7 @@ defineProps<{
<slot name="header" /> <slot name="header" />
</div> </div>
<div :class="{ 'xl:block': $route.name !== 'tag' }" hidden h-6 /> <div :class="{ 'xl:block': $route.name !== 'tag' }" hidden h-6 />
<PwaInstallPrompt lg:hidden />
<slot /> <slot />
</div> </div>
</template> </template>

View file

@ -0,0 +1,22 @@
<template>
<div
v-if="$pwa?.showInstallPrompt && !$pwa?.needRefresh"
m-2 p5 bg="primary-fade" relative
rounded-lg of-hidden
flex="~ col gap-3"
v-bind="$attrs"
>
<h2 flex="~ gap-2" items-center>
{{ $t('pwa.install_title') }}
</h2>
<div flex="~ gap-1">
<button type="button" btn-solid px-4 py-1 text-center text-sm @click="$pwa.install()">
{{ $t('pwa.install') }}
</button>
<button type="button" btn-text filter-saturate-0 px-4 py-1 text-center text-sm @click="$pwa.cancelInstall()">
{{ $t('pwa.dismiss') }}
</button>
</div>
<div i-material-symbols:install-desktop-rounded absolute text-6em bottom--2 inset-ie--2 text-primary op10 class="-z-1 rtl-flip" />
</div>
</template>

View file

@ -65,6 +65,7 @@ const isGrayscale = usePreferences('grayscaleMode')
<div flex-auto /> <div flex-auto />
<PwaPrompt /> <PwaPrompt />
<PwaInstallPrompt />
<LazyCommonPreviewPrompt v-if="info.env === 'preview'" /> <LazyCommonPreviewPrompt v-if="info.env === 'preview'" />
<NavFooter /> <NavFooter />
</slot> </slot>

View file

@ -179,6 +179,8 @@
}, },
"pwa": { "pwa": {
"dismiss": "Dismiss", "dismiss": "Dismiss",
"install": "Install",
"install_title": "Install Elk",
"title": "New Elk update available!", "title": "New Elk update available!",
"update": "Update", "update": "Update",
"update_available_short": "Update Elk" "update_available_short": "Update Elk"

View file

@ -248,6 +248,8 @@
}, },
"pwa": { "pwa": {
"dismiss": "Dismiss", "dismiss": "Dismiss",
"install": "Install",
"install_title": "Install Elk",
"title": "New Elk update available!", "title": "New Elk update available!",
"update": "Update", "update": "Update",
"update_available_short": "Update Elk", "update_available_short": "Update Elk",

View file

@ -204,6 +204,8 @@
}, },
"pwa": { "pwa": {
"dismiss": "Descartar", "dismiss": "Descartar",
"install": "Instalar",
"install_title": "Instalar Elk",
"title": "Nueva versión de Elk disponible", "title": "Nueva versión de Elk disponible",
"update": "Actualizar", "update": "Actualizar",
"update_available_short": "Actualiza Elk", "update_available_short": "Actualiza Elk",

View file

@ -253,6 +253,8 @@
}, },
"pwa": { "pwa": {
"dismiss": "Fermer", "dismiss": "Fermer",
"install": "Installer",
"install_title": "Installer Elk",
"title": "Nouvelle mise à jour Elk disponible !", "title": "Nouvelle mise à jour Elk disponible !",
"update": "Mettre à jour", "update": "Mettre à jour",
"update_available_short": "Mettre à jour Elk", "update_available_short": "Mettre à jour Elk",

View file

@ -4,6 +4,7 @@ export default defineNuxtPlugin(() => {
const online = useOnline() const online = useOnline()
const registrationError = ref(false) const registrationError = ref(false)
const swActivated = ref(false) const swActivated = ref(false)
const showInstallPrompt = ref(false)
// https://thomashunter.name/posts/2021-12-11-detecting-if-pwa-twa-is-installed // https://thomashunter.name/posts/2021-12-11-detecting-if-pwa-twa-is-installed
const ua = navigator.userAgent const ua = navigator.userAgent
@ -57,10 +58,51 @@ export default defineNuxtPlugin(() => {
needRefresh.value = false 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 { return {
provide: { provide: {
pwa: reactive({ pwa: reactive({
isInstalled, isInstalled,
showInstallPrompt,
cancelInstall,
install,
swActivated, swActivated,
registrationError, registrationError,
needRefresh, needRefresh,