Cleanup file upload behavior
This commit is contained in:
parent
1cfa4100ad
commit
4458822c60
2 changed files with 47 additions and 42 deletions
|
@ -35,8 +35,9 @@ export default ({ className }: WithClassname) => {
|
||||||
|
|
||||||
const uuid = ServerContext.useStoreState((state) => state.server.data!.uuid);
|
const uuid = ServerContext.useStoreState((state) => state.server.data!.uuid);
|
||||||
const directory = ServerContext.useStoreState((state) => state.files.directory);
|
const directory = ServerContext.useStoreState((state) => state.files.directory);
|
||||||
const appendFileUpload = ServerContext.useStoreActions((actions) => actions.files.appendFileUpload);
|
const { clearFileUploads, appendFileUpload, removeFileUpload } = ServerContext.useStoreActions(
|
||||||
const removeFileUpload = ServerContext.useStoreActions((actions) => actions.files.removeFileUpload);
|
(actions) => actions.files
|
||||||
|
);
|
||||||
|
|
||||||
useEventListener(
|
useEventListener(
|
||||||
'dragenter',
|
'dragenter',
|
||||||
|
@ -52,62 +53,57 @@ export default ({ className }: WithClassname) => {
|
||||||
|
|
||||||
useEventListener('dragexit', () => setVisible(false), { capture: true });
|
useEventListener('dragexit', () => setVisible(false), { capture: true });
|
||||||
|
|
||||||
useEffect(() => {
|
useEventListener('keydown', () => {
|
||||||
if (!visible) return;
|
visible && setVisible(false);
|
||||||
|
});
|
||||||
const hide = () => setVisible(false);
|
|
||||||
|
|
||||||
window.addEventListener('keydown', hide);
|
|
||||||
return () => {
|
|
||||||
window.removeEventListener('keydown', hide);
|
|
||||||
};
|
|
||||||
}, [visible]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
return () => timeouts.forEach(clearTimeout);
|
return () => timeouts.forEach(clearTimeout);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const onFileSubmission = (files: FileList) => {
|
const onUploadProgress = (data: ProgressEvent, name: string) => {
|
||||||
const formData: FormData[] = [];
|
appendFileUpload({ name, loaded: data.loaded, total: data.total });
|
||||||
|
if (data.loaded >= data.total) {
|
||||||
|
const timeout = setTimeout(() => removeFileUpload(name), 500);
|
||||||
|
setTimeouts((t) => [...t, timeout]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onFileSubmission = (files: FileList) => {
|
||||||
clearAndAddHttpError();
|
clearAndAddHttpError();
|
||||||
const list = Array.from(files);
|
const list = Array.from(files);
|
||||||
if (list.some((file) => !file.type && file.size % 4096 === 0)) {
|
if (list.some((file) => !file.type && file.size % 4096 === 0)) {
|
||||||
return addError('Folder uploads are not supported at this time.', 'Error');
|
return addError('Folder uploads are not supported at this time.', 'Error');
|
||||||
}
|
}
|
||||||
|
|
||||||
Array.from(files).forEach((file) => {
|
if (!list.length) {
|
||||||
const form = new FormData();
|
|
||||||
form.append('files', file);
|
|
||||||
formData.push(form);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (formData.length === 0) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Promise.all(
|
const uploads = list.map((file) => {
|
||||||
Array.from(formData).map((f) =>
|
appendFileUpload({ name: file.name, loaded: 0, total: file.size });
|
||||||
|
return () =>
|
||||||
getFileUploadUrl(uuid).then((url) =>
|
getFileUploadUrl(uuid).then((url) =>
|
||||||
axios.post(`${url}&directory=${directory}`, f, {
|
axios.post(
|
||||||
|
url,
|
||||||
|
{ files: file },
|
||||||
|
{
|
||||||
headers: { 'Content-Type': 'multipart/form-data' },
|
headers: { 'Content-Type': 'multipart/form-data' },
|
||||||
onUploadProgress: (data: ProgressEvent) => {
|
params: { directory },
|
||||||
// @ts-expect-error this is valid
|
onUploadProgress: (data) => {
|
||||||
const name = f.getAll('files')[0].name;
|
onUploadProgress(data, file.name);
|
||||||
|
|
||||||
appendFileUpload({ name: name, loaded: data.loaded, total: data.total });
|
|
||||||
|
|
||||||
if (data.loaded === data.total) {
|
|
||||||
const timeout = setTimeout(() => removeFileUpload(name), 500);
|
|
||||||
setTimeouts((t) => [...t, timeout]);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
})
|
}
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
Promise.all(uploads.map((fn) => fn()))
|
||||||
.then(() => mutate())
|
.then(() => mutate())
|
||||||
.catch(clearAndAddHttpError);
|
.catch((error) => {
|
||||||
|
clearFileUploads();
|
||||||
|
clearAndAddHttpError(error);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -17,6 +17,7 @@ export interface ServerFileStore {
|
||||||
appendSelectedFile: Action<ServerFileStore, string>;
|
appendSelectedFile: Action<ServerFileStore, string>;
|
||||||
removeSelectedFile: Action<ServerFileStore, string>;
|
removeSelectedFile: Action<ServerFileStore, string>;
|
||||||
|
|
||||||
|
clearFileUploads: Action<ServerFileStore>;
|
||||||
appendFileUpload: Action<ServerFileStore, FileUpload>;
|
appendFileUpload: Action<ServerFileStore, FileUpload>;
|
||||||
removeFileUpload: Action<ServerFileStore, string>;
|
removeFileUpload: Action<ServerFileStore, string>;
|
||||||
}
|
}
|
||||||
|
@ -42,12 +43,20 @@ const files: ServerFileStore = {
|
||||||
state.selectedFiles = state.selectedFiles.filter((f) => f !== payload);
|
state.selectedFiles = state.selectedFiles.filter((f) => f !== payload);
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
clearFileUploads: action((state) => {
|
||||||
|
state.uploads = [];
|
||||||
|
}),
|
||||||
|
|
||||||
appendFileUpload: action((state, payload) => {
|
appendFileUpload: action((state, payload) => {
|
||||||
state.uploads = state.uploads.filter((f) => f.name !== payload.name).concat(payload);
|
if (!state.uploads.some(({ name }) => name === payload.name)) {
|
||||||
|
state.uploads = [...state.uploads, payload];
|
||||||
|
} else {
|
||||||
|
state.uploads = state.uploads.map((file) => (file.name === payload.name ? payload : file));
|
||||||
|
}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
removeFileUpload: action((state, payload) => {
|
removeFileUpload: action((state, payload) => {
|
||||||
state.uploads = state.uploads.filter((f) => f.name !== payload);
|
state.uploads = state.uploads.filter(({ name }) => name !== payload);
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue