/** * Composable to handle PWA installation * * Usage: * const { canInstall, isInstalled, promptInstall, dismissInstall } = usePWAInstall() */ export function usePWAInstall() { const canInstall = ref(false) const isInstalled = ref(false) const deferredPrompt = ref(null) if (process.client) { // Check if already installed if (window.matchMedia('(display-mode: standalone)').matches) { isInstalled.value = true } // Listen for beforeinstallprompt event window.addEventListener('beforeinstallprompt', (e) => { // Prevent the mini-infobar from appearing on mobile e.preventDefault() // Stash the event so it can be triggered later deferredPrompt.value = e canInstall.value = true }) // Listen for appinstalled event window.addEventListener('appinstalled', () => { isInstalled.value = true canInstall.value = false deferredPrompt.value = null }) } async function promptInstall() { if (!deferredPrompt.value) { return { outcome: 'not-available' } } // Show the install prompt deferredPrompt.value.prompt() // Wait for the user to respond to the prompt const { outcome } = await deferredPrompt.value.userChoice // Clear the deferredPrompt deferredPrompt.value = null if (outcome === 'accepted') { canInstall.value = false } return { outcome } } function dismissInstall() { canInstall.value = false deferredPrompt.value = null // Remember dismissal for 7 days if (process.client) { localStorage.setItem('pwa-install-dismissed', Date.now().toString()) } } function shouldShowPrompt() { if (!canInstall.value || isInstalled.value) { return false } if (process.client) { const dismissed = localStorage.getItem('pwa-install-dismissed') if (dismissed) { const dismissedTime = parseInt(dismissed) const sevenDays = 7 * 24 * 60 * 60 * 1000 if (Date.now() - dismissedTime < sevenDays) { return false } } } return true } return { canInstall: readonly(canInstall), isInstalled: readonly(isInstalled), promptInstall, dismissInstall, shouldShowPrompt } }