diff --git a/index.html b/index.html index b68d535..a60e88f 100644 --- a/index.html +++ b/index.html @@ -191,6 +191,17 @@ }); } + // ── PWA Install Logic ────────────────────────────────────────── + window.deferredPrompt = null; + + window.addEventListener('beforeinstallprompt', (e) => { + // Prevent automatic prompt + e.preventDefault(); + window.deferredPrompt = e; + // Dispatch a custom event so sections can update their UI + window.dispatchEvent(new Event('pwa-installable')); + }); + // ── Check Web Bluetooth availability ────────────────────────── if (!navigator.bluetooth) { setTimeout(() => { diff --git a/web/js/sections/home.js b/web/js/sections/home.js index ebff574..89bdfbb 100644 --- a/web/js/sections/home.js +++ b/web/js/sections/home.js @@ -116,9 +116,37 @@ const HomeSection = { }; BLE.on('connected', update); BLE.on('disconnected', update); + + // PWA Install Logic + const pwaCard = container.querySelector('#home-pwa-install-card'); + const pwaBtn = container.querySelector('#home-btn-install-pwa'); + + const checkPwaStatus = () => { + if (window.deferredPrompt && pwaCard) { + pwaCard.style.display = 'block'; + } + }; + + // Check initially in case the event fired before we mounted + checkPwaStatus(); + + window.addEventListener('pwa-installable', checkPwaStatus); + + if (pwaBtn) { + pwaBtn.addEventListener('click', async () => { + if (!window.deferredPrompt) return; + window.deferredPrompt.prompt(); + const { outcome } = await window.deferredPrompt.userChoice; + console.log(`User response to the install prompt: ${outcome}`); + window.deferredPrompt = null; + pwaCard.style.display = 'none'; + }); + } + this._cleanup = [ () => BLE.off('connected', update), () => BLE.off('disconnected', update), + () => window.removeEventListener('pwa-installable', checkPwaStatus), ]; },