From ed225e4db6d025272f37765369c4391ae7e572be Mon Sep 17 00:00:00 2001 From: Glenn Van De Putte Date: Tue, 20 Aug 2024 11:24:58 +0200 Subject: [PATCH] fix: recursively read folder entries because most browsers only return the first 100 entries --- .../src/system/data-transfer-wrapper.ts | 39 ++++++++++++++----- .../unit/system/data-transfer-wrapper-test.js | 13 ++++++- 2 files changed, 41 insertions(+), 11 deletions(-) diff --git a/ember-file-upload/src/system/data-transfer-wrapper.ts b/ember-file-upload/src/system/data-transfer-wrapper.ts index 42eae7bed..f41de2cee 100644 --- a/ember-file-upload/src/system/data-transfer-wrapper.ts +++ b/ember-file-upload/src/system/data-transfer-wrapper.ts @@ -19,7 +19,9 @@ const readEntry = (entry: FileSystemEntry): Promise => { resolve(fileEntry); }); } else { - console.warn(`The dropped directory contains a subdirectory ${entry.fullPath}, the contents of this will be skipped.`); + console.warn( + `The dropped directory contains a subdirectory ${entry.fullPath}, the contents of this will be skipped.`, + ); resolve(); } }); @@ -43,14 +45,33 @@ const readAllFilesInDirectory = (item: DataTransferItem): Promise => reject('Could not read directory'); } - entry?.createReader()?.readEntries(async (entries: FileSystemEntry[]) => { - const readFiles: (File | void)[] = await Promise.all(entries.map(readEntry)) - .catch( - (err) => { - console.error(err) - throw err; - }, - ); + const reader = entry?.createReader(); + if (!reader) { + reject('Could not read directory'); + } + const entries: FileSystemEntry[] = []; + const read = () => + new Promise((resolve, reject) => { + const readChunk = () => { + reader.readEntries((newEntries: FileSystemEntry[]) => { + if (newEntries.length > 0) { + entries.push(...newEntries); + readChunk(); + } else { + resolve(); + } + }, reject); + }; + readChunk(); + }); + + read().then(async () => { + const readFiles: (File | void)[] = await Promise.all( + entries.map(readEntry), + ).catch((err) => { + console.error(err); + throw err; + }); resolve(readFiles.filter(Boolean) as File[]); }); }); diff --git a/test-app/tests/unit/system/data-transfer-wrapper-test.js b/test-app/tests/unit/system/data-transfer-wrapper-test.js index 2082fdb55..1e45caf71 100644 --- a/test-app/tests/unit/system/data-transfer-wrapper-test.js +++ b/test-app/tests/unit/system/data-transfer-wrapper-test.js @@ -62,9 +62,17 @@ module('Unit | DataTransferWrapper', function (hooks) { name: 'zoey.png', type: 'image/png', }, + { + name: 'tomster.jpg', + type: 'image/jpeg', + }, + { + name: 'zoey.png', + type: 'image/png', + }, ], }; - assert.strictEqual(this.subject.filesOrItems.length, 2); + assert.strictEqual(this.subject.filesOrItems.length, 4); }); test('directory dropped', async function (assert) { @@ -85,7 +93,8 @@ module('Unit | DataTransferWrapper', function (hooks) { isDirectory: true, createReader: () => ({ readEntries: (callback) => { - const entryFiles = filesInDirectory.map((file) => { + const readingFiles = filesInDirectory.splice(0, 2) + const entryFiles = readingFiles.map((file) => { return { isFile: true, file: (callback) => {