(undefined);
@@ -806,17 +841,7 @@ export default function FileExplorer({ onLogout }: FileExplorerProps) {
if (isMedia && file.checksum && viewMode === 'grid') {
return (
-
})
{
- e.currentTarget.style.display = 'none';
- const next = e.currentTarget.nextElementSibling as HTMLElement;
- if (next) next.style.display = 'block';
- }}
- />
-
{fallbackIcon}
+
);
}
@@ -977,16 +1002,24 @@ export default function FileExplorer({ onLogout }: FileExplorerProps) {
}}
onDragOver={(e) => {
e.preventDefault();
+ setDragOverPinnedItem(file.path);
+ }}
+ onDragLeave={() => {
+ setDragOverPinnedItem(null);
}}
onDrop={(e) => {
e.preventDefault();
+ setDragOverPinnedItem(null);
const source = e.dataTransfer.getData('text/plain');
if (source && source !== file.path) {
handlePinnedDragEnd(source, file.path);
}
}}
className="group flex items-center justify-between px-10 py-2 text-sm font-medium cursor-pointer rounded-lg transition-colors hover:bg-white/5 gap-3"
- style={{ color: 'var(--color-text-secondary)' }}
+ style={{
+ color: 'var(--color-text-secondary)',
+ borderTop: dragOverPinnedItem === file.path ? '2px solid var(--color-accent)' : '2px solid transparent',
+ }}
onClick={() => { setActiveSection('files'); navigateTo(file.path); }}
>
diff --git a/frontend/src/components/FilePreview.tsx b/frontend/src/components/FilePreview.tsx
index bffa7d2..915dbd5 100644
--- a/frontend/src/components/FilePreview.tsx
+++ b/frontend/src/components/FilePreview.tsx
@@ -5,6 +5,8 @@ import { motion, AnimatePresence } from 'framer-motion';
import { X, Download, File, Image as ImageIcon, Film, Music, FileText, Code, Loader2 } from 'lucide-react';
import api from '@/lib/api';
import dynamic from 'next/dynamic';
+import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
+import { vscDarkPlus } from 'react-syntax-highlighter/dist/esm/styles/prism';
const DynamicPdfViewer = dynamic(() => import('./PdfViewer'), { ssr: false });
@@ -83,9 +85,9 @@ export default function FilePreview({ file, onClose }: FilePreviewProps) {
exit={{ scale: 0.95, opacity: 0, y: 20 }}
onClick={(e) => e.stopPropagation()}
className={`relative flex flex-col max-w-[95vw] max-h-[95vh] rounded-2xl overflow-hidden shadow-2xl ${
- (previewType === 'image' || previewType === 'video' || previewType === 'pdf') ? 'w-fit' : 'w-full'
+ (previewType === 'image' || previewType === 'video' || previewType === 'pdf' || previewType === 'audio') ? 'w-fit' : 'w-full'
} ${
- (previewType === 'image' || previewType === 'video') ? 'h-fit' : 'h-full'
+ (previewType === 'image' || previewType === 'video' || previewType === 'audio') ? 'h-fit' : 'h-full'
}`}
style={{ backgroundColor: 'var(--color-bg-elevated)', border: '1px solid var(--color-border)' }}
>
@@ -173,6 +175,17 @@ export default function FilePreview({ file, onClose }: FilePreviewProps) {
Download File
+ ) : previewType === 'code' ? (
+
+
+ {content || ''}
+
+
) : (