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:
1 parent
e9e07f9bed
commit
b5a83e4057
11 files changed
+92
-3
No files matched your search
@@ -0,0 +1,44 @@
|
||||
import { useEffect, useRef } from 'react'
|
||||
|
||||
/**
|
||||
* Läuft gerade ein Ziehvorgang, der **in dieser Seite** begonnen hat?
|
||||
*
|
||||
* Anlass war ein Fehler, den man nur beim Benutzen findet: Zieht man das
|
||||
* angezeigte Bild ein Stück zur Seite, legt Chrome es als echte Datei in die
|
||||
* Zwischenablage des Ziehvorgangs – `dataTransfer.types` enthält dann
|
||||
* `Files`, genau wie bei einer Datei aus dem Dateimanager. Die Ablagefläche
|
||||
* konnte beides nicht unterscheiden und lud das Bild ein zweites Mal hoch.
|
||||
*
|
||||
* Die Kennungen `aether-file-id` und `aether-folder-id` helfen hier nicht:
|
||||
* Die setzt unser eigener Verschiebe-Code, ein vom Browser begonnener
|
||||
* Bild-Zug hat sie nicht.
|
||||
*
|
||||
* Deshalb der Umweg über das Ereignis: `dragstart` feuert nur, wenn die
|
||||
* Quelle in diesem Dokument liegt. Kommt etwas von außen, gibt es kein
|
||||
* `dragstart` – und nur dann darf hochgeladen werden.
|
||||
*/
|
||||
export function useInternalDrag(): () => boolean {
|
||||
const active = useRef(false)
|
||||
|
||||
useEffect(() => {
|
||||
const start = () => { active.current = true }
|
||||
// Der Rückweg über zwei Ereignisse: `dragend` feuert an der Quelle,
|
||||
// `drop` am Ziel. Fällt eines aus (abgebrochener Zug außerhalb des
|
||||
// Fensters), setzt das andere zurück.
|
||||
const stop = () => { active.current = false }
|
||||
// Setzen in der Erfassungsphase, damit die Marke steht, bevor irgendein
|
||||
// Handler sie liest. **Zurücksetzen dagegen in der Blasenphase**: Ein
|
||||
// `drop`-Listener am Dokument mit `capture` liefe *vor* der Ablagefläche,
|
||||
// hätte die Marke also schon gelöscht, wenn sie gebraucht wird.
|
||||
document.addEventListener('dragstart', start, true)
|
||||
document.addEventListener('dragend', stop)
|
||||
document.addEventListener('drop', stop)
|
||||
return () => {
|
||||
document.removeEventListener('dragstart', start, true)
|
||||
document.removeEventListener('dragend', stop)
|
||||
document.removeEventListener('drop', stop)
|
||||
}
|
||||
}, [])
|
||||
|
||||
return () => active.current
|
||||
}
|
||||
Reference in new issue
Block a user