nomadweb/frontend/src/components/PwaInstallHint.tsx
eric dac99e8ef4 Polish map empty states, login hints, PWA install, live mobile.
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-30 21:11:28 -05:00

56 lines
1.6 KiB
TypeScript

"use client";
import { useEffect, useState } from "react";
import { useI18n } from "@/lib/i18n";
/** Soft install hint — shows once when browser fires beforeinstallprompt. */
export default function PwaInstallHint() {
const { t } = useI18n();
const [deferred, setDeferred] = useState<{ prompt: () => Promise<void> } | null>(null);
const [hidden, setHidden] = useState(true);
useEffect(() => {
if (window.matchMedia("(display-mode: standalone)").matches) return;
if (localStorage.getItem("nomadro-pwa-hint") === "1") return;
const onBip = (e: Event) => {
e.preventDefault();
const ev = e as Event & { prompt: () => Promise<void> };
setDeferred({ prompt: () => ev.prompt() });
setHidden(false);
};
window.addEventListener("beforeinstallprompt", onBip);
return () => window.removeEventListener("beforeinstallprompt", onBip);
}, []);
if (hidden || !deferred) return null;
const dismiss = () => {
localStorage.setItem("nomadro-pwa-hint", "1");
setHidden(true);
};
const install = async () => {
try {
await deferred.prompt();
} catch {
/* ignore */
}
dismiss();
};
return (
<div className="pwa-install-hint" role="status">
<p>{t.pwa.installHint}</p>
<div className="pwa-install-actions">
<button type="button" className="btn btn-primary btn-sm" onClick={() => void install()}>
安装
</button>
<button type="button" className="btn btn-ghost btn-sm" onClick={dismiss}>
稍后再说
</button>
</div>
</div>
);
}