feat: add pwa install button (#27)

* feat: add pwa tooltip

* feat: add pwa install button
This commit is contained in:
云游君
2022-04-30 20:39:24 +08:00
committed by GitHub
parent 50156534c2
commit 2712616683
9 changed files with 154 additions and 68 deletions

View File

@@ -1,4 +1,5 @@
<script setup lang="ts">
import { installPrompt } from './utils/pwa'
import { isDark } from '~/composables'
// https://github.com/vueuse/head
// you can use this to manipulate the document head in any components,
@@ -16,6 +17,8 @@ useHead({
},
],
})
installPrompt()
</script>
<template>

1
src/components.d.ts vendored
View File

@@ -10,6 +10,7 @@ declare module '@vue/runtime-core' {
ChooseFood: typeof import('./components/ChooseFood.vue')['default']
Counter: typeof import('./components/Counter.vue')['default']
DishTag: typeof import('./components/tags/DishTag.vue')['default']
InstallPwa: typeof import('./components/InstallPwa.vue')['default']
MeatTag: typeof import('./components/tags/MeatTag.vue')['default']
Menu: typeof import('./components/Menu.vue')['default']
README: typeof import('./components/README.md')['default']

View File

@@ -0,0 +1,29 @@
<script lang="ts" setup>
import { useAppStore } from '~/stores/app'
const app = useAppStore()
const install = () => {
const deferredPrompt = app.deferredPrompt
// Show the install prompt
deferredPrompt.prompt()
// Wait for the user to respond to the prompt
deferredPrompt.userChoice.then((choiceResult: any) => {
if (choiceResult.outcome === 'accepted')
// eslint-disable-next-line no-console
console.log('User accepted the install prompt')
else
// eslint-disable-next-line no-console
console.log('User dismissed the install prompt')
})
}
</script>
<template>
<Transition>
<div v-if="app.deferredPrompt" text="center" m="t-2">
<button class="shadow" bg="green-500" p="x-4 y-0" m="2" @click="install">
安装
</button>
</div>
</Transition>
</template>

View File

@@ -25,6 +25,8 @@ title: 帮助
- 点击首页最上方的大锅图标,可清空所选食材和工具。
- 本项目支持 PWA使用浏览器打开时可将其添加到主屏幕以获得近原生 APP 的体验。
<InstallPwa />
## FAQ
### 页面无法点击、资源加载失败?

4
src/shims.d.ts vendored
View File

@@ -1,6 +1,10 @@
declare interface Window {
// extend the window
wx: any
/**
* pwa install prompt event
*/
deferredPrompt: Event | any
}
// with vite-plugin-md, markdowns can be treat as Vue components

12
src/stores/app.ts Normal file
View File

@@ -0,0 +1,12 @@
import { acceptHMRUpdate, defineStore } from 'pinia'
export const useAppStore = defineStore('app', () => {
const deferredPrompt = ref<Event | any>()
return {
deferredPrompt,
}
})
if (import.meta.hot)
import.meta.hot.accept(acceptHMRUpdate(useAppStore, import.meta.hot))

35
src/utils/pwa.ts Normal file
View File

@@ -0,0 +1,35 @@
import { isClient } from '@vueuse/core'
import { useAppStore } from '~/stores/app'
/**
* https://web.dev/customize-install/#detect-install
* @returns
*/
export function installPrompt() {
if (!isClient)
return
const app = useAppStore()
window.addEventListener('beforeinstallprompt', (e) => {
// Prevent the mini-infobar from appearing on mobile
// e.preventDefault()
// Stash the event so it can be triggered later.
app.deferredPrompt = e
// Update UI notify the user they can install the PWA
// showInstallPromotion()
// Optionally, send analytics event that PWA install promo was shown.
// eslint-disable-next-line no-console
console.log('\'beforeinstallprompt\' event was fired.')
})
window.addEventListener('appinstalled', () => {
// Hide the app-provided install promotion
// hideInstallPromotion()
// Clear the deferredPrompt so it can be garbage collected
app.deferredPrompt = null
// Optionally, send analytics event to indicate successful install
// eslint-disable-next-line no-console
console.log('PWA was installed')
})
}