refactor: use confirmDialog and unique draft agent IDs
This commit is contained in:
@@ -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}
|
||||
|
||||
Reference in New Issue
Block a user