import { EventType } from "@umt/contracts"; import { useEffect, useRef, useState } from "react"; import { type FilesIdentifyResult, type IdentifyCompletedPayload, useIdentify } from "~/api/files.ts"; import { useSse } from "~/lib/sse.ts"; import { applyIdentifyCompleted } from "./model.ts"; /** * useIdentify + 远端结果回填(S-7):响应带 remoteTaskId 时,用 SSE identify.completed 里同一 taskId 的完整结果 * 按 root + path 替换条目。事件可能比 HTTP 响应先到,所以挂载期间一直订阅,并缓存最近几条。 * data 是回填后的结果;remotePending 表示还在等远端。 */ export function useIdentifyLive() { const m = useIdentify(); const [data, setData] = useState(undefined); const early = useRef(new Map()); useEffect(() => { const d = m.data; const hit = d?.remoteTaskId ? early.current.get(d.remoteTaskId) : undefined; setData(d && hit ? applyIdentifyCompleted(d, hit) : d); }, [m.data]); useSse([EventType.identifyCompleted], (ev) => { if (ev.type !== EventType.identifyCompleted) return; const p = ev.payload as IdentifyCompletedPayload; early.current.set(p.taskId, p); if (early.current.size > 20) early.current.delete(early.current.keys().next().value as string); setData((d) => (d ? applyIdentifyCompleted(d, p) : d)); }); return { ...m, data, remotePending: !!data?.remoteTaskId }; }