mirror of
https://github.com/stablyai/orca.git
synced 2026-09-22 00:02:31 +00:00
fix(editor): keep long file paths distinguishable (#21631)
* fix(editor): keep filename visible in long paths * fix(review): keep diff filenames visible * fix(review): prevent path metadata overlap
This commit is contained in:
@@ -1094,14 +1094,18 @@ html.native-shell .app-layout {
|
||||
.editor-header-text {
|
||||
min-width: 0;
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.editor-header-path {
|
||||
display: block;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
min-width: 0;
|
||||
flex: 0 1 auto;
|
||||
flex: 1 1 auto;
|
||||
padding: 0;
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: var(--muted-foreground);
|
||||
@@ -1116,9 +1120,21 @@ html.native-shell .app-layout {
|
||||
Consolas,
|
||||
monospace;
|
||||
white-space: nowrap;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.path-display-prefix,
|
||||
.editor-header-path-prefix {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
text-align: left;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.path-display-file,
|
||||
.editor-header-path-file {
|
||||
flex: 0 0 auto;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.editor-header-path:hover,
|
||||
@@ -1140,6 +1156,7 @@ html.native-shell .app-layout {
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.editor-header-copy-toast {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { ChevronDown, ChevronRight, ExternalLink, Eye } from 'lucide-react'
|
||||
import type { MouseEvent, ReactElement, ReactNode } from 'react'
|
||||
import { translate } from '@/i18n/i18n'
|
||||
import { splitPathForDisplay } from './editor-path-display'
|
||||
|
||||
export function DiffSectionHeader({
|
||||
path,
|
||||
@@ -25,16 +26,17 @@ export function DiffSectionHeader({
|
||||
onOpenPreview?: (event: MouseEvent) => void
|
||||
trailingContent?: ReactNode
|
||||
}): ReactElement {
|
||||
const displayPath = splitPathForDisplay(path)
|
||||
return (
|
||||
<div
|
||||
className="sticky top-0 z-10 bg-background flex items-center w-full px-3 py-1.5 text-left text-xs hover:bg-accent transition-colors group cursor-pointer"
|
||||
onClick={onToggle}
|
||||
>
|
||||
<span className="min-w-0 flex-1 truncate text-muted-foreground">
|
||||
<span className="flex min-w-0 flex-1 items-center text-muted-foreground">
|
||||
<span
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
className="cursor-copy hover:underline"
|
||||
className="flex min-w-0 flex-1 cursor-copy overflow-hidden hover:underline"
|
||||
onMouseDown={(event) => {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
@@ -60,16 +62,19 @@ export function DiffSectionHeader({
|
||||
}}
|
||||
title={translate('auto.components.editor.DiffSectionHeader.8915726e93', 'Copy path')}
|
||||
>
|
||||
{path}
|
||||
<span className="path-display-prefix">{displayPath.prefix}</span>
|
||||
<span className="path-display-file">{displayPath.fileName}</span>
|
||||
</span>
|
||||
<span className="flex shrink-0 items-center">
|
||||
{dirty && <span className="font-medium ml-1">M</span>}
|
||||
{(added > 0 || removed > 0) && (
|
||||
<span className="tabular-nums ml-2">
|
||||
{added > 0 && <span className="text-green-600 dark:text-green-500">+{added}</span>}
|
||||
{added > 0 && removed > 0 && <span> </span>}
|
||||
{removed > 0 && <span className="text-red-500">-{removed}</span>}
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
{dirty && <span className="font-medium ml-1">M</span>}
|
||||
{(added > 0 || removed > 0) && (
|
||||
<span className="tabular-nums ml-2">
|
||||
{added > 0 && <span className="text-green-600 dark:text-green-500">+{added}</span>}
|
||||
{added > 0 && removed > 0 && <span> </span>}
|
||||
{removed > 0 && <span className="text-red-500">-{removed}</span>}
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
<div className="flex items-center gap-1 shrink-0 ml-2">
|
||||
{trailingContent}
|
||||
|
||||
@@ -15,6 +15,7 @@ import type { OpenFile } from '@/store/slices/editor'
|
||||
import { CLOSE_ALL_CONTEXT_MENUS_EVENT } from '../tab-bar/SortableTab'
|
||||
import { useEditorHeaderFileRename } from './editor-header-file-rename'
|
||||
import { getEditorHeaderCopyState } from './editor-header'
|
||||
import { splitPathForDisplay } from './editor-path-display'
|
||||
|
||||
const isMac = navigator.userAgent.includes('Mac')
|
||||
const isLinux = navigator.userAgent.includes('Linux')
|
||||
@@ -55,6 +56,7 @@ export function EditorPanelHeaderPath({
|
||||
const [pathMenuPoint, setPathMenuPoint] = useState({ x: 0, y: 0 })
|
||||
const skipMenuFocusRestoreRef = useRef(false)
|
||||
const headerCopyState = getEditorHeaderCopyState(activeFile)
|
||||
const displayPath = splitPathForDisplay(headerCopyState.pathLabel)
|
||||
const canCopyHeaderPath = headerCopyState.copyText !== null
|
||||
const isVirtualEditorTab = activeFile.mode === 'check-details'
|
||||
const markdownPreviewShortcutLabel = useShortcutLabel('editor.markdownPreview')
|
||||
@@ -124,7 +126,8 @@ export function EditorPanelHeaderPath({
|
||||
disabled={!canCopyHeaderPath}
|
||||
title={headerCopyState.pathTitle}
|
||||
>
|
||||
{headerCopyState.pathLabel}
|
||||
<span className="editor-header-path-prefix">{displayPath.prefix}</span>
|
||||
<span className="editor-header-path-file">{displayPath.fileName}</span>
|
||||
</button>
|
||||
)}
|
||||
<span
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { splitPathForDisplay } from './editor-path-display'
|
||||
|
||||
describe('splitPathForDisplay', () => {
|
||||
it.each([
|
||||
['/repo/src/file.ts', { prefix: '/repo/src/', fileName: 'file.ts' }],
|
||||
['C:\\repo\\src\\file.ts', { prefix: 'C:\\repo\\src\\', fileName: 'file.ts' }],
|
||||
['file.ts', { prefix: '', fileName: 'file.ts' }]
|
||||
])('keeps the final filename separate for %s', (path, expected) => {
|
||||
expect(splitPathForDisplay(path)).toEqual(expected)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,10 @@
|
||||
export function splitPathForDisplay(path: string): { prefix: string; fileName: string } {
|
||||
const separatorIndex = Math.max(path.lastIndexOf('/'), path.lastIndexOf('\\'))
|
||||
if (separatorIndex < 0) {
|
||||
return { prefix: '', fileName: path }
|
||||
}
|
||||
return {
|
||||
prefix: path.slice(0, separatorIndex + 1),
|
||||
fileName: path.slice(separatorIndex + 1)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user