"use client"; import { useSyncExternalStore } from "react"; import { STUDENT_ACTIVITY_EVENT } from "@/lib/student-activity"; // ============================================================================= // Live activity subscription. student-activity.ts already dispatches // STUDENT_ACTIVITY_EVENT on every write (and localStorage fires `storage` in // other tabs); this turns those signals into a React subscription so any // surface — Home's "pick up where you left off", Progress, Notes, Quizzes — // re-reads the moment the student does something, in this tab or another, // without a full reload. Without it the ledger felt static: act on one page, // come back to another, see stale numbers. // ============================================================================= let version = 0; const listeners = new Set<() => void>(); function bump(): void { version += 1; for (const listener of listeners) listener(); } let wired = false; function ensureWired(): void { if (wired || typeof window === "undefined") return; wired = true; window.addEventListener(STUDENT_ACTIVITY_EVENT, bump); window.addEventListener("storage", (event) => { // Cross-tab: another tab wrote a docdoe:* key. if (!event.key || event.key.startsWith("docdoe:")) bump(); }); } function subscribe(onChange: () => void): () => void { ensureWired(); listeners.add(onChange); return () => { listeners.delete(onChange); }; } /** * Returns a version token that increments whenever saved activity, notes, or * quizzes change. Use it as an effect dependency to re-read the ledger, e.g. * `useEffect(() => setEvents(listActivities()), [version])`. */ export function useStudentActivityVersion(): number { return useSyncExternalStore( subscribe, () => version, () => 0, ); }