Skip to content

Commit dec1e45

Browse files
committed
fix(files): refresh preview handoff on open
Mount Files only while Computer is active and discard its short-lived IDE capability on close. Reopening now obtains a fresh handoff instead of replaying an expired URL.
1 parent da3ce2f commit dec1e45

2 files changed

Lines changed: 43 additions & 19 deletions

File tree

apps/web/src/components/home/home-computer-pane.tsx

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,17 +54,24 @@ function HomeComputerAside({
5454
className={homeComputerClass(computerOpen)}
5555
inert={computerOpen ? undefined : true}
5656
>
57-
<HomeComputerBody activeTab={activeTab} onClose={onClose} setActiveTab={setActiveTab} />
57+
<HomeComputerBody
58+
activeTab={activeTab}
59+
computerOpen={computerOpen}
60+
onClose={onClose}
61+
setActiveTab={setActiveTab}
62+
/>
5863
</aside>
5964
);
6065
}
6166

6267
function HomeComputerBody({
6368
activeTab,
69+
computerOpen,
6470
onClose,
6571
setActiveTab,
6672
}: {
6773
activeTab: PreviewTab;
74+
computerOpen: boolean;
6875
onClose: () => void;
6976
setActiveTab: (tab: PreviewTab) => void;
7077
}) {
@@ -85,17 +92,27 @@ function HomeComputerBody({
8592
activeTab === "files" ? <ConsoleStrip sandboxAvailable threadId={null} /> : null
8693
}
8794
>
88-
<HomeComputerTabContent activeTab={activeTab} />
95+
<HomeComputerTabContent activeTab={activeTab} computerOpen={computerOpen} />
8996
</ComputerSurfaceFrame>
9097
</div>
9198
);
9299
}
93100

94-
function HomeComputerTabContent({ activeTab }: { activeTab: PreviewTab }) {
101+
function HomeComputerTabContent({
102+
activeTab,
103+
computerOpen,
104+
}: {
105+
activeTab: PreviewTab;
106+
computerOpen: boolean;
107+
}) {
95108
return (
96109
<div className="h-full min-h-0">
97110
<Activity mode={activeTab === "files" ? "visible" : "hidden"}>
98-
<SandboxIdeTab active previewReloadToken={0} threadId={null} />
111+
<SandboxIdeTab
112+
active={computerOpen && activeTab === "files"}
113+
previewReloadToken={0}
114+
threadId={null}
115+
/>
99116
</Activity>
100117
<Activity mode={activeTab === "app" ? "visible" : "hidden"}>
101118
<HomeBrowserEmpty />

apps/web/src/components/preview/sandbox-ide-tab.tsx

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,24 @@ export function SandboxIdeTab({
4343
active: boolean;
4444
previewReloadToken: number;
4545
threadId: string | null;
46+
}) {
47+
if (!active) {
48+
return null;
49+
}
50+
return <ActiveSandboxIdeTab previewReloadToken={previewReloadToken} threadId={threadId} />;
51+
}
52+
53+
function ActiveSandboxIdeTab({
54+
previewReloadToken,
55+
threadId,
56+
}: {
57+
previewReloadToken: number;
58+
threadId: string | null;
4659
}) {
4760
const { getToken } = useAuth();
4861
const { resolvedTheme } = useTheme();
4962
const [frameReloadToken, setFrameReloadToken] = useState(0);
50-
const ideQuery = useSandboxIdeQuery(active, threadId, getToken);
63+
const ideQuery = useSandboxIdeQuery(threadId, getToken);
5164
const requestedIframeUrl = ideQuery.data
5265
? codeServerIframeUrl(
5366
ideQuery.data.url,
@@ -57,7 +70,7 @@ export function SandboxIdeTab({
5770
)
5871
: null;
5972
const iframeUrl = useStablePreviewSource(requestedIframeUrl);
60-
const bridge = useCodeServerBridge(active, iframeUrl, threadId);
73+
const bridge = useCodeServerBridge(iframeUrl, threadId);
6174
const refetchSession = () => void ideQuery.refetch();
6275
const reloadFrame = () => setFrameReloadToken((current) => current + 1);
6376
return (
@@ -72,14 +85,10 @@ export function SandboxIdeTab({
7285
);
7386
}
7487

75-
function useSandboxIdeQuery(
76-
active: boolean,
77-
threadId: string | null,
78-
getToken: () => Promise<null | string>,
79-
) {
88+
function useSandboxIdeQuery(threadId: string | null, getToken: () => Promise<null | string>) {
8089
// Files resolves either the per-user computer root or the active project folder.
8190
return useQuery({
82-
enabled: active,
91+
gcTime: 0,
8392
queryFn: ({ signal }) =>
8493
threadId === null
8594
? openComputerIde(getToken, signal)
@@ -90,7 +99,7 @@ function useSandboxIdeQuery(
9099
refetchIntervalInBackground: false,
91100
refetchOnWindowFocus: false,
92101
retry: 1,
93-
staleTime: 40 * 60 * 1000,
102+
staleTime: 0,
94103
});
95104
}
96105

@@ -192,7 +201,7 @@ function SandboxIdeFrame({
192201
);
193202
}
194203

195-
function useCodeServerBridge(active: boolean, iframeUrl: string | null, threadId: string | null) {
204+
function useCodeServerBridge(iframeUrl: string | null, threadId: string | null) {
196205
const iframeRef = useRef<HTMLIFrameElement | null>(null);
197206
const [readyIframeUrl, setReadyIframeUrl] = useState<string | null>(null);
198207
const [timedOutIframeUrl, setTimedOutIframeUrl] = useState<string | null>(null);
@@ -216,7 +225,6 @@ function useCodeServerBridge(active: boolean, iframeUrl: string | null, threadId
216225
const isReady = iframeUrl !== null && readyIframeUrl === iframeUrl;
217226
const requestReadyState = () => requestCodeServerState(iframeOrigin, iframeRef);
218227
useCodeServerHandshake({
219-
active,
220228
iframeOrigin,
221229
iframeRef,
222230
iframeUrl,
@@ -241,16 +249,15 @@ function useCodeServerBridge(active: boolean, iframeUrl: string | null, threadId
241249
}
242250

243251
function useCodeServerHandshake(input: {
244-
active: boolean;
245252
iframeOrigin: string | null;
246253
iframeRef: RefObject<HTMLIFrameElement | null>;
247254
iframeUrl: string | null;
248255
isReady: boolean;
249256
setTimedOutIframeUrl: (iframeUrl: string | null) => void;
250257
}): void {
251-
const { active, iframeOrigin, iframeRef, iframeUrl, isReady, setTimedOutIframeUrl } = input;
258+
const { iframeOrigin, iframeRef, iframeUrl, isReady, setTimedOutIframeUrl } = input;
252259
useEffect(() => {
253-
if (!active || !iframeOrigin || !iframeUrl || isReady) return;
260+
if (!iframeOrigin || !iframeUrl || isReady) return;
254261
setTimedOutIframeUrl(null);
255262
requestCodeServerState(iframeOrigin, iframeRef);
256263
const interval = window.setInterval(
@@ -265,7 +272,7 @@ function useCodeServerHandshake(input: {
265272
window.clearInterval(interval);
266273
window.clearTimeout(timeout);
267274
};
268-
}, [active, iframeOrigin, iframeRef, iframeUrl, isReady, setTimedOutIframeUrl]);
275+
}, [iframeOrigin, iframeRef, iframeUrl, isReady, setTimedOutIframeUrl]);
269276
}
270277

271278
function requestCodeServerState(

0 commit comments

Comments
 (0)