authorgravatar for hey@charliej.comCharlie J <hey@charliej.com> 2026-10-07 18:06:29+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-10-07 17:06:29+00:00
log8d564a3e5c77d283994119eca82881f8c37a4a4d
tree95af08e654de0d1fa6c3b4e21d40cf72621eaeda
parenta8c480241836a7f6b79862e4504f37801cda6cde
signature Signed by PGP key B5690EEEBB952194

fix(mobile): hide threads from switched-off environments (#16886)


2 files changed, 25 insertions(+), 1 deletions(-)

packages/client-runtime/src/state/threadShell.test.ts+24
......@@ -103,6 +103,30 @@ describe("v2 thread shell lists", () => {
103103 registry.dispose();
104104 });
105105
106 it("leaves switched-off environments out of navigation", () => {
107 const { registry, threads, catalogValueAtom } = makeHarness([
108 environmentId,
109 remoteEnvironmentId,
110 ]);
111 const dispose = registry.mount(threads.navigationThreadShellsAtom);
112 const environmentsOf = () =>
113 new Set(registry.get(threads.navigationThreadShellsAtom).map((t) => t.environmentId));
114 expect(environmentsOf()).toEqual(new Set([environmentId, remoteEnvironmentId]));
115
116 const setRemoteEnabled = (enabled: boolean) => {
117 const catalog = registry.get(catalogValueAtom);
118 const entries = new Map(catalog.entries);
119 entries.set(remoteEnvironmentId, { ...entries.get(remoteEnvironmentId)!, enabled });
120 registry.set(catalogValueAtom, { ...catalog, entries });
121 };
122 setRemoteEnabled(false);
123 expect(environmentsOf()).toEqual(new Set([environmentId]));
124 setRemoteEnabled(true);
125 expect(environmentsOf()).toEqual(new Set([environmentId, remoteEnvironmentId]));
126 dispose();
127 registry.dispose();
128 });
129
106130 it("shares point and list values without retaining an atom for every listed thread", () => {
107131 const harness = makeHarness();
108132 const snapshot = {
packages/client-runtime/src/state/threadShell.ts+1-1
......@@ -202,7 +202,7 @@ export function createEnvironmentThreadShellAtoms(input: {
202202 let previousNavigationShells: ReadonlyArray<EnvironmentThreadShell> = [];
203203 const navigationThreadShellsAtom = Atom.make((get) => {
204204 const next: EnvironmentThreadShell[] = [];
205 for (const environmentId of get(input.catalogValueAtom).entries.keys()) {
205 for (const environmentId of enabledEnvironmentIds(get(input.catalogValueAtom))) {
206206 for (const thread of get(environmentThreadsAtom(environmentId))) {
207207 if (thread.archivedAt !== null || thread.lineage.relationshipToParent === "subagent")
208208 continue;