fix: simplify workspace route navigation

This commit is contained in:
Mohamed Boudra
2026-04-14 15:41:49 +07:00
parent d0be7c3ee7
commit 9c90657d60
3 changed files with 88 additions and 17 deletions

View File

@@ -12,6 +12,7 @@ import {
} from "./helpers/new-workspace";
import { createTempGitRepo } from "./helpers/workspace";
import {
expectSidebarWorkspaceSelected,
expectWorkspaceHeader,
switchWorkspaceViaSidebar,
waitForSidebarHydration,
@@ -101,6 +102,87 @@ test.describe("New workspace flow", () => {
}
});
test("same-project workspaces switch content without requiring refresh", async ({ page }) => {
const serverId = process.env.E2E_SERVER_ID;
if (!serverId) {
throw new Error("E2E_SERVER_ID is not set.");
}
const repo = await createTempGitRepo("workspace-nav-same-project-");
try {
const rootWorkspace = await openProjectViaDaemon(client, repo.path);
const worktreeWorkspace = await createWorktreeViaDaemon(client, {
cwd: repo.path,
slug: `nav-${Date.now()}`,
});
localWorkspaceIds.add(rootWorkspace.workspaceId);
createdWorktreeIds.add(worktreeWorkspace.workspaceId);
await gotoAppShell(page);
await waitForSidebarHydration(page);
await switchWorkspaceViaSidebar({
page,
serverId,
targetWorkspacePath: rootWorkspace.workspaceId,
});
await expectWorkspaceHeader(page, {
title: rootWorkspace.workspaceName,
subtitle: rootWorkspace.projectDisplayName,
});
await expectSidebarWorkspaceSelected({
page,
serverId,
workspaceId: rootWorkspace.workspaceId,
});
await switchWorkspaceViaSidebar({
page,
serverId,
targetWorkspacePath: worktreeWorkspace.workspaceId,
});
await expectWorkspaceHeader(page, {
title: worktreeWorkspace.workspaceName,
subtitle: worktreeWorkspace.projectDisplayName,
});
await expectSidebarWorkspaceSelected({
page,
serverId,
workspaceId: worktreeWorkspace.workspaceId,
});
await expectSidebarWorkspaceSelected({
page,
serverId,
workspaceId: rootWorkspace.workspaceId,
selected: false,
});
await switchWorkspaceViaSidebar({
page,
serverId,
targetWorkspacePath: rootWorkspace.workspaceId,
});
await expectWorkspaceHeader(page, {
title: rootWorkspace.workspaceName,
subtitle: rootWorkspace.projectDisplayName,
});
await expectSidebarWorkspaceSelected({
page,
serverId,
workspaceId: rootWorkspace.workspaceId,
});
await expectSidebarWorkspaceSelected({
page,
serverId,
workspaceId: worktreeWorkspace.workspaceId,
selected: false,
});
} finally {
await repo.cleanup();
}
});
test("clicking new workspace redirects, renders header, shows sidebar row, and keeps one draft tab", async ({
page,
}) => {

View File

@@ -811,17 +811,7 @@ function RootStack() {
getId={({ params }) => {
const serverId = getRouteParamValue(params?.serverId);
const workspaceId = getRouteParamValue(params?.workspaceId);
const openIntent = getRouteParamValue(
params && typeof params === "object" && "open" in params
? (params as { open?: string | string[] }).open
: undefined,
);
if (!serverId || !workspaceId) {
return undefined;
}
return openIntent
? `${serverId}:${workspaceId}:open:${openIntent}`
: `${serverId}:${workspaceId}`;
return serverId && workspaceId ? `${serverId}:${workspaceId}` : undefined;
}}
/>
<Stack.Screen name="h/[serverId]/agent/[agentId]" options={{ gestureEnabled: false }} />

View File

@@ -3,7 +3,6 @@ import { useIsFocused, useNavigation } from "@react-navigation/native";
import {
useGlobalSearchParams,
useLocalSearchParams,
usePathname,
useRouter,
useRootNavigationState,
} from "expo-router";
@@ -13,7 +12,6 @@ import { WorkspaceScreen } from "@/screens/workspace/workspace-screen";
import {
buildHostWorkspaceRoute,
decodeWorkspaceIdFromPathSegment,
parseHostWorkspaceRouteFromPathname,
parseWorkspaceOpenIntent,
type WorkspaceOpenIntent,
} from "@/utils/host-routes";
@@ -85,7 +83,6 @@ function HostWorkspaceLayoutContent() {
const rootNavigationState = useRootNavigationState();
const consumedIntentRef = useRef<string | null>(null);
const [intentConsumed, setIntentConsumed] = useState(false);
const pathname = usePathname();
const params = useLocalSearchParams<{
serverId?: string | string[];
workspaceId?: string | string[];
@@ -93,9 +90,11 @@ function HostWorkspaceLayoutContent() {
const globalParams = useGlobalSearchParams<{
open?: string | string[];
}>();
const parsedWorkspaceRoute = parseHostWorkspaceRouteFromPathname(pathname);
const serverId = parsedWorkspaceRoute?.serverId ?? "";
const workspaceId = parsedWorkspaceRoute?.workspaceId ?? "";
const serverId = getParamValue(params.serverId);
const workspaceValue = getParamValue(params.workspaceId);
const workspaceId = workspaceValue
? (decodeWorkspaceIdFromPathSegment(workspaceValue) ?? "")
: "";
const openValue = getParamValue(globalParams.open);
useEffect(() => {