UNPKG

@rpldy/uploader

Version:

the processing and queuing engine for react-uploady

150 lines 4.83 kB
import { logger, hasWindow, isFunction, scheduleIdleWork } from "@rpldy/shared"; import createState from "@rpldy/simple-state"; import { SENDER_EVENTS, UPLOADER_EVENTS } from "../consts"; import processQueueNext from "./processQueueNext"; import { processAbortItem, processAbortBatch, processAbortAll } from "./processAbort"; import { detachRecycledFromPreviousBatch, getBatchFromState, preparePendingForUpload, removePendingBatches, clearBatchData, cancelBatchWithId, triggerUploaderBatchEvent } from "./batchHelpers"; const createUploaderQueue = (options, trigger, cancellable, sender, uploaderId) => { const { state, update } = createState({ itemQueue: {}, batchQueue: [], currentBatch: null, batchesStartPending: [], batches: {}, items: {}, activeIds: [], aborts: {} }); const getState = () => state; const updateState = updater => { update(updater); }; const add = item => { if (state.items[item.id] && !item.recycled) { throw new Error(`Uploader queue conflict - item ${item.id} already exists`); } if (item.recycled) { detachRecycledFromPreviousBatch(queueState, item); } updateState(state => { state.items[item.id] = item; }); }; const handleItemProgress = (item, completed, loaded, total) => { if (state.items[item.id]) { updateState(state => { const stateItem = state.items[item.id]; stateItem.loaded = loaded; stateItem.completed = completed; stateItem.total = total; }); trigger(UPLOADER_EVENTS.ITEM_PROGRESS, getState().items[item.id]); } }; sender.on(SENDER_EVENTS.ITEM_PROGRESS, handleItemProgress); sender.on(SENDER_EVENTS.BATCH_PROGRESS, batch => { const batchItems = state.batches[batch.id]?.batch.items; if (batchItems) { const [loaded, total] = batchItems.reduce((res, { id }) => { const { loaded, file } = state.items[id]; const size = file?.size || loaded || 1; res[0] += loaded; res[1] += size; return res; }, [0, 0]); updateState(state => { const stateBatch = state.batches[batch.id].batch; stateBatch.total = total; stateBatch.loaded = loaded; stateBatch.completed = loaded / total; }); triggerUploaderBatchEvent(queueState, batch.id, UPLOADER_EVENTS.BATCH_PROGRESS); } }); const queueState = { uploaderId, getOptions: () => options, getCurrentActiveCount: () => state.activeIds.length, getState, updateState, trigger, runCancellable: (name, ...args) => { if (!isFunction(cancellable)) { throw new Error("Uploader queue - cancellable is of wrong type"); } return cancellable(name, ...args); }, sender, handleItemProgress, clearAllUploads: () => { queueState.updateState(state => { state.itemQueue = {}; state.batchQueue = []; state.currentBatch = null; state.batches = {}; state.items = {}; state.activeIds = []; }); }, clearBatchUploads: batchId => { scheduleIdleWork(() => { logger.debugLog(`uploader.queue: started scheduled work to clear batch uploads (${batchId})`); if (getState().batches[batchId]) { clearBatchData(queueState, batchId); } }); } }; if (hasWindow() && logger.isDebugOn()) { window[`__rpldy_${uploaderId}_queue_state`] = queueState; } return { updateState, getState: queueState.getState, runCancellable: queueState.runCancellable, uploadBatch: (batch, batchOptions) => { if (batchOptions) { updateState(state => { state.batches[batch.id].batchOptions = batchOptions; }); } processQueueNext(queueState); }, addBatch: (batch, batchOptions) => { updateState(state => { state.batches[batch.id] = { batch, batchOptions, itemBatchOptions: {}, finishedCounter: 0 }; state.batchQueue.push(batch.id); state.itemQueue[batch.id] = batch.items.map(({ id }) => id); }); batch.items.forEach(add); return getBatchFromState(state, batch.id); }, abortItem: (...args) => processAbortItem(queueState, ...args), abortBatch: (...args) => processAbortBatch(queueState, ...args), abortAll: (...args) => processAbortAll(queueState, ...args), clearPendingBatches: () => { removePendingBatches(queueState); }, uploadPendingBatches: uploadOptions => { preparePendingForUpload(queueState, uploadOptions); processQueueNext(queueState); }, cancelBatch: batch => cancelBatchWithId(queueState, batch.id) }; }; export default createUploaderQueue;