feat: show notification to install miniplan as app
Deploy Miniplan / build (push) Successful in 59s

This commit is contained in:
2026-07-21 16:38:05 +02:00
parent 1104280c0c
commit 87812d02d3
5 changed files with 181 additions and 75 deletions
+1
View File
@@ -2,3 +2,4 @@
.idea .idea
node_modules node_modules
package-lock.json package-lock.json
/.idea/
+1
View File
@@ -26,3 +26,4 @@ coverage
*.njsproj *.njsproj
*.sln *.sln
*.sw? *.sw?
/dev-dist/
+36
View File
@@ -6,6 +6,8 @@ import {onMounted, ref} from "vue";
import {Auth} from "@/services/auth"; import {Auth} from "@/services/auth";
import DialogHost from "@/components/dialog/DialogHost.vue"; import DialogHost from "@/components/dialog/DialogHost.vue";
import {LoginService} from "@/services/LoginService"; import {LoginService} from "@/services/LoginService";
import {Dialogs} from "@/services/DialogService";
import InstallPWADialog from "@/components/dialog/InstallPWADialog.vue";
let showPopup = ref(false) let showPopup = ref(false)
let loggedIn = ref(false) let loggedIn = ref(false)
@@ -33,6 +35,40 @@ LoginService.subject.subscribe(() => {
showPopup.value = true showPopup.value = true
}) })
const installEvent = ref<Event>()
window.addEventListener('beforeinstallprompt', (e) => {
e.preventDefault()
console.log("beforeinstallprompt")
installEvent.value = e
scheduleInstallDialog()
})
function scheduleInstallDialog() {
if (isPwa()) return
if (localStorage.getItem('installPromptDismissed')) return
if (!installEvent.value) return
Dialogs.createDialog(InstallPWADialog, {
onPositive(dontShowAgain: boolean) {
if (dontShowAgain) localStorage.setItem('installPromptDismissed', 'true')
;(installEvent.value as any).prompt()
},
onNegative(dontShowAgain: boolean) {
if (dontShowAgain) localStorage.setItem('installPromptDismissed', 'true')
},
onDismiss() {}
}, {})
}
function isPwa() {
return window.matchMedia('(display-mode: standalone)').matches
}
window.addEventListener('appinstalled', () => {
localStorage.setItem('installPromptDismissed', 'true')
})
</script> </script>
<template> <template>
@@ -0,0 +1,66 @@
<script setup lang="ts">
import {ref} from "vue";
import Dialog from "@/components/dialog/Dialog.vue";
import type {DialogControls} from "@/components/dialog/dialog";
interface InstallPWADialogProps extends DialogControls {
}
defineProps<InstallPWADialogProps>()
const dontShowAgain = ref<boolean>(false)
</script>
<template>
<Dialog class="dialog">
<h3 style="margin-bottom: 10px; display: flex; gap: 1rem; align-items: center">
Zum Startbildschirm hinzufügen
</h3>
<p style="line-height: 1.7rem">
Dein Miniplan kann jetzt auf Ihrem Gerät installiert werden, um schnell und einfach darauf zuzugreifen.
</p>
<label class="checkbox">
<input type="checkbox" v-model="dontShowAgain" />
Nicht mehr anzeigen
</label>
<div class="buttons">
<button @click="onNegative(dontShowAgain)" class="dismiss">Später</button>
<button @click="onPositive(dontShowAgain)" ><i>browser_updated</i>Jetzt hinzufügen</button>
</div>
</Dialog>
</template>
<style scoped lang="less">
.dialog {
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
width: 500px
}
.checkbox {
display: flex;
align-items: center;
gap: 8px;
margin-top: 16px;
font-size: 14px;
cursor: pointer;
}
.buttons {
display: flex;
justify-content: end;
margin-top: 20px;
.dismiss {
background: transparent;
}
}
</style>
+10 -8
View File
@@ -1,19 +1,20 @@
import { fileURLToPath, URL } from 'node:url' import {fileURLToPath, URL} from 'node:url'
import { defineConfig } from 'vite' import {defineConfig} from 'vite'
import vue from '@vitejs/plugin-vue' import vue from '@vitejs/plugin-vue'
import { VitePWA } from 'vite-plugin-pwa' import {VitePWA} from 'vite-plugin-pwa'
export default defineConfig({ export default defineConfig(({mode}) => (
{
plugins: [ plugins: [
vue(), vue(),
VitePWA({ VitePWA({
registerType: 'autoUpdate', registerType: 'autoUpdate',
includeAssets: ['favicon.ico', 'minis_logo.png'], includeAssets: ['favicon.ico', 'minis_logo.png'],
manifest: { manifest: {
name: 'Miniplan', name: 'Miniplan App',
short_name: 'Miniplan', short_name: 'Miniplan',
description: 'Miniplan', description: 'Lade deinen Miniplan direkt auf dein Handy. So hast du den Miniplan jederzeit und schnell erreichbar.',
theme_color: '#ffffff', theme_color: '#ffffff',
background_color: '#ffffff', background_color: '#ffffff',
display: 'standalone', display: 'standalone',
@@ -67,7 +68,7 @@ export default defineConfig({
] ]
}, },
devOptions: { devOptions: {
enabled: false enabled: mode === "development"
} }
}) })
], ],
@@ -76,4 +77,5 @@ export default defineConfig({
'@': fileURLToPath(new URL('./src', import.meta.url)) '@': fileURLToPath(new URL('./src', import.meta.url))
} }
} }
}) })
)