File
Blob: src/client/lib/install-gate.ts
| 1 | import { selectHasLocalSession, useAuthStore } from "@/client/stores/auth-store"; |
| 2 | |
| 3 | const MANIFEST_HREF = "/manifest.webmanifest"; |
| 4 | |
| 5 | function findManifestLink(): HTMLLinkElement | null { |
| 6 | return document.head.querySelector<HTMLLinkElement>('link[rel="manifest"]'); |
| 7 | } |
| 8 | |
| 9 | function mountManifestLink(): void { |
| 10 | if (findManifestLink()) return; |
| 11 | const link = document.createElement("link"); |
| 12 | link.rel = "manifest"; |
| 13 | link.href = MANIFEST_HREF; |
| 14 | document.head.appendChild(link); |
| 15 | } |
| 16 | |
| 17 | function removeManifestLink(): void { |
| 18 | const existing = findManifestLink(); |
| 19 | if (existing) existing.remove(); |
| 20 | } |
| 21 | |
| 22 | function apply(hasLocal: boolean): void { |
| 23 | if (hasLocal) mountManifestLink(); |
| 24 | else removeManifestLink(); |
| 25 | } |
| 26 | |
| 27 | /** |
| 28 | * Mount `<link rel="manifest">` only while the user has a local session |
| 29 | * (AUTHENTICATED / LOCAL_ONLY / EXPIRED). Anonymous `/` visits stay |
| 30 | * uninstallable so the browser's install heuristic never triggers before |
| 31 | * the user signs in. |
| 32 | */ |
| 33 | export function installManifestGate(): () => void { |
| 34 | if (typeof document === "undefined") return () => {}; |
| 35 | apply(selectHasLocalSession(useAuthStore.getState())); |
| 36 | return useAuthStore.subscribe((state) => { |
| 37 | apply(selectHasLocalSession(state)); |
| 38 | }); |
| 39 | } |