From 1b5d8efbc30423631b12e713a2f70965f94197f7 Mon Sep 17 00:00:00 2001 From: seb Date: Tue, 6 Oct 2026 12:53:32 +0200 Subject: [PATCH] u --- src/components/chat/ChatAttachmentItems.jsx | 259 +++++++++----------- src/components/chat/HealingMarkdown.jsx | 20 +- 2 files changed, 119 insertions(+), 160 deletions(-) diff --git a/src/components/chat/ChatAttachmentItems.jsx b/src/components/chat/ChatAttachmentItems.jsx index 9932626..4337460 100644 --- a/src/components/chat/ChatAttachmentItems.jsx +++ b/src/components/chat/ChatAttachmentItems.jsx @@ -9,7 +9,6 @@ import Box from '@mui/material/Box'; import Typography from '@mui/material/Typography'; import IconButton from '@mui/material/IconButton'; import CircularProgress from '@mui/material/CircularProgress'; -import Tooltip from '@mui/material/Tooltip'; import CloseRoundedIcon from '@mui/icons-material/CloseRounded'; import PictureAsPdfRoundedIcon from '@mui/icons-material/PictureAsPdfRounded'; import TableChartRoundedIcon from '@mui/icons-material/TableChartRounded'; @@ -399,7 +398,6 @@ export class VfsAttachmentLink extends PureComponent { target="_blank" rel="noopener noreferrer" onClick={this.handleClick} - title={notFound ? 'Nicht mehr vorhanden (404)' : `VFS Bild im neuen Tab öffnen: ${downloadName}`} sx={{ display: 'block', cursor: notFound ? 'not-allowed' : 'pointer', @@ -437,18 +435,17 @@ export class VfsAttachmentLink extends PureComponent { }} > - - {downloadName} + {downloadName} - {effectiveType || 'image'} @@ -457,24 +454,22 @@ export class VfsAttachmentLink extends PureComponent { )} {!notFound && ( <> - - - - - - - - - - + + + + + + )} @@ -483,142 +478,108 @@ export class VfsAttachmentLink extends PureComponent { ); } - const titleText = notFound - ? `Datei nicht mehr im VFS vorhanden (404): ${downloadName}` - : isOpening - ? `Wird im neuen Tab geöffnet…` - : isDownloading - ? `Wird heruntergeladen…` - : canView - ? `In neuem Tab öffnen (${downloadName})` - : `Herunterladen (${downloadName})`; - return ( - - (theme.palette.mode === 'dark' ? 'background.paper' : 'rgba(0, 0, 0, 0.02)')), + textDecoration: notFound ? 'line-through' : 'none', + color: notFound + ? (isUser ? 'rgba(255,255,255,0.6)' : 'text.disabled') + : (isUser ? 'inherit' : 'primary.main'), + opacity: notFound ? 0.7 : ((isDownloading || isOpening) ? 0.75 : 1), + cursor: notFound ? 'not-allowed' : 'pointer', + verticalAlign: 'middle', + maxWidth: '100%', + transition: 'all 150ms ease-in-out', + '&:hover': notFound ? {} : { + bgcolor: isUser ? 'rgba(255, 255, 255, 0.28)' : 'action.hover', + borderColor: isUser ? '#fff' : 'primary.main', + boxShadow: '0 2px 8px rgba(0,0,0,0.1)', + }, + }} + > + (theme.palette.mode === 'dark' ? 'background.paper' : 'rgba(0, 0, 0, 0.02)')), + fontSize: '0.82rem', + fontWeight: 500, + color: 'inherit', + overflow: 'hidden', + textOverflow: 'ellipsis', + whiteSpace: 'nowrap', + lineHeight: 1.25, textDecoration: notFound ? 'line-through' : 'none', - color: notFound - ? (isUser ? 'rgba(255,255,255,0.6)' : 'text.disabled') - : (isUser ? 'inherit' : 'primary.main'), - opacity: notFound ? 0.7 : ((isDownloading || isOpening) ? 0.75 : 1), - cursor: notFound ? 'not-allowed' : 'pointer', - verticalAlign: 'middle', - maxWidth: '100%', - transition: 'all 150ms ease-in-out', - '&:hover': notFound ? {} : { - bgcolor: isUser ? 'rgba(255, 255, 255, 0.28)' : 'action.hover', - borderColor: isUser ? '#fff' : 'primary.main', - boxShadow: '0 2px 8px rgba(0,0,0,0.1)', - }, }} > - {isDownloading || isOpening ? ( - - ) : notFound ? ( - - ) : ( - getAttachmentIcon(effectiveType, downloadName, isUser) - )} - - + {!notFound && ( + e.stopPropagation()} + > + {(isDownloading || isOpening) && ( + + )} + {canView && ( + + + + )} + - {displayName} - - - {notFound - ? 'nicht mehr vorhanden (404)' - : (label && label !== downloadName ? `${downloadName} · ${effectiveType || 'VFS'}` : (effectiveType || 'VFS Datei'))} - + + - {!notFound && ( - e.stopPropagation()} - > - {canView && ( - - - - - - )} - - - - - - - )} - - + )} + ); } } diff --git a/src/components/chat/HealingMarkdown.jsx b/src/components/chat/HealingMarkdown.jsx index 7b5611d..4a576a3 100644 --- a/src/components/chat/HealingMarkdown.jsx +++ b/src/components/chat/HealingMarkdown.jsx @@ -9,7 +9,7 @@ import { TABLE_HEADER_PAIR, byMode, } from '../../colors'; -import { VfsAttachmentLink, parseAttachmentTag, classifyLinkTarget } from './ChatAttachmentItems'; +import { VfsAttachmentLink, parseAttachmentTag, classifyLinkTarget, resolveVfsUrl } from './ChatAttachmentItems'; /** * Healing markdown renderer. @@ -43,16 +43,14 @@ function resolveImageUrl(rawUrl) { const url = String(rawUrl ?? '').trim(); if (!url) return null; if (/^data:image\//i.test(url)) return url; - if (/^https?:\/\//i.test(url) || url.startsWith('/')) return url; - - // Everything else is a VFS name: strip a leading `./`, encode each segment, keep subdirs. - const segments = url - .replace(/^\.\//, '') - .split('/') - .filter((s) => s && s !== '.') - .map((s) => encodeURIComponent(s)); - if (segments.length === 0 || segments.includes('..')) return null; - return `/api/vfs/${segments.join('/')}`; + const classified = classifyLinkTarget(url); + if (classified.kind === 'web') return classified.url; + if (classified.kind === 'vfs') { + if (classified.path.includes('..')) return null; + return resolveVfsUrl(classified.path); + } + if (classified.kind === 'nav') return classified.url; + return null; } /**