3e237e177a
* feat: add code-walkthrough backend (MCP tool, service, persistence, WS events) * feat: render agent code walkthroughs as line-anchored cards + editor window * test: add code-walkthrough re-emit mock-agent scenario * fix: rework code-walkthrough UX (floating card, line reveal, minimize, clickable file) * fix: improve code walkthrough editor UX * fix: backfill walkthrough launcher after websocket connect * fix: improve walkthrough requests and editor anchors * fix: clear walkthrough highlights on close * feat: add walkthrough discard and prompt customization * fix: send walkthrough requests through saved prompt * fix: support postgres built-in prompt seeding * fix: address walkthrough review feedback * fix: address walkthrough review follow-ups * fix: harden walkthrough lifecycle races * fix: reuse walkthrough notification cleanup * fix: guard stale walkthrough file opens * fix: abort stale file opens before paint * fix: stabilize github settings e2e readiness * fix: use stable github settings e2e selector
37 lines
1020 B
TypeScript
37 lines
1020 B
TypeScript
import { useCallback, useSyncExternalStore } from "react";
|
|
|
|
type Listener = () => void;
|
|
|
|
let openTaskId: string | null = null;
|
|
const listeners = new Set<Listener>();
|
|
|
|
function emit() {
|
|
for (const listener of listeners) listener();
|
|
}
|
|
|
|
export function setOpenWalkthroughTaskId(taskId: string | null): void {
|
|
if (openTaskId === taskId) return;
|
|
openTaskId = taskId;
|
|
emit();
|
|
}
|
|
|
|
export function clearOpenWalkthroughTaskId(taskId: string): void {
|
|
if (openTaskId !== taskId) return;
|
|
openTaskId = null;
|
|
emit();
|
|
}
|
|
|
|
export function getOpenWalkthroughTaskId(): string | null {
|
|
return openTaskId;
|
|
}
|
|
|
|
export function subscribeOpenWalkthroughTask(listener: Listener): () => void {
|
|
listeners.add(listener);
|
|
return () => listeners.delete(listener);
|
|
}
|
|
|
|
export function useIsWalkthroughOpenForTask(taskId: string | null | undefined): boolean {
|
|
const getSnapshot = useCallback(() => !!taskId && openTaskId === taskId, [taskId]);
|
|
return useSyncExternalStore(subscribeOpenWalkthroughTask, getSnapshot, getSnapshot);
|
|
}
|