Skip to content

Commit 93b5cce

Browse files
centdixclaude
andauthored
perf: lazy-load diff dialog (#217)
* perf: lazy-load diff dialog Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: share diff dialog props type Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 47b26be commit 93b5cce

4 files changed

Lines changed: 54 additions & 11 deletions

File tree

frontend/src/App.svelte

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<script lang="ts">
2-
import { onMount } from "svelte";
2+
import { onMount, type Component } from "svelte";
33
import WorktreeList from "./lib/WorktreeList.svelte";
44
import TopBar from "./lib/TopBar.svelte";
55
import Terminal from "./lib/Terminal.svelte";
@@ -8,7 +8,6 @@
88
import SettingsDialog from "./lib/SettingsDialog.svelte";
99
import CiDetailsDialog from "./lib/CiDetailsDialog.svelte";
1010
import CommentReviewDialog from "./lib/CommentReviewDialog.svelte";
11-
import DiffDialog from "./lib/DiffDialog.svelte";
1211
import PaneBar from "./lib/PaneBar.svelte";
1312
import ToastStack from "./lib/ToastStack.svelte";
1413
import LinearPanel from "./lib/LinearPanel.svelte";
@@ -20,6 +19,7 @@
2019
AppConfig,
2120
AppNotification,
2221
CreateWorktreeRequest,
22+
DiffDialogProps,
2323
PrEntry,
2424
LinearIssueAvailability,
2525
LinearIssue,
@@ -81,6 +81,7 @@
8181
let ciDetailsPr = $state<PrEntry | null>(null);
8282
let commentReviewPr = $state<PrEntry | null>(null);
8383
let showDiffDialog = $state(false);
84+
let DiffDialogComponent = $state<Component<DiffDialogProps> | null>(null);
8485
let pullMainConfirm = $state(false);
8586
let pullMainLoading = $state(false);
8687
let pullMainError = $state("");
@@ -114,6 +115,7 @@
114115
let availableBranchRequests: Partial<Record<BranchCacheKey, Promise<AvailableBranch[]>>> = {};
115116
let baseBranchCache: AvailableBranch[] | null = null;
116117
let baseBranchRequest: Promise<AvailableBranch[]> | null = null;
118+
let diffDialogLoad: Promise<void> | null = null;
117119
118120
// Linear integration
119121
let linearIssues = $state<LinearIssue[]>([]);
@@ -229,6 +231,34 @@
229231
}, AUTO_DISMISS_MS);
230232
}
231233
234+
function ensureDiffDialogLoaded(): Promise<void> {
235+
if (DiffDialogComponent) return Promise.resolve();
236+
if (diffDialogLoad) return diffDialogLoad;
237+
238+
diffDialogLoad = import("./lib/DiffDialog.svelte")
239+
.then(({ default: component }) => {
240+
DiffDialogComponent = component;
241+
})
242+
.finally(() => {
243+
diffDialogLoad = null;
244+
});
245+
246+
return diffDialogLoad;
247+
}
248+
249+
async function openDiffDialog(): Promise<void> {
250+
try {
251+
await ensureDiffDialogLoaded();
252+
showDiffDialog = true;
253+
} catch (err: unknown) {
254+
showToast({
255+
tone: "error",
256+
message: "Failed to load changes view.",
257+
detail: errorMessage(err),
258+
});
259+
}
260+
}
261+
232262
function handleInitialNotification(n: AppNotification): void {
233263
if (notificationHistory.some((x) => x.id === n.id)) return;
234264
notificationHistory = [n, ...notificationHistory].slice(0, MAX_HISTORY);
@@ -1068,7 +1098,7 @@
10681098
if (selectedBranch) removeBranch = selectedBranch;
10691099
}}
10701100
onsettings={() => (showSettingsDialog = true)}
1071-
ondirtyclick={() => (showDiffDialog = true)}
1101+
ondirtyclick={openDiffDialog}
10721102
onCiClick={(pr) => (ciDetailsPr = pr)}
10731103
onReviewsClick={(pr) => (commentReviewPr = pr)}
10741104
onbellopen={handleBellOpen}
@@ -1240,8 +1270,8 @@
12401270
/>
12411271
{/if}
12421272

1243-
{#if showDiffDialog && selectedBranch}
1244-
<DiffDialog
1273+
{#if showDiffDialog && selectedBranch && DiffDialogComponent}
1274+
<DiffDialogComponent
12451275
branch={selectedBranch}
12461276
cursorUrl={makeCursorUrl(selectedWorktree?.dir, sshHost)}
12471277
onclose={() => (showDiffDialog = false)}

frontend/src/lib/DiffDialog.svelte

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import { html as diff2html } from "diff2html";
33
import { ColorSchemeType } from "diff2html/lib/types";
44
import "diff2html/bundles/css/diff2html.min.css";
5-
import type { UnpushedCommit } from "./types";
5+
import type { DiffDialogProps, UnpushedCommit } from "./types";
66
import { api } from "./api";
77
import { errorMessage } from "./utils";
88
import BaseDialog from "./BaseDialog.svelte";
@@ -13,11 +13,7 @@
1313
branch,
1414
cursorUrl = null,
1515
onclose,
16-
}: {
17-
branch: string;
18-
cursorUrl?: string | null;
19-
onclose: () => void;
20-
} = $props();
16+
}: DiffDialogProps = $props();
2117
2218
let uncommitted = $state("");
2319
let uncommittedTruncated = $state(false);

frontend/src/lib/types.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,12 @@ export interface FileUploadResult {
4646
files: Array<{ path: string }>;
4747
}
4848

49+
export interface DiffDialogProps {
50+
branch: string;
51+
cursorUrl?: string | null;
52+
onclose: () => void;
53+
}
54+
4955
export interface WorktreeInfo {
5056
branch: string;
5157
baseBranch?: string;

frontend/vite.config.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,17 @@ const port = parseInt(process.env.FRONTEND_PORT || "5112");
99

1010
export default defineConfig({
1111
plugins: [svelte(), tailwindcss()],
12+
build: {
13+
rollupOptions: {
14+
output: {
15+
manualChunks(id) {
16+
if (id.includes("node_modules/@xterm/")) {
17+
return "vendor-xterm";
18+
}
19+
},
20+
},
21+
},
22+
},
1223
server: {
1324
port,
1425
proxy: {

0 commit comments

Comments
 (0)