fix(desktop): Change Launch Mode menu performs reset entirely in main

Replace the renderer-event approach (which silently failed when the
renderer-side listener wasn't yet registered) with an onChangeLaunchMode
callback wired through AppMenuOptions. The callback runs
resetLaunchModeAndReload in main: writes shell settings to clear the
chosen mode, stops the embedded runtime, then navigates the window
directly to the renderer entrypoint with no cached query params so the
launch gate re-prompts.

Also surface the same flow from the dashboard's BackendConnectionErrorPage:
when running inside the desktop shell, the "Can't reach the Fusion backend"
page now offers a "Change Launch Mode…" button alongside Retry, so a user
who chose a broken backend isn't stuck without the Electron menubar.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsxdsm
2026-05-17 22:58:34 -07:00
parent 02ba659dd8
commit 10d5afdb8e
3 changed files with 75 additions and 6 deletions

View File

@@ -21,7 +21,7 @@ import {
import { setupTray } from "./tray.js";
import { getRendererUrl, getRendererFilePath, isUrlRenderer } from "./renderer.js";
import { LocalRuntimeManager } from "./local-runtime.js";
import { readShellSettings } from "./shell-settings.js";
import { readShellSettings, writeShellSettings } from "./shell-settings.js";
// Re-export for backward compatibility
export { IS_DEVELOPMENT } from "./renderer.js";
@@ -70,6 +70,44 @@ export function getCurrentDesktopLaunchMode(): DesktopLaunchMode {
return currentDesktopLaunchMode;
}
async function resetLaunchModeAndReload(window: BrowserWindow): Promise<void> {
console.log("[desktop/main] resetLaunchModeAndReload start");
try {
const settings = await readShellSettings();
settings.desktopMode = null;
settings.hasCompletedModeSelection = false;
await writeShellSettings(settings);
await saveDesktopLaunchMode("choose");
} catch (error) {
console.error("[desktop/main] Failed to reset shell settings", error);
}
if (localRuntimeManager) {
try {
await localRuntimeManager.stopLocal();
} catch (error) {
console.error("[desktop/main] Failed to stop local runtime during reset", error);
}
}
currentDesktopLaunchMode = "choose";
currentRemoteLaunch = null;
localRuntimeStartupAttempted = false;
// Force a clean reload to the renderer entrypoint without any cached
// serverBaseUrl / shellMode query params so the gate re-prompts.
try {
if (isUrlRenderer()) {
console.log("[desktop/main] reloading URL renderer", getRendererUrl());
await window.loadURL(getRendererUrl());
} else {
console.log("[desktop/main] reloading file renderer", getRendererFilePath());
await window.loadFile(getRendererFilePath());
}
console.log("[desktop/main] resetLaunchModeAndReload complete");
} catch (error) {
console.error("[desktop/main] reload failed", error);
}
}
export function createMainWindow(state?: WindowState, launchTargetUrl?: string): BrowserWindow {
const hasValidPosition = typeof state?.x === "number" && typeof state?.y === "number";
@@ -179,6 +217,9 @@ export async function initializeApp(): Promise<void> {
buildAppMenu({
mainWindow: createdWindow,
appName: "Fusion",
onChangeLaunchMode: async () => {
await resetLaunchModeAndReload(createdWindow);
},
});
tray = new Tray(nativeImage.createEmpty());

View File

@@ -8,20 +8,24 @@ import {
export interface AppMenuOptions {
mainWindow: BrowserWindow;
appName: string;
onChangeLaunchMode?: () => Promise<void> | void;
}
function buildConnectionSubmenu(options: AppMenuOptions): MenuItemConstructorOptions {
const { mainWindow } = options;
return {
label: "Connection",
submenu: [
{
label: "Change Launch Mode…",
click: () => {
// The renderer-side gate listens for this and calls
// shell.resetDesktopMode() before reloading without the cached
// serverBaseUrl query param.
mainWindow.webContents.send("shell:reset-desktop-mode-request");
console.log("[desktop/menu] Change Launch Mode clicked");
if (!options.onChangeLaunchMode) {
console.warn("[desktop/menu] onChangeLaunchMode callback not provided");
return;
}
void Promise.resolve(options.onChangeLaunchMode()).catch((error: unknown) => {
console.error("[desktop/menu] onChangeLaunchMode failed", error);
});
},
},
],