fix(composer): attach image AND paste text when clipboard carries both

The paste handler (boot.js) bailed entirely when the clipboard contained
both text and image items, preventing image attachment in the most common
real-world scenario: right-click → Copy Image from browsers, Notes, Slack,
etc. — these almost always carry a text/html or text/plain representation
alongside the image.

Previous behavior (from #1620 fix):
  - clipboard has text only → normal text paste (correct)
  - clipboard has image only → attach image (correct)
  - clipboard has BOTH → text pasted, image silently dropped (wrong)

New behavior:
  - clipboard has text only → normal text paste (unchanged)
  - clipboard has image only → preventDefault + attach image (unchanged)
  - clipboard has BOTH → let text paste normally AND attach image

The key change: preventDefault() is now only called when no text is
present (true screenshot paste), so the browser handles text insertion
naturally while addFiles() runs regardless.

Fixes the regression introduced by the #1620 fix. Closes #1620.
This commit is contained in:
kaishi00 authored and nesquena-hermes committed 2026-06-17 04:37:29 +00:00
1 parent ae8d56080f
commit ad99ff4976
1 file changed
+8 -9
+8 -9
View File
@@ -1531,16 +1531,15 @@ document.addEventListener('keydown',async e=>{
});
$('msg').addEventListener('paste',e=>{
const items=Array.from(e.clipboardData?.items||[]);
// When the clipboard carries BOTH text and an image (common from Notes,
// Word, browsers, Slack — the OS attaches a rendered preview alongside
// the plain text), prefer the text and let the browser paste normally.
// Only intercept when the clipboard is image-only (true screenshot paste).
// Tighten the image filter to kind==='file' so string items advertising an
// image MIME (e.g. text/html with an embedded data URI) are not misclassified.
const hasText=items.some(i=>i.kind==='string'&&(i.type==='text/plain'||i.type==='text/html'));
// Extract image items (kind==='file' filter avoids misclassifying text/html
// with embedded data URIs as images).
const imageItems=items.filter(i=>i.kind==='file'&&i.type.startsWith('image/'));
if(!imageItems.length||hasText)return;
e.preventDefault();
if(!imageItems.length)return;
// If text is also present (common when copying images from browsers, Notes,
// Slack, etc.), let the browser paste the text normally AND attach the image.
// Only preventDefault when the clipboard is image-only (true screenshot paste).
const hasText=items.some(i=>i.kind==='string'&&(i.type==='text/plain'||i.type==='text/html'));
if(!hasText)e.preventDefault();
const pasteTs=Date.now();
const files=imageItems.map((i,idx)=>{
const blob=i.getAsFile();