Keep New Workspace on the current project (#1806)
* fix(app): keep New Workspace on the active project New Workspace preselection was falling back to stale remembered host state when multiple hosts existed. Pass durable active-project context from workspace entry points and centralize initial host selection so stale offline hosts cannot steal the form while startup restore remains last-workspace only. * fix(app): address New Workspace review feedback * fix(app): stabilize New Workspace host selection * fix(app): preserve New Workspace host fallback * test(app): loosen stale-host project assertion * fix(app): prefer reachable new workspace hosts * fix(app): avoid stale offline workspace preselect * fix(app): prefer online project hosts
This commit is contained in:
@@ -3,9 +3,8 @@ import { router } from "expo-router";
|
||||
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 { useWorkspace } from "@/stores/session-store-hooks";
|
||||
import { buildNewWorkspaceRoute } from "@/utils/host-routes";
|
||||
import { projectDisplayNameFromProjectId } from "@/utils/project-display-name";
|
||||
|
||||
const WORKTREE_NEW_ACTIONS: readonly KeyboardActionId[] = ["worktree.new"];
|
||||
|
||||
@@ -13,44 +12,27 @@ export function useActiveWorktreeNewAction() {
|
||||
const selection = useActiveWorkspaceSelection();
|
||||
const serverId = selection?.serverId ?? null;
|
||||
const workspaceId = selection?.workspaceId ?? null;
|
||||
|
||||
const activeGitWorkspace = useSessionStore((state) => {
|
||||
if (!serverId || !workspaceId) {
|
||||
return null;
|
||||
}
|
||||
const workspace = state.sessions[serverId]?.workspaces?.get(workspaceId);
|
||||
if (!workspace || workspace.projectKind !== "git") {
|
||||
return null;
|
||||
}
|
||||
return workspace;
|
||||
});
|
||||
|
||||
const workingDir = activeGitWorkspace?.projectRootPath ?? null;
|
||||
const projectId = activeGitWorkspace?.projectId ?? null;
|
||||
const displayName = activeGitWorkspace
|
||||
? activeGitWorkspace.projectDisplayName ||
|
||||
projectDisplayNameFromProjectId(activeGitWorkspace.projectId)
|
||||
: null;
|
||||
const activeWorkspace = useWorkspace(serverId, workspaceId);
|
||||
const activeGitWorkspace = activeWorkspace?.projectKind === "git" ? activeWorkspace : null;
|
||||
|
||||
const handle = useCallback(() => {
|
||||
if (!serverId || !workingDir) {
|
||||
if (!serverId || !activeGitWorkspace) {
|
||||
return false;
|
||||
}
|
||||
router.navigate(
|
||||
buildNewWorkspaceRoute({
|
||||
serverId,
|
||||
sourceDirectory: workingDir,
|
||||
displayName: displayName ?? undefined,
|
||||
projectId: projectId ?? undefined,
|
||||
sourceDirectory: activeGitWorkspace.projectRootPath,
|
||||
projectId: activeGitWorkspace.projectId,
|
||||
}) as never,
|
||||
);
|
||||
return true;
|
||||
}, [serverId, workingDir, displayName, projectId]);
|
||||
}, [activeGitWorkspace, serverId]);
|
||||
|
||||
useKeyboardActionHandler({
|
||||
handlerId: "worktree-new-active",
|
||||
actions: WORKTREE_NEW_ACTIONS,
|
||||
enabled: serverId !== null && workingDir !== null,
|
||||
enabled: serverId !== null && activeGitWorkspace !== null,
|
||||
priority: 0,
|
||||
handle,
|
||||
});
|
||||
|
||||
@@ -2,8 +2,11 @@ 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 { canCreateWorktreeForProjectKind } from "@/projects/host-projects";
|
||||
import { useHostFeature } from "@/runtime/host-features";
|
||||
import { useHosts } from "@/runtime/host-runtime";
|
||||
import { useActiveWorkspaceSelection } from "@/stores/navigation-active-workspace-store";
|
||||
import { useWorkspace } from "@/stores/session-store-hooks";
|
||||
import { buildNewWorkspaceRoute } from "@/utils/host-routes";
|
||||
|
||||
const WORKSPACE_NEW_ACTIONS: readonly KeyboardActionId[] = ["workspace.new"];
|
||||
@@ -11,15 +14,34 @@ const WORKSPACE_NEW_ACTIONS: readonly KeyboardActionId[] = ["workspace.new"];
|
||||
export function useGlobalNewWorkspaceAction() {
|
||||
const selection = useActiveWorkspaceSelection();
|
||||
const serverId = selection?.serverId ?? null;
|
||||
const workspaceId = selection?.workspaceId ?? null;
|
||||
const hosts = useHosts();
|
||||
const activeWorkspace = useWorkspace(serverId, workspaceId);
|
||||
const supportsWorkspaceMultiplicity = useHostFeature(serverId, "workspaceMultiplicity");
|
||||
const canUseActiveWorkspaceContext = Boolean(
|
||||
activeWorkspace &&
|
||||
(supportsWorkspaceMultiplicity || canCreateWorktreeForProjectKind(activeWorkspace.projectKind)),
|
||||
);
|
||||
|
||||
const handle = useCallback(() => {
|
||||
if (hosts.length === 0) {
|
||||
return false;
|
||||
}
|
||||
router.navigate(buildNewWorkspaceRoute(serverId ? { serverId } : undefined) as never);
|
||||
router.navigate(
|
||||
(serverId
|
||||
? buildNewWorkspaceRoute(
|
||||
activeWorkspace && canUseActiveWorkspaceContext
|
||||
? {
|
||||
serverId,
|
||||
sourceDirectory: activeWorkspace.projectRootPath,
|
||||
projectId: activeWorkspace.projectId,
|
||||
}
|
||||
: { serverId },
|
||||
)
|
||||
: buildNewWorkspaceRoute()) as never,
|
||||
);
|
||||
return true;
|
||||
}, [hosts.length, serverId]);
|
||||
}, [activeWorkspace, canUseActiveWorkspaceContext, hosts.length, serverId]);
|
||||
|
||||
useKeyboardActionHandler({
|
||||
handlerId: "workspace-new-global",
|
||||
|
||||
Reference in New Issue
Block a user