Added TTL to desync flag

This commit is contained in:
Nik Afiq 2025-11-11 23:43:39 +09:00
parent 2023e12658
commit baa1894926
2 changed files with 43 additions and 5 deletions

View File

@ -5,7 +5,7 @@ import ShowsPage from "./pages/ShowsPage";
import TimeSyncNotice from "./components/TimeSyncNotice"; import TimeSyncNotice from "./components/TimeSyncNotice";
import "./index.css"; import "./index.css";
const TIME_SYNC_OFF_THRESHOLD = 500; const TIME_SYNC_OFF_THRESHOLD = 200;
export default function App() { export default function App() {
const [open, setOpen] = React.useState(false); const [open, setOpen] = React.useState(false);

View File

@ -16,22 +16,57 @@ export default function TimeSyncNotice({
thresholdMs = 500, thresholdMs = 500,
intervalMs, intervalMs,
lang = "ja", lang = "ja",
dismissTtlMs = 5 * 60_000, // ✅ reappear after 5 minutes by default
storageScope = "session", // "session" | "local"
}: { }: {
thresholdMs?: number; thresholdMs?: number;
intervalMs?: number; intervalMs?: number;
lang?: "ja" | "en"; lang?: "ja" | "en";
dismissTtlMs?: number;
storageScope?: "session" | "local";
}) { }) {
// removed `error`
const { skewMs, rttMs, recheck } = useTimeSkew({ intervalMs }); const { skewMs, rttMs, recheck } = useTimeSkew({ intervalMs });
const KEY = "timesync.dismissedUntil";
const store = storageScope === "local" ? window.localStorage : window.sessionStorage;
// read dismissed state (true if now < dismissedUntil)
const [dismissed, setDismissed] = useState<boolean>(() => { const [dismissed, setDismissed] = useState<boolean>(() => {
try { return sessionStorage.getItem("timesync.dismissed") === "1"; } catch { return false; } try {
const raw = store.getItem(KEY);
const until = raw ? Number(raw) : 0;
return Number.isFinite(until) && Date.now() < until;
} catch {
return false;
}
}); });
// auto-unset when TTL passes (while component stays mounted)
useEffect(() => {
if (!dismissed) return;
let id: number | null = null;
try {
const raw = store.getItem(KEY);
const until = raw ? Number(raw) : 0;
const delay = Math.max(0, until - Date.now());
if (delay > 0) {
id = window.setTimeout(() => setDismissed(false), delay);
} else {
setDismissed(false);
store.removeItem(KEY);
}
} catch {
/* ignore */
}
return () => { if (id) clearTimeout(id); };
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [dismissed]);
// if skew returns within threshold, clear dismissal so it can show again later if it drifts
useEffect(() => { useEffect(() => {
if (skewMs != null && Math.abs(skewMs) <= thresholdMs && dismissed) { if (skewMs != null && Math.abs(skewMs) <= thresholdMs && dismissed) {
setDismissed(false); setDismissed(false);
try { sessionStorage.removeItem("timesync.dismissed"); } catch { } try { store.removeItem(KEY); } catch { }
} }
}, [skewMs, thresholdMs, dismissed]); }, [skewMs, thresholdMs, dismissed]);
@ -47,7 +82,10 @@ export default function TimeSyncNotice({
const onClose = () => { const onClose = () => {
setDismissed(true); setDismissed(true);
try { sessionStorage.setItem("timesync.dismissed", "1"); } catch { } try {
const until = Date.now() + dismissTtlMs;
store.setItem(KEY, String(until));
} catch { }
}; };
return ( return (