import { useEffect, useRef, useState } from 'react' import { api } from '../api/client' // How often to ask the server whether a newer frontend has shipped. Gentle — // a deploy is rare, and the check is a tiny no-store GET. const POLL_MS = 90_000 // useVersionWatch records the build id the app loaded with, then quietly polls // /api/version. When the server reports a different id, a new version has been // deployed and `updateAvailable` flips true (and stays true) so the UI can // offer a refresh. Network blips are ignored — it only ever reacts to a real, // confirmed change. Returns false until the baseline is established. export function useVersionWatch(): boolean { const [updateAvailable, setUpdateAvailable] = useState(false) // The version we're currently running. Null until the first successful fetch. const baseline = useRef(null) useEffect(() => { let active = true const check = async () => { try { const { version } = await api.version() if (!active || !version) return if (baseline.current === null) { baseline.current = version // first read: this is "us" } else if (version !== baseline.current) { setUpdateAvailable(true) } } catch { /* offline / server bounce — try again next tick, never alarm the user */ } } check() const id = setInterval(check, POLL_MS) // Re-check the moment she returns to the tab, so a deploy that happened while // she was away surfaces right away instead of up to POLL_MS later. const onVisible = () => { if (document.visibilityState === 'visible') check() } document.addEventListener('visibilitychange', onVisible) return () => { active = false clearInterval(id) document.removeEventListener('visibilitychange', onVisible) } }, []) return updateAvailable }