import type { PullRequestFileViewedState, PullRequestFilesViewedResult } from "@t3tools/contracts"; export type FileViewedStates = ReadonlyMap; export type FileViewedOverlay = ReadonlyMap; export function toFileViewedStates( result: PullRequestFilesViewedResult | null, ): FileViewedStates | null { if (result === null) return null; return new Map(result.files.map((file) => [file.path, file.state])); } function isViewedState(state: PullRequestFileViewedState | undefined): boolean { return state === "viewed"; } export function isStaleViewedState(state: PullRequestFileViewedState | undefined): boolean { return state === "dismissed"; } export function isFileViewed( path: string, states: FileViewedStates | null, overlay: FileViewedOverlay, ): boolean { const pressed = overlay.get(path); return pressed ?? isViewedState(states?.get(path)); } /** Retain presses until a read could have observed the write. */ export function settleFileViewedOverlay( overlay: FileViewedOverlay, states: FileViewedStates | null, pending: ReadonlySet, answered: ReadonlySet, ): FileViewedOverlay { if (states === null || overlay.size === 0) return overlay; const next = new Map(overlay); for (const [path, pressed] of overlay) { if (pending.has(path)) continue; if (answered.has(path) || isViewedState(states.get(path)) === pressed) next.delete(path); } return next.size === overlay.size ? overlay : next; } /** Revert only owned paths; later presses belong to other requests. */ export function revertFileViewedOverlay( overlay: FileViewedOverlay, batch: ReadonlyArray<{ readonly path: string; readonly viewed: boolean }>, owned: ReadonlySet, ): FileViewedOverlay { const next = new Map(overlay); for (const { path, viewed } of batch) { if (!owned.has(path)) continue; if (next.get(path) === viewed) next.delete(path); } return next.size === overlay.size ? overlay : next; } export function toFileViewedBatch( overlay: FileViewedOverlay, ): ReadonlyArray<{ readonly path: string; readonly viewed: boolean }> { return [...overlay].map(([path, viewed]) => ({ path, viewed })); }