Export template source from be30143a326d5d7d7b0cbabea5bc5ac0301ef5b9:examples/local-first/packages/language-reader-presentation
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { referenceOf, useCaminoQuery, type ExactReference } from "@quixos/camino-react";
|
||||
import { queries } from "./gen/client.js";
|
||||
import { asInterface, type JobNode } from "./model.js";
|
||||
import { mergeCachedAnnotationEntries } from "./work.js";
|
||||
|
||||
type Entry = { node: JobNode };
|
||||
|
||||
/** Successes outlive request history. Read every retained page instead of
|
||||
* treating the first bounded graph query as the entire semantic cache. */
|
||||
export function useCachedAnnotations(reference?: ExactReference | null) {
|
||||
const query = useCaminoQuery(queries.DocumentView, {
|
||||
enabled: !!reference,
|
||||
root: reference ? asInterface(reference, "document") : undefined,
|
||||
input: {},
|
||||
admission: { query: queries.DocumentInputs, input: {} },
|
||||
});
|
||||
const [pages, setPages] = useState<{ object: string; entries: Record<string, readonly Entry[]> }>({
|
||||
object: "",
|
||||
entries: {},
|
||||
});
|
||||
const report = useCallback(
|
||||
(cursor: string, entries: readonly Entry[] | null) => {
|
||||
const object = reference?.object ?? "";
|
||||
setPages((previous) => {
|
||||
const next = previous.object === object ? { ...previous.entries } : {};
|
||||
if (entries) next[cursor] = entries;
|
||||
else delete next[cursor];
|
||||
return { object, entries: next };
|
||||
});
|
||||
},
|
||||
[reference?.object],
|
||||
);
|
||||
const node =
|
||||
query.status === "ready" && referenceOf(query.data.root).object === reference?.object ? query.data.root : null;
|
||||
const entries = useMemo(
|
||||
() =>
|
||||
mergeCachedAnnotationEntries(
|
||||
[
|
||||
...(node?.results.entries ?? []),
|
||||
...(pages.object === reference?.object ? Object.values(pages.entries).flat() : []),
|
||||
],
|
||||
node?.jobs.entries ?? [],
|
||||
),
|
||||
[node, pages, reference?.object],
|
||||
);
|
||||
return {
|
||||
ready: !!node,
|
||||
entries,
|
||||
continuation:
|
||||
node?.results.pageInfo.hasNextPage && node.results.pageInfo.endCursor ? (
|
||||
<CachedResultsTail
|
||||
key={reference!.object}
|
||||
reference={reference!}
|
||||
cursor={node.results.pageInfo.endCursor}
|
||||
report={report}
|
||||
/>
|
||||
) : null,
|
||||
};
|
||||
}
|
||||
|
||||
function CachedResultsTail({
|
||||
reference,
|
||||
cursor,
|
||||
report,
|
||||
}: {
|
||||
reference: ExactReference;
|
||||
cursor: string;
|
||||
report(cursor: string, entries: readonly Entry[] | null): void;
|
||||
}) {
|
||||
const query = useCaminoQuery(queries.CachedResultsView, {
|
||||
root: asInterface(reference, "document"),
|
||||
input: { after: cursor },
|
||||
admission: { query: queries.CachedResultsInputs, input: { after: cursor } },
|
||||
});
|
||||
const results = query.status === "ready" ? query.data.root.results : null;
|
||||
useEffect(() => {
|
||||
if (results) report(cursor, results.entries);
|
||||
return () => report(cursor, null);
|
||||
}, [results, cursor, report]);
|
||||
return results?.pageInfo.hasNextPage && results.pageInfo.endCursor ? (
|
||||
<CachedResultsTail reference={reference} cursor={results.pageInfo.endCursor} report={report} />
|
||||
) : null;
|
||||
}
|
||||
Reference in New Issue
Block a user