diff --git a/apps/web/src/routes/threads/controller.tsx b/apps/web/src/routes/threads/controller.tsx index 20594057..2dab7006 100644 --- a/apps/web/src/routes/threads/controller.tsx +++ b/apps/web/src/routes/threads/controller.tsx @@ -77,10 +77,10 @@ function ThreadsWorkspace({ const actions = useThreadActions({ activeAppId, activeThreadId: route.activeThreadId, - allThreads: threads.allThreads, closeComposeDialog: route.closeComposeDialog, markThreadReadLocal: ui.markThreadRead, navigateToList: route.backToList, + threadsById: threads.threadsById, togglePinnedThreadLocal: ui.togglePinnedThread, }); const handleReadSyncError = useCallback( diff --git a/apps/web/src/routes/threads/model/use-actions.ts b/apps/web/src/routes/threads/model/use-actions.ts index 568e8722..0effcfc7 100644 --- a/apps/web/src/routes/threads/model/use-actions.ts +++ b/apps/web/src/routes/threads/model/use-actions.ts @@ -20,18 +20,18 @@ import type { ThreadListItem } from "./thread"; export function useThreadActions({ activeAppId, activeThreadId, - allThreads, closeComposeDialog, markThreadReadLocal, navigateToList, + threadsById, togglePinnedThreadLocal, }: { activeAppId: string | null; activeThreadId: string | null; - allThreads: readonly ThreadListItem[]; closeComposeDialog: () => void; markThreadReadLocal: (input: { readAt: string; threadId: string }) => void; navigateToList: () => void; + threadsById: ReadonlyMap; togglePinnedThreadLocal: (threadId: string) => void; }) { const queryClient = useQueryClient(); @@ -156,7 +156,7 @@ export function useThreadActions({ const togglePinnedThread = useCallback( async (threadId: string): Promise => { - const thread = allThreads.find((candidate) => candidate.id === threadId) ?? null; + const thread = threadsById.get(threadId) ?? null; if (thread === null) { return; @@ -169,12 +169,12 @@ export function useThreadActions({ setActionError(getMutationErrorMessage(error, "Failed to update pinned state.")); } }, - [allThreads, togglePinnedThreadLocal], + [threadsById, togglePinnedThreadLocal], ); const archiveThread = useCallback( async (threadId: string): Promise => { - const thread = allThreads.find((candidate) => candidate.id === threadId) ?? null; + const thread = threadsById.get(threadId) ?? null; try { if (thread === null) { @@ -190,7 +190,7 @@ export function useThreadActions({ setActionError(getMutationErrorMessage(error, "Failed to archive thread.")); } }, - [allThreads, archiveMutation], + [threadsById, archiveMutation], ); const deleteThread = useCallback( @@ -201,7 +201,7 @@ export function useThreadActions({ } try { - const thread = allThreads.find((candidate) => candidate.id === threadId) ?? null; + const thread = threadsById.get(threadId) ?? null; if (thread === null) { throw new Error("Thread not found."); @@ -220,7 +220,7 @@ export function useThreadActions({ setActionError(getMutationErrorMessage(error, "Failed to delete thread.")); } }, - [activeThreadId, allThreads, deleteMutation, navigateToList], + [activeThreadId, threadsById, deleteMutation, navigateToList], ); const sendFollowUp = useCallback( diff --git a/apps/web/src/routes/threads/model/use-queries.ts b/apps/web/src/routes/threads/model/use-queries.ts index f15b626d..016cf555 100644 --- a/apps/web/src/routes/threads/model/use-queries.ts +++ b/apps/web/src/routes/threads/model/use-queries.ts @@ -78,7 +78,11 @@ export function useThreadQueries({ ) .toSorted(compareThreads); }, [activeSessionsQuery.data, agentsById, archivedSessionsQuery.data, ui]); - const selectedThread = allThreads.find((thread) => thread.id === activeThreadId) ?? null; + const threadsById = useMemo( + () => new Map(allThreads.map((thread) => [thread.id, thread])), + [allThreads], + ); + const selectedThread = activeThreadId === null ? null : (threadsById.get(activeThreadId) ?? null); const messagesQuery = useQuery({ enabled: selectedThread !== null, queryFn: async () => { @@ -182,5 +186,6 @@ export function useThreadQueries({ retrieveQuery, selectedThread, threadsBySection, + threadsById, }; }