2026-06-04 15:52:06 -07:00
|
|
|
import { StartClient } from "@tanstack/react-start/client"
|
2026-07-01 21:53:28 -04:00
|
|
|
import { StrictMode, useEffect, useState } from "react"
|
2026-06-04 15:52:06 -07:00
|
|
|
import { hydrateRoot } from "react-dom/client"
|
|
|
|
|
import { registerSW } from "virtual:pwa-register"
|
|
|
|
|
|
2026-07-01 21:53:28 -04:00
|
|
|
import { PwaUpdateToast } from "@/components/PwaUpdateToast"
|
|
|
|
|
|
|
|
|
|
// Prompt-mode PWA: vite-plugin-pwa still generates a SW that precaches the
|
|
|
|
|
// production bundle, but it does not force skipWaiting/clientsClaim. Instead,
|
|
|
|
|
// the new SW waits until the user accepts the update, so open dashboard tabs
|
|
|
|
|
// are not reloaded mid-session. This protects in-flight agent runs and any
|
|
|
|
|
// unsaved text in the compose box. Skip in dev — the SW precaches production-only
|
|
|
|
|
// build artifacts that 404 against the dev server.
|
|
|
|
|
function PwaUpdateProvider() {
|
|
|
|
|
const [needRefresh, setNeedRefresh] = useState(false)
|
|
|
|
|
const [updateSW, setUpdateSW] = useState<(() => Promise<void>) | undefined>(undefined)
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (!import.meta.env.PROD) return
|
|
|
|
|
const updateSWRef = registerSW({
|
|
|
|
|
onNeedRefresh() {
|
|
|
|
|
setNeedRefresh(true)
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
setUpdateSW(() => updateSWRef)
|
|
|
|
|
}, [])
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<PwaUpdateToast
|
|
|
|
|
needRefresh={needRefresh}
|
|
|
|
|
updateServiceWorker={updateSW}
|
|
|
|
|
/>
|
|
|
|
|
)
|
2026-06-04 16:47:35 -07:00
|
|
|
}
|
2026-06-04 15:52:06 -07:00
|
|
|
|
|
|
|
|
hydrateRoot(
|
|
|
|
|
document,
|
|
|
|
|
<StrictMode>
|
|
|
|
|
<StartClient />
|
2026-07-01 21:53:28 -04:00
|
|
|
<PwaUpdateProvider />
|
2026-06-04 15:52:06 -07:00
|
|
|
</StrictMode>
|
|
|
|
|
)
|