文件搜索结果里对目录图标着色
This commit is contained in:
@@ -142,7 +142,8 @@ export function SearchCommandDialog({
|
|||||||
entry.relativePath
|
entry.relativePath
|
||||||
)
|
)
|
||||||
const lastSlash = entry.relativePath.lastIndexOf("/")
|
const lastSlash = entry.relativePath.lastIndexOf("/")
|
||||||
const dir = lastSlash === -1 ? "" : entry.relativePath.slice(0, lastSlash)
|
const dir =
|
||||||
|
lastSlash === -1 ? "" : entry.relativePath.slice(0, lastSlash)
|
||||||
matchers.push({
|
matchers.push({
|
||||||
prefix: dir ? dir + "/" : "",
|
prefix: dir ? dir + "/" : "",
|
||||||
matcher: ig().add(result.content),
|
matcher: ig().add(result.content),
|
||||||
@@ -168,8 +169,7 @@ export function SearchCommandDialog({
|
|||||||
if (!f.relativePath.startsWith(prefix)) continue
|
if (!f.relativePath.startsWith(prefix)) continue
|
||||||
const relPath = f.relativePath.slice(prefix.length)
|
const relPath = f.relativePath.slice(prefix.length)
|
||||||
if (!relPath) continue
|
if (!relPath) continue
|
||||||
const testPath =
|
const testPath = f.kind === "dir" ? `${relPath}/` : relPath
|
||||||
f.kind === "dir" ? `${relPath}/` : relPath
|
|
||||||
if (matcher.ignores(testPath)) {
|
if (matcher.ignores(testPath)) {
|
||||||
if (f.kind === "dir") ignoredDirs.add(f.relativePath)
|
if (f.kind === "dir") ignoredDirs.add(f.relativePath)
|
||||||
return false
|
return false
|
||||||
@@ -284,9 +284,7 @@ export function SearchCommandDialog({
|
|||||||
)
|
)
|
||||||
|
|
||||||
const placeholder =
|
const placeholder =
|
||||||
activeTab === "conversations"
|
activeTab === "conversations" ? t("placeholder") : t("filePlaceholder")
|
||||||
? t("placeholder")
|
|
||||||
: t("filePlaceholder")
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CommandDialog
|
<CommandDialog
|
||||||
@@ -387,9 +385,8 @@ export function SearchCommandDialog({
|
|||||||
<span
|
<span
|
||||||
className={cn(
|
className={cn(
|
||||||
"w-2 h-2 rounded-full shrink-0",
|
"w-2 h-2 rounded-full shrink-0",
|
||||||
STATUS_COLORS[
|
STATUS_COLORS[conv.status as ConversationStatus] ??
|
||||||
conv.status as ConversationStatus
|
"bg-gray-400"
|
||||||
] ?? "bg-gray-400"
|
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<span className="flex-1 truncate">
|
<span className="flex-1 truncate">
|
||||||
@@ -430,13 +427,11 @@ export function SearchCommandDialog({
|
|||||||
onSelect={() => handleSelectFile(entry)}
|
onSelect={() => handleSelectFile(entry)}
|
||||||
>
|
>
|
||||||
{entry.kind === "dir" ? (
|
{entry.kind === "dir" ? (
|
||||||
<Folder className="w-4 h-4 shrink-0 text-muted-foreground" />
|
<Folder className="w-4 h-4 shrink-0 text-blue-500" />
|
||||||
) : (
|
) : (
|
||||||
<File className="w-4 h-4 shrink-0 text-muted-foreground" />
|
<File className="w-4 h-4 shrink-0 text-muted-foreground" />
|
||||||
)}
|
)}
|
||||||
<span className="flex-1 truncate">
|
<span className="flex-1 truncate">{entry.name}</span>
|
||||||
{entry.name}
|
|
||||||
</span>
|
|
||||||
<span className="text-xs text-muted-foreground shrink-0 truncate max-w-48">
|
<span className="text-xs text-muted-foreground shrink-0 truncate max-w-48">
|
||||||
{entry.relativePath}
|
{entry.relativePath}
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -2321,7 +2321,9 @@ export function FileTreeTab() {
|
|||||||
<DialogContent
|
<DialogContent
|
||||||
onOpenAutoFocus={(e) => {
|
onOpenAutoFocus={(e) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
const input = (e.currentTarget as HTMLElement | null)?.querySelector("input")
|
const input = (
|
||||||
|
e.currentTarget as HTMLElement | null
|
||||||
|
)?.querySelector("input")
|
||||||
if (input) requestAnimationFrame(() => input.focus())
|
if (input) requestAnimationFrame(() => input.focus())
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -2388,7 +2390,9 @@ export function FileTreeTab() {
|
|||||||
<DialogContent
|
<DialogContent
|
||||||
onOpenAutoFocus={(e) => {
|
onOpenAutoFocus={(e) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
const input = (e.currentTarget as HTMLElement | null)?.querySelector("input")
|
const input = (
|
||||||
|
e.currentTarget as HTMLElement | null
|
||||||
|
)?.querySelector("input")
|
||||||
if (input) requestAnimationFrame(() => input.focus())
|
if (input) requestAnimationFrame(() => input.focus())
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -26,13 +26,15 @@ export function AuxPanel() {
|
|||||||
activeTab === "git_log"
|
activeTab === "git_log"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Sync mount flags when activeTab changes programmatically (e.g. revealInFileTree)
|
// Sync mount flags when activeTab changes programmatically (e.g. revealInFileTree).
|
||||||
|
/* eslint-disable react-hooks/set-state-in-effect */
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isOpen) return
|
if (!isOpen) return
|
||||||
if (activeTab === "file_tree") setHasMountedFileTree(true)
|
if (activeTab === "file_tree") setHasMountedFileTree(true)
|
||||||
else if (activeTab === "changes") setHasMountedChanges(true)
|
else if (activeTab === "changes") setHasMountedChanges(true)
|
||||||
else if (activeTab === "git_log") setHasMountedGitLog(true)
|
else if (activeTab === "git_log") setHasMountedGitLog(true)
|
||||||
}, [isOpen, activeTab])
|
}, [isOpen, activeTab])
|
||||||
|
/* eslint-enable react-hooks/set-state-in-effect */
|
||||||
|
|
||||||
const handleTabValueChange = useCallback(
|
const handleTabValueChange = useCallback(
|
||||||
(value: string) => {
|
(value: string) => {
|
||||||
|
|||||||
@@ -2040,10 +2040,7 @@ function hasComparableVersion(
|
|||||||
}
|
}
|
||||||
|
|
||||||
function buildVersionCheck(agent: AcpAgentInfo): UiCheckItem | null {
|
function buildVersionCheck(agent: AcpAgentInfo): UiCheckItem | null {
|
||||||
if (
|
if (agent.distribution_type !== "binary" && agent.distribution_type !== "npx")
|
||||||
agent.distribution_type !== "binary" &&
|
|
||||||
agent.distribution_type !== "npx"
|
|
||||||
)
|
|
||||||
return null
|
return null
|
||||||
|
|
||||||
const remoteVersion = agent.registry_version ?? "unknown"
|
const remoteVersion = agent.registry_version ?? "unknown"
|
||||||
@@ -2390,46 +2387,51 @@ export function AcpAgentSettings() {
|
|||||||
|
|
||||||
const runPreflight = useCallback(
|
const runPreflight = useCallback(
|
||||||
async (agentType: AgentType, forceRefresh?: boolean) => {
|
async (agentType: AgentType, forceRefresh?: boolean) => {
|
||||||
setChecking((prev) => ({ ...prev, [agentType]: true }))
|
setChecking((prev) => ({ ...prev, [agentType]: true }))
|
||||||
try {
|
try {
|
||||||
const [resultState, versionState] = await Promise.allSettled([
|
const [resultState, versionState] = await Promise.allSettled([
|
||||||
acpPreflight(agentType, forceRefresh),
|
acpPreflight(agentType, forceRefresh),
|
||||||
acpDetectAgentLocalVersion(agentType),
|
acpDetectAgentLocalVersion(agentType),
|
||||||
])
|
])
|
||||||
|
|
||||||
if (versionState.status === "fulfilled") {
|
if (versionState.status === "fulfilled") {
|
||||||
setAgents((prev) => {
|
setAgents((prev) => {
|
||||||
if (versionState.value === null) return prev
|
if (versionState.value === null) return prev
|
||||||
let changed = false
|
let changed = false
|
||||||
const next = prev.map((agent) => {
|
const next = prev.map((agent) => {
|
||||||
if (agent.agent_type !== agentType) return agent
|
if (agent.agent_type !== agentType) return agent
|
||||||
if (agent.installed_version === versionState.value) return agent
|
if (agent.installed_version === versionState.value) return agent
|
||||||
changed = true
|
changed = true
|
||||||
return { ...agent, installed_version: versionState.value }
|
return { ...agent, installed_version: versionState.value }
|
||||||
|
})
|
||||||
|
return changed ? next : prev
|
||||||
})
|
})
|
||||||
return changed ? next : prev
|
}
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (resultState.status === "fulfilled") {
|
if (resultState.status === "fulfilled") {
|
||||||
setCheckState((prev) => ({
|
setCheckState((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
[agentType]: { result: resultState.value },
|
[agentType]: { result: resultState.value },
|
||||||
}))
|
}))
|
||||||
} else {
|
} else {
|
||||||
const message =
|
const message =
|
||||||
resultState.reason instanceof Error
|
resultState.reason instanceof Error
|
||||||
? resultState.reason.message
|
? resultState.reason.message
|
||||||
: String(resultState.reason)
|
: String(resultState.reason)
|
||||||
|
setCheckState((prev) => ({
|
||||||
|
...prev,
|
||||||
|
[agentType]: { error: message },
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
const message = err instanceof Error ? err.message : String(err)
|
||||||
setCheckState((prev) => ({ ...prev, [agentType]: { error: message } }))
|
setCheckState((prev) => ({ ...prev, [agentType]: { error: message } }))
|
||||||
|
} finally {
|
||||||
|
setChecking((prev) => ({ ...prev, [agentType]: false }))
|
||||||
}
|
}
|
||||||
} catch (err) {
|
},
|
||||||
const message = err instanceof Error ? err.message : String(err)
|
[]
|
||||||
setCheckState((prev) => ({ ...prev, [agentType]: { error: message } }))
|
)
|
||||||
} finally {
|
|
||||||
setChecking((prev) => ({ ...prev, [agentType]: false }))
|
|
||||||
}
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
const runAllPreflight = useCallback(
|
const runAllPreflight = useCallback(
|
||||||
async (agentTypes: AgentType[]) => {
|
async (agentTypes: AgentType[]) => {
|
||||||
@@ -2790,10 +2792,7 @@ export function AcpAgentSettings() {
|
|||||||
await runNpxAction(agent, "upgrade")
|
await runNpxAction(agent, "upgrade")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (
|
if (action.kind === "uninstall_binary" || action.kind === "uninstall_npx") {
|
||||||
action.kind === "uninstall_binary" ||
|
|
||||||
action.kind === "uninstall_npx"
|
|
||||||
) {
|
|
||||||
setUninstallConfirmAgent(agent)
|
setUninstallConfirmAgent(agent)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user