From 8002b76a00af9fd8e19ea340788d27391050f974 Mon Sep 17 00:00:00 2001 From: NotAnNvidiaFan <85665968+NotAnNvidiaFan@users.noreply.github.com> Date: Sat, 31 Oct 2026 10:41:17 -0500 Subject: [PATCH] fix(web): sidebar drops a deleted project's filter with the local environment disabled Desktops with Local disabled never discover a primary environment, so project snapshot readiness waited for one forever and the sidebar kept a saved filter for a deleted project. Readiness now expects a primary only when the client can have one, the same rule as #26099. Co-Authored-By: Claude Opus 5.5 --- apps/web/src/localEnvironment.ts | 4 +++- apps/web/src/state/shell.test.ts | 17 +++++++++++++++-- apps/web/src/state/shell.ts | 8 +++++++- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/apps/web/src/localEnvironment.ts b/apps/web/src/localEnvironment.ts index d9f4be0e29518..bccffd64ce23d 100644 --- a/apps/web/src/localEnvironment.ts +++ b/apps/web/src/localEnvironment.ts @@ -1,3 +1,5 @@ export function isLocalEnvironmentDisabled(): boolean { - return window.desktopBridge?.getLocalEnvironmentEnabled() === false; + return ( + typeof window !== "undefined" && window.desktopBridge?.getLocalEnvironmentEnabled() === false + ); } diff --git a/apps/web/src/state/shell.test.ts b/apps/web/src/state/shell.test.ts index 4d5920a94ad85..19a88cfbb19f9 100644 --- a/apps/web/src/state/shell.test.ts +++ b/apps/web/src/state/shell.test.ts @@ -7,9 +7,9 @@ import { EMPTY_SHELL_STATE, type EnvironmentShellState } from "@t3tools/client-r import { EnvironmentId } from "@t3tools/contracts"; import * as Option from "effect/Option"; import { Atom, AtomRegistry } from "effect/reactivity"; -import { describe, expect, it } from "vite-plus/test"; +import { describe, expect, it, vi } from "vite-plus/test"; -import { createAllEnvironmentProjectSnapshotsReadyAtom } from "./shell"; +import { createAllEnvironmentProjectSnapshotsReadyAtom, expectsPrimaryEnvironment } from "./shell"; const LOCAL = EnvironmentId.make("local"); const REMOTE = EnvironmentId.make("remote"); @@ -135,3 +135,16 @@ describe("project snapshot readiness", () => { registry.dispose(); }); }); + +it("expects a primary environment only on desktops with the local environment enabled", () => { + const desktop = (enabled: boolean) => { + vi.stubGlobal("window", { desktopBridge: { getLocalEnvironmentEnabled: () => enabled } }); + try { + return expectsPrimaryEnvironment(); + } finally { + vi.unstubAllGlobals(); + } + }; + expect(desktop(true)).toBe(true); + expect(desktop(false)).toBe(false); +}); diff --git a/apps/web/src/state/shell.ts b/apps/web/src/state/shell.ts index c4675d3d01301..43c75335265a6 100644 --- a/apps/web/src/state/shell.ts +++ b/apps/web/src/state/shell.ts @@ -21,6 +21,7 @@ import { AsyncResult, Atom } from "effect/reactivity"; import { environmentCatalog } from "../connection/catalog"; import { connectionAtomRuntime } from "../connection/runtime"; import { isHostedStaticApp } from "../hostedPairing"; +import { isLocalEnvironmentDisabled } from "../localEnvironment"; export const shellEnvironment = createShellEnvironmentAtoms(connectionAtomRuntime); export const environmentShell = createEnvironmentShellAtoms(connectionAtomRuntime); @@ -123,9 +124,14 @@ export const allEnvironmentProjectSnapshotsReadyAtom = createAllEnvironmentProjectSnapshotsReadyAtom({ catalogValueAtom: environmentCatalog.catalogValueAtom, shellStateValueAtom: environmentShell.stateValueAtom, - requiresPrimaryEnvironment: !isHostedStaticApp(), + requiresPrimaryEnvironment: expectsPrimaryEnvironment(), }); +/** Hosted clients and desktops with the local environment disabled never discover a primary. */ +export function expectsPrimaryEnvironment(): boolean { + return !isHostedStaticApp() && !isLocalEnvironmentDisabled(); +} + export const allReachableShellsLiveAtom = Atom.make((get) => { const catalog = get(environmentCatalog.catalogValueAtom); if (!catalogIsComplete(catalog, !isHostedStaticApp())) return false;