diff --git a/apps/web/src/components/settings/UpdateTrackSwitchDialog.tsx b/apps/web/src/components/settings/UpdateTrackSwitchDialog.tsx index f5db42c452c14..ce36f8ccd7e5c 100644 --- a/apps/web/src/components/settings/UpdateTrackSwitchDialog.tsx +++ b/apps/web/src/components/settings/UpdateTrackSwitchDialog.tsx @@ -7,6 +7,7 @@ import { useState } from "react"; import { AsyncResult } from "effect/reactivity"; import { APP_VERSION } from "~/branding"; +import { isLocalEnvironmentDisabled } from "~/localEnvironment"; import { useDesktopUpdateState } from "~/state/desktopUpdate"; import { useEnvironments } from "~/state/environments"; import { npmReleaseAtom, npmReleaseFailureMessage } from "~/state/npmRelease"; @@ -91,6 +92,7 @@ function SwitchPlan({ databaseMigration: environment.serverConfig?.environment.databaseMigration, })), window.desktopBridge?.getLocalEnvironmentBootstraps().length ?? 0, + !isLocalEnvironmentDisabled(), ); const run = async () => { diff --git a/apps/web/src/components/sidebar/updateEverything.logic.test.ts b/apps/web/src/components/sidebar/updateEverything.logic.test.ts index 58328dbc1eeeb..8018410cb0181 100644 --- a/apps/web/src/components/sidebar/updateEverything.logic.test.ts +++ b/apps/web/src/components/sidebar/updateEverything.logic.test.ts @@ -254,7 +254,7 @@ describe("localSwitchBlockReason", () => { const nightly = "0.1.4-nightly.20261027.3796"; const windows = { connected: true, databaseMigration: 69 }; - expect(localSwitchBlockReason(nightly, stable, [windows], 1)).toBeNull(); + expect(localSwitchBlockReason(nightly, stable, [windows], 1, true)).toBeNull(); // A WSL server's newer migration blocks the reinstall that would restart it. expect( localSwitchBlockReason( @@ -262,17 +262,39 @@ describe("localSwitchBlockReason", () => { stable, [windows, { connected: true, databaseMigration: 72 }], 2, + true, ), ).toContain("does not support yet"); // A WSL backend still starting has no client entry, so its database is unchecked. - expect(localSwitchBlockReason(nightly, stable, [windows], 2)).toBe( + expect(localSwitchBlockReason(nightly, stable, [windows], 2, true)).toBe( "its server is not connected, so its database cannot be checked", ); // A cached head from a disconnected server proves nothing. expect( - localSwitchBlockReason(nightly, stable, [{ connected: false, databaseMigration: 69 }], 1), + localSwitchBlockReason( + nightly, + stable, + [{ connected: false, databaseMigration: 69 }], + 1, + true, + ), ).toBe("its server is not connected, so its database cannot be checked"); - expect(localSwitchBlockReason("0.1.3", stable, [], 1)).toBeNull(); + expect(localSwitchBlockReason("0.1.3", stable, [], 1, true)).toBeNull(); + }); + + it("does not block an app with Local environment off, which hosts no server", () => { + const nightly = { + channel: "nightly" as const, + version: "0.1.8-nightly.20261029.1", + databaseMigration: 72, + }; + const stable = "0.1.7"; + + expect(localSwitchBlockReason(stable, nightly, [], 0, false)).toBeNull(); + // With Local environment on, a primary backend still starting has no entry or bootstrap yet. + expect(localSwitchBlockReason(stable, nightly, [], 0, true)).toBe( + "its server is not connected, so its database cannot be checked", + ); }); }); diff --git a/apps/web/src/components/sidebar/updateEverything.logic.ts b/apps/web/src/components/sidebar/updateEverything.logic.ts index cbbd3baa7c776..efc5ad6612e99 100644 --- a/apps/web/src/components/sidebar/updateEverything.logic.ts +++ b/apps/web/src/components/sidebar/updateEverything.logic.ts @@ -176,7 +176,8 @@ function channelSwitchBlockReason( /** This app's reinstall restarts every server it hosts, so each of their databases must allow the * switch. `backendCount` is the desktop's own inventory: a backend still starting has no client - * entry yet. A cached config can outlive its connection, so only a connected server's head counts. */ + * entry yet. A cached config can outlive its connection, so only a connected server's head counts. + * With Local environment off this app runs no server, so its reinstall restarts none. */ export function localSwitchBlockReason( appVersion: string, release: ChannelSwitchRelease, @@ -185,8 +186,9 @@ export function localSwitchBlockReason( readonly databaseMigration: number | undefined; }>, backendCount: number, + localEnvironmentEnabled: boolean, ): string | null { - if (!crossesTrack(appVersion, release)) return null; + if (!localEnvironmentEnabled || !crossesTrack(appVersion, release)) return null; if ( hosted.length === 0 || hosted.length < backendCount ||