refactor: use confirmDialog and unique draft agent IDs

This commit is contained in:
Mohamed Boudra
2026-03-04 15:28:55 +07:00
parent f47ea7afe5
commit 430ad54d77
5 changed files with 58 additions and 48 deletions
@@ -5,7 +5,6 @@ import {
Image,
Platform,
ActivityIndicator,
Alert,
StatusBar,
ScrollView,
type GestureResponderEvent,
@@ -53,6 +52,7 @@ import { useToast } from '@/contexts/toast-context'
import { useCheckoutGitActionsStore } from '@/stores/checkout-git-actions-store'
import { buildSidebarShortcutModel } from '@/utils/sidebar-shortcuts'
import { hasVisibleOrderChanged, mergeWithRemainder } from '@/utils/sidebar-reorder'
import { confirmDialog } from '@/utils/confirm-dialog'
const PASEO_WORKTREE_PATH_MARKER = '/.paseo/worktrees'
@@ -459,7 +459,6 @@ function WorkspaceRowInner({
dragHandleProps,
menuController,
}: WorkspaceRowInnerProps) {
const { theme } = useUnistyles()
const createdAtLabel = resolveWorkspaceCreatedAtLabel(workspace)
const interaction = useLongPressDragInteraction({
drag,
@@ -547,12 +546,6 @@ function WorkspaceRowInner({
return (
<View style={styles.workspaceRowContainer}>
{content}
{isArchiving ? (
<View style={styles.workspaceArchivingOverlay} testID={`sidebar-workspace-archiving-${workspace.workspaceKey}`}>
<ActivityIndicator size="small" color={theme.colors.foregroundMuted} />
<Text style={styles.workspaceArchivingText}>Archiving</Text>
</View>
) : null}
</View>
)
}
@@ -593,31 +586,28 @@ function WorkspaceRowWithMenu({
return
}
Alert.alert(
'Archive worktree?',
`Archive "${workspace.name}"?\n\nThis removes the worktree from the sidebar.`,
[
{
text: 'Cancel',
style: 'cancel',
},
{
text: 'Archive',
style: 'destructive',
onPress: () => {
void archiveWorktree({
serverId: workspace.serverId,
cwd: workspace.workspaceId,
worktreePath: workspace.workspaceId,
}).catch((error) => {
const message = error instanceof Error ? error.message : 'Failed to archive worktree'
toast.error(message)
})
},
},
],
{ cancelable: true }
)
void (async () => {
const confirmed = await confirmDialog({
title: 'Archive worktree?',
message: `Archive "${workspace.name}"?\n\nThis removes the worktree from the sidebar.`,
confirmLabel: 'Archive',
cancelLabel: 'Cancel',
destructive: true,
})
if (!confirmed) {
return
}
void archiveWorktree({
serverId: workspace.serverId,
cwd: workspace.workspaceId,
worktreePath: workspace.workspaceId,
}).catch((error) => {
const message = error instanceof Error ? error.message : 'Failed to archive worktree'
toast.error(message)
})
})()
}, [archiveWorktree, isArchiving, toast, workspace.name, workspace.serverId, workspace.workspaceId])
return (
@@ -124,19 +124,19 @@ export function useAgentAutocomplete(input: UseAgentAutocompleteInput): AgentAut
[draftConfig]
)
const isRealAgent = Boolean(agentId) && !agentId.startsWith('__')
const queryDraftConfig = isRealAgent ? undefined : normalizedDraftConfig
const canLoadCommands = Boolean(serverId) && (isRealAgent || !!queryDraftConfig)
const isDraftContext = normalizedDraftConfig !== undefined
const queryDraftConfig = isDraftContext ? normalizedDraftConfig : undefined
const canLoadCommands = Boolean(serverId) && (Boolean(agentId) || isDraftContext)
const agentCwd = useSessionStore(
(state) => state.sessions[serverId]?.agents?.get(agentId)?.cwd ?? ''
)
const autocompleteCwd = useMemo(() => {
if (isRealAgent) {
return agentCwd.trim()
if (isDraftContext) {
return queryDraftConfig?.cwd ?? ''
}
return queryDraftConfig?.cwd ?? ''
}, [agentCwd, isRealAgent, queryDraftConfig])
return agentCwd.trim()
}, [agentCwd, isDraftContext, queryDraftConfig])
const { client, isConnected } = useHostRuntimeSession(serverId)
@@ -1,8 +1,30 @@
import { describe, expect, it } from "vitest";
import { canToggleFileExplorerShortcut } from "./keyboard-shortcut-routing";
import {
canToggleFileExplorerShortcut,
resolveSelectedOrRouteAgentKey,
} from "./keyboard-shortcut-routing";
describe("keyboard-shortcut-routing", () => {
describe("resolveSelectedOrRouteAgentKey", () => {
it("returns selected agent key when provided", () => {
const key = resolveSelectedOrRouteAgentKey({
selectedAgentId: "server-1:agent-1",
pathname: "/h/server-1/workspace/workspace-1/tab/draft_123",
});
expect(key).toBe("server-1:agent-1");
});
it("maps workspace draft tabs to the draft tab id key", () => {
const key = resolveSelectedOrRouteAgentKey({
pathname: "/h/server-1/workspace/workspace-1/tab/draft_123",
});
expect(key).toBe("server-1:draft_123");
});
});
describe("canToggleFileExplorerShortcut", () => {
const toggleFileExplorer = () => undefined;
@@ -4,8 +4,6 @@ import {
parseHostWorkspaceTabRouteFromPathname,
} from "@/utils/host-routes";
const DRAFT_AGENT_ID = "__new_agent__";
export function resolveSelectedOrRouteAgentKey(input: {
selectedAgentId?: string;
pathname: string;
@@ -22,7 +20,7 @@ export function resolveSelectedOrRouteAgentKey(input: {
return agentId ? `${workspaceTabRoute.serverId}:${agentId}` : null;
}
if (tabId.startsWith("draft_")) {
return `${workspaceTabRoute.serverId}:${DRAFT_AGENT_ID}`;
return `${workspaceTabRoute.serverId}:${tabId}`;
}
}
@@ -53,7 +53,6 @@ import { useTauriDragHandlers } from '@/utils/tauri-window'
import { useKeyboardShiftStyle } from '@/hooks/use-keyboard-shift-style'
import { normalizeAgentSnapshot } from '@/utils/agent-snapshots'
const DRAFT_AGENT_ID = '__new_agent__'
const EMPTY_PENDING_PERMISSIONS = new Map()
const EMPTY_STREAM_ITEMS: StreamItem[] = []
const MAX_INITIAL_AGENT_TITLE_CHARS = 60
@@ -252,6 +251,7 @@ function DraftAgentScreenContent({
const tauriDragHandlers = useTauriDragHandlers()
const isExplorerOpen = isMobile ? mobileView === 'file-explorer' : desktopFileExplorerOpen
const draftIdRef = useRef(generateDraftId())
const draftAgentIdRef = useRef(generateDraftId())
const [worktreeMode, setWorktreeMode] = useState<'none' | 'create' | 'attach'>('none')
const [baseBranch, setBaseBranch] = useState('')
@@ -866,7 +866,7 @@ function DraftAgentScreenContent({
return {
serverId,
id: DRAFT_AGENT_ID,
id: draftAgentIdRef.current,
provider,
status: 'running',
createdAt: now,
@@ -1160,7 +1160,7 @@ function DraftAgentScreenContent({
{machine.tag === 'creating' && draftAgent && selectedServerId ? (
<View style={styles.streamContainer}>
<AgentStreamView
agentId={DRAFT_AGENT_ID}
agentId={draftAgentIdRef.current}
serverId={selectedServerId}
agent={draftAgent}
streamItems={optimisticStreamItems}
@@ -1346,7 +1346,7 @@ function DraftAgentScreenContent({
</Animated.View>
<View style={styles.inputAreaWrapper}>
<AgentInputArea
agentId={DRAFT_AGENT_ID}
agentId={draftAgentIdRef.current}
serverId={selectedServerId ?? ''}
onSubmitMessage={handleCreateFromInput}
isSubmitLoading={isSubmitting}