feat(desktop-client): give login and main views their own BrowserWindow

Spawn a separate window per mode keyed by a ?window= query param so each surface keeps its size, devtools, and renderer state independently. Logout now persists the cleared session and switches windows before awaiting the runtime release, avoiding a stale main-window flash on the way out.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-30 20:56:03 +08:00
parent cdd63db7f1
commit ed38721feb
7 changed files with 265 additions and 95 deletions
+7 -2
View File
@@ -22,6 +22,11 @@ interface DesktopClientIDScope {
user_id: number;
}
interface WindowModeRequest {
source?: "auth-state" | "login" | "logout";
animate?: boolean;
}
const rendererProxyRequestChannel = "desktop:renderer-devtools-proxy:request";
const rendererProxyResponseChannel = "desktop:renderer-devtools-proxy:response";
@@ -119,8 +124,8 @@ const desktopBridge = {
ipcRenderer.invoke("desktop:runtime-session-sync", session) as Promise<null>,
releaseRuntimeSession: (revoke?: boolean) =>
ipcRenderer.invoke("desktop:runtime-session-release", revoke) as Promise<null>,
setWindowMode: (mode: "login" | "main") =>
ipcRenderer.invoke("desktop:set-window-mode", mode) as Promise<null>,
setWindowMode: (mode: "login" | "main", request?: WindowModeRequest) =>
ipcRenderer.invoke("desktop:set-window-mode", mode, request) as Promise<null>,
onRuntimeInvalidated: (
listener: (event: { reason: "account-health"; at: number; accountId?: string }) => void,
) => {