49 lines
1.6 KiB
TypeScript
49 lines
1.6 KiB
TypeScript
|
|
// Deler ett globalt "beforeinstallprompt"-event mellom root layout (som
|
||
|
|
// fanger det så tidlig som mulig via SwRegister, ADR-028) og
|
||
|
|
// InstallPrompt-komponenten på dashbordet (som faktisk viser UI-et).
|
||
|
|
// Nettleseren fyrer eventet KUN én gang per side-liv og kun hvis ingen har
|
||
|
|
// kalt preventDefault() før -- må derfor fanges globalt, ikke lokalt i en
|
||
|
|
// komponent som kan mountes for sent.
|
||
|
|
|
||
|
|
export type BeforeInstallPromptEvent = Event & {
|
||
|
|
prompt: () => Promise<void>
|
||
|
|
userChoice: Promise<{ outcome: "accepted" | "dismissed"; platform: string }>
|
||
|
|
}
|
||
|
|
|
||
|
|
type Listener = (event: BeforeInstallPromptEvent | null) => void
|
||
|
|
|
||
|
|
let deferredEvent: BeforeInstallPromptEvent | null = null
|
||
|
|
const listeners = new Set<Listener>()
|
||
|
|
|
||
|
|
export function initInstallPromptCapture() {
|
||
|
|
if (typeof window === "undefined") return
|
||
|
|
const w = window as typeof window & { __teecupInstallCaptureInitialized?: boolean }
|
||
|
|
if (w.__teecupInstallCaptureInitialized) return
|
||
|
|
w.__teecupInstallCaptureInitialized = true
|
||
|
|
|
||
|
|
window.addEventListener("beforeinstallprompt", (event) => {
|
||
|
|
event.preventDefault()
|
||
|
|
deferredEvent = event as BeforeInstallPromptEvent
|
||
|
|
listeners.forEach((l) => l(deferredEvent))
|
||
|
|
})
|
||
|
|
window.addEventListener("appinstalled", () => {
|
||
|
|
deferredEvent = null
|
||
|
|
listeners.forEach((l) => l(null))
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
export function getDeferredInstallPrompt() {
|
||
|
|
return deferredEvent
|
||
|
|
}
|
||
|
|
|
||
|
|
export function clearDeferredInstallPrompt() {
|
||
|
|
deferredEvent = null
|
||
|
|
}
|
||
|
|
|
||
|
|
export function subscribeInstallPrompt(listener: Listener) {
|
||
|
|
listeners.add(listener)
|
||
|
|
return () => {
|
||
|
|
listeners.delete(listener)
|
||
|
|
}
|
||
|
|
}
|