WIP PWA for Grain
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 60 lines 1.3 kB view raw
1// PWA install prompt service 2class PWAService { 3 #deferredPrompt = null; 4 #listeners = new Set(); 5 6 constructor() { 7 window.addEventListener('beforeinstallprompt', (e) => { 8 e.preventDefault(); 9 this.#deferredPrompt = e; 10 this.#notify(); 11 }); 12 13 window.addEventListener('appinstalled', () => { 14 this.#deferredPrompt = null; 15 this.#notify(); 16 }); 17 } 18 19 get isIOS() { 20 return /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream; 21 } 22 23 get isStandalone() { 24 return window.matchMedia('(display-mode: standalone)').matches || 25 window.navigator.standalone === true; 26 } 27 28 get canInstall() { 29 return this.#deferredPrompt !== null; 30 } 31 32 get showIOSInstructions() { 33 return this.isIOS && !this.isStandalone; 34 } 35 36 async install() { 37 if (!this.#deferredPrompt) return false; 38 39 this.#deferredPrompt.prompt(); 40 const { outcome } = await this.#deferredPrompt.userChoice; 41 42 if (outcome === 'accepted') { 43 this.#deferredPrompt = null; 44 this.#notify(); 45 } 46 47 return outcome === 'accepted'; 48 } 49 50 subscribe(callback) { 51 this.#listeners.add(callback); 52 return () => this.#listeners.delete(callback); 53 } 54 55 #notify() { 56 this.#listeners.forEach(cb => cb(this.canInstall)); 57 } 58} 59 60export const pwa = new PWAService();