import { computed, onMounted, ref } from 'vue' import { message } from 'ant-design-vue' import type { PwaPlatform } from '@/modules/pwa/pwaInstallGuideSteps' import { getDefaultPwaPlatform, initPwaInstallPromptListener, isPwaInstallBannerDismissed, isStandalonePwa, markPwaInstallBannerAsShown, shouldOfferPwaInstall, shouldShowPwaInstallPrompt, triggerNativePwaInstall, } from '@/modules/pwa/pwaInstall' import { isTWA } from '@/utils/config' const guideOpen = ref(false) const bannerVisible = ref(false) const platform = ref(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) { refreshOfferInstall() // فقط وقتی واقعاً داخل PWA/TWA هستیم راهنما را نشان نده if (isStandalonePwa() || isTWA()) return consumeInstallBanner() const next = nextPlatform === 'ios' || nextPlatform === 'android' ? nextPlatform : getDefaultPwaPlatform() platform.value = next 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) { ensureListener() refreshOfferInstall() if (isStandalonePwa() || isTWA()) { message.info('نسخه وب‌اپ از قبل نصب شده است') offerInstall.value = false return false } const installed = await triggerNativePwaInstall() if (installed) { offerInstall.value = false consumeInstallBanner() message.success('نصب وب‌اپ آغاز شد') return true } // Chrome روی HTTP/IP یا Safari معمولاً prompt بومی ندارد — راهنما را باز کن openGuide(nextPlatform) return false } return { guideOpen, bannerVisible, platform, canPrompt, showInstallEntry, openGuide, closeGuide, showBanner, hideBanner, dismissBanner, completeGuide, tryInstallOrOpenGuide, } }