fix(upload): gezogenes Vorschaubild wurde erneut hochgeladen

Zieht man das angezeigte Bild ein Stueck zur Seite, legt Chrome es als
echte Datei in den Ziehvorgang. dataTransfer.types enthaelt dann
"Files" - nicht zu unterscheiden von einer Datei aus dem Dateimanager.
Die Ablageflaeche lud das eigene Bild daraufhin ein zweites Mal hoch.

Zwei Riegel: draggable={false} an allen Bildern, die kein eigenes
Ziehen brauchen (die Kachel bleibt ziehbar und verschiebt die Datei),
und useInternalDrag - was in dieser Seite losgezogen ist, wird nie als
Upload behandelt. dragstart feuert nur bei eigener Quelle.

Gemessen: vorher 1 Upload, nachher 0. Ein Zug von aussen laedt
unveraendert hoch.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
marcandClaude Opus 5 committed 2026-08-24 17:24:22 +02:00
1 parent e9e07f9bed
commit b5a83e4057
11 files changed
+92 -3

No files matched your search

+5
View File
@@ -22,6 +22,11 @@ export default function FileCover({ file }: { file: FileItem }) {
return (
<>
<img
/* Ein Bild ist von Haus aus ziehbar – und Chrome legt beim Ziehen
eine echte Datei in die Zwischenablage. Fällt die auf die
Ablagefläche, lädt die Cloud ihr eigenes Bild erneut hoch.
Die Kachel selbst bleibt ziehbar; sie verschiebt die Datei. */
draggable={false}
src={filesApi.thumbnail(file.id)}
alt=""
onError={() => setFailed(true)}
+3
View File
@@ -280,6 +280,9 @@ export default function FilePreview({ file, onPrev, onNext, onClose, onSaved, se
{kind === 'image' && (
<img src={src} alt={file.name}
/* Nicht ziehbar: Sonst nimmt Chrome das angezeigte Bild als Datei
und die darunterliegende Ablagefläche lädt es erneut hoch. */
draggable={false}
style={{ maxWidth: '100%', maxHeight: '100%', objectFit: 'contain' }} />
)}
+1 -1
View File
@@ -186,7 +186,7 @@ export default function SearchBox({ onOpenFolder, onOpenFile }: Props) {
{hit.kind === 'folder' ? (
<FolderGlyph size={24} />
) : hit.has_thumbnail ? (
<img src={filesApi.thumbnail(hit.id)} alt="" style={{
<img src={filesApi.thumbnail(hit.id)} alt="" draggable={false} style={{
width: 18, height: 18, borderRadius: 3, objectFit: 'cover',
}} />
) : (
+1
View File
@@ -379,6 +379,7 @@ export default function Sidebar({ user, view, activeTagId, onOpenTag,
<div style={{ padding: '20px 16px 16px', display: 'flex', alignItems: 'center', gap: 10 }}>
{logoUrl ? (
<img
draggable={false}
src={logoUrl}
alt=""
style={{ height: 30, maxWidth: 120, objectFit: 'contain', flexShrink: 0 }}
+1
View File
@@ -181,6 +181,7 @@ export function Avatar({ name, src, size = 26 }: { name: string; src?: string |
{src && (
<img
src={src}
draggable={false}
alt=""
width={size}
height={size}