Skip to content

Commit

Permalink
fix:delay folder upload until all children files are parsed when drag (
Browse files Browse the repository at this point in the history
…#561)

* fix:delay folder upload until all children files are parsed when drag

* fix: isAcceptable case

* feat: use queue

* feat: readEntries add errorCallback

* fix: improve code

* feat:improve code

* fix:ci

* feat: improve code
  • Loading branch information
coderz-w authored Jul 11, 2024
1 parent d077f39 commit dfb14cd
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 30 deletions.
59 changes: 30 additions & 29 deletions src/traverseFileTree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,28 @@ interface InternalDataTransferItem extends DataTransferItem {
path: string;
}

function loopFiles(item: InternalDataTransferItem, callback) {
const dirReader = item.createReader();
let fileList = [];
const traverseFileTree = (files: InternalDataTransferItem[], callback, isAccepted) => {
const flattenFileList = [];
const progressFileList = [];
files.forEach(file => progressFileList.push(file.webkitGetAsEntry() as any));
function loopFiles(item: InternalDataTransferItem) {
const dirReader = item.createReader();

function sequence() {
dirReader.readEntries((entries: InternalDataTransferItem[]) => {
const entryList = Array.prototype.slice.apply(entries);
fileList = fileList.concat(entryList);
function sequence() {
dirReader.readEntries((entries: InternalDataTransferItem[]) => {
const entryList = Array.prototype.slice.apply(entries);

// Check if all the file has been viewed
const isFinished = !entryList.length;
progressFileList.push(...entryList);
// Check if all the file has been viewed
const isFinished = !entryList.length;
if (!isFinished) {
sequence();
}
});
}

if (isFinished) {
callback(fileList);
} else {
sequence();
}
});
sequence();
}

sequence();
}

const traverseFileTree = (files: InternalDataTransferItem[], callback, isAccepted) => {
// eslint-disable-next-line @typescript-eslint/naming-convention
const _traverseFileTree = (item: InternalDataTransferItem, path?: string) => {
if (!item) {
Expand All @@ -59,20 +57,23 @@ const traverseFileTree = (files: InternalDataTransferItem[], callback, isAccepte
},
});
}
callback([file]);
flattenFileList.push(file);
}
});
} 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() {
let wipIndex = 0;
while (wipIndex < progressFileList.length) {
_traverseFileTree(progressFileList[wipIndex]);
wipIndex++;
}
callback(flattenFileList);
}
walkFiles();
};

export default traverseFileTree;
49 changes: 48 additions & 1 deletion tests/uploader.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const makeFileSystemEntry = item => {
return {
readEntries(handle) {
if (!first) {
return [];
return handle([]);
}

first = false;
Expand Down Expand Up @@ -373,7 +373,54 @@ describe('uploader', () => {
beforeEach(() => {
uploader = render(<Upload {...props} />);
});
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 <Upload {...props} beforeUpload={beforeUpload} />;
};

const { container } = render(<Test />);
const files = {
name: 'foo',
children: [
{
name: 'bar',
children: [
{
name: '1.png',
},
{
name: '2.png',
},
{
name: 'rc',
children: [
{
name: '5.webp',
},
{
name: '4.webp',
},
],
},
],
},
],
};
const input = container.querySelector('input')!;
fireEvent.drop(input, { dataTransfer: { items: [makeDataTransferItem(files)] } });
setTimeout(() => {
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);
});
it('unaccepted type files to upload will not trigger onStart', done => {
const input = uploader.container.querySelector('input')!;
const files = {
Expand Down

0 comments on commit dfb14cd

Please sign in to comment.