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", () => {...@@ -103,6 +103,30 @@ describe("v2 thread shell lists", () => {
103 registry.dispose();103 registry.dispose();
104 });104 });
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
106 it("shares point and list values without retaining an atom for every listed thread", () => {130 it("shares point and list values without retaining an atom for every listed thread", () => {
107 const harness = makeHarness();131 const harness = makeHarness();
108 const snapshot = {132 const snapshot = {
packages/client-runtime/src/state/threadShell.ts+1-1
...@@ -202,7 +202,7 @@ export function createEnvironmentThreadShellAtoms(input: {...@@ -202,7 +202,7 @@ export function createEnvironmentThreadShellAtoms(input: {
202 let previousNavigationShells: ReadonlyArray<EnvironmentThreadShell> = [];202 let previousNavigationShells: ReadonlyArray<EnvironmentThreadShell> = [];
203 const navigationThreadShellsAtom = Atom.make((get) => {203 const navigationThreadShellsAtom = Atom.make((get) => {
204 const next: EnvironmentThreadShell[] = [];204 const next: EnvironmentThreadShell[] = [];
205 for (const environmentId of get(input.catalogValueAtom).entries.keys()) {205 for (const environmentId of enabledEnvironmentIds(get(input.catalogValueAtom))) {
206 for (const thread of get(environmentThreadsAtom(environmentId))) {206 for (const thread of get(environmentThreadsAtom(environmentId))) {
207 if (thread.archivedAt !== null || thread.lineage.relationshipToParent === "subagent")207 if (thread.archivedAt !== null || thread.lineage.relationshipToParent === "subagent")
208 continue;208 continue;