Julius MarmingeT3 Code Mobile [WIP] (#2013)b3e8c035 months agoHistory
176 lines · 5.8 KB · TypeScript
RawDownload
import { useAtomValue } from "@effect/atom-react";import { useCallback, useMemo, useState } from "react"; import { ApprovalRequestId, CommandId, type ProviderApprovalDecision } from "@t3tools/contracts";import { Atom } from "effect/unstable/reactivity"; import { scopedRequestKey } from "../lib/scopedEntities";import {  buildPendingUserInputAnswers,  derivePendingApprovals,  derivePendingUserInputs,  setPendingUserInputCustomAnswer,  type PendingUserInputDraftAnswer,} from "../lib/threadActivity";import { uuidv4 } from "../lib/uuid";import { appAtomRegistry } from "./atom-registry";import { getEnvironmentClient } from "./environment-session-registry";import { useSelectedThreadDetail } from "./use-thread-detail";import { useThreadSelection } from "./use-thread-selection"; const userInputDraftsByRequestKeyAtom = Atom.make<  Record<string, Record<string, PendingUserInputDraftAnswer>>>({}).pipe(Atom.keepAlive, Atom.withLabel("mobile:user-input-drafts")); function setUserInputDraftOption(requestKey: string, questionId: string, label: string): void {  const current = appAtomRegistry.get(userInputDraftsByRequestKeyAtom);  appAtomRegistry.set(userInputDraftsByRequestKeyAtom, {    ...current,    [requestKey]: {      ...current[requestKey],      [questionId]: {        selectedOptionLabel: label,      },    },  });} function setUserInputDraftCustomAnswer(  requestKey: string,  questionId: string,  customAnswer: string,): void {  const current = appAtomRegistry.get(userInputDraftsByRequestKeyAtom);  appAtomRegistry.set(userInputDraftsByRequestKeyAtom, {    ...current,    [requestKey]: {      ...current[requestKey],      [questionId]: setPendingUserInputCustomAnswer(        current[requestKey]?.[questionId],        customAnswer,      ),    },  });} export function useSelectedThreadRequests() {  const { selectedThread: selectedThreadShell } = useThreadSelection();  const selectedThread = useSelectedThreadDetail();  const userInputDraftsByRequestKey = useAtomValue(userInputDraftsByRequestKeyAtom);  const [respondingApprovalId, setRespondingApprovalId] = useState<ApprovalRequestId | null>(null);  const [respondingUserInputId, setRespondingUserInputId] = useState<ApprovalRequestId | null>(    null,  );   const activePendingApprovals = useMemo(    () => (selectedThread ? derivePendingApprovals(selectedThread.activities) : []),    [selectedThread],  );  const activePendingApproval = activePendingApprovals[0] ?? null;  const activePendingUserInputs = useMemo(    () => (selectedThread ? derivePendingUserInputs(selectedThread.activities) : []),    [selectedThread],  );  const activePendingUserInput = activePendingUserInputs[0] ?? null;  const activePendingUserInputDrafts =    activePendingUserInput && selectedThreadShell      ? (userInputDraftsByRequestKey[          scopedRequestKey(selectedThreadShell.environmentId, activePendingUserInput.requestId)        ] ?? {})      : {};  const activePendingUserInputAnswers = activePendingUserInput    ? buildPendingUserInputAnswers(activePendingUserInput.questions, activePendingUserInputDrafts)    : null;   const onSelectUserInputOption = useCallback(    (requestId: ApprovalRequestId, questionId: string, label: string) => {      if (!selectedThreadShell) {        return;      }       const requestKey = scopedRequestKey(selectedThreadShell.environmentId, requestId);      setUserInputDraftOption(requestKey, questionId, label);    },    [selectedThreadShell],  );   const onChangeUserInputCustomAnswer = useCallback(    (requestId: ApprovalRequestId, questionId: string, customAnswer: string) => {      if (!selectedThreadShell) {        return;      }       const requestKey = scopedRequestKey(selectedThreadShell.environmentId, requestId);      setUserInputDraftCustomAnswer(requestKey, questionId, customAnswer);    },    [selectedThreadShell],  );   const onRespondToApproval = useCallback(    async (requestId: ApprovalRequestId, decision: ProviderApprovalDecision) => {      if (!selectedThreadShell) {        return;      }       const client = getEnvironmentClient(selectedThreadShell.environmentId);      if (!client) {        return;      }       setRespondingApprovalId(requestId);      try {        await client.orchestration.dispatchCommand({          type: "thread.approval.respond",          commandId: CommandId.make(uuidv4()),          threadId: selectedThreadShell.id,          requestId,          decision,          createdAt: new Date().toISOString(),        });      } finally {        setRespondingApprovalId((current) => (current === requestId ? null : current));      }    },    [selectedThreadShell],  );   const onSubmitUserInput = useCallback(async () => {    if (!selectedThreadShell || !activePendingUserInput || !activePendingUserInputAnswers) {      return;    }     const client = getEnvironmentClient(selectedThreadShell.environmentId);    if (!client) {      return;    }     setRespondingUserInputId(activePendingUserInput.requestId);    try {      await client.orchestration.dispatchCommand({        type: "thread.user-input.respond",        commandId: CommandId.make(uuidv4()),        threadId: selectedThreadShell.id,        requestId: activePendingUserInput.requestId,        answers: activePendingUserInputAnswers,        createdAt: new Date().toISOString(),      });    } finally {      setRespondingUserInputId((current) =>        current === activePendingUserInput.requestId ? null : current,      );    }  }, [activePendingUserInput, activePendingUserInputAnswers, selectedThreadShell]);   return {    activePendingApproval,    activePendingUserInput,    activePendingUserInputDrafts,    activePendingUserInputAnswers,    respondingApprovalId,    respondingUserInputId,    onRespondToApproval,    onSelectUserInputOption,    onChangeUserInputCustomAnswer,    onSubmitUserInput,  };}