- Remove refreshActiveSnapshot from unarchiveThread: the EventRouter's recovery coordinator already handles thread.unarchived events via fallbackToSnapshotRecovery, which properly updates latestSequence. Calling syncServerReadModel directly left the coordinator stale, causing already-applied events to be re-processed and potentially corrupting streaming message content via double concatenation. - Fix archived threads loading state: placeholderData always returned EMPTY_ARCHIVED_THREADS on first load, making isPending permanently false and the loading UI unreachable. Now only uses previous query data as placeholder, allowing isPending to be true on first fetch.
Unified · Split
| @@ -18,7 +18,6 @@ import { useSettings } from "./useSettings"; · 17 unmodified lines | ||
| 18 | 18 | |
| 19 | 19 | export function useThreadActions() { |
| 20 | 20 | const appSettings = useSettings(); |
| 21 | − const syncServerReadModel = useStore((store) => store.syncServerReadModel); | |
| 22 | 21 | const clearComposerDraftForThread = useComposerDraftStore((store) => store.clearDraftThread); |
| 23 | 22 | const clearProjectDraftThreadById = useComposerDraftStore( |
| 24 | 23 | (store) => store.clearProjectDraftThreadById, |
| @@ -33,13 +32,6 @@ export function useThreadActions() { · 8 unmodified lines | ||
| 33 | 32 | const queryClient = useQueryClient(); |
| 34 | 33 | const removeWorktreeMutation = useMutation(gitRemoveWorktreeMutationOptions({ queryClient })); |
| 35 | 34 | |
| 36 | − const refreshActiveSnapshot = useCallback(async () => { | |
| 37 | − const api = readNativeApi(); | |
| 38 | − if (!api) return; | |
| 39 | − const snapshot = await api.orchestration.getActiveSnapshot(); | |
| 40 | − syncServerReadModel(snapshot); | |
| 41 | − }, [syncServerReadModel]); | |
| 42 | − | |
| 43 | 35 | const archiveThread = useCallback( |
| 44 | 36 | async (threadId: ThreadId) => { |
| 45 | 37 | const api = readNativeApi(); |
| @@ -73,10 +65,9 @@ export function useThreadActions() { · 27 unmodified lines | ||
| 73 | 65 | commandId: newCommandId(), |
| 74 | 66 | threadId, |
| 75 | 67 | }); |
| 76 | − await refreshActiveSnapshot(); | |
| 77 | 68 | void queryClient.invalidateQueries({ queryKey: orchestrationQueryKeys.archivedThreads() }); |
| 78 | 69 | }, |
| 79 | − [queryClient, refreshActiveSnapshot], | |
| 70 | + [queryClient], | |
| 80 | 71 | ); |
| 81 | 72 | |
| 82 | 73 | const deleteThread = useCallback( |
| @@ -1,4 +1,3 @@ | ||
| 1 | −import type { OrchestrationListArchivedThreadsResult } from "@t3tools/contracts"; | |
| 2 | 1 | import { queryOptions } from "@tanstack/react-query"; |
| 3 | 2 | import { ensureNativeApi } from "~/nativeApi"; |
| 4 | 3 | |
| @@ -8,7 +7,6 @@ export const orchestrationQueryKeys = { · 3 unmodified lines | ||
| 8 | 7 | }; |
| 9 | 8 | |
| 10 | 9 | const DEFAULT_ARCHIVED_THREADS_STALE_TIME = 15_000; |
| 11 | −const EMPTY_ARCHIVED_THREADS: OrchestrationListArchivedThreadsResult = []; | |
| 12 | 10 | |
| 13 | 11 | export function archivedThreadsQueryOptions() { |
| 14 | 12 | return queryOptions({ |
| @@ -18,6 +16,6 @@ export function archivedThreadsQueryOptions() { · 3 unmodified lines | ||
| 18 | 16 | return api.orchestration.listArchivedThreads(); |
| 19 | 17 | }, |
| 20 | 18 | staleTime: DEFAULT_ARCHIVED_THREADS_STALE_TIME, |
| 21 | − placeholderData: (previous) => previous ?? EMPTY_ARCHIVED_THREADS, | |
| 19 | + placeholderData: (previous) => previous, | |
| 22 | 20 | }); |
| 23 | 21 | } |