refactor: move workspace tab navigation logic to prepareWorkspaceTab
This commit is contained in:
@@ -2,11 +2,7 @@ import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
buildHostAgentDetailRoute,
|
||||
buildHostRootRoute,
|
||||
buildHostWorkspaceAgentRoute,
|
||||
buildHostWorkspaceFileRoute,
|
||||
buildHostWorkspaceRoute,
|
||||
buildHostWorkspaceRouteWithOpenIntent,
|
||||
buildHostWorkspaceTerminalRoute,
|
||||
decodeFilePathFromPathSegment,
|
||||
decodeWorkspaceIdFromPathSegment,
|
||||
encodeFilePathForPathSegment,
|
||||
@@ -65,24 +61,6 @@ describe("workspace route parsing", () => {
|
||||
expect(buildHostRootRoute("local")).toBe("/h/local");
|
||||
});
|
||||
|
||||
it("builds workspace routes with open intent query", () => {
|
||||
expect(buildHostWorkspaceAgentRoute("local", "/tmp/repo", "agent-1")).toBe(
|
||||
"/h/local/workspace/L3RtcC9yZXBv?open=agent%3Aagent-1"
|
||||
);
|
||||
expect(buildHostWorkspaceTerminalRoute("local", "/tmp/repo", "term-1")).toBe(
|
||||
"/h/local/workspace/L3RtcC9yZXBv?open=terminal%3Aterm-1"
|
||||
);
|
||||
expect(buildHostWorkspaceFileRoute("local", "/tmp/repo", "src/index.ts")).toBe(
|
||||
"/h/local/workspace/L3RtcC9yZXBv?open=file%3Ac3JjL2luZGV4LnRz"
|
||||
);
|
||||
expect(
|
||||
buildHostWorkspaceRouteWithOpenIntent("local", "/tmp/repo", {
|
||||
kind: "draft",
|
||||
draftId: "new",
|
||||
})
|
||||
).toBe("/h/local/workspace/L3RtcC9yZXBv?open=draft%3Anew");
|
||||
});
|
||||
|
||||
it("parses workspace open intent from pathname query", () => {
|
||||
expect(
|
||||
parseHostWorkspaceOpenIntentFromPathname(
|
||||
@@ -106,7 +84,7 @@ describe("workspace route parsing", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("keeps agent detail workspace routing on workspace path with open intent", () => {
|
||||
it("uses the plain workspace route when workspace context is provided", () => {
|
||||
expect(buildHostAgentDetailRoute("local", "agent-1", "/tmp/repo")).toBe(
|
||||
"/h/local/workspace/L3RtcC9yZXBv?open=agent%3Aagent-1"
|
||||
);
|
||||
|
||||
@@ -144,29 +144,6 @@ export function parseWorkspaceOpenIntent(
|
||||
return null;
|
||||
}
|
||||
|
||||
export function buildWorkspaceOpenIntentParam(
|
||||
intent: WorkspaceOpenIntent
|
||||
): string | null {
|
||||
if (intent.kind === "agent") {
|
||||
const agentId = trimNonEmpty(intent.agentId);
|
||||
return agentId ? `agent:${agentId}` : null;
|
||||
}
|
||||
if (intent.kind === "terminal") {
|
||||
const terminalId = trimNonEmpty(intent.terminalId);
|
||||
return terminalId ? `terminal:${terminalId}` : null;
|
||||
}
|
||||
if (intent.kind === "draft") {
|
||||
const draftId = trimNonEmpty(intent.draftId);
|
||||
return draftId ? `draft:${draftId}` : null;
|
||||
}
|
||||
const normalizedPath = trimNonEmpty(intent.path);
|
||||
if (!normalizedPath) {
|
||||
return null;
|
||||
}
|
||||
const encodedPath = encodeFilePathForPathSegment(normalizedPath);
|
||||
return encodedPath ? `file:${encodedPath}` : null;
|
||||
}
|
||||
|
||||
export function parseHostWorkspaceOpenIntentFromPathname(
|
||||
pathname: string
|
||||
): WorkspaceOpenIntent | null {
|
||||
@@ -311,55 +288,6 @@ export function buildHostWorkspaceRoute(
|
||||
return `/h/${encodeSegment(normalizedServerId)}/workspace/${encodeSegment(encodedWorkspaceId)}`;
|
||||
}
|
||||
|
||||
export function buildHostWorkspaceRouteWithOpenIntent(
|
||||
serverId: string,
|
||||
workspaceId: string,
|
||||
intent: WorkspaceOpenIntent
|
||||
): string {
|
||||
const base = buildHostWorkspaceRoute(serverId, workspaceId);
|
||||
if (base === "/") {
|
||||
return "/";
|
||||
}
|
||||
const open = buildWorkspaceOpenIntentParam(intent);
|
||||
if (!open) {
|
||||
return "/";
|
||||
}
|
||||
return `${base}?open=${encodeURIComponent(open)}`;
|
||||
}
|
||||
|
||||
export function buildHostWorkspaceAgentRoute(
|
||||
serverId: string,
|
||||
workspaceId: string,
|
||||
agentId: string
|
||||
): string {
|
||||
return buildHostWorkspaceRouteWithOpenIntent(serverId, workspaceId, {
|
||||
kind: "agent",
|
||||
agentId,
|
||||
});
|
||||
}
|
||||
|
||||
export function buildHostWorkspaceTerminalRoute(
|
||||
serverId: string,
|
||||
workspaceId: string,
|
||||
terminalId: string
|
||||
): string {
|
||||
return buildHostWorkspaceRouteWithOpenIntent(serverId, workspaceId, {
|
||||
kind: "terminal",
|
||||
terminalId,
|
||||
});
|
||||
}
|
||||
|
||||
export function buildHostWorkspaceFileRoute(
|
||||
serverId: string,
|
||||
workspaceId: string,
|
||||
filePath: string
|
||||
): string {
|
||||
return buildHostWorkspaceRouteWithOpenIntent(serverId, workspaceId, {
|
||||
kind: "file",
|
||||
path: filePath,
|
||||
});
|
||||
}
|
||||
|
||||
export function buildHostAgentDetailRoute(
|
||||
serverId: string,
|
||||
agentId: string,
|
||||
@@ -367,11 +295,15 @@ export function buildHostAgentDetailRoute(
|
||||
): string {
|
||||
const normalizedWorkspaceId = trimNonEmpty(workspaceId);
|
||||
if (normalizedWorkspaceId) {
|
||||
return buildHostWorkspaceAgentRoute(
|
||||
serverId,
|
||||
normalizedWorkspaceId,
|
||||
agentId
|
||||
);
|
||||
const normalizedAgentId = trimNonEmpty(agentId);
|
||||
if (!normalizedAgentId) {
|
||||
return "/";
|
||||
}
|
||||
const base = buildHostWorkspaceRoute(serverId, normalizedWorkspaceId);
|
||||
if (base === "/") {
|
||||
return "/";
|
||||
}
|
||||
return `${base}?open=${encodeURIComponent(`agent:${normalizedAgentId}`)}`;
|
||||
}
|
||||
const normalizedServerId = trimNonEmpty(serverId);
|
||||
const normalizedAgentId = trimNonEmpty(agentId);
|
||||
@@ -437,19 +369,10 @@ export function mapPathnameToServer(
|
||||
}
|
||||
const workspaceRoute = parseHostWorkspaceRouteFromPathname(pathname);
|
||||
if (workspaceRoute) {
|
||||
const workspacePath = buildHostWorkspaceRoute(
|
||||
return buildHostWorkspaceRoute(
|
||||
normalized,
|
||||
workspaceRoute.workspaceId
|
||||
);
|
||||
const openIntent = parseHostWorkspaceOpenIntentFromPathname(pathname);
|
||||
if (!openIntent) {
|
||||
return workspacePath;
|
||||
}
|
||||
return buildHostWorkspaceRouteWithOpenIntent(
|
||||
normalized,
|
||||
workspaceRoute.workspaceId,
|
||||
openIntent
|
||||
);
|
||||
}
|
||||
if (suffix.startsWith("agent/")) {
|
||||
return `${base}/${suffix}`;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {
|
||||
buildHostAgentDetailRoute,
|
||||
buildHostRootRoute,
|
||||
buildHostWorkspaceAgentRoute,
|
||||
buildHostWorkspaceRoute,
|
||||
} from "@/utils/host-routes";
|
||||
|
||||
type NotificationData = Record<string, unknown> | null | undefined;
|
||||
@@ -36,7 +36,8 @@ export function buildNotificationRoute(data: NotificationData): string {
|
||||
const { serverId, agentId, workspaceId } = resolveNotificationTarget(data);
|
||||
if (serverId && agentId) {
|
||||
if (workspaceId) {
|
||||
return buildHostWorkspaceAgentRoute(serverId, workspaceId, agentId);
|
||||
const base = buildHostWorkspaceRoute(serverId, workspaceId);
|
||||
return `${base}?open=${encodeURIComponent(`agent:${agentId}`)}`;
|
||||
}
|
||||
return buildHostAgentDetailRoute(serverId, agentId);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
import { useWorkspaceLayoutStore } from "@/stores/workspace-layout-store";
|
||||
import { generateDraftId } from "@/stores/draft-keys";
|
||||
import {
|
||||
buildWorkspaceTabPersistenceKey,
|
||||
type WorkspaceTabTarget,
|
||||
} from "@/stores/workspace-tabs-store";
|
||||
import { buildHostWorkspaceRoute } from "@/utils/host-routes";
|
||||
|
||||
interface PrepareWorkspaceTabInput {
|
||||
serverId: string;
|
||||
workspaceId: string;
|
||||
target: WorkspaceTabTarget;
|
||||
pin?: boolean;
|
||||
}
|
||||
|
||||
function getPreparedTarget(target: WorkspaceTabTarget): WorkspaceTabTarget {
|
||||
if (target.kind !== "draft" || target.draftId.trim() !== "new") {
|
||||
return target;
|
||||
}
|
||||
return { kind: "draft", draftId: generateDraftId() };
|
||||
}
|
||||
|
||||
export function prepareWorkspaceTab(input: PrepareWorkspaceTabInput): string {
|
||||
const target = getPreparedTarget(input.target);
|
||||
const key =
|
||||
buildWorkspaceTabPersistenceKey({
|
||||
serverId: input.serverId,
|
||||
workspaceId: input.workspaceId,
|
||||
}) ?? "";
|
||||
|
||||
const tabId = useWorkspaceLayoutStore.getState().openTab(key, target);
|
||||
|
||||
if (tabId) {
|
||||
useWorkspaceLayoutStore.getState().focusTab(key, tabId);
|
||||
}
|
||||
|
||||
if (input.pin && target.kind === "agent") {
|
||||
useWorkspaceLayoutStore.getState().pinAgent(key, target.agentId);
|
||||
}
|
||||
|
||||
return buildHostWorkspaceRoute(input.serverId, input.workspaceId);
|
||||
}
|
||||
Reference in New Issue
Block a user