Skip to content

Commit 9fbccc0

Browse files
chore: improve iframe loading time (#18134)
- Pre-load all the embed app iframes - Avoid reloading the iframe when the selected app changes
1 parent 00502dc commit 9fbccc0

File tree

2 files changed

+56
-22
lines changed

2 files changed

+56
-22
lines changed

site/src/pages/TaskPage/TaskPage.stories.tsx

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { Meta, StoryObj } from "@storybook/react";
2-
import { spyOn } from "@storybook/test";
2+
import { expect, spyOn, within } from "@storybook/test";
33
import {
44
MockFailedWorkspace,
55
MockStartingWorkspace,
@@ -115,9 +115,8 @@ export const Active: Story = {
115115
...MockWorkspaceApp,
116116
id: "claude-code",
117117
display_name: "Claude Code",
118+
slug: "claude-code",
118119
icon: "/icon/claude.svg",
119-
url: `${window.location.protocol}/iframe.html?viewMode=story&id=pages-terminal--ready&args=&globals=`,
120-
external: true,
121120
statuses: [
122121
MockWorkspaceAppStatus,
123122
{
@@ -131,11 +130,13 @@ export const Active: Story = {
131130
{
132131
...MockWorkspaceApp,
133132
id: "vscode",
133+
slug: "vscode",
134134
display_name: "VS Code Web",
135135
icon: "/icon/code.svg",
136136
},
137137
{
138138
...MockWorkspaceApp,
139+
slug: "zed",
139140
id: "zed",
140141
display_name: "Zed",
141142
icon: "/icon/zed.svg",
@@ -153,4 +154,15 @@ export const Active: Story = {
153154
},
154155
});
155156
},
157+
play: async ({ canvasElement }) => {
158+
const canvas = within(canvasElement);
159+
160+
const vscodeIframe = await canvas.findByTitle("VS Code Web");
161+
const zedIframe = await canvas.findByTitle("Zed");
162+
const claudeIframe = await canvas.findByTitle("Claude Code");
163+
164+
expect(vscodeIframe).not.toBeVisible();
165+
expect(zedIframe).not.toBeVisible();
166+
expect(claudeIframe).toBeVisible();
167+
},
156168
};

site/src/pages/TaskPage/TaskPage.tsx

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,13 @@ import {
1919
TooltipProvider,
2020
TooltipTrigger,
2121
} from "components/Tooltip/Tooltip";
22-
import { useProxy } from "contexts/ProxyContext";
2322
import {
2423
ArrowLeftIcon,
2524
ChevronDownIcon,
2625
LayoutGridIcon,
2726
RotateCcwIcon,
2827
} from "lucide-react";
2928
import { AppStatusIcon } from "modules/apps/AppStatusIcon";
30-
import { getAppHref } from "modules/apps/apps";
3129
import { useAppLink } from "modules/apps/useAppLink";
3230
import { AI_PROMPT_PARAMETER_NAME, type Task } from "modules/tasks/tasks";
3331
import { WorkspaceAppStatus } from "modules/workspaces/WorkspaceAppStatus/WorkspaceAppStatus";
@@ -312,17 +310,6 @@ const TaskApps: FC<TaskAppsProps> = ({ task }) => {
312310
throw new Error(`Agent for app ${activeAppId} not found in task workspace`);
313311
}
314312

315-
const { proxy } = useProxy();
316-
const [iframeSrc, setIframeSrc] = useState(() => {
317-
const src = getAppHref(activeApp, {
318-
agent,
319-
workspace: task.workspace,
320-
path: proxy.preferredPathAppURL,
321-
host: proxy.preferredWildcardHostname,
322-
});
323-
return src;
324-
});
325-
326313
const embeddedApps = apps.filter((app) => !app.external);
327314
const externalApps = apps.filter((app) => app.external);
328315

@@ -344,7 +331,6 @@ const TaskApps: FC<TaskAppsProps> = ({ task }) => {
344331

345332
e.preventDefault();
346333
setActiveAppId(app.id);
347-
setIframeSrc(e.currentTarget.href);
348334
}}
349335
/>
350336
))}
@@ -387,11 +373,16 @@ const TaskApps: FC<TaskAppsProps> = ({ task }) => {
387373
</div>
388374

389375
<div className="flex-1">
390-
<iframe
391-
title={activeApp.display_name ?? activeApp.slug}
392-
className="w-full h-full border-0"
393-
src={iframeSrc}
394-
/>
376+
{embeddedApps.map((app) => {
377+
return (
378+
<TaskAppIFrame
379+
key={app.id}
380+
active={activeAppId === app.id}
381+
app={app}
382+
task={task}
383+
/>
384+
);
385+
})}
395386
</div>
396387
</main>
397388
);
@@ -443,6 +434,37 @@ const TaskAppButton: FC<TaskAppButtonProps> = ({
443434
);
444435
};
445436

437+
type TaskAppIFrameProps = {
438+
task: Task;
439+
app: WorkspaceApp;
440+
active: boolean;
441+
};
442+
443+
const TaskAppIFrame: FC<TaskAppIFrameProps> = ({ task, app, active }) => {
444+
const agent = task.workspace.latest_build.resources
445+
.flatMap((r) => r.agents)
446+
.filter((a) => !!a)
447+
.find((a) => a.apps.some((a) => a.id === app.id));
448+
449+
if (!agent) {
450+
throw new Error(`Agent for app ${app.id} not found in task workspace`);
451+
}
452+
453+
const link = useAppLink(app, {
454+
agent,
455+
workspace: task.workspace,
456+
});
457+
458+
return (
459+
<iframe
460+
src={link.href}
461+
title={link.label}
462+
loading="eager"
463+
className={cn([active ? "block" : "hidden", "w-full h-full border-0"])}
464+
/>
465+
);
466+
};
467+
446468
export const data = {
447469
fetchTask: async (workspaceOwnerUsername: string, workspaceName: string) => {
448470
const workspace = await API.getWorkspaceByOwnerAndName(

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy