2021-09-07 15:26:05 +03:00
|
|
|
import * as FileUtilities from "~/common/file-utilities";
|
|
|
|
import * as Logging from "~/common/logging";
|
|
|
|
import * as Actions from "~/common/actions";
|
|
|
|
|
|
|
|
let UploadStore = {
|
|
|
|
queue: [],
|
|
|
|
failedFilesCache: {},
|
|
|
|
isUploading: false,
|
|
|
|
};
|
|
|
|
|
2021-09-09 14:21:56 +03:00
|
|
|
// NOTE(amine): utilities
|
|
|
|
export const getFileKey = ({ lastModified, name }) => `${lastModified}-${name}`;
|
|
|
|
|
|
|
|
// NOTE(amine): queue utilities
|
|
|
|
const isQueueEmpty = () => UploadStore.queue.length === 0;
|
|
|
|
const getFileFromQueue = () => UploadStore.queue.shift() || {};
|
|
|
|
const getFileKeysFromQueue = () => UploadStore.queue.map(({ file }) => getFileKey(file));
|
|
|
|
const pushFileToQueue = ({ file, slate, bucket }) =>
|
|
|
|
UploadStore.queue.push({ file, slate, bucket });
|
|
|
|
const resetQueue = () => (UploadStore.queue = []);
|
|
|
|
const removeFileFromQueue = ({ fileKey }) =>
|
|
|
|
(UploadStore.queue = UploadStore.queue.filter(({ file }) => getFileKey(file) !== fileKey));
|
|
|
|
|
|
|
|
// NOTE(amine): failedFilesCache utilities
|
|
|
|
const storeFileInCache = ({ file, slate, bucketName }) =>
|
|
|
|
(UploadStore.failedFilesCache[getFileKey(file)] = { file, slate, bucketName });
|
|
|
|
const deleteFileFromCache = ({ fileKey }) => delete UploadStore.failedFilesCache[fileKey];
|
|
|
|
const getFileFromCache = ({ fileKey }) => UploadStore.failedFilesCache[fileKey] || {};
|
|
|
|
|
2021-09-07 15:26:05 +03:00
|
|
|
// NOTE(amine): upload factory function
|
|
|
|
export function createUploadProvider({
|
|
|
|
onStart,
|
|
|
|
onFinish,
|
|
|
|
onAddedToQueue,
|
|
|
|
onProgress,
|
|
|
|
onSuccess,
|
|
|
|
onError,
|
2021-09-09 14:21:56 +03:00
|
|
|
onCancel,
|
2021-09-07 15:26:05 +03:00
|
|
|
onDuplicate,
|
|
|
|
}) {
|
|
|
|
const scheduleQueueUpload = async () => {
|
|
|
|
if (UploadStore.isUploading) return;
|
|
|
|
|
2021-09-09 14:21:56 +03:00
|
|
|
const { file, slate, bucketName } = getFileFromQueue();
|
2021-09-07 15:26:05 +03:00
|
|
|
if (!file) return;
|
|
|
|
|
|
|
|
UploadStore.isUploading = true;
|
|
|
|
|
|
|
|
let fileKey = getFileKey(file);
|
|
|
|
|
|
|
|
try {
|
2021-09-09 14:21:56 +03:00
|
|
|
let response = await FileUtilities.upload({
|
2021-09-07 15:26:05 +03:00
|
|
|
file,
|
|
|
|
bucketName,
|
|
|
|
onProgress: (e) => onProgress({ fileKey, loaded: e.loaded }),
|
|
|
|
});
|
|
|
|
|
|
|
|
if (!response || response.error) {
|
2021-09-09 14:21:56 +03:00
|
|
|
UploadStore.isUploading = false;
|
2021-09-07 15:26:05 +03:00
|
|
|
|
2021-09-09 14:21:56 +03:00
|
|
|
storeFileInCache({ file, slate, bucketName });
|
2021-09-07 15:26:05 +03:00
|
|
|
if (onError) onError({ fileKey });
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
let createResponse = await Actions.createFile({ files: [response], slate });
|
|
|
|
if (!createResponse || createResponse.error) {
|
2021-09-09 14:21:56 +03:00
|
|
|
storeFileInCache({ file, slate, bucketName });
|
2021-09-07 15:26:05 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
const isDuplicate = createResponse?.data?.skipped > 0;
|
|
|
|
if (isDuplicate) {
|
|
|
|
if (onDuplicate) onDuplicate({ fileKey });
|
|
|
|
} else {
|
|
|
|
if (onSuccess) onSuccess({ fileKey });
|
|
|
|
}
|
|
|
|
} catch (e) {
|
2021-09-09 14:21:56 +03:00
|
|
|
UploadStore.isUploading = true;
|
|
|
|
storeFileInCache({ file, slate, bucketName });
|
2021-09-07 15:26:05 +03:00
|
|
|
if (onError) onError({ fileKey });
|
|
|
|
Logging.error(e);
|
|
|
|
}
|
|
|
|
|
2021-09-09 14:21:56 +03:00
|
|
|
UploadStore.isUploading = false;
|
|
|
|
|
|
|
|
if (!isQueueEmpty()) {
|
2021-09-07 15:26:05 +03:00
|
|
|
scheduleQueueUpload();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (onFinish) onFinish();
|
|
|
|
};
|
|
|
|
|
|
|
|
const addToUploadQueue = ({ files, slate, bucketName }) => {
|
2021-09-09 14:21:56 +03:00
|
|
|
if (isQueueEmpty() && !UploadStore.isUploading && onStart) onStart();
|
2021-09-07 15:26:05 +03:00
|
|
|
|
2021-09-09 14:21:56 +03:00
|
|
|
if (!files || !files.length) return;
|
2021-09-07 15:26:05 +03:00
|
|
|
|
|
|
|
for (let i = 0; i < files.length; i++) {
|
2021-09-09 14:21:56 +03:00
|
|
|
if (onAddedToQueue) onAddedToQueue(files[i]);
|
|
|
|
pushFileToQueue({ file: files[i], slate, bucketName });
|
2021-09-07 15:26:05 +03:00
|
|
|
scheduleQueueUpload();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-09-09 14:21:56 +03:00
|
|
|
const retry = ({ fileKey }) => {
|
|
|
|
const { file, slate, bucketName } = getFileFromCache({ fileKey });
|
|
|
|
addToUploadQueue({ files: [file], slate, bucketName });
|
|
|
|
deleteFileFromCache({ fileKey });
|
|
|
|
};
|
|
|
|
|
|
|
|
const cancel = ({ fileKey }) => {
|
|
|
|
removeFileFromQueue({ fileKey });
|
|
|
|
if (onCancel) onCancel({ fileKeys: [fileKey] });
|
|
|
|
};
|
|
|
|
|
|
|
|
const cancelAll = () => {
|
|
|
|
const keys = getFileKeysFromQueue();
|
|
|
|
resetQueue();
|
|
|
|
if (onCancel) onCancel({ fileKeys: keys });
|
|
|
|
};
|
|
|
|
|
2021-09-07 15:26:05 +03:00
|
|
|
return {
|
|
|
|
upload: addToUploadQueue,
|
2021-09-09 14:21:56 +03:00
|
|
|
retry,
|
|
|
|
cancel,
|
|
|
|
cancelAll,
|
2021-09-07 15:26:05 +03:00
|
|
|
};
|
|
|
|
}
|