diff --git a/src/app/providers.tsx b/src/app/providers.tsx index 975b8c4..fab14ea 100644 --- a/src/app/providers.tsx +++ b/src/app/providers.tsx @@ -5,6 +5,7 @@ import { I18nProvider } from '@/core/i18n'; import { StorageProvider } from '@/core/storage'; import { FeatureFlagProvider } from '@/core/feature-flags'; import { AuthProvider } from '@/core/auth'; +import { VersionWatcher } from '@/core/version/version-watcher'; import { DEFAULT_FLAGS } from '@/config/flags'; // Ensure module registry is populated @@ -22,6 +23,7 @@ export function Providers({ children }: ProvidersProps) { {children} + diff --git a/src/core/version/version-watcher.tsx b/src/core/version/version-watcher.tsx new file mode 100644 index 0000000..964dbd2 --- /dev/null +++ b/src/core/version/version-watcher.tsx @@ -0,0 +1,76 @@ +"use client"; + +import { useEffect, useRef, useState } from "react"; +import { RefreshCw, X } from "lucide-react"; + +const POLL_INTERVAL_MS = 60_000; +const ENDPOINT = "/api/version"; + +type VersionPayload = { commit: string; commitShort: string; buildTime: string }; + +export function VersionWatcher() { + const initialRef = useRef(null); + const [latest, setLatest] = useState(null); + const [dismissed, setDismissed] = useState(false); + + useEffect(() => { + let cancelled = false; + + const fetchVersion = async () => { + try { + const res = await fetch(ENDPOINT, { cache: "no-store" }); + if (!res.ok || cancelled) return; + const data = (await res.json()) as VersionPayload; + if (!data?.commit) return; + if (initialRef.current === null) { + initialRef.current = data.commit; + return; + } + if (data.commit !== initialRef.current) { + setLatest(data); + } + } catch { + // network noise — ignore + } + }; + + fetchVersion(); + const interval = setInterval(fetchVersion, POLL_INTERVAL_MS); + return () => { + cancelled = true; + clearInterval(interval); + }; + }, []); + + if (!latest || dismissed) return null; + + return ( +
+ +
+ Versiune nouă disponibilă + + {latest.commitShort} · apasă pentru reîncărcare + +
+ + +
+ ); +}