import { useEffect, useState } from 'react'; interface BeforeInstallPromptEvent extends Event { prompt: () => Promise; userChoice: Promise<{ outcome: 'accepted' | 'dismissed' }>; } declare global { interface Navigator { standalone?: boolean } interface WindowEventMap { beforeinstallprompt: BeforeInstallPromptEvent; } } const LAST_SHOWN_KEY = 'pwaInstallPrompt_lastShown'; const ANDROID_DISMISSED_KEY = 'pwaInstallPrompt_androidDismissed'; function isIOS(): boolean { if (typeof navigator === 'undefined') return false; const ua = navigator.userAgent || ''; const iOS = /iPhone|iPad|iPod/i.test(ua); const iPadOS13Plus = /Macintosh/.test(ua) && 'ontouchend' in document; return iOS || iPadOS13Plus; } function isSafari(): boolean { const ua = navigator.userAgent || ''; const isSafari = /Safari/i.test(ua) && !/CriOS|FxiOS|EdgiOS/i.test(ua); return isSafari; } function isStandalone(): boolean { const navStandalone = (navigator as any)?.standalone === true; const mm = typeof window !== 'undefined' && window.matchMedia ? window.matchMedia('(display-mode: standalone)').matches : false; return Boolean(navStandalone || mm); } export function PWAInstallPrompt({ hidden = false }: { hidden?: boolean }) { if (hidden) return null; const [show, setShow] = useState(false); const [promptType, setPromptType] = useState<'ios' | 'android' | null>(null); const [deferredPrompt, setDeferredPrompt] = useState(null); const [initialized, setInitialized] = useState(false); useEffect(() => { // Only run on client if (typeof window === 'undefined') return; // Check if already in standalone mode if (isStandalone()) { setInitialized(true); return; } // Handle iOS const isIOSDevice = isIOS() && isSafari(); if (isIOSDevice) { let lastShown = 0; try { lastShown = Number(localStorage.getItem(LAST_SHOWN_KEY) || 0); } catch {} const oneWeek = 7 * 24 * 60 * 60 * 1000; const shouldShow = !lastShown || Date.now() - lastShown > oneWeek; if (shouldShow) { setPromptType('ios'); setShow(true); } setInitialized(true); return; } // Handle Android (beforeinstallprompt) const handleBeforeInstall = (e: BeforeInstallPromptEvent) => { e.preventDefault(); // Check if user has dismissed Android prompt before let dismissed = false; try { dismissed = localStorage.getItem(ANDROID_DISMISSED_KEY) === 'true'; } catch {} if (!dismissed) { setDeferredPrompt(e); setPromptType('android'); setShow(true); } }; window.addEventListener('beforeinstallprompt', handleBeforeInstall); setInitialized(true); return () => { window.removeEventListener('beforeinstallprompt', handleBeforeInstall); }; }, []); const dismiss = () => { if (promptType === 'ios') { try { localStorage.setItem(LAST_SHOWN_KEY, String(Date.now())); } catch {} } else if (promptType === 'android') { try { localStorage.setItem(ANDROID_DISMISSED_KEY, 'true'); } catch {} } setShow(false); }; const handleAndroidInstall = async () => { if (!deferredPrompt) return; try { await deferredPrompt.prompt(); const choiceResult = await deferredPrompt.userChoice; if (choiceResult.outcome === 'accepted') { console.log('PWA installation accepted'); } setDeferredPrompt(null); setShow(false); } catch (error) { console.error('Error during PWA installation:', error); } }; if (!initialized || !show || !promptType) return null; return (
{promptType === 'android' ? ( // Android: Direct install button
📱

App installieren

Installiere Stargirlnails als App für schnellen Zugriff direkt vom Startbildschirm!

) : ( // iOS: Manual instructions
📱

App installieren

So installierst du Stargirlnails als App auf deinem iPhone/iPad:

  1. Öffne diese Seite in Safari (nicht Chrome oder andere Browser).
  2. Tippe auf das Teilen-Symbol (□↑) unten in der Mitte.
  3. Scrolle nach unten und wähle „Zum Home-Bildschirm".
  4. Tippe auf „Hinzufügen".

✨ Schneller Zugriff, keine App-Store-Installation nötig, automatische Updates.

)}
); } export default PWAInstallPrompt;