diff --git a/packages/app/src/hooks/use-providers-snapshot.ts b/packages/app/src/hooks/use-providers-snapshot.ts
index 2dccfe618..f7a4a12f4 100644
--- a/packages/app/src/hooks/use-providers-snapshot.ts
+++ b/packages/app/src/hooks/use-providers-snapshot.ts
@@ -30,13 +30,19 @@ interface UseProvidersSnapshotResult {
refetchIfStale: () => void;
}
+interface UseProvidersSnapshotOptions {
+ enabled?: boolean;
+}
+
export function useProvidersSnapshot(
serverId: string | null,
cwd?: string | null,
+ options: UseProvidersSnapshotOptions = {},
): UseProvidersSnapshotResult {
const queryClient = useQueryClient();
const client = useHostRuntimeClient(serverId ?? "");
const isConnected = useHostRuntimeIsConnected(serverId ?? "");
+ const enabled = options.enabled ?? true;
const normalizedCwd = cwd?.trim() || undefined;
const normalizedCwdKey = normalizeProvidersSnapshotCwdKey(normalizedCwd);
const supportsSnapshot = useSessionStore(
@@ -50,7 +56,7 @@ export function useProvidersSnapshot(
const snapshotQuery = useQuery({
queryKey,
- enabled: Boolean(supportsSnapshot && serverId && client && isConnected),
+ enabled: Boolean(enabled && supportsSnapshot && serverId && client && isConnected),
staleTime: 60_000,
queryFn: async () => {
if (!client) {
@@ -71,7 +77,7 @@ export function useProvidersSnapshot(
const { mutateAsync: refreshSnapshot, isPending: isRefreshing } = refreshMutation;
useEffect(() => {
- if (!supportsSnapshot || !client || !isConnected || !serverId) {
+ if (!enabled || !supportsSnapshot || !client || !isConnected || !serverId) {
return;
}
@@ -89,7 +95,16 @@ export function useProvidersSnapshot(
requestId: "providers_snapshot_update",
});
});
- }, [client, isConnected, normalizedCwdKey, queryClient, queryKey, serverId, supportsSnapshot]);
+ }, [
+ client,
+ enabled,
+ isConnected,
+ normalizedCwdKey,
+ queryClient,
+ queryKey,
+ serverId,
+ supportsSnapshot,
+ ]);
const refresh = useCallback(
async (providers?: AgentProvider[]) => {
diff --git a/packages/app/src/screens/workspace/workspace-screen.tsx b/packages/app/src/screens/workspace/workspace-screen.tsx
index 884feafd9..75e1e8d9a 100644
--- a/packages/app/src/screens/workspace/workspace-screen.tsx
+++ b/packages/app/src/screens/workspace/workspace-screen.tsx
@@ -131,6 +131,10 @@ type WorkspaceScreenProps = {
workspaceId: string;
};
+type WorkspaceScreenContentProps = WorkspaceScreenProps & {
+ isRouteFocused: boolean;
+};
+
function trimNonEmpty(value: string | null | undefined): string | null {
if (typeof value !== "string") {
return null;
@@ -566,13 +570,13 @@ function useStableTabDescriptorMap(tabDescriptors: WorkspaceTabDescriptor[]) {
export function WorkspaceScreen({ serverId, workspaceId }: WorkspaceScreenProps) {
const isFocused = useIsFocused();
- if (!isFocused) {
- return ;
- }
-
return (
-
+
);
}
@@ -604,7 +608,11 @@ function useCloseTabs(): UseCloseTabsResult {
return { closingTabIds, closeTab };
}
-function WorkspaceScreenContent({ serverId, workspaceId }: WorkspaceScreenProps) {
+function WorkspaceScreenContent({
+ serverId,
+ workspaceId,
+ isRouteFocused,
+}: WorkspaceScreenContentProps) {
const { theme } = useUnistyles();
const insets = useSafeAreaInsets();
const mainBackgroundColor = theme.colors.surfaceWorkspace;
@@ -646,11 +654,15 @@ function WorkspaceScreenContent({ serverId, workspaceId }: WorkspaceScreenProps)
// Warm the server-side provider snapshot for this workspace cwd so the model
// picker is ready when opened. Consumers share the same query cache key.
- useProvidersSnapshot(normalizedServerId, workspaceDirectory);
+ useProvidersSnapshot(normalizedServerId, workspaceDirectory, {
+ enabled: isRouteFocused,
+ });
const [pendingTerminalCreateInput, setPendingTerminalCreateInput] = useState<{
paneId?: string;
} | null>(null);
- const canCreateTerminalNow = Boolean(client && isConnected && workspaceDirectory);
+ const canCreateTerminalNow = Boolean(
+ isRouteFocused && client && isConnected && workspaceDirectory,
+ );
const workspaceAgentVisibility = useStoreWithEqualityFn(
useSessionStore,
@@ -669,7 +681,7 @@ function WorkspaceScreenContent({ serverId, workspaceId }: WorkspaceScreenProps)
type ListTerminalsPayload = ListTerminalsResponse["payload"];
const terminalsQuery = useQuery({
queryKey: terminalsQueryKey,
- enabled: Boolean(client && isConnected) && Boolean(workspaceDirectory),
+ enabled: Boolean(isRouteFocused && client && isConnected && workspaceDirectory),
queryFn: async () => {
if (!client || !workspaceDirectory) {
throw new Error("Host is not connected");
@@ -736,7 +748,7 @@ function WorkspaceScreenContent({ serverId, workspaceId }: WorkspaceScreenProps)
const { archiveAgent } = useArchiveAgent();
useEffect(() => {
- if (!client || !isConnected || !workspaceDirectory) {
+ if (!isRouteFocused || !client || !isConnected || !workspaceDirectory) {
return;
}
@@ -758,9 +770,11 @@ function WorkspaceScreenContent({ serverId, workspaceId }: WorkspaceScreenProps)
unsubscribeChanged();
client.unsubscribeTerminals({ cwd: workspaceDirectory });
};
- }, [client, isConnected, queryClient, terminalsQueryKey, workspaceDirectory]);
+ }, [client, isConnected, isRouteFocused, queryClient, terminalsQueryKey, workspaceDirectory]);
- const isCheckoutQueryEnabled = Boolean(client && isConnected) && Boolean(workspaceDirectory);
+ const isCheckoutQueryEnabled = Boolean(
+ isRouteFocused && client && isConnected && workspaceDirectory,
+ );
const checkoutQuery = useQuery({
queryKey: checkoutStatusQueryKey(
normalizedServerId,
@@ -851,8 +865,11 @@ function WorkspaceScreenContent({ serverId, workspaceId }: WorkspaceScreenProps)
}, [isGitCheckout, normalizedServerId, workspaceDirectory]);
useEffect(() => {
+ if (!isRouteFocused) {
+ return;
+ }
setActiveExplorerCheckout(activeExplorerCheckout);
- }, [activeExplorerCheckout, setActiveExplorerCheckout]);
+ }, [activeExplorerCheckout, isRouteFocused, setActiveExplorerCheckout]);
const openExplorerForWorkspace = useCallback(() => {
if (!activeExplorerCheckout) {
@@ -876,7 +893,7 @@ function WorkspaceScreenContent({ serverId, workspaceId }: WorkspaceScreenProps)
});
useEffect(() => {
- if (isWeb || !isExplorerOpen) {
+ if (!isRouteFocused || isWeb || !isExplorerOpen) {
return;
}
@@ -889,7 +906,7 @@ function WorkspaceScreenContent({ serverId, workspaceId }: WorkspaceScreenProps)
});
return () => handler.remove();
- }, [closeToAgent, isExplorerOpen]);
+ }, [closeToAgent, isExplorerOpen, isRouteFocused]);
const persistenceKey = useMemo(
() =>
@@ -979,14 +996,20 @@ function WorkspaceScreenContent({ serverId, workspaceId }: WorkspaceScreenProps)
}, [focusedPaneTabState.activeTab]);
useEffect(() => {
+ if (!isRouteFocused) {
+ return;
+ }
setFocusedAgentId(normalizedServerId, focusedPaneAgentId);
- }, [focusedPaneAgentId, normalizedServerId, setFocusedAgentId]);
+ }, [focusedPaneAgentId, isRouteFocused, normalizedServerId, setFocusedAgentId]);
useEffect(() => {
+ if (!isRouteFocused) {
+ return;
+ }
return () => {
setFocusedAgentId(normalizedServerId, null);
};
- }, [normalizedServerId, setFocusedAgentId]);
+ }, [isRouteFocused, normalizedServerId, setFocusedAgentId]);
const ensureWorkspaceTab = useCallback(
function ensureWorkspaceTab(target: WorkspaceTabTarget): string | null {
@@ -1018,6 +1041,9 @@ function WorkspaceScreenContent({ serverId, workspaceId }: WorkspaceScreenProps)
);
useEffect(() => {
+ if (!isRouteFocused) {
+ return;
+ }
if (!normalizedServerId || !normalizedWorkspaceId || !persistenceKey) {
return;
}
@@ -1040,6 +1066,7 @@ function WorkspaceScreenContent({ serverId, workspaceId }: WorkspaceScreenProps)
});
}, [
hasHydratedAgents,
+ isRouteFocused,
pendingByDraftId,
persistenceKey,
reconcileWorkspaceTabs,
@@ -1077,6 +1104,9 @@ function WorkspaceScreenContent({ serverId, workspaceId }: WorkspaceScreenProps)
const emptyWorkspaceSeedRef = useRef(null);
const autoOpenedSetupTabWorkspaceRef = useRef(null);
useEffect(() => {
+ if (!isRouteFocused) {
+ return;
+ }
if (!persistenceKey) {
return;
}
@@ -1099,12 +1129,16 @@ function WorkspaceScreenContent({ serverId, workspaceId }: WorkspaceScreenProps)
normalizedWorkspaceId,
openWorkspaceDraftTab,
persistenceKey,
+ isRouteFocused,
terminals.length,
tabs.length,
workspaceAgentVisibility.activeAgentIds.size,
]);
useEffect(() => {
+ if (!isRouteFocused) {
+ return;
+ }
if (!persistenceKey) {
return;
}
@@ -1146,6 +1180,7 @@ function WorkspaceScreenContent({ serverId, workspaceId }: WorkspaceScreenProps)
autoOpenedSetupTabWorkspaceRef.current = persistenceKey;
}, [
hasSetupTab,
+ isRouteFocused,
normalizedWorkspaceId,
openWorkspaceTabInBackground,
persistenceKey,
@@ -1763,7 +1798,7 @@ function WorkspaceScreenContent({ serverId, workspaceId }: WorkspaceScreenProps)
"workspace.tab.navigate-relative",
"workspace.terminal.new",
] as const,
- enabled: Boolean(normalizedServerId && normalizedWorkspaceId),
+ enabled: Boolean(isRouteFocused && normalizedServerId && normalizedWorkspaceId),
priority: 100,
isActive: () => true,
handle: handleWorkspaceTabAction,
@@ -1784,7 +1819,7 @@ function WorkspaceScreenContent({ serverId, workspaceId }: WorkspaceScreenProps)
"workspace.pane.move-tab.down",
"workspace.pane.close",
] as const,
- enabled: Boolean(normalizedServerId && normalizedWorkspaceId),
+ enabled: Boolean(isRouteFocused && normalizedServerId && normalizedWorkspaceId),
priority: 100,
isActive: () => true,
handle: handleWorkspacePaneAction,
@@ -1794,11 +1829,11 @@ function WorkspaceScreenContent({ serverId, workspaceId }: WorkspaceScreenProps)
const canRenderDesktopPaneSplits = supportsDesktopPaneSplits();
const shouldRenderDesktopPaneFallback = !isMobile && !canRenderDesktopPaneSplits;
useEffect(() => {
- if (isNative || typeof document === "undefined" || activeTabDescriptor) {
+ if (!isRouteFocused || isNative || typeof document === "undefined" || activeTabDescriptor) {
return;
}
document.title = "Workspace";
- }, [activeTabDescriptor]);
+ }, [activeTabDescriptor, isRouteFocused]);
const buildPaneContentModel = useCallback(
(input: {
tab: WorkspaceTabDescriptor;
@@ -1810,7 +1845,7 @@ function WorkspaceScreenContent({ serverId, workspaceId }: WorkspaceScreenProps)
tab: input.tab,
normalizedServerId,
normalizedWorkspaceId,
- isPaneFocused: input.isPaneFocused,
+ isPaneFocused: isRouteFocused && input.isPaneFocused,
onOpenTab: (target) => {
if (!persistenceKey) {
return;
@@ -1846,6 +1881,7 @@ function WorkspaceScreenContent({ serverId, workspaceId }: WorkspaceScreenProps)
[
handleCloseTabById,
handleOpenFileFromChat,
+ isRouteFocused,
focusWorkspacePane,
navigateToTabId,
normalizedServerId,
@@ -1919,8 +1955,8 @@ function WorkspaceScreenContent({ serverId, workspaceId }: WorkspaceScreenProps)
@@ -2029,7 +2065,7 @@ function WorkspaceScreenContent({ serverId, workspaceId }: WorkspaceScreenProps)
return (
- {isWeb && activeTabDescriptor ? (
+ {isRouteFocused && isWeb && activeTabDescriptor ? (
- {(!isFocusModeEnabled || isMobile) &&
+ {isRouteFocused &&
+ (!isFocusModeEnabled || isMobile) &&
(workspaceDirectory ? (