diff --git a/src/components/chat/ChatDrawer.jsx b/src/components/chat/ChatDrawer.jsx
index d25e770..a94214c 100644
--- a/src/components/chat/ChatDrawer.jsx
+++ b/src/components/chat/ChatDrawer.jsx
@@ -797,11 +797,11 @@ export default class ChatDrawer extends PureComponent {
)}
-
+
vfsAutomat.actions.toggleVfs()}
- aria-label="VFS Dateisystem"
+ aria-label="Dateien"
sx={{
p: 0.5,
color: isVfsOpen ? 'primary.main' : 'text.secondary',
@@ -1322,36 +1322,54 @@ export default class ChatDrawer extends PureComponent {
)}
- {/* Vertical Split Resizer between VFS and Chat */}
+ {/* Vertical Split Resizer between VFS and Chat (0px width so no layout shift or grey bar) */}
{isVfsOpen && (
+ {/* Invisible wide hit area (16px wide, centered on the 1px border) */}
+ {/* Visual handle indicator on hover / active */}
+
- theme.palette.mode === 'dark' ? 'rgba(255,255,255,0.35)' : 'rgba(0,0,0,0.25)',
+ bgcolor: 'divider',
+ opacity: 0.5,
+ transition: 'background-color 0.15s, height 0.15s, width 0.15s, opacity 0.15s, box-shadow 0.15s',
+ pointerEvents: 'none',
}}
/>
diff --git a/src/components/vfs/VfsEditorPanel.jsx b/src/components/vfs/VfsEditorPanel.jsx
index 0bb9551..5ecce1f 100644
--- a/src/components/vfs/VfsEditorPanel.jsx
+++ b/src/components/vfs/VfsEditorPanel.jsx
@@ -2,7 +2,6 @@ import React, { PureComponent } from 'react';
import Box from '@mui/material/Box';
import Typography from '@mui/material/Typography';
import IconButton from '@mui/material/IconButton';
-import Tooltip from '@mui/material/Tooltip';
import FolderOpenRoundedIcon from '@mui/icons-material/FolderOpenRounded';
import CloseRoundedIcon from '@mui/icons-material/CloseRounded';
@@ -61,13 +60,20 @@ export default class VfsEditorPanel extends PureComponent {
this.unsub?.();
}
- handleMentionInChat = (file) => {
+ handleMentionInChat = (file, lineInfo = null) => {
if (!file) return;
if (this.props.onInsertToChat) {
const isImg = file.isImage;
- const tag = isImg
- ? ``
- : `[${file.name}](${file.name})`;
+ let tag = '';
+ if (lineInfo?.startLine) {
+ const lineRef =
+ lineInfo.startLine === lineInfo.endLine
+ ? `L${lineInfo.startLine}`
+ : `L${lineInfo.startLine}-L${lineInfo.endLine}`;
+ tag = `[${file.name}#${lineRef}](${file.name}#${lineRef})`;
+ } else {
+ tag = isImg ? `` : `[${file.name}](${file.name})`;
+ }
this.props.onInsertToChat(tag);
}
};
@@ -116,7 +122,7 @@ export default class VfsEditorPanel extends PureComponent {
onSave={() => vfsAutomat.actions.saveCurrentFile()}
onClose={() => vfsAutomat.actions.selectFile(null)}
onDownload={() => vfsAutomat.actions.downloadFile(selectedFileName)}
- onMentionInChat={() => this.handleMentionInChat(selectedFile)}
+ onMentionInChat={(lineInfo) => this.handleMentionInChat(selectedFile, lineInfo)}
/>
) : selectedFileName && !selectedFile?.isText ? (
/* Single Column Mode: Preview (Image, PDF, Binary) */
@@ -147,19 +153,17 @@ export default class VfsEditorPanel extends PureComponent {
- VFS Dateisystem
+ Dateien
-
- vfsAutomat.actions.closeVfs()}
- aria-label="VFS schließen"
- >
-
-
-
+ vfsAutomat.actions.closeVfs()}
+ aria-label="VFS schließen"
+ >
+
+
diff --git a/src/components/vfs/VfsFileExplorer.jsx b/src/components/vfs/VfsFileExplorer.jsx
index f582dc2..ada6e12 100644
--- a/src/components/vfs/VfsFileExplorer.jsx
+++ b/src/components/vfs/VfsFileExplorer.jsx
@@ -2,18 +2,14 @@ import React, { PureComponent } from 'react';
import Box from '@mui/material/Box';
import Typography from '@mui/material/Typography';
import IconButton from '@mui/material/IconButton';
-import Button from '@mui/material/Button';
import InputBase from '@mui/material/InputBase';
-import Tooltip from '@mui/material/Tooltip';
import CircularProgress from '@mui/material/CircularProgress';
-import Chip from '@mui/material/Chip';
import Menu from '@mui/material/Menu';
import MenuItem from '@mui/material/MenuItem';
import ListItemIcon from '@mui/material/ListItemIcon';
import ListItemText from '@mui/material/ListItemText';
import SearchRoundedIcon from '@mui/icons-material/SearchRounded';
import ClearRoundedIcon from '@mui/icons-material/ClearRounded';
-import RefreshRoundedIcon from '@mui/icons-material/RefreshRounded';
import NoteAddRoundedIcon from '@mui/icons-material/NoteAddRounded';
import CloudUploadRoundedIcon from '@mui/icons-material/CloudUploadRounded';
import DownloadRoundedIcon from '@mui/icons-material/DownloadRounded';
@@ -28,7 +24,7 @@ import KeyboardArrowRightRoundedIcon from '@mui/icons-material/KeyboardArrowRigh
import ContentCopyRoundedIcon from '@mui/icons-material/ContentCopyRounded';
import ChatBubbleOutlineRoundedIcon from '@mui/icons-material/ChatBubbleOutlineRounded';
-import VfsFileIcon, { getCategoryBadge } from './VfsFileIcon';
+import VfsFileIcon from './VfsFileIcon';
import { formatVfsSize, formatVfsDate } from './vfsUtils';
/**
@@ -336,7 +332,6 @@ export default class VfsFileExplorer extends PureComponent {
renderFileNode = (file, depth) => {
const { selectedFileName, onSelectFile } = this.props;
const isSelected = file.path === selectedFileName;
- const badge = getCategoryBadge(file.path, file.fileData.mime);
return (
-
-
- {file.name}
-
-
- theme.palette.mode === 'dark' ? 'rgba(255,255,255,0.08)' : 'rgba(0,0,0,0.06)',
- color: badge.color,
- }}
- />
-
+
+ {file.name}
+
@@ -417,24 +397,14 @@ export default class VfsFileExplorer extends PureComponent {
sx={{
display: 'flex',
alignItems: 'center',
- gap: 0.2,
opacity: isSelected ? 1 : 0.7,
'&:hover': { opacity: 1 },
}}
>
-
- this.props.onDownload(file.path)}
- sx={{ p: 0.5 }}
- >
-
-
-
-
this.handleOpenMenu(e, file.fileData)}
+ aria-label="Weitere Optionen"
sx={{ p: 0.5 }}
>
@@ -561,62 +531,22 @@ export default class VfsFileExplorer extends PureComponent {
)}
- {/* Explorer Header / Actions */}
+ {/* Explorer Header / Actions Row */}
- {/* Top Bar with Action Buttons */}
-
-
- {loading && }
-
-
-
-
-
-
-
-
-
-
-
-
- }
- onClick={this.handleTriggerUpload}
- sx={{ borderRadius: 2, py: 0.3, px: 1, fontSize: '0.75rem' }}
- >
- Upload
-
-
-
-
- }
- onClick={onOpenNewDialog}
- sx={{ borderRadius: 2, py: 0.3, px: 1, fontSize: '0.75rem' }}
- >
- Neu
-
-
-
-
-
{/* Search Filter Bar */}
({
+ flexGrow: 1,
display: 'flex',
alignItems: 'center',
px: 1,
@@ -638,12 +568,33 @@ export default class VfsFileExplorer extends PureComponent {
onChange={(e) => onSearchChange(e.target.value)}
sx={{ fontSize: '0.82rem' }}
/>
+ {loading && }
{searchQuery && (
onSearchChange('')} sx={{ p: 0.2 }}>
)}
+
+ {/* Upload Icon Button (no word) */}
+
+
+
+
+ {/* New File Icon Button (no word) */}
+
+
+
{/* Scrollable File List */}
diff --git a/src/components/vfs/VfsFilePreview.jsx b/src/components/vfs/VfsFilePreview.jsx
index e1f509b..fc38916 100644
--- a/src/components/vfs/VfsFilePreview.jsx
+++ b/src/components/vfs/VfsFilePreview.jsx
@@ -3,15 +3,13 @@ import Box from '@mui/material/Box';
import Typography from '@mui/material/Typography';
import Button from '@mui/material/Button';
import IconButton from '@mui/material/IconButton';
-import Tooltip from '@mui/material/Tooltip';
-import Chip from '@mui/material/Chip';
import OpenInNewRoundedIcon from '@mui/icons-material/OpenInNewRounded';
import DownloadRoundedIcon from '@mui/icons-material/DownloadRounded';
import CloseRoundedIcon from '@mui/icons-material/CloseRounded';
import ArrowBackRoundedIcon from '@mui/icons-material/ArrowBackRounded';
import ChatBubbleOutlineRoundedIcon from '@mui/icons-material/ChatBubbleOutlineRounded';
-import VfsFileIcon, { getCategoryBadge } from './VfsFileIcon';
+import VfsFileIcon from './VfsFileIcon';
import { formatVfsSize, formatVfsDate } from './vfsUtils';
export default class VfsFilePreview extends PureComponent {
@@ -128,7 +126,6 @@ export default class VfsFilePreview extends PureComponent {
render() {
const { fileName, file, onClose, onDownload, onMentionInChat } = this.props;
- const badge = getCategoryBadge(fileName, file?.mime);
const vfsUrl = `/api/vfs/${encodeURIComponent(fileName).replace(/%2F/g, '/')}?raw=1`;
return (
@@ -149,11 +146,9 @@ export default class VfsFilePreview extends PureComponent {
}}
>
-
-
-
-
-
+
+
+
{fileName}
-
- theme.palette.mode === 'dark' ? 'rgba(255,255,255,0.08)' : 'rgba(0,0,0,0.06)',
- color: badge.color,
- }}
- />
{onMentionInChat && (
-
-
-
-
-
+
+
+
)}
-
-
-
-
-
-
-
-
-
-
-
+
+
+
diff --git a/src/components/vfs/VfsTextEditor.jsx b/src/components/vfs/VfsTextEditor.jsx
index e397c8c..a6f2d1a 100644
--- a/src/components/vfs/VfsTextEditor.jsx
+++ b/src/components/vfs/VfsTextEditor.jsx
@@ -3,16 +3,13 @@ import Box from '@mui/material/Box';
import Typography from '@mui/material/Typography';
import IconButton from '@mui/material/IconButton';
import Button from '@mui/material/Button';
-import Tooltip from '@mui/material/Tooltip';
import CircularProgress from '@mui/material/CircularProgress';
import Chip from '@mui/material/Chip';
import SaveRoundedIcon from '@mui/icons-material/SaveRounded';
import UndoRoundedIcon from '@mui/icons-material/UndoRounded';
-import DownloadRoundedIcon from '@mui/icons-material/DownloadRounded';
import CloseRoundedIcon from '@mui/icons-material/CloseRounded';
import ArrowBackRoundedIcon from '@mui/icons-material/ArrowBackRounded';
import ChatBubbleOutlineRoundedIcon from '@mui/icons-material/ChatBubbleOutlineRounded';
-import WrapTextRoundedIcon from '@mui/icons-material/WrapTextRounded';
import Alert from '@mui/material/Alert';
import VfsFileIcon from './VfsFileIcon';
@@ -69,6 +66,37 @@ export default class VfsTextEditor extends PureComponent {
}
};
+ handleMentionInChat = () => {
+ const ta = this.textareaRef.current;
+ let lineInfo = null;
+ if (ta) {
+ const start = ta.selectionStart;
+ const end = ta.selectionEnd;
+ if (typeof start === 'number' && typeof end === 'number' && end > start) {
+ const content = this.props.content || '';
+ const beforeStart = content.substring(0, start);
+ const startLine = beforeStart.split('\n').length;
+
+ let effectiveEnd = end;
+ if (effectiveEnd > start && content[effectiveEnd - 1] === '\n') {
+ effectiveEnd -= 1;
+ }
+ const beforeEnd = content.substring(0, effectiveEnd);
+ const endLine = Math.max(startLine, beforeEnd.split('\n').length);
+
+ lineInfo = {
+ startLine,
+ endLine,
+ selectedText: content.substring(start, end),
+ };
+ }
+ }
+
+ if (this.props.onMentionInChat) {
+ this.props.onMentionInChat(lineInfo);
+ }
+ };
+
handleKeyDown = (e) => {
// Ctrl+S or Cmd+S -> Save
if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === 's') {
@@ -159,11 +187,9 @@ export default class VfsTextEditor extends PureComponent {
>
{/* File Name & Status */}
-
-
-
-
-
+
+
+
- {isDirty ? (
+ {isDirty && (
- ) : (
-
)}
{/* Action Buttons */}
{onMentionInChat && (
-
-
-
-
-
- )}
-
-
-
-
+
+
-
+ )}
{isDirty && (
-
-
-
-
-
- )}
-
-
-
-
+
+
-
+ )}