"use client"; import { useEffect, useState } from "react"; // Extend the BeforeInstallPromptEvent type (not in standard lib) interface BeforeInstallPromptEvent extends Event { prompt(): Promise; readonly userChoice: Promise<{ outcome: "accepted" | "dismissed" }>; } function IOSInstallInstructions({ onDismiss }: { onDismiss: () => void }) { return (
🌸 Install Tia

Add Tia to your home screen for the best experience.

Tap ⬆️ then "Add to Home Screen"
); } const DISMISSED_KEY = "tia_install_prompt_dismissed"; export function InstallPrompt() { const [deferred, setDeferred] = useState(null); const [isIOS, setIsIOS] = useState(false); const [dismissed, setDismissed] = useState(true); // start hidden to avoid flash useEffect(() => { if (typeof window === "undefined") return; const alreadyDismissed = localStorage.getItem(DISMISSED_KEY) === "1"; if (alreadyDismissed) return; const standalone = window.matchMedia("(display-mode: standalone)").matches; if (standalone) return; // already installed // iOS Safari: no beforeinstallprompt, needs manual instructions const ios = /iphone|ipad|ipod/i.test(navigator.userAgent); const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent); if (ios && isSafari) { setIsIOS(true); setDismissed(false); } // Android / Chrome: capture the deferred install event const handler = (e: Event) => { e.preventDefault(); setDeferred(e as BeforeInstallPromptEvent); setDismissed(false); }; window.addEventListener("beforeinstallprompt", handler); return () => window.removeEventListener("beforeinstallprompt", handler); }, []); const handleDismiss = () => { setDismissed(true); localStorage.setItem(DISMISSED_KEY, "1"); }; const handleInstall = async () => { if (!deferred) return; await deferred.prompt(); const { outcome } = await deferred.userChoice; if (outcome === "accepted") { setDeferred(null); setDismissed(true); } }; if (dismissed) return null; if (deferred) { return (
🌸

Install Tia

Add to home screen for quick access

); } if (isIOS) { return ; } return null; }