Fix: preserve attached files during file input changes (#4877) * fix: preserve attached files during file input changes * Reverse order of duplicate pasted files check
Signed| @@ -348,8 +348,7 @@ async function validateFile(file) { | |||
| 348 | export function hasPendingFileAttachment() { | 348 | export function hasPendingFileAttachment() { |
| 349 | const fileInput = document.getElementById('file_form_input'); | 349 | const fileInput = document.getElementById('file_form_input'); |
| 350 | if (!(fileInput instanceof HTMLInputElement)) return false; | 350 | if (!(fileInput instanceof HTMLInputElement)) return false; |
| 351 | const file = fileInput.files[0]; | 351 | return fileInput.files.length > 0; |
| 352 | return !!file; | ||
| 353 | } | 352 | } |
| 354 | 353 | ||
| 355 | /** | 354 | /** |
| @@ -2183,9 +2182,31 @@ export function initChatUtilities() { | |||
| 2183 | fileInput.click(); | 2182 | fileInput.click(); |
| 2184 | }); | 2183 | }); |
| 2185 | 2184 | ||
| 2185 | const fileInput = document.getElementById('file_form_input'); | ||
| 2186 | |||
| 2186 | // Do not change. #attachFile is added by extension. | 2187 | // Do not change. #attachFile is added by extension. |
| 2187 | $(document).on('click', '#attachFile', function () { | 2188 | $(document).on('click', '#attachFile', function () { |
| 2188 | $('#file_form_input').trigger('click'); | 2189 | if (!(fileInput instanceof HTMLInputElement)) return; |
| 2190 | const $fileInput = $(fileInput); | ||
| 2191 | |||
| 2192 | // Preserve existing files in DataTransfer | ||
| 2193 | const dataTransfer = new DataTransfer(); | ||
| 2194 | for (const file of fileInput.files) { | ||
| 2195 | dataTransfer.items.add(file); | ||
| 2196 | } | ||
| 2197 | |||
| 2198 | $fileInput.off('change').on('change', async () => { | ||
| 2199 | for (const file of fileInput.files) { | ||
| 2200 | if (!Array.from(dataTransfer.files).some(f => isSameFile(f, file))) { | ||
| 2201 | dataTransfer.items.add(file); | ||
| 2202 | } | ||
| 2203 | } | ||
| 2204 | |||
| 2205 | fileInput.files = dataTransfer.files; | ||
| 2206 | await onFileAttach(fileInput.files); | ||
| 2207 | }); | ||
| 2208 | |||
| 2209 | $fileInput.trigger('click'); | ||
| 2189 | }); | 2210 | }); |
| 2190 | 2211 | ||
| 2191 | // Do not change. #manageAttachments is added by extension. | 2212 | // Do not change. #manageAttachments is added by extension. |
| @@ -2348,11 +2369,6 @@ export function initChatUtilities() { | |||
| 2348 | await onImageSwiped(messageId, messageBlock, SWIPE_DIRECTION.RIGHT); | 2369 | await onImageSwiped(messageId, messageBlock, SWIPE_DIRECTION.RIGHT); |
| 2349 | }); | 2370 | }); |
| 2350 | 2371 | ||
| 2351 | $('#file_form_input').on('change', async () => { | ||
| 2352 | const fileInput = document.getElementById('file_form_input'); | ||
| 2353 | if (!(fileInput instanceof HTMLInputElement)) return; | ||
| 2354 | await onFileAttach(fileInput.files); | ||
| 2355 | }); | ||
| 2356 | $('#file_form').on('reset', function () { | 2372 | $('#file_form').on('reset', function () { |
| 2357 | $('#file_form').addClass('displayNone'); | 2373 | $('#file_form').addClass('displayNone'); |
| 2358 | }); | 2374 | }); |
| @@ -2378,17 +2394,16 @@ export function initChatUtilities() { | |||
| 2378 | * @returns {Promise<void>} | 2394 | * @returns {Promise<void>} |
| 2379 | */ | 2395 | */ |
| 2380 | async function handleFileAttach(files) { | 2396 | async function handleFileAttach(files) { |
| 2381 | const fileInput = document.getElementById('file_form_input'); | ||
| 2382 | if (!(fileInput instanceof HTMLInputElement)) return; | 2397 | if (!(fileInput instanceof HTMLInputElement)) return; |
| 2383 | 2398 | ||
| 2384 | // Workaround for Firefox: Use a DataTransfer object to indirectly set fileInput.files | 2399 | // Workaround for Firefox: Use a DataTransfer object to indirectly set fileInput.files |
| 2385 | const dataTransfer = new DataTransfer(); | 2400 | const dataTransfer = new DataTransfer(); |
| 2386 | for (let i = 0; i < files.length; i++) { | 2401 | for (const file of fileInput.files) { |
| 2387 | dataTransfer.items.add(files[i]); | 2402 | dataTransfer.items.add(file); |
| 2388 | } | 2403 | } |
| 2389 | 2404 | ||
| 2390 | // Preserve existing non-duplicate files in the input | 2405 | // Preserve existing non-duplicate files in the input |
| 2391 | for (const file of fileInput.files) { | 2406 | for (const file of files) { |
| 2392 | if (!Array.from(dataTransfer.files).some(f => isSameFile(f, file))) { | 2407 | if (!Array.from(dataTransfer.files).some(f => isSameFile(f, file))) { |
| 2393 | dataTransfer.items.add(file); | 2408 | dataTransfer.items.add(file); |
| 2394 | } | 2409 | } |