1
0
Fork 0
mirror of https://github.com/muerwre/vault-frontend.git synced 2025-04-25 12:56:41 +07:00

removed upload redux store

This commit is contained in:
Fedor Katurov 2022-01-06 21:04:14 +07:00
parent 140e36b6b7
commit 95b92b643f
38 changed files with 398 additions and 691 deletions

View file

@ -1,89 +0,0 @@
import React, {
createContext,
FC,
useCallback,
useContext,
useEffect,
useMemo,
useState,
} from 'react';
import { IFile, IFileWithUUID } from '~/redux/types';
import { UPLOAD_SUBJECTS, UPLOAD_TARGETS } from '~/redux/uploads/constants';
import { getFileType } from '~/utils/uploader';
import uuid from 'uuid4';
import { useDispatch } from 'react-redux';
import { uploadUploadFiles } from '~/redux/uploads/actions';
import { useShallowSelect } from '~/hooks/data/useShallowSelect';
import { selectUploads } from '~/redux/uploads/selectors';
import { path } from 'ramda';
import { IUploadStatus } from '~/redux/uploads/reducer';
export const useFileUploader = (
subject: typeof UPLOAD_SUBJECTS[keyof typeof UPLOAD_SUBJECTS],
target: typeof UPLOAD_TARGETS[keyof typeof UPLOAD_TARGETS],
initialFiles?: IFile[]
) => {
const dispatch = useDispatch();
const { files: uploadedFiles, statuses } = useShallowSelect(selectUploads);
const [files, setFiles] = useState<IFile[]>(initialFiles || []);
const [pendingIDs, setPendingIDs] = useState<string[]>([]);
const uploadFiles = useCallback(
(files: File[]) => {
const items: IFileWithUUID[] = files.map(
(file: File): IFileWithUUID => ({
file,
temp_id: uuid(),
subject,
target,
type: getFileType(file),
})
);
const temps = items.filter(el => !!el.temp_id).map(file => file.temp_id!);
setPendingIDs([...pendingIDs, ...temps]);
dispatch(uploadUploadFiles(items));
},
[pendingIDs, setPendingIDs, dispatch, subject, target]
);
useEffect(() => {
const added = pendingIDs
.map(temp_uuid => path([temp_uuid, 'uuid'], statuses) as IUploadStatus['uuid'])
.filter(el => el)
.map(el => (path([String(el)], uploadedFiles) as IFile) || undefined)
.filter(el => !!el! && !files.some(file => file && file.id === el.id));
const newPending = pendingIDs.filter(
temp_id =>
statuses[temp_id] &&
(!statuses[temp_id].uuid || !added.some(file => file.id === statuses[temp_id].uuid))
);
if (added.length) {
setPendingIDs(newPending);
setFiles([...files, ...added]);
}
}, [statuses, files, pendingIDs, setFiles, setPendingIDs, uploadedFiles]);
const pending = useMemo(() => pendingIDs.map(id => statuses[id]).filter(el => !!el), [
statuses,
pendingIDs,
]);
const isLoading = pending.length > 0;
return { uploadFiles, pending, files, setFiles, isUploading: isLoading };
};
export type FileUploader = ReturnType<typeof useFileUploader>;
const FileUploaderContext = createContext<FileUploader | undefined>(undefined);
export const FileUploaderProvider: FC<{ value: FileUploader; children }> = ({
value,
children,
}) => <FileUploaderContext.Provider value={value}>{children}</FileUploaderContext.Provider>;
export const useFileUploaderContext = () => useContext(FileUploaderContext);

View file

@ -0,0 +1,63 @@
import { UploadSubject, UploadTarget } from '~/constants/uploads';
import { IFile } from '~/redux/types';
import { useCallback } from 'react';
import { apiUploadFile } from '~/api/uploads';
import { keys } from 'ramda';
import { useLocalObservable } from 'mobx-react-lite';
import { UploaderStore } from '~/store/uploader/UploaderStore';
import { showErrorToast } from '~/utils/errors/showToast';
import uuid from 'uuid4';
export const useUploader = (
subject: UploadSubject,
target: UploadTarget,
initialFiles?: IFile[]
) => {
const store = useLocalObservable(() => new UploaderStore(initialFiles));
const uploadFile = useCallback(
async (file: File) => {
const id = uuid();
try {
// TODO: pass CancelationToken for axios as cancel() to pending
// TODO: cancel all uploads on unmount
const pending = await store.addPending(id, file);
const onProgress = ({ loaded, total }) => store.updateProgress(id, loaded, total);
const result = await apiUploadFile({ file, target, type: pending.type, onProgress });
store.removePending(id);
store.addFile(result);
return result;
} catch (error) {
store.removePending(id);
showErrorToast(error);
}
},
[store, target]
);
const uploadFiles = useCallback(
async (files: File[]) => {
await Promise.any(files.map(file => uploadFile(file)));
},
[uploadFile]
);
const isUploading = keys(store.pending).length > 0;
return {
uploadFile,
uploadFiles,
files: store.files,
filesImages: store.filesImages,
filesAudios: store.filesAudios,
pending: store.pending,
pendingImages: store.pendingImages,
pendingAudios: store.pendingAudios,
isUploading,
setFiles: store.setFiles,
};
};