Bound retained workspace screens (#1472)

* fix(app): prune retained workspace deck entries

* fix(app): narrow workspace deck retention selectors

* fix(app): preserve deck lru during route transitions

* test(app): update startup reconnect expectation
This commit is contained in:
Mohamed Boudra
2026-06-11 17:00:05 +00:00
committed by GitHub
parent c0614c3207
commit 62d9e656d7
7 changed files with 317 additions and 34 deletions
@@ -0,0 +1,107 @@
import { describe, expect, it } from "vitest";
import type { ActiveWorkspaceSelection } from "@/stores/navigation-active-workspace-store";
import {
pruneMountedWorkspaceSelections,
shouldKeepWorkspaceDeckEntryMounted,
} from "@/screens/workspace/workspace-deck-retention";
function workspace(workspaceId: string, serverId = "server"): ActiveWorkspaceSelection {
return { serverId, workspaceId };
}
function mountedWorkspaceIds(selections: ActiveWorkspaceSelection[]): string[] {
return selections.map((selection) => selection.workspaceId);
}
describe("pruneMountedWorkspaceSelections", () => {
it("keeps the active workspace and the two most recent inactive workspaces", () => {
const mountedAfterA = pruneMountedWorkspaceSelections({
currentSelections: [],
activeSelection: workspace("A"),
});
const mountedAfterB = pruneMountedWorkspaceSelections({
currentSelections: mountedAfterA,
activeSelection: workspace("B"),
});
const mountedAfterC = pruneMountedWorkspaceSelections({
currentSelections: mountedAfterB,
activeSelection: workspace("C"),
});
const mountedAfterD = pruneMountedWorkspaceSelections({
currentSelections: mountedAfterC,
activeSelection: workspace("D"),
});
expect(mountedWorkspaceIds(mountedAfterD)).toEqual(["D", "C", "B"]);
});
it("retains the active workspace", () => {
const mountedSelections = pruneMountedWorkspaceSelections({
currentSelections: [workspace("A")],
activeSelection: workspace("A"),
});
expect(mountedWorkspaceIds(mountedSelections)).toEqual(["A"]);
});
it("deduplicates retained workspace selections", () => {
const mountedSelections = pruneMountedWorkspaceSelections({
currentSelections: [workspace("B"), workspace("A"), workspace("B")],
activeSelection: workspace("A"),
});
expect(mountedWorkspaceIds(mountedSelections)).toEqual(["A", "B"]);
});
it("always allows at least the active workspace", () => {
const mountedSelections = pruneMountedWorkspaceSelections({
currentSelections: [workspace("A"), workspace("B")],
activeSelection: workspace("C"),
maxMountedWorkspaces: 0,
});
expect(mountedWorkspaceIds(mountedSelections)).toEqual(["C"]);
});
});
describe("shouldKeepWorkspaceDeckEntryMounted", () => {
it("keeps the active workspace mounted even when it is missing from hydrated workspaces", () => {
expect(
shouldKeepWorkspaceDeckEntryMounted({
isActive: true,
hasHydratedWorkspaces: true,
workspaceExists: false,
}),
).toBe(true);
});
it("keeps inactive workspaces mounted until workspace hydration finishes", () => {
expect(
shouldKeepWorkspaceDeckEntryMounted({
isActive: false,
hasHydratedWorkspaces: false,
workspaceExists: false,
}),
).toBe(true);
});
it("unmounts inactive workspaces that are gone after hydration", () => {
expect(
shouldKeepWorkspaceDeckEntryMounted({
isActive: false,
hasHydratedWorkspaces: true,
workspaceExists: false,
}),
).toBe(false);
});
it("keeps inactive workspaces that still exist after hydration", () => {
expect(
shouldKeepWorkspaceDeckEntryMounted({
isActive: false,
hasHydratedWorkspaces: true,
workspaceExists: true,
}),
).toBe(true);
});
});
@@ -0,0 +1,89 @@
import type { ActiveWorkspaceSelection } from "@/stores/navigation-active-workspace-store";
export const WORKSPACE_DECK_MAX_MOUNTED_WORKSPACES = 3;
interface PruneMountedWorkspaceSelectionsInput {
currentSelections: ActiveWorkspaceSelection[];
activeSelection: ActiveWorkspaceSelection | null;
maxMountedWorkspaces?: number;
}
interface WorkspaceDeckEntryMountInput {
isActive: boolean;
hasHydratedWorkspaces: boolean;
workspaceExists: boolean;
}
export function getWorkspaceSelectionKey(selection: ActiveWorkspaceSelection): string {
return `${selection.serverId}:${selection.workspaceId}`;
}
export function areWorkspaceSelectionsEqual(
left: ActiveWorkspaceSelection | null,
right: ActiveWorkspaceSelection | null,
): boolean {
return left?.serverId === right?.serverId && left?.workspaceId === right?.workspaceId;
}
export function areWorkspaceSelectionListsEqual(
left: ActiveWorkspaceSelection[],
right: ActiveWorkspaceSelection[],
): boolean {
if (left.length !== right.length) {
return false;
}
return left.every((selection, index) =>
areWorkspaceSelectionsEqual(selection, right[index] ?? null),
);
}
export function pruneMountedWorkspaceSelections({
currentSelections,
activeSelection,
maxMountedWorkspaces = WORKSPACE_DECK_MAX_MOUNTED_WORKSPACES,
}: PruneMountedWorkspaceSelectionsInput): ActiveWorkspaceSelection[] {
if (!activeSelection) {
return [];
}
const maxSelections = Math.max(1, maxMountedWorkspaces);
const nextSelections: ActiveWorkspaceSelection[] = [];
const seenSelectionKeys = new Set<string>();
function appendSelection(selection: ActiveWorkspaceSelection): void {
if (nextSelections.length >= maxSelections) {
return;
}
const selectionKey = getWorkspaceSelectionKey(selection);
if (seenSelectionKeys.has(selectionKey)) {
return;
}
seenSelectionKeys.add(selectionKey);
nextSelections.push(selection);
}
appendSelection(activeSelection);
for (const selection of currentSelections) {
if (areWorkspaceSelectionsEqual(selection, activeSelection)) {
continue;
}
appendSelection(selection);
}
return nextSelections;
}
export function shouldKeepWorkspaceDeckEntryMounted({
isActive,
hasHydratedWorkspaces,
workspaceExists,
}: WorkspaceDeckEntryMountInput): boolean {
if (isActive) {
return true;
}
if (!hasHydratedWorkspaces) {
return true;
}
return workspaceExists;
}