fix: route clipboard image pastes to the attachment strip #295
@@ -5,6 +5,19 @@ interface UseFileInputOptions {
|
||||
enabled: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Files carried by a paste. A pasted image is usually exposed only through
|
||||
* `items` (`getAsFile`), with `files` left empty, so read `items` first and
|
||||
* fall back to `files` for the rare clipboard that populates only the latter.
|
||||
*/
|
||||
function clipboardFiles(data: DataTransfer): File[] {
|
||||
const fromItems = Array.from(data.items)
|
||||
.filter((item) => item.kind === 'file')
|
||||
.map((item) => item.getAsFile())
|
||||
.filter((file): file is File => file !== null);
|
||||
return fromItems.length > 0 ? fromItems : Array.from(data.files);
|
||||
}
|
||||
|
||||
export function useFileInput({
|
||||
onFilesSelected,
|
||||
enabled,
|
||||
@@ -49,14 +62,20 @@ export function useFileInput({
|
||||
if (!enabled) return;
|
||||
|
||||
// Capture phase so file pastes always become attachments — ProseMirror
|
||||
// would otherwise inline pasted images as ephemeral blob: URLs. Mixed
|
||||
// clipboards (e.g. Excel/Word ship an image rendition alongside the text)
|
||||
// must still paste as text, so only file-only pastes are intercepted.
|
||||
// (the markdown editor) would otherwise inline a pasted image as an
|
||||
// ephemeral blob: URL and get stuck on its "uploading" placeholder.
|
||||
const handlePaste = (e: ClipboardEvent) => {
|
||||
const data = e.clipboardData;
|
||||
if (!data) return;
|
||||
const files = Array.from(data.files);
|
||||
if (files.length === 0 || data.types.includes('text/plain')) return;
|
||||
|
||||
// Actual text means "paste as text", even when the clipboard also ships
|
||||
// an image rendition (Excel/Word, or "copy image" from a page with alt
|
||||
// text). Test the payload, not the advertised types: image pastes often
|
||||
// list an *empty* text/plain entry that must not block the attachment.
|
||||
if (data.getData('text/plain').trim().length > 0) return;
|
||||
|
||||
const files = clipboardFiles(data);
|
||||
if (files.length === 0) return;
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
onFilesRef.current(files);
|
||||
|
||||
Reference in New Issue
Block a user