From f2963ca951439185f82ea9b0c9dd5f9073c63b60 Mon Sep 17 00:00:00 2001 From: elpatron Date: Tue, 7 Oct 2025 13:57:28 +0200 Subject: [PATCH] =?UTF-8?q?Android=20PWA-Installationshinweis=20mit=20dire?= =?UTF-8?q?ktem=20Install-Button=20hinzugef=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/client/components/pwa-install-prompt.tsx | 144 +++++++++++++++---- 1 file changed, 119 insertions(+), 25 deletions(-) diff --git a/src/client/components/pwa-install-prompt.tsx b/src/client/components/pwa-install-prompt.tsx index 463df61..46fb8d0 100644 --- a/src/client/components/pwa-install-prompt.tsx +++ b/src/client/components/pwa-install-prompt.tsx @@ -1,10 +1,19 @@ 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; @@ -31,59 +40,144 @@ function isStandalone(): boolean { 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; - const eligible = isIOS() && isSafari() && !isStandalone(); - if (!eligible) { + // Check if already in standalone mode + if (isStandalone()) { setInitialized(true); return; } - 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; + // 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; - setShow(shouldShow); + 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 = () => { - try { localStorage.setItem(LAST_SHOWN_KEY, String(Date.now())); } catch {} + 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); }; - if (!initialized || !show) return null; + 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 (
-
-
📱
-
-

App installieren

-

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

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

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

+ + {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. +
  3. Tippe auf das Teilen-Symbol (□↑) unten in der Mitte.
  4. +
  5. Scrolle nach unten und wähle „Zum Home-Bildschirm".
  6. +
  7. Tippe auf „Hinzufügen".
  8. +
+

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

+
+
+ )}
);