feat(FN-3406): add shell context hook plumbing for dashboard

Adds a new `useShellContext` hook with tests to the dashboard, integrated into `App.tsx` and `Header.tsx` to provide shell context plumbing throughout the UI.

Fusion-Task-Id: FN-3406
This commit is contained in:
Fusion
2026-05-07 22:00:41 -07:00
committed by gsxdsm
parent 954ae1078d
commit a6c4ee2b8c
23 changed files with 785 additions and 23 deletions

View File

@@ -11,12 +11,16 @@ import {
saveDesktopLaunchMode,
saveWindowState,
setupAutoUpdater,
normalizeDesktopRemoteLaunch,
buildRemoteShellHandoffUrl,
type DesktopLaunchMode,
type NormalizedDesktopRemoteLaunch,
type WindowState,
} from "./native.js";
import { setupTray } from "./tray.js";
import { getRendererUrl, getRendererFilePath, isUrlRenderer } from "./renderer.js";
import { LocalRuntimeManager } from "./local-runtime.js";
import { readShellSettings } from "./shell-settings.js";
// Re-export for backward compatibility
export { IS_DEVELOPMENT } from "./renderer.js";
@@ -39,6 +43,7 @@ let mainWindow: BrowserWindow | null = null;
let tray: Tray | null = null;
let localRuntimeManager: LocalRuntimeManager | null = null;
let currentDesktopLaunchMode: DesktopLaunchMode = "choose";
let currentRemoteLaunch: NormalizedDesktopRemoteLaunch | null = null;
let localRuntimeStartupAttempted = false;
function getAppWithQuitFlag(): Electron.App & AppWithQuitFlag {
@@ -64,7 +69,7 @@ export function getCurrentDesktopLaunchMode(): DesktopLaunchMode {
return currentDesktopLaunchMode;
}
export function createMainWindow(state?: WindowState): BrowserWindow {
export function createMainWindow(state?: WindowState, launchTargetUrl?: string): BrowserWindow {
const hasValidPosition = typeof state?.x === "number" && typeof state?.y === "number";
const window = new BrowserWindow({
@@ -79,7 +84,9 @@ export function createMainWindow(state?: WindowState): BrowserWindow {
},
});
if (isUrlRenderer()) {
if (launchTargetUrl) {
void window.loadURL(launchTargetUrl);
} else if (isUrlRenderer()) {
void window.loadURL(getRendererUrl());
} else {
void window.loadFile(getRendererFilePath());
@@ -110,8 +117,20 @@ export async function initializeApp(): Promise<void> {
localRuntimeManager = new LocalRuntimeManager({ rootDir: process.cwd() });
currentDesktopLaunchMode = rememberedLaunchMode;
currentRemoteLaunch = null;
localRuntimeStartupAttempted = false;
if (rememberedLaunchMode === "remote") {
const shellSettings = await readShellSettings();
const normalizedRemoteLaunch = normalizeDesktopRemoteLaunch(shellSettings);
if (normalizedRemoteLaunch) {
currentRemoteLaunch = normalizedRemoteLaunch;
} else {
currentDesktopLaunchMode = "choose";
await saveDesktopLaunchMode("choose");
}
}
if (rememberedLaunchMode === "local") {
try {
await startLocalRuntimeOnce();
@@ -129,7 +148,12 @@ export async function initializeApp(): Promise<void> {
currentDesktopLaunchMode = "local";
}
const createdWindow = createMainWindow(state ?? undefined);
const createdWindow = createMainWindow(
state ?? undefined,
currentDesktopLaunchMode === "remote" && currentRemoteLaunch
? buildRemoteShellHandoffUrl(currentRemoteLaunch)
: undefined,
);
buildAppMenu({
mainWindow: createdWindow,
@@ -146,11 +170,14 @@ export async function initializeApp(): Promise<void> {
}
currentDesktopLaunchMode = mode;
if (mode === "local") {
currentRemoteLaunch = null;
localRuntimeStartupAttempted = false;
await startLocalRuntimeOnce();
} else {
localRuntimeStartupAttempted = false;
await localRuntimeManager.stopLocal();
const shellSettings = await readShellSettings();
currentRemoteLaunch = normalizeDesktopRemoteLaunch({ ...shellSettings, desktopMode: "remote" });
}
await saveDesktopLaunchMode(mode);
},
@@ -161,9 +188,12 @@ export async function initializeApp(): Promise<void> {
currentDesktopLaunchMode = mode;
localRuntimeStartupAttempted = false;
if (mode === "local") {
currentRemoteLaunch = null;
await startLocalRuntimeOnce();
} else {
await localRuntimeManager.stopLocal();
const shellSettings = await readShellSettings();
currentRemoteLaunch = normalizeDesktopRemoteLaunch({ ...shellSettings, desktopMode: "remote" });
}
await saveDesktopLaunchMode(mode);
},
@@ -172,6 +202,7 @@ export async function initializeApp(): Promise<void> {
stopLocalRuntime: () => localRuntimeManager?.stopLocal() ?? Promise.resolve({ source: "none", state: "stopped" }),
getServerPort: () => localRuntimeManager?.getServerPort(),
getDesktopLaunchMode: () => currentDesktopLaunchMode,
getDesktopLaunchContext: () => currentRemoteLaunch,
});
registerDeepLinkProtocol();
setupDeepLinkHandler(createdWindow);