Skip to content

Commit af67e12

Browse files
authored
Centralize desktop renderer URL resolution (#383)
- Add a shared helper for dev and packaged renderer URLs - Use it for main and pop-out windows to preserve query params - Update the Electron history comment for the desktop shell origin
1 parent 88a159d commit af67e12

File tree

4 files changed

+114
-11
lines changed

4 files changed

+114
-11
lines changed

apps/desktop/src/main.ts

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import { RotatingFileSink } from "@okcode/shared/logging";
3434
import { showDesktopConfirmDialog } from "./confirmDialog";
3535
import { createEmptyTabsState } from "./preview";
3636
import { DesktopPreviewController } from "./previewController";
37+
import { resolveDesktopRendererUrl } from "./rendererUrl";
3738
import { syncShellEnvironment } from "./syncShellEnvironment";
3839
import { getAutoUpdateDisabledReason, shouldBroadcastDownloadProgress } from "./updateState";
3940
import {
@@ -1501,13 +1502,14 @@ function registerIpcHandlers(): void {
15011502

15021503
// Load the same app URL but with a query parameter so the renderer
15031504
// can detect pop-out mode and render a simplified UI if needed.
1504-
if (isDevelopment && process.env.VITE_DEV_SERVER_URL) {
1505-
void popOut.loadURL(`${process.env.VITE_DEV_SERVER_URL}?popout=true`);
1506-
} else {
1507-
void popOut.loadFile(Path.join(__dirname, "../../web/dist/index.html"), {
1508-
query: { popout: "true" },
1509-
});
1510-
}
1505+
void popOut.loadURL(
1506+
resolveDesktopRendererUrl({
1507+
isDevelopment,
1508+
devServerUrl: process.env.VITE_DEV_SERVER_URL,
1509+
scheme: DESKTOP_SCHEME,
1510+
query: { popout: true },
1511+
}),
1512+
);
15111513
});
15121514

15131515
ipcMain.removeHandler(PREVIEW_POP_IN_CHANNEL);
@@ -1600,11 +1602,16 @@ function createWindow(): BrowserWindow {
16001602
window.show();
16011603
});
16021604

1605+
void window.loadURL(
1606+
resolveDesktopRendererUrl({
1607+
isDevelopment,
1608+
devServerUrl: process.env.VITE_DEV_SERVER_URL,
1609+
scheme: DESKTOP_SCHEME,
1610+
}),
1611+
);
1612+
16031613
if (isDevelopment) {
1604-
void window.loadURL(process.env.VITE_DEV_SERVER_URL as string);
16051614
window.webContents.openDevTools({ mode: "detach" });
1606-
} else {
1607-
void window.loadURL(`${DESKTOP_SCHEME}://app/index.html`);
16081615
}
16091616

16101617
window.on("closed", () => {
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import { describe, expect, it } from "vitest";
2+
3+
import { resolveDesktopRendererUrl } from "./rendererUrl";
4+
5+
describe("resolveDesktopRendererUrl", () => {
6+
it("builds the packaged renderer URL from the desktop protocol", () => {
7+
expect(
8+
resolveDesktopRendererUrl({
9+
isDevelopment: false,
10+
scheme: "okcode",
11+
}),
12+
).toBe("okcode://app/index.html");
13+
});
14+
15+
it("adds query parameters for packaged pop-out windows", () => {
16+
expect(
17+
resolveDesktopRendererUrl({
18+
isDevelopment: false,
19+
scheme: "okcode",
20+
query: {
21+
popout: true,
22+
},
23+
}),
24+
).toBe("okcode://app/index.html?popout=true");
25+
});
26+
27+
it("adds query parameters to the dev server URL", () => {
28+
expect(
29+
resolveDesktopRendererUrl({
30+
isDevelopment: true,
31+
devServerUrl: "http://127.0.0.1:5173/",
32+
scheme: "okcode",
33+
query: {
34+
popout: true,
35+
},
36+
}),
37+
).toBe("http://127.0.0.1:5173/?popout=true");
38+
});
39+
40+
it("preserves existing dev server search params", () => {
41+
expect(
42+
resolveDesktopRendererUrl({
43+
isDevelopment: true,
44+
devServerUrl: "http://127.0.0.1:5173/?client=desktop",
45+
scheme: "okcode",
46+
query: {
47+
popout: true,
48+
},
49+
}),
50+
).toBe("http://127.0.0.1:5173/?client=desktop&popout=true");
51+
});
52+
53+
it("requires a dev server URL in development mode", () => {
54+
expect(() =>
55+
resolveDesktopRendererUrl({
56+
isDevelopment: true,
57+
scheme: "okcode",
58+
}),
59+
).toThrow("VITE_DEV_SERVER_URL is required when resolving a development renderer URL.");
60+
});
61+
});

apps/desktop/src/rendererUrl.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
export interface DesktopRendererUrlInput {
2+
readonly isDevelopment: boolean;
3+
readonly devServerUrl?: string | undefined;
4+
readonly scheme: string;
5+
readonly query?: Record<string, string | number | boolean | null | undefined> | undefined;
6+
}
7+
8+
function applyQuery(url: URL, query: DesktopRendererUrlInput["query"]): URL {
9+
if (!query) {
10+
return url;
11+
}
12+
13+
for (const [key, value] of Object.entries(query)) {
14+
if (value === null || value === undefined) {
15+
url.searchParams.delete(key);
16+
continue;
17+
}
18+
url.searchParams.set(key, String(value));
19+
}
20+
21+
return url;
22+
}
23+
24+
export function resolveDesktopRendererUrl(input: DesktopRendererUrlInput): string {
25+
if (input.isDevelopment) {
26+
const devServerUrl = input.devServerUrl;
27+
if (!devServerUrl) {
28+
throw new Error("VITE_DEV_SERVER_URL is required when resolving a development renderer URL.");
29+
}
30+
31+
return applyQuery(new URL(devServerUrl), input.query).toString();
32+
}
33+
34+
return applyQuery(new URL(`${input.scheme}://app/index.html`), input.query).toString();
35+
}

apps/web/src/main.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { getRouter } from "./router";
1111
import { APP_DISPLAY_NAME } from "./branding";
1212
import { DiffWorkerPoolProvider } from "./components/DiffWorkerPoolProvider";
1313

14-
// Electron loads the app from a file-backed shell, so hash history avoids path resolution issues.
14+
// Electron loads the app from a desktop shell origin, so hash history avoids path resolution issues.
1515
const history = isElectron ? createHashHistory() : createBrowserHistory();
1616

1717
const router = getRouter(history);

0 commit comments

Comments
 (0)