fix(desktop): Windows path separator handling across 10 components

On Windows, Tauri returns paths with backslash separators. Multiple
components used .split('/') to extract filenames/segments, which
returned the entire path as a single element on Windows. Changed all
instances to .split(/[/\]/) to handle both Unix and Windows paths.

Affected: ProjectContextChip, ToolCallBlock, PermissionDialog,
ToolCallGroup, FileSearchMenu, InlineImageGallery,
LocalSlashCommandPanel, ProjectFilter, StatusBar, DirectoryPicker.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-17 18:57:40 +08:00
co-authored by Claude Opus 4.6
parent a4e566019a
commit 1090cd0809
10 changed files with 14 additions and 14 deletions
@@ -137,8 +137,8 @@ export const FileSearchMenu = forwardRef<FileSearchMenuHandle, Props>(({ cwd, fi
// Build breadcrumb segments from current path relative to cwd
const breadcrumbs: string[] = []
if (currentPath !== cwd && currentPath.startsWith(cwd)) {
const rel = currentPath.slice(cwd.length).replace(/^\//, '')
if (rel) breadcrumbs.push(...rel.split('/'))
const rel = currentPath.slice(cwd.length).replace(/^[/\\]/, '')
if (rel) breadcrumbs.push(...rel.split(/[/\\]/))
}
const dirs = entries.filter((e) => e.isDirectory)
@@ -153,7 +153,7 @@ export const FileSearchMenu = forwardRef<FileSearchMenuHandle, Props>(({ cwd, fi
{/* Header with path */}
<div className="flex items-center gap-1.5 border-b border-[var(--color-border)] px-3 py-2 text-[11px]">
<span className="material-symbols-outlined text-[14px] text-[var(--color-text-tertiary)]">folder_open</span>
<span className="text-[var(--color-text-tertiary)] font-mono">{cwd.split('/').pop() || cwd}</span>
<span className="text-[var(--color-text-tertiary)] font-mono">{cwd.split(/[/\\]/).pop() || cwd}</span>
{breadcrumbs.map((seg, i) => (
<span key={i} className="flex items-center gap-1">
<span className="text-[var(--color-text-tertiary)]">/</span>
@@ -32,7 +32,7 @@ function fileUrl(filePath: string): string {
}
function fileName(filePath: string): string {
return filePath.split('/').pop() || filePath
return filePath.split(/[/\\]/).pop() || filePath
}
type Props = {
@@ -59,7 +59,7 @@ function scopeLabel(scope: string, t: ReturnType<typeof useTranslation>) {
function projectBadge(path?: string, t?: ReturnType<typeof useTranslation>) {
if (!path || !t) return null
const label = path.replace(/\/$/, '').split('/').pop() || path
const label = path.replace(/\/$/, '').split(/[/\\]/).pop() || path
return t('slash.mcp.projectBadge', { name: label })
}
@@ -73,7 +73,7 @@ function extractToolDetails(toolName: string, input: unknown, t: (key: Translati
function getPermissionTitle(toolName: string, input: unknown, t: (key: TranslationKey, params?: Record<string, string | number>) => string) {
const obj = (input && typeof input === 'object') ? input as Record<string, unknown> : {}
const filePath = typeof obj.file_path === 'string' ? obj.file_path : ''
const fileName = filePath ? filePath.split('/').pop() || filePath : ''
const fileName = filePath ? filePath.split(/[/\\]/).pop() || filePath : ''
switch (toolName) {
case 'Edit':
@@ -68,7 +68,7 @@ export function ToolCallBlock({ toolName, input, result, compact = false }: Prop
</span>
{filePath ? (
<span className="min-w-0 flex-1 truncate font-[var(--font-mono)] text-[11px] text-[var(--color-text-tertiary)]">
{filePath.split('/').pop()}
{filePath.split(/[/\\]/).pop()}
</span>
) : summary ? (
<span className="min-w-0 flex-1 truncate font-[var(--font-mono)] text-[11px] text-[var(--color-text-tertiary)]">
@@ -518,7 +518,7 @@ function formatRecentToolUseSummary(
case 'Bash':
return `Bash · ${typeof input.command === 'string' ? input.command : ''}${suffix}`
case 'Read':
return `Read · ${typeof input.file_path === 'string' ? input.file_path.split('/').pop() : 'file'}${suffix}`
return `Read · ${typeof input.file_path === 'string' ? input.file_path.split(/[/\\]/).pop() : 'file'}${suffix}`
case 'Glob':
return `Glob · ${typeof input.pattern === 'string' ? input.pattern : ''}${suffix}`
case 'Grep':
@@ -284,8 +284,8 @@ function compareProjectOptions(a: ProjectOption, b: ProjectOption) {
function fallbackProjectTitle(projectPath: string, fallback: string) {
if (!projectPath || projectPath === '_unknown') return fallback
if (projectPath.includes('/')) {
return projectPath.split('/').filter(Boolean).pop() || fallback
if (projectPath.includes('/') || projectPath.includes('\\')) {
return projectPath.split(/[/\\]/).filter(Boolean).pop() || fallback
}
const segments = projectPath.split('-').filter(Boolean)
@@ -12,7 +12,7 @@ export function StatusBar() {
const projectPath = useSessionStore((s) => s.sessions.find((session) => session.id === activeTabId)?.projectPath)
const projectName = projectPath
? projectPath.split('-').filter(Boolean).pop() || ''
? projectPath.split(/[/\\]/).filter(Boolean).pop() || ''
: ''
const modelLabel = runtimeSelection?.modelId ?? currentModel?.name ?? null
@@ -154,7 +154,7 @@ export function DirectoryPicker({ value, onChange }: Props) {
<span className="material-symbols-outlined text-[14px] text-[var(--color-text-secondary)]">folder</span>
)}
<span className="font-medium text-[var(--color-text-primary)]">
{selectedProject?.repoName || selectedProject?.projectName || value.split('/').pop()}
{selectedProject?.repoName || selectedProject?.projectName || value.split(/[/\\]/).pop()}
</span>
{selectedProject?.branch && (
<>
@@ -259,7 +259,7 @@ export function DirectoryPicker({ value, onChange }: Props) {
{'← ' + t('dirPicker.recent')}
</button>
<button onClick={() => loadBrowseDir('/')} className="text-[10px] text-[var(--color-text-tertiary)] hover:text-[var(--color-text-primary)]">/</button>
{browsePath.split('/').filter(Boolean).map((seg, i, arr) => (
{browsePath.split(/[/\\]/).filter(Boolean).map((seg, i, arr) => (
<span key={i} className="flex items-center gap-1">
<span className="text-[10px] text-[var(--color-text-tertiary)]">/</span>
<button
@@ -5,7 +5,7 @@ type Props = {
}
export function ProjectContextChip({ workDir, repoName, branch }: Props) {
const label = branch ? (repoName || workDir?.split('/').pop() || '') : (workDir?.split('/').pop() || repoName || '')
const label = branch ? (repoName || workDir?.split(/[/\\]/).pop() || '') : (workDir?.split(/[/\\]/).pop() || repoName || '')
if (!label) return null