1import { useAtomValue } from "@effect/atom-react";
2import {
3 EMPTY_V2_ITEM_SUPPORT,
4 resolveV2ItemSupport,
5 v2ItemSupportEqual,
6 type V2ItemSupport,
7} from "@t3tools/client-runtime/state/item-support";
8import type { EnvironmentId, ThreadId, TurnItemId } from "@t3tools/contracts";
9import { scopeThreadRef } from "@t3tools/client-runtime/environment";
10import { Atom } from "effect/reactivity";
11
12import { environmentThreadDetails } from "./threads";
13
14function supportKey(input: {
15 readonly environmentId: EnvironmentId;
16 readonly threadId: ThreadId;
17 readonly itemId: TurnItemId;
18}): string {
19 return JSON.stringify(input);
20}
21
22function parseSupportKey(key: string): {
23 readonly environmentId: EnvironmentId;
24 readonly threadId: ThreadId;
25 readonly itemId: TurnItemId;
26} {
27 return JSON.parse(key) as {
28 readonly environmentId: EnvironmentId;
29 readonly threadId: ThreadId;
30 readonly itemId: TurnItemId;
31 };
32}
33
34const itemSupportAtomFamily = Atom.family((key: string) => {
35 const target = parseSupportKey(key);
36 const ref = scopeThreadRef(target.environmentId, target.threadId);
37 let previous = EMPTY_V2_ITEM_SUPPORT;
38 return Atom.make((get): V2ItemSupport => {
39 const scoped = get(environmentThreadDetails.threadAtom(ref));
40 if (scoped === null) return EMPTY_V2_ITEM_SUPPORT;
41 const next = resolveV2ItemSupport(scoped.projection, target.itemId);
42 if (v2ItemSupportEqual(previous, next)) return previous;
43 previous = next;
44 return next;
45 }).pipe(Atom.withLabel(`web-v2-item-support:${key}`));
46});
47
48export function useV2ItemSupport(input: {
49 readonly environmentId: EnvironmentId;
50 readonly sourceThreadId: ThreadId;
51 readonly sourceItemId: TurnItemId;
52}): V2ItemSupport {
53 return useAtomValue(
54 itemSupportAtomFamily(
55 supportKey({
56 environmentId: input.environmentId,
57 threadId: input.sourceThreadId,
58 itemId: input.sourceItemId,
59 }),
60 ),
61 );
62}