UNPKG

@wordpress/upload-media

Version:
352 lines (332 loc) 8.22 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.addItem = addItem; exports.finishOperation = finishOperation; exports.pauseQueue = pauseQueue; exports.prepareItem = prepareItem; exports.processItem = processItem; exports.removeItem = removeItem; exports.resumeQueue = resumeQueue; exports.revokeBlobUrls = revokeBlobUrls; exports.updateSettings = updateSettings; exports.uploadItem = uploadItem; var _uuid = require("uuid"); var _blob = require("@wordpress/blob"); var _utils = require("../utils"); var _stubFile = require("../stub-file"); var _types = require("./types"); /** * External dependencies */ /** * WordPress dependencies */ /** * Internal dependencies */ /** * Adds a new item to the upload queue. * * @param $0 * @param $0.file File * @param [$0.batchId] Batch ID. * @param [$0.onChange] Function called each time a file or a temporary representation of the file is available. * @param [$0.onSuccess] Function called after the file is uploaded. * @param [$0.onBatchSuccess] Function called after a batch of files is uploaded. * @param [$0.onError] Function called when an error happens. * @param [$0.additionalData] Additional data to include in the request. * @param [$0.sourceUrl] Source URL. Used when importing a file from a URL or optimizing an existing file. * @param [$0.sourceAttachmentId] Source attachment ID. Used when optimizing an existing file for example. * @param [$0.abortController] Abort controller for upload cancellation. * @param [$0.operations] List of operations to perform. Defaults to automatically determined list, based on the file. */ function addItem({ file: fileOrBlob, batchId, onChange, onSuccess, onBatchSuccess, onError, additionalData = {}, sourceUrl, sourceAttachmentId, abortController, operations }) { return async ({ dispatch }) => { const itemId = (0, _uuid.v4)(); // Hardening in case a Blob is passed instead of a File. // See https://github.com/WordPress/gutenberg/pull/65693 for an example. const file = (0, _utils.convertBlobToFile)(fileOrBlob); let blobUrl; // StubFile could be coming from addItemFromUrl(). if (!(file instanceof _stubFile.StubFile)) { blobUrl = (0, _blob.createBlobURL)(file); dispatch({ type: _types.Type.CacheBlobUrl, id: itemId, blobUrl }); } dispatch({ type: _types.Type.Add, item: { id: itemId, batchId, status: _types.ItemStatus.Processing, sourceFile: (0, _utils.cloneFile)(file), file, attachment: { url: blobUrl }, additionalData: { convert_format: false, ...additionalData }, onChange, onSuccess, onBatchSuccess, onError, sourceUrl, sourceAttachmentId, abortController: abortController || new AbortController(), operations: Array.isArray(operations) ? operations : [_types.OperationType.Prepare] } }); dispatch.processItem(itemId); }; } /** * Processes a single item in the queue. * * Runs the next operation in line and invokes any callbacks. * * @param id Item ID. */ function processItem(id) { return async ({ select, dispatch }) => { if (select.isPaused()) { return; } const item = select.getItem(id); const { attachment, onChange, onSuccess, onBatchSuccess, batchId } = item; const operation = Array.isArray(item.operations?.[0]) ? item.operations[0][0] : item.operations?.[0]; if (attachment) { onChange?.([attachment]); } /* If there are no more operations, the item can be removed from the queue, but only if there are no thumbnails still being side-loaded, or if itself is a side-loaded item. */ if (!operation) { if (attachment) { onSuccess?.([attachment]); } // dispatch.removeItem( id ); dispatch.revokeBlobUrls(id); if (batchId && select.isBatchUploaded(batchId)) { onBatchSuccess?.(); } /* At this point we are dealing with a parent whose children haven't fully uploaded yet. Do nothing and let the removal happen once the last side-loaded item finishes. */ return; } if (!operation) { // This shouldn't really happen. return; } dispatch({ type: _types.Type.OperationStart, id, operation }); switch (operation) { case _types.OperationType.Prepare: dispatch.prepareItem(item.id); break; case _types.OperationType.Upload: dispatch.uploadItem(id); break; } }; } /** * Returns an action object that pauses all processing in the queue. * * Useful for testing purposes. * * @return Action object. */ function pauseQueue() { return { type: _types.Type.PauseQueue }; } /** * Resumes all processing in the queue. * * Dispatches an action object for resuming the queue itself, * and triggers processing for each remaining item in the queue individually. */ function resumeQueue() { return async ({ select, dispatch }) => { dispatch({ type: _types.Type.ResumeQueue }); for (const item of select.getAllItems()) { dispatch.processItem(item.id); } }; } /** * Removes a specific item from the queue. * * @param id Item ID. */ function removeItem(id) { return async ({ select, dispatch }) => { const item = select.getItem(id); if (!item) { return; } dispatch({ type: _types.Type.Remove, id }); }; } /** * Finishes an operation for a given item ID and immediately triggers processing the next one. * * @param id Item ID. * @param updates Updated item data. */ function finishOperation(id, updates) { return async ({ dispatch }) => { dispatch({ type: _types.Type.OperationFinish, id, item: updates }); dispatch.processItem(id); }; } /** * Prepares an item for initial processing. * * Determines the list of operations to perform for a given image, * depending on its media type. * * For example, HEIF images first need to be converted, resized, * compressed, and then uploaded. * * Or videos need to be compressed, and then need poster generation * before upload. * * @param id Item ID. */ function prepareItem(id) { return async ({ dispatch }) => { const operations = [_types.OperationType.Upload]; dispatch({ type: _types.Type.AddOperations, id, operations }); dispatch.finishOperation(id, {}); }; } /** * Uploads an item to the server. * * @param id Item ID. */ function uploadItem(id) { return async ({ select, dispatch }) => { const item = select.getItem(id); select.getSettings().mediaUpload({ filesList: [item.file], additionalData: item.additionalData, signal: item.abortController?.signal, onFileChange: ([attachment]) => { if (!(0, _blob.isBlobURL)(attachment.url)) { dispatch.finishOperation(id, { attachment }); } }, onSuccess: ([attachment]) => { dispatch.finishOperation(id, { attachment }); }, onError: error => { dispatch.cancelItem(id, error); } }); }; } /** * Revokes all blob URLs for a given item, freeing up memory. * * @param id Item ID. */ function revokeBlobUrls(id) { return async ({ select, dispatch }) => { const blobUrls = select.getBlobUrls(id); for (const blobUrl of blobUrls) { (0, _blob.revokeBlobURL)(blobUrl); } dispatch({ type: _types.Type.RevokeBlobUrls, id }); }; } /** * Returns an action object that pauses all processing in the queue. * * Useful for testing purposes. * * @param settings * @return Action object. */ function updateSettings(settings) { return { type: _types.Type.UpdateSettings, settings }; } //# sourceMappingURL=private-actions.js.map