133 lines
3.3 KiB
TypeScript
133 lines
3.3 KiB
TypeScript
import { computed, onMounted, ref } from 'vue'
|
|
import type { PwaPlatform } from '@/modules/pwa/pwaInstallGuideSteps'
|
|
import {
|
|
getDefaultPwaPlatform,
|
|
initPwaInstallPromptListener,
|
|
isPwaInstallBannerDismissed,
|
|
markPwaInstallBannerAsShown,
|
|
shouldOfferPwaInstall,
|
|
shouldShowPwaInstallPrompt,
|
|
triggerNativePwaInstall,
|
|
} from '@/modules/pwa/pwaInstall'
|
|
|
|
const guideOpen = ref(false)
|
|
const bannerVisible = ref(false)
|
|
const platform = ref<PwaPlatform>(getDefaultPwaPlatform())
|
|
const installBannerConsumed = ref(isPwaInstallBannerDismissed())
|
|
/** false وقتی اپ بهصورت PWA/TWA باز شده یا همین الان نصب شده */
|
|
const offerInstall = ref(shouldOfferPwaInstall())
|
|
let listenerReady = false
|
|
let offerListenersBound = false
|
|
|
|
function refreshOfferInstall() {
|
|
offerInstall.value = shouldOfferPwaInstall()
|
|
}
|
|
|
|
function bindOfferInstallListeners() {
|
|
if (offerListenersBound || typeof window === 'undefined') return
|
|
offerListenersBound = true
|
|
|
|
refreshOfferInstall()
|
|
|
|
const onInstalled = () => {
|
|
offerInstall.value = false
|
|
}
|
|
window.addEventListener('appinstalled', onInstalled)
|
|
|
|
const modes = ['standalone', 'fullscreen', 'minimal-ui', 'window-controls-overlay'] as const
|
|
const mediaLists = modes.map((mode) => window.matchMedia(`(display-mode: ${mode})`))
|
|
const onDisplayModeChange = () => refreshOfferInstall()
|
|
for (const mql of mediaLists) {
|
|
mql.addEventListener('change', onDisplayModeChange)
|
|
}
|
|
}
|
|
|
|
function ensureListener() {
|
|
if (listenerReady) return
|
|
listenerReady = true
|
|
initPwaInstallPromptListener()
|
|
bindOfferInstallListeners()
|
|
}
|
|
|
|
export function usePwaInstall() {
|
|
ensureListener()
|
|
|
|
onMounted(() => {
|
|
refreshOfferInstall()
|
|
})
|
|
|
|
const canPrompt = computed(() => {
|
|
if (installBannerConsumed.value) return false
|
|
return shouldShowPwaInstallPrompt()
|
|
})
|
|
|
|
const showInstallEntry = computed(() => offerInstall.value)
|
|
|
|
function consumeInstallBanner() {
|
|
if (installBannerConsumed.value) return
|
|
markPwaInstallBannerAsShown()
|
|
installBannerConsumed.value = true
|
|
bannerVisible.value = false
|
|
}
|
|
|
|
function openGuide(nextPlatform?: PwaPlatform) {
|
|
if (!offerInstall.value) return
|
|
consumeInstallBanner()
|
|
platform.value = nextPlatform ?? getDefaultPwaPlatform()
|
|
guideOpen.value = true
|
|
}
|
|
|
|
function closeGuide() {
|
|
guideOpen.value = false
|
|
}
|
|
|
|
function showBanner() {
|
|
if (!canPrompt.value) return
|
|
bannerVisible.value = true
|
|
markPwaInstallBannerAsShown()
|
|
installBannerConsumed.value = true
|
|
}
|
|
|
|
function hideBanner() {
|
|
bannerVisible.value = false
|
|
}
|
|
|
|
function dismissBanner() {
|
|
consumeInstallBanner()
|
|
}
|
|
|
|
async function completeGuide() {
|
|
await triggerNativePwaInstall()
|
|
consumeInstallBanner()
|
|
closeGuide()
|
|
}
|
|
|
|
/** نصب مستقیم مرورگر؛ اگر ممکن نبود مدال آموزش. */
|
|
async function tryInstallOrOpenGuide(nextPlatform?: PwaPlatform) {
|
|
if (!offerInstall.value) return false
|
|
const installed = await triggerNativePwaInstall()
|
|
if (installed) {
|
|
offerInstall.value = false
|
|
consumeInstallBanner()
|
|
return true
|
|
}
|
|
openGuide(nextPlatform)
|
|
return false
|
|
}
|
|
|
|
return {
|
|
guideOpen,
|
|
bannerVisible,
|
|
platform,
|
|
canPrompt,
|
|
showInstallEntry,
|
|
openGuide,
|
|
closeGuide,
|
|
showBanner,
|
|
hideBanner,
|
|
dismissBanner,
|
|
completeGuide,
|
|
tryInstallOrOpenGuide,
|
|
}
|
|
}
|