diff --git a/apps/desktop/src/renderer/src/components/desktop-runtimes-page.test.tsx b/apps/desktop/src/renderer/src/components/desktop-runtimes-page.test.tsx new file mode 100644 index 000000000..c4ce3a437 --- /dev/null +++ b/apps/desktop/src/renderer/src/components/desktop-runtimes-page.test.tsx @@ -0,0 +1,37 @@ +import { render } from "@testing-library/react"; +import { beforeEach, describe, expect, it, vi } from "vitest"; + +const runtimesPage = vi.fn<(props: Record) => null>(() => null); +const useDesktopRuntimeContext = vi.fn(); + +vi.mock("@multica/views/runtimes", () => ({ + RuntimesPage: (props: Record) => runtimesPage(props), +})); + +vi.mock("./use-desktop-runtime-context", () => ({ + useDesktopRuntimeContext: () => useDesktopRuntimeContext(), +})); + +import { DesktopRuntimesPage } from "./desktop-runtimes-page"; + +describe("DesktopRuntimesPage", () => { + beforeEach(() => { + runtimesPage.mockClear(); + useDesktopRuntimeContext.mockReturnValue({ + localDaemonId: "daemon-local", + localMachineName: "Jiayuan's MacBook", + bootstrapping: false, + }); + }); + + it("keeps daemon controls out of the machine collection", () => { + render(); + + expect(runtimesPage).toHaveBeenCalledWith({ + localDaemonId: "daemon-local", + localMachineName: "Jiayuan's MacBook", + hasLocalMachine: true, + bootstrapping: false, + }); + }); +}); diff --git a/apps/desktop/src/renderer/src/components/desktop-runtimes-page.tsx b/apps/desktop/src/renderer/src/components/desktop-runtimes-page.tsx index a66d949e5..207bfa894 100644 --- a/apps/desktop/src/renderer/src/components/desktop-runtimes-page.tsx +++ b/apps/desktop/src/renderer/src/components/desktop-runtimes-page.tsx @@ -1,5 +1,4 @@ import { RuntimesPage } from "@multica/views/runtimes"; -import { DaemonRuntimeActions } from "./daemon-runtime-card"; import { useDesktopRuntimeContext } from "./use-desktop-runtime-context"; /** @@ -23,11 +22,10 @@ export function DesktopRuntimesPage() { } // Desktop owns a local machine for the lifetime of the app, even - // while the daemon is stopped or hasn't registered yet. The shared - // page synthesizes a placeholder local row when no real runtime - // matches, so the Start button is always reachable. + // while the daemon is stopped or hasn't registered yet. Lifecycle + // controls live on the machine detail page so this collection stays + // consistent with every other machine row. hasLocalMachine bootstrapping={context.bootstrapping} /> diff --git a/packages/views/runtimes/components/runtimes-page.tsx b/packages/views/runtimes/components/runtimes-page.tsx index 492277cec..7483c26aa 100644 --- a/packages/views/runtimes/components/runtimes-page.tsx +++ b/packages/views/runtimes/components/runtimes-page.tsx @@ -41,8 +41,6 @@ export interface RuntimesPageProps { localDaemonId?: string | null; /** Desktop-only friendly device name for the local daemon. */ localMachineName?: string | null; - /** Desktop-only daemon controls attached to the local machine row. */ - localMachineActions?: React.ReactNode; /** Keep the local device visible even before its first runtime registers. */ hasLocalMachine?: boolean; /** The bundled daemon is starting but has not registered yet. */ @@ -63,7 +61,6 @@ function useNowTick(intervalMs = 30_000): number { export function RuntimesPage({ localDaemonId, localMachineName, - localMachineActions, hasLocalMachine, bootstrapping, cloudRuntimeEnabled = false, @@ -156,7 +153,6 @@ export function RuntimesPage({ )} {orphanProfileRuntimes.length > 0 && ( @@ -252,11 +248,9 @@ function PageHeaderBar({ function MachineList({ machines, bootstrapping, - localMachineActions, }: { machines: RuntimeMachine[]; bootstrapping?: boolean; - localMachineActions?: React.ReactNode; }) { const { t } = useT("runtimes"); if (machines.length === 0) { @@ -281,24 +275,14 @@ function MachineList({
{machines.map((machine) => ( - + ))}
); } -function MachineRow({ - machine, - actions, -}: { - machine: RuntimeMachine; - actions?: React.ReactNode; -}) { +function MachineRow({ machine }: { machine: RuntimeMachine }) { const { t } = useT("runtimes"); const healthLabel = useHealthLabel(); const timeAgo = useTimeAgo(); @@ -316,20 +300,22 @@ function MachineRow({ /> - - {machine.title} + + {machine.title} + + + + {machine.subtitle ?? + (machine.section === "cloud" + ? t(($) => $.machine.metrics.cloud_worker) + : t(($) => $.machine.metrics.local_daemon))} + {machine.isCurrent && ( - + {t(($) => $.machine.this_machine)} )} - - {machine.subtitle ?? - (machine.section === "cloud" - ? t(($) => $.machine.metrics.cloud_worker) - : t(($) => $.machine.metrics.local_daemon))} - @@ -365,15 +351,12 @@ function MachineRow({ ); return ( -
- - {body} - - {actions &&
{actions}
} -
+ + {body} + ); }