diff --git a/apps/app/src/components/layout/AppLayout.tsx b/apps/app/src/components/layout/AppLayout.tsx index 1375802d48..00783cf55a 100644 --- a/apps/app/src/components/layout/AppLayout.tsx +++ b/apps/app/src/components/layout/AppLayout.tsx @@ -37,7 +37,6 @@ import { AppPageHeader, HEADER_ICON_BUTTON_CLASS } from "./AppPageHeader"; import { stripProjectThreads } from "@/hooks/queries/project-queries"; import { useSidebarNavigation } from "@/hooks/queries/sidebar-navigation-query"; import { - didThreadDetailBootstrapRefreshAfterMount, getLatestPendingInteraction, useThread, useThreadDetailBootstrap, @@ -515,8 +514,6 @@ export function AppLayout({ children }: AppLayoutProps) { enabled: isThreadView && Boolean(threadId), timelinePrefetch: isThreadView && Boolean(threadId), }); - const hasThreadDetailBootstrapSettled = - threadDetailBootstrapQuery.isSuccess || threadDetailBootstrapQuery.isError; const [isSidebarResizing, setIsSidebarResizing] = useState(false); const startXRef = useRef(0); const startWidthRef = useRef(0); @@ -540,15 +537,12 @@ export function AppLayout({ children }: AppLayoutProps) { : null; const projectName = projectId ? project?.name : undefined; const projectLabel = projectName ?? (projectId ? projectId : undefined); - const { data: thread } = useThread(threadId ?? "", { - enabled: - Boolean(threadId) && (!isThreadView || hasThreadDetailBootstrapSettled), - refetchOnMount: - isThreadView && - didThreadDetailBootstrapRefreshAfterMount(threadDetailBootstrapQuery) - ? false - : "always", - }); + const { data: thread } = useThread( + threadId ?? "", + isThreadView + ? { bootstrap: threadDetailBootstrapQuery } + : { enabled: Boolean(threadId), refetchOnMount: "always" }, + ); const threadDisplayTitle = thread ? getThreadDisplayTitle(thread) : threadId diff --git a/apps/app/src/hooks/queries/thread-queries.test.tsx b/apps/app/src/hooks/queries/thread-queries.test.tsx index 7b8399ccfd..662a3f0dd2 100644 --- a/apps/app/src/hooks/queries/thread-queries.test.tsx +++ b/apps/app/src/hooks/queries/thread-queries.test.tsx @@ -1,7 +1,6 @@ // @vitest-environment jsdom import { act, cleanup, renderHook, waitFor } from "@testing-library/react"; -import { useQueryClient } from "@tanstack/react-query"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import type { PendingInteraction, ThreadListEntry } from "@bb/domain"; import type { @@ -29,7 +28,6 @@ import { COMPACT_THREAD_TIMELINE_SEGMENT_LIMIT, didThreadDetailBootstrapRefreshAfterMount, isPendingInteractionStateUnknown, - resolveThreadDetailQueryMount, useArchivedThreads, useChildThreads, useThread, @@ -417,16 +415,8 @@ describe("useThreadDetailBootstrap", () => { }); function useMountedThreadQuery(threadId: string) { - const queryClient = useQueryClient(); const bootstrap = useThreadDetailBootstrap(threadId); - return useThread( - threadId, - resolveThreadDetailQueryMount({ - bootstrap, - queryClient, - threadId, - }), - ); + return useThread(threadId, { bootstrap }); } describe("useArchivedThreads", () => { diff --git a/apps/app/src/hooks/queries/thread-queries.ts b/apps/app/src/hooks/queries/thread-queries.ts index 3437c4e790..b8a314c1dc 100644 --- a/apps/app/src/hooks/queries/thread-queries.ts +++ b/apps/app/src/hooks/queries/thread-queries.ts @@ -86,7 +86,15 @@ import { import { ARCHIVED_THREADS_PAGE_SIZE } from "./archived-threads-page-size"; import { ingestThreadDetailBootstrap } from "../cache-owners/thread-detail-cache-owner"; +interface ThreadDetailBootstrapMountSnapshot { + dataUpdatedAt: number; + isError: boolean; + isFetchedAfterMount: boolean; + isSuccess: boolean; +} + interface QueryOptions { + bootstrap?: ThreadDetailBootstrapMountSnapshot; enabled?: boolean; refetchOnMount?: boolean | "always"; staleTime?: number; @@ -118,12 +126,7 @@ export function didThreadDetailBootstrapRefreshAfterMount(query: { } export function resolveThreadDetailQueryMount(args: { - bootstrap: { - dataUpdatedAt: number; - isError: boolean; - isFetchedAfterMount: boolean; - isSuccess: boolean; - }; + bootstrap: ThreadDetailBootstrapMountSnapshot; queryClient: QueryClient; threadId: string; }): { enabled: boolean; refetchOnMount: boolean | "always" } { @@ -637,7 +640,16 @@ export function useThreadSearch({ export function useThread(id: string, options?: QueryOptions) { const queryClient = useQueryClient(); - const enabled = (options?.enabled ?? true) && Boolean(id); + const bootstrapMount = + options?.bootstrap === undefined + ? null + : resolveThreadDetailQueryMount({ + bootstrap: options.bootstrap, + queryClient, + threadId: id, + }); + const enabled = + (bootstrapMount?.enabled ?? options?.enabled ?? true) && Boolean(id); useThreadDetailRealtimeSubscription(id, { enabled }); return useQuery({ @@ -649,7 +661,8 @@ export function useThread(id: string, options?: QueryOptions) { }), enabled, staleTime: THREAD_DETAIL_STALE_TIME_MS, - refetchOnMount: options?.refetchOnMount ?? true, + refetchOnMount: + bootstrapMount?.refetchOnMount ?? options?.refetchOnMount ?? true, retry: shouldRetryTransientReadQuery, retryDelay: TRANSIENT_READ_RETRY_DELAY_MS, placeholderData: (previousData, previousQuery) => diff --git a/apps/app/src/views/thread-detail/ThreadDetailView.tsx b/apps/app/src/views/thread-detail/ThreadDetailView.tsx index 3c42eafdef..ac508d09c8 100644 --- a/apps/app/src/views/thread-detail/ThreadDetailView.tsx +++ b/apps/app/src/views/thread-detail/ThreadDetailView.tsx @@ -6,7 +6,6 @@ import { useState, type ReactNode, } from "react"; -import { useQueryClient } from "@tanstack/react-query"; import { nanoid } from "nanoid"; import { useSystemProviderInfo } from "@/hooks/queries/system-queries"; import { useNavigate } from "react-router-dom"; @@ -69,7 +68,6 @@ import { import { getLatestPendingInteraction, isPendingInteractionStateUnknown, - resolveThreadDetailQueryMount, useChildThreads, useProjectThreadSubset, useThread, @@ -515,7 +513,6 @@ function ThreadDetailViewInternal(props: ThreadRoutePathArgs) { const { isFocused, navigateInPane, onRequestClose, isBoundedPane } = usePaneContext(); const navigate = useNavigate(); - const queryClient = useQueryClient(); useFixedPanelTabsStorageMaintenance(); const systemConfigQuery = useSystemConfig(); const threadDetailBootstrapQuery = useThreadDetailBootstrap(threadId); @@ -526,14 +523,9 @@ function ThreadDetailViewInternal(props: ThreadRoutePathArgs) { isFetching, isLoadingError, error, - } = useThread( - threadId, - resolveThreadDetailQueryMount({ - bootstrap: threadDetailBootstrapQuery, - queryClient, - threadId, - }), - ); + } = useThread(threadId, { + bootstrap: threadDetailBootstrapQuery, + }); const environmentQuery = useEnvironment(thread?.environmentId, { enabled: hasThreadDetailBootstrapSettled, staleTime: 5_000,