Make New Workspace an app-wide screen (#1746)

* fix(app): make new workspace global

New Workspace now opens as an app-wide screen. Host and project context can still preselect the form through query params, but the route itself no longer lives under a host.

* fix(app): simplify new workspace selection
This commit is contained in:
Mohamed Boudra
2026-06-26 15:50:02 +08:00
committed by GitHub
parent 14a91d889c
commit 3fbd82664d
14 changed files with 140 additions and 89 deletions
@@ -4,7 +4,7 @@ import { useKeyboardActionHandler } from "@/hooks/use-keyboard-action-handler";
import type { KeyboardActionId } from "@/keyboard/keyboard-action-dispatcher";
import { useActiveWorkspaceSelection } from "@/stores/navigation-active-workspace-store";
import { useSessionStore } from "@/stores/session-store";
import { buildHostNewWorkspaceRoute } from "@/utils/host-routes";
import { buildNewWorkspaceRoute } from "@/utils/host-routes";
import { projectDisplayNameFromProjectId } from "@/utils/project-display-name";
const WORKTREE_NEW_ACTIONS: readonly KeyboardActionId[] = ["worktree.new"];
@@ -14,7 +14,7 @@ export function useActiveWorktreeNewAction() {
const serverId = selection?.serverId ?? null;
const workspaceId = selection?.workspaceId ?? null;
const workingDir = useSessionStore((state) => {
const activeGitWorkspace = useSessionStore((state) => {
if (!serverId || !workspaceId) {
return null;
}
@@ -22,31 +22,30 @@ export function useActiveWorktreeNewAction() {
if (!workspace || workspace.projectKind !== "git") {
return null;
}
return workspace.projectRootPath;
return workspace;
});
const displayName = useSessionStore((state) => {
if (!serverId || !workspaceId) {
return null;
}
const workspace = state.sessions[serverId]?.workspaces?.get(workspaceId);
if (!workspace || workspace.projectKind !== "git") {
return null;
}
return workspace.projectDisplayName || projectDisplayNameFromProjectId(workspace.projectId);
});
const workingDir = activeGitWorkspace?.projectRootPath ?? null;
const projectId = activeGitWorkspace?.projectId ?? null;
const displayName = activeGitWorkspace
? activeGitWorkspace.projectDisplayName ||
projectDisplayNameFromProjectId(activeGitWorkspace.projectId)
: null;
const handle = useCallback(() => {
if (!serverId || !workingDir) {
return false;
}
router.navigate(
buildHostNewWorkspaceRoute(serverId, workingDir, {
buildNewWorkspaceRoute({
serverId,
sourceDirectory: workingDir,
displayName: displayName ?? undefined,
projectId: projectId ?? undefined,
}) as never,
);
return true;
}, [serverId, workingDir, displayName]);
}, [serverId, workingDir, displayName, projectId]);
useKeyboardActionHandler({
handlerId: "worktree-new-active",
@@ -2,27 +2,29 @@ import { useCallback } from "react";
import { router } from "expo-router";
import { useKeyboardActionHandler } from "@/hooks/use-keyboard-action-handler";
import type { KeyboardActionId } from "@/keyboard/keyboard-action-dispatcher";
import { useHosts } from "@/runtime/host-runtime";
import { useActiveWorkspaceSelection } from "@/stores/navigation-active-workspace-store";
import { buildHostNewWorkspaceRoute } from "@/utils/host-routes";
import { buildNewWorkspaceRoute } from "@/utils/host-routes";
const WORKSPACE_NEW_ACTIONS: readonly KeyboardActionId[] = ["workspace.new"];
export function useGlobalNewWorkspaceAction() {
const selection = useActiveWorkspaceSelection();
const serverId = selection?.serverId ?? null;
const hosts = useHosts();
const handle = useCallback(() => {
if (!serverId) {
if (hosts.length === 0) {
return false;
}
router.navigate(buildHostNewWorkspaceRoute(serverId) as never);
router.navigate(buildNewWorkspaceRoute(serverId ? { serverId } : undefined) as never);
return true;
}, [serverId]);
}, [hosts.length, serverId]);
useKeyboardActionHandler({
handlerId: "workspace-new-global",
actions: WORKSPACE_NEW_ACTIONS,
enabled: serverId !== null,
enabled: hosts.length > 0,
priority: 0,
handle,
});