|
61 | 61 | } |
62 | 62 |
|
63 | 63 | async handlePaste(e) { |
64 | | - e.preventDefault(); |
65 | | - const items = e.clipboardData?.items; |
66 | | - if (!items) return; |
| 64 | + const clipboard = e.clipboardData; |
| 65 | + const items = clipboard?.items; |
| 66 | + if (!items || items.length === 0) return; |
67 | 67 |
|
| 68 | + const imageFiles = []; |
68 | 69 | for (const item of items) { |
69 | | - if (item.type.startsWith('image/')) { |
| 70 | + if (item.type && item.type.startsWith('image/')) { |
70 | 71 | const file = item.getAsFile(); |
71 | | - if (file) await this.uploadImage(file); |
72 | | - } else if (item.type === 'text/plain') { |
73 | | - const text = await item.getAsString(); |
74 | | - const input = document.getElementById("compose-input"); |
75 | | - if (input) { |
76 | | - // Insert text directly into contenteditable |
77 | | - const textNode = document.createTextNode(text); |
78 | | - if (input.childNodes.length === 0) { |
79 | | - input.appendChild(textNode); |
80 | | - } else { |
81 | | - input.appendChild(textNode); |
82 | | - } |
83 | | - input.focus(); |
84 | | - } |
| 72 | + if (file) imageFiles.push(file); |
85 | 73 | } |
86 | 74 | } |
| 75 | + |
| 76 | + // Only intercept when images exist; otherwise keep native text paste behavior. |
| 77 | + if (imageFiles.length === 0) { |
| 78 | + return; |
| 79 | + } |
| 80 | + |
| 81 | + e.preventDefault(); |
| 82 | + |
| 83 | + for (const file of imageFiles) { |
| 84 | + await this.uploadImage(file); |
| 85 | + } |
| 86 | + |
| 87 | + // For mixed clipboard content, keep text by inserting plain text manually. |
| 88 | + const text = clipboard.getData('text/plain'); |
| 89 | + if (text) { |
| 90 | + this.insertTextAtCursor(text); |
| 91 | + } |
| 92 | + } |
| 93 | + |
| 94 | + insertTextAtCursor(text) { |
| 95 | + const input = this.querySelector('#compose-input'); |
| 96 | + if (!input || !text) return; |
| 97 | + |
| 98 | + input.focus(); |
| 99 | + const selection = window.getSelection(); |
| 100 | + if (!selection || selection.rangeCount === 0) { |
| 101 | + input.appendChild(document.createTextNode(text)); |
| 102 | + return; |
| 103 | + } |
| 104 | + |
| 105 | + const range = selection.getRangeAt(0); |
| 106 | + range.deleteContents(); |
| 107 | + const textNode = document.createTextNode(text); |
| 108 | + range.insertNode(textNode); |
| 109 | + |
| 110 | + // Move caret to after inserted text. |
| 111 | + range.setStartAfter(textNode); |
| 112 | + range.collapse(true); |
| 113 | + selection.removeAllRanges(); |
| 114 | + selection.addRange(range); |
87 | 115 | } |
88 | 116 |
|
89 | 117 | handleDrop(e) { |
|
0 commit comments