From f1a30e821db16bf702a6f3d4a518f589968b8dd5 Mon Sep 17 00:00:00 2001 From: zhwcreate <3331598351@qq.com> Date: Fri, 5 Jul 2024 21:17:17 +0800 Subject: [PATCH 1/8] fix:delay folder upload until all children files are parsed when drag --- src/traverseFileTree.ts | 49 ++++++++++++++++++++++----------------- tests/uploader.spec.tsx | 51 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 78 insertions(+), 22 deletions(-) diff --git a/src/traverseFileTree.ts b/src/traverseFileTree.ts index 06665d3c..4c1f644f 100644 --- a/src/traverseFileTree.ts +++ b/src/traverseFileTree.ts @@ -10,33 +10,36 @@ interface InternalDataTransferItem extends DataTransferItem { path: string; } -function loopFiles(item: InternalDataTransferItem, callback) { - const dirReader = item.createReader(); - let fileList = []; - - function sequence() { - dirReader.readEntries((entries: InternalDataTransferItem[]) => { - const entryList = Array.prototype.slice.apply(entries); - fileList = fileList.concat(entryList); +const traverseFileTree = (files: InternalDataTransferItem[], callback, isAccepted) => { + let restFile = files.length; + const flattenFileList = []; + function loopFiles(item: InternalDataTransferItem, InnerCallback) { + const dirReader = item.createReader(); + let fileList = []; - // Check if all the file has been viewed - const isFinished = !entryList.length; + function sequence() { + dirReader.readEntries((entries: InternalDataTransferItem[]) => { + const entryList = Array.prototype.slice.apply(entries); + fileList = fileList.concat(entryList); - if (isFinished) { - callback(fileList); - } else { - sequence(); - } - }); - } + // Check if all the file has been viewed + const isFinished = !entryList.length; - sequence(); -} + if (isFinished) { + restFile = restFile - 1 + fileList.length; + InnerCallback(fileList); + } else { + sequence(); + } + }); + } -const traverseFileTree = (files: InternalDataTransferItem[], callback, isAccepted) => { + sequence(); + } // eslint-disable-next-line @typescript-eslint/naming-convention const _traverseFileTree = (item: InternalDataTransferItem, path?: string) => { if (!item) { + restFile = restFile - 1; return; } // eslint-disable-next-line no-param-reassign @@ -59,7 +62,11 @@ const traverseFileTree = (files: InternalDataTransferItem[], callback, isAccepte }, }); } - callback([file]); + flattenFileList.push(file); + restFile = restFile - 1; + if (restFile === 0) { + callback(flattenFileList); + } } }); } else if (item.isDirectory) { diff --git a/tests/uploader.spec.tsx b/tests/uploader.spec.tsx index b7e060cd..77b90cc8 100644 --- a/tests/uploader.spec.tsx +++ b/tests/uploader.spec.tsx @@ -25,7 +25,7 @@ const makeFileSystemEntry = item => { return { readEntries(handle) { if (!first) { - return []; + return handle([]); } first = false; @@ -373,7 +373,56 @@ describe('uploader', () => { beforeEach(() => { uploader = render(); }); + it('beforeUpload should run after all children files are parsed', done => { + const props = { action: '/test', directory: true, accept: '.png' }; + const mockBeforeUpload = jest.fn(); + const beforeUpload = (file, fileList) => { + console.log('beforeUpload', file, fileList); + mockBeforeUpload(file, fileList); + }; + const Test = () => { + return ; + }; + const { container } = render(); + const files = { + name: 'foo', + children: [ + { + name: 'bar', + children: [ + { + name: '1.png', + }, + { + name: '2.png', + }, + { + name: 'rc', + children: [ + { + name: '3.png', + }, + { + name: '4.png', + }, + ], + }, + ], + }, + ], + }; + const input = container.querySelector('input')!; + fireEvent.drop(input, { dataTransfer: { items: [makeDataTransferItem(files)] } }); + setTimeout(() => { + expect(mockBeforeUpload.mock.calls.length).toBe(4); + expect(mockBeforeUpload.mock.calls[0][1].length).toBe(4); + expect(mockBeforeUpload.mock.calls[1][1].length).toBe(4); + expect(mockBeforeUpload.mock.calls[2][1].length).toBe(4); + expect(mockBeforeUpload.mock.calls[3][1].length).toBe(4); + done(); + }, 100); + }); it('unaccepted type files to upload will not trigger onStart', done => { const input = uploader.container.querySelector('input')!; const files = { From bf48f50db1ae3cd633d542df56610cc147428af6 Mon Sep 17 00:00:00 2001 From: zhwcreate <3331598351@qq.com> Date: Tue, 9 Jul 2024 21:15:40 +0800 Subject: [PATCH 2/8] fix: isAcceptable case --- src/traverseFileTree.ts | 5 +++++ tests/uploader.spec.tsx | 12 +++++------- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/traverseFileTree.ts b/src/traverseFileTree.ts index 4c1f644f..57420d4e 100644 --- a/src/traverseFileTree.ts +++ b/src/traverseFileTree.ts @@ -67,6 +67,11 @@ const traverseFileTree = (files: InternalDataTransferItem[], callback, isAccepte if (restFile === 0) { callback(flattenFileList); } + } else { + restFile = restFile - 1; + if (restFile === 0) { + callback(flattenFileList); + } } }); } else if (item.isDirectory) { diff --git a/tests/uploader.spec.tsx b/tests/uploader.spec.tsx index 77b90cc8..ba3e47d0 100644 --- a/tests/uploader.spec.tsx +++ b/tests/uploader.spec.tsx @@ -401,10 +401,10 @@ describe('uploader', () => { name: 'rc', children: [ { - name: '3.png', + name: '5.webp', }, { - name: '4.png', + name: '4.webp', }, ], }, @@ -415,11 +415,9 @@ describe('uploader', () => { const input = container.querySelector('input')!; fireEvent.drop(input, { dataTransfer: { items: [makeDataTransferItem(files)] } }); setTimeout(() => { - expect(mockBeforeUpload.mock.calls.length).toBe(4); - expect(mockBeforeUpload.mock.calls[0][1].length).toBe(4); - expect(mockBeforeUpload.mock.calls[1][1].length).toBe(4); - expect(mockBeforeUpload.mock.calls[2][1].length).toBe(4); - expect(mockBeforeUpload.mock.calls[3][1].length).toBe(4); + expect(mockBeforeUpload.mock.calls.length).toBe(2); + expect(mockBeforeUpload.mock.calls[0][1].length).toBe(2); + expect(mockBeforeUpload.mock.calls[1][1].length).toBe(2); done(); }, 100); }); From d841736b627087f9536a4be0095ea70c4896d89d Mon Sep 17 00:00:00 2001 From: zhwcreate <3331598351@qq.com> Date: Wed, 10 Jul 2024 20:22:26 +0800 Subject: [PATCH 3/8] feat: use queue --- src/traverseFileTree.ts | 41 +++++++++++++++++++---------------------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/src/traverseFileTree.ts b/src/traverseFileTree.ts index 57420d4e..a67b3f9a 100644 --- a/src/traverseFileTree.ts +++ b/src/traverseFileTree.ts @@ -11,9 +11,11 @@ interface InternalDataTransferItem extends DataTransferItem { } const traverseFileTree = (files: InternalDataTransferItem[], callback, isAccepted) => { - let restFile = files.length; const flattenFileList = []; - function loopFiles(item: InternalDataTransferItem, InnerCallback) { + let progressFileList = []; + let wipIndex = 0; + files.forEach(file => progressFileList.push(file.webkitGetAsEntry() as any)); + function loopFiles(item: InternalDataTransferItem) { const dirReader = item.createReader(); let fileList = []; @@ -26,8 +28,8 @@ const traverseFileTree = (files: InternalDataTransferItem[], callback, isAccepte const isFinished = !entryList.length; if (isFinished) { - restFile = restFile - 1 + fileList.length; - InnerCallback(fileList); + wipIndex++; + progressFileList = progressFileList.concat(fileList); } else { sequence(); } @@ -39,7 +41,7 @@ const traverseFileTree = (files: InternalDataTransferItem[], callback, isAccepte // eslint-disable-next-line @typescript-eslint/naming-convention const _traverseFileTree = (item: InternalDataTransferItem, path?: string) => { if (!item) { - restFile = restFile - 1; + wipIndex++; return; } // eslint-disable-next-line no-param-reassign @@ -63,28 +65,23 @@ const traverseFileTree = (files: InternalDataTransferItem[], callback, isAccepte }); } flattenFileList.push(file); - restFile = restFile - 1; - if (restFile === 0) { - callback(flattenFileList); - } - } else { - restFile = restFile - 1; - if (restFile === 0) { - callback(flattenFileList); - } } }); + wipIndex++; } else if (item.isDirectory) { - loopFiles(item, (entries: InternalDataTransferItem[]) => { - entries.forEach(entryItem => { - _traverseFileTree(entryItem, `${path}${item.name}/`); - }); - }); + loopFiles(item); } }; - files.forEach(file => { - _traverseFileTree(file.webkitGetAsEntry() as any); - }); + + function walkFiles() { + while (wipIndex < progressFileList.length) { + _traverseFileTree(progressFileList[wipIndex]); + if (wipIndex === progressFileList.length) { + callback(flattenFileList); + } + } + } + walkFiles(); }; export default traverseFileTree; From 1f172a543d890c94b371a26da6965f23289a1c90 Mon Sep 17 00:00:00 2001 From: zhwcreate <3331598351@qq.com> Date: Thu, 11 Jul 2024 12:37:54 +0800 Subject: [PATCH 4/8] feat: readEntries add errorCallback --- src/traverseFileTree.ts | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/traverseFileTree.ts b/src/traverseFileTree.ts index a67b3f9a..7592c431 100644 --- a/src/traverseFileTree.ts +++ b/src/traverseFileTree.ts @@ -20,20 +20,25 @@ const traverseFileTree = (files: InternalDataTransferItem[], callback, isAccepte let fileList = []; function sequence() { - dirReader.readEntries((entries: InternalDataTransferItem[]) => { - const entryList = Array.prototype.slice.apply(entries); - fileList = fileList.concat(entryList); + dirReader.readEntries( + (entries: InternalDataTransferItem[]) => { + const entryList = Array.prototype.slice.apply(entries); + fileList = fileList.concat(entryList); - // Check if all the file has been viewed - const isFinished = !entryList.length; + // Check if all the file has been viewed + const isFinished = !entryList.length; - if (isFinished) { + if (isFinished) { + wipIndex++; + progressFileList = progressFileList.concat(fileList); + } else { + sequence(); + } + }, + () => { wipIndex++; - progressFileList = progressFileList.concat(fileList); - } else { - sequence(); - } - }); + }, + ); } sequence(); From b381da436361e41d7635dc819078ac9b14c190fa Mon Sep 17 00:00:00 2001 From: zhwcreate <3331598351@qq.com> Date: Thu, 11 Jul 2024 15:58:24 +0800 Subject: [PATCH 5/8] fix: improve code --- src/traverseFileTree.ts | 35 +++++++++++++---------------------- 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/src/traverseFileTree.ts b/src/traverseFileTree.ts index 7592c431..53b0555a 100644 --- a/src/traverseFileTree.ts +++ b/src/traverseFileTree.ts @@ -20,25 +20,19 @@ const traverseFileTree = (files: InternalDataTransferItem[], callback, isAccepte let fileList = []; function sequence() { - dirReader.readEntries( - (entries: InternalDataTransferItem[]) => { - const entryList = Array.prototype.slice.apply(entries); - fileList = fileList.concat(entryList); + dirReader.readEntries((entries: InternalDataTransferItem[]) => { + const entryList = Array.prototype.slice.apply(entries); + fileList.push(...entryList); - // Check if all the file has been viewed - const isFinished = !entryList.length; + // Check if all the file has been viewed + const isFinished = !entryList.length; - if (isFinished) { - wipIndex++; - progressFileList = progressFileList.concat(fileList); - } else { - sequence(); - } - }, - () => { - wipIndex++; - }, - ); + if (isFinished) { + progressFileList = progressFileList.concat(fileList); + } else { + sequence(); + } + }); } sequence(); @@ -46,7 +40,6 @@ const traverseFileTree = (files: InternalDataTransferItem[], callback, isAccepte // eslint-disable-next-line @typescript-eslint/naming-convention const _traverseFileTree = (item: InternalDataTransferItem, path?: string) => { if (!item) { - wipIndex++; return; } // eslint-disable-next-line no-param-reassign @@ -72,7 +65,6 @@ const traverseFileTree = (files: InternalDataTransferItem[], callback, isAccepte flattenFileList.push(file); } }); - wipIndex++; } else if (item.isDirectory) { loopFiles(item); } @@ -81,10 +73,9 @@ const traverseFileTree = (files: InternalDataTransferItem[], callback, isAccepte function walkFiles() { while (wipIndex < progressFileList.length) { _traverseFileTree(progressFileList[wipIndex]); - if (wipIndex === progressFileList.length) { - callback(flattenFileList); - } + wipIndex++; } + callback(flattenFileList); } walkFiles(); }; From c151816c3baecdea7811dc2d2ed7f07e7e8c4c2c Mon Sep 17 00:00:00 2001 From: zhwcreate <3331598351@qq.com> Date: Thu, 11 Jul 2024 16:56:40 +0800 Subject: [PATCH 6/8] feat:improve code --- src/traverseFileTree.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/traverseFileTree.ts b/src/traverseFileTree.ts index 53b0555a..18a35b0a 100644 --- a/src/traverseFileTree.ts +++ b/src/traverseFileTree.ts @@ -13,22 +13,19 @@ interface InternalDataTransferItem extends DataTransferItem { const traverseFileTree = (files: InternalDataTransferItem[], callback, isAccepted) => { const flattenFileList = []; let progressFileList = []; - let wipIndex = 0; files.forEach(file => progressFileList.push(file.webkitGetAsEntry() as any)); function loopFiles(item: InternalDataTransferItem) { const dirReader = item.createReader(); - let fileList = []; function sequence() { dirReader.readEntries((entries: InternalDataTransferItem[]) => { const entryList = Array.prototype.slice.apply(entries); - fileList.push(...entryList); + progressFileList.push(...entryList); // Check if all the file has been viewed const isFinished = !entryList.length; - if (isFinished) { - progressFileList = progressFileList.concat(fileList); + return; } else { sequence(); } @@ -71,6 +68,7 @@ const traverseFileTree = (files: InternalDataTransferItem[], callback, isAccepte }; function walkFiles() { + let wipIndex = 0; while (wipIndex < progressFileList.length) { _traverseFileTree(progressFileList[wipIndex]); wipIndex++; From 56ccb4cca8a22e11a5eeb31d5e7004f161cb9068 Mon Sep 17 00:00:00 2001 From: zhwcreate <3331598351@qq.com> Date: Thu, 11 Jul 2024 17:35:20 +0800 Subject: [PATCH 7/8] fix:ci --- src/traverseFileTree.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/traverseFileTree.ts b/src/traverseFileTree.ts index 18a35b0a..ad89f055 100644 --- a/src/traverseFileTree.ts +++ b/src/traverseFileTree.ts @@ -12,7 +12,7 @@ interface InternalDataTransferItem extends DataTransferItem { const traverseFileTree = (files: InternalDataTransferItem[], callback, isAccepted) => { const flattenFileList = []; - let progressFileList = []; + const progressFileList = []; files.forEach(file => progressFileList.push(file.webkitGetAsEntry() as any)); function loopFiles(item: InternalDataTransferItem) { const dirReader = item.createReader(); From 523a319a049ff1423d045fd26f9c90e19a560df3 Mon Sep 17 00:00:00 2001 From: zhwcreate <3331598351@qq.com> Date: Thu, 11 Jul 2024 17:43:47 +0800 Subject: [PATCH 8/8] feat: improve code --- src/traverseFileTree.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/traverseFileTree.ts b/src/traverseFileTree.ts index ad89f055..7b74c0ba 100644 --- a/src/traverseFileTree.ts +++ b/src/traverseFileTree.ts @@ -24,9 +24,7 @@ const traverseFileTree = (files: InternalDataTransferItem[], callback, isAccepte progressFileList.push(...entryList); // Check if all the file has been viewed const isFinished = !entryList.length; - if (isFinished) { - return; - } else { + if (!isFinished) { sequence(); } });