import { useEffect, useMemo, useRef } from 'react'; import { viewerEpoch } from '../utils/writeThroughHold'; /** * Who a reread is for and which notice it answers. A reread may publish only while the same opening (the viewer or * the open item, as `key` names it) and the signed-in viewer stand, and no later event about the same resource has * arrived since: a newer notice, a removal, or a whole resource. Anything else is retired, success and refusal alike. */ export const useNoticeFence = (key: unknown) => { const opening = useRef(0); const generations = useRef(new Map()); // A change of viewer or item, a close and an unmount all end the opening. useEffect(() => () => { opening.current += 1; }, [key]); return useMemo(() => ({ /** Marks a new event about `id`; the returned check says whether that event still stands. */ claim(id: string): () => boolean { const at = opening.current; // Read at the answer too: a viewer change counts even before React has drawn it. const viewer = viewerEpoch(); const mine = (generations.current.get(id) ?? 0) + 1; generations.current.set(id, mine); return () => opening.current === at && viewerEpoch() === viewer && generations.current.get(id) === mine; }, }), []); };