diff --git a/packages/block-editor/src/components/media-placeholder/README.md b/packages/block-editor/src/components/media-placeholder/README.md index caba06f5845c67..807b4c3c2347a7 100644 --- a/packages/block-editor/src/components/media-placeholder/README.md +++ b/packages/block-editor/src/components/media-placeholder/README.md @@ -140,6 +140,14 @@ Callback called when an upload error happens. - Required: No - Platform: Web +### onFilesUpload + +Callback called when files started to be uploaded. + +- Type: `Function` +- Required: No +- Platform: Web + ### onSelect Callback called when the files are selected/uploaded. @@ -153,6 +161,15 @@ The argument of the callback is an object containing the following properties: - Web: `{ url, alt, id, link, caption, sizes, media_details }` - Mobile: `{ id, url }` +### selectAllUploads + +Whether to get the entire list of selected files with `onSelect` without using `multiple` option. + +- Type: `Boolean` +- Required: No +- Default: `false` +- Platform: Web + ### value An object or an array of objects that contain media ID (`id` property) to be selected by default when opening the media library. diff --git a/packages/block-editor/src/components/media-placeholder/index.js b/packages/block-editor/src/components/media-placeholder/index.js index 505464b7264b2e..5dbed5ddf2ffff 100644 --- a/packages/block-editor/src/components/media-placeholder/index.js +++ b/packages/block-editor/src/components/media-placeholder/index.js @@ -114,6 +114,7 @@ export class MediaPlaceholder extends Component { allowedTypes, mediaUpload, multiple, + selectAllUploads, onError, onSelect, value = [], @@ -129,8 +130,15 @@ export class MediaPlaceholder extends Component { setMedia = onSelect; } } else { - setMedia = ( [ media ] ) => onSelect( media ); + setMedia = selectAllUploads + ? onSelect + : ( [ media ] ) => onSelect( media ); } + + if ( this.props.onFilesUpload ) { + this.props.onFilesUpload( files ); + } + mediaUpload( { allowedTypes, filesList: files, diff --git a/packages/block-library/src/image/edit.js b/packages/block-library/src/image/edit.js index 30ddaefd89602e..deaa0108acd348 100644 --- a/packages/block-library/src/image/edit.js +++ b/packages/block-library/src/image/edit.js @@ -17,6 +17,7 @@ import { TextControl, ToolbarGroup, withNotices, + Placeholder, } from '@wordpress/components'; import { compose } from '@wordpress/compose'; import { withSelect, withDispatch } from '@wordpress/data'; @@ -38,6 +39,7 @@ import { __, sprintf } from '@wordpress/i18n'; import { getPath } from '@wordpress/url'; import { withViewportMatch } from '@wordpress/viewport'; import { image as icon } from '@wordpress/icons'; +import { createBlock } from '@wordpress/blocks'; /** * Internal dependencies @@ -86,6 +88,12 @@ const isTemporaryImage = ( id, url ) => ! id && isBlobURL( url ); */ const isExternalImage = ( id, url ) => url && ! id && ! isBlobURL( url ); +const isUploadingImages = ( media ) => + media.filter( ( image ) => isBlobURL( image.url ) ).length > 0; + +const currentlyUploadingImage = ( media ) => + media.filter( ( image ) => isBlobURL( image.url ) )[ 0 ]; + export class ImageEdit extends Component { constructor() { super( ...arguments ); @@ -94,6 +102,8 @@ export class ImageEdit extends Component { this.onFocusCaption = this.onFocusCaption.bind( this ); this.onImageClick = this.onImageClick.bind( this ); this.onSelectImage = this.onSelectImage.bind( this ); + this.onFilesUpload = this.onFilesUpload.bind( this ); + this.setupImage = this.setupImage.bind( this ); this.onSelectURL = this.onSelectURL.bind( this ); this.updateImage = this.updateImage.bind( this ); this.onSetHref = this.onSetHref.bind( this ); @@ -104,6 +114,8 @@ export class ImageEdit extends Component { this.state = { captionFocused: false, + uploadingMultipleImages: false, + imageFileName: null, }; } @@ -158,6 +170,39 @@ export class ImageEdit extends Component { } onSelectImage( media ) { + if ( ! Array.isArray( media ) ) { + // selected by Media library. + this.setupImage( media ); + } else if ( this.state.uploadingMultipleImages ) { + if ( isUploadingImages( media ) ) { + this.setState( { + imageFileName: currentlyUploadingImage( media ), + } ); + } else { + // Reset current component for undo. + this.props.setAttributes( { + url: undefined, + alt: undefined, + id: undefined, + title: undefined, + caption: undefined, + } ); + this.props.replaceWithMultipleImageBlocks( media ); + } + } else { + this.setupImage( media[ 0 ] ); + } + } + + onFilesUpload( files ) { + if ( files.length > 1 ) { + this.setState( { + uploadingMultipleImages: true, + } ); + } + } + + setupImage( media ) { if ( ! media || ! media.url ) { this.props.setAttributes( { url: undefined, @@ -415,6 +460,8 @@ export class ImageEdit extends Component { value={ { id, src } } mediaPreview={ mediaPreview } disableMediaButtons={ url } + selectAllUploads + onFilesUpload={ this.onFilesUpload } /> ); @@ -440,6 +487,21 @@ export class ImageEdit extends Component { ); } + if ( this.state.uploadingMultipleImages ) { + return ( + + + + { __( 'Uploading Images. Please wait.' ) } + + } + > + + ); + } + const classes = classnames( className, { 'is-transient': isBlobURL( url ), 'is-resized': !! width || !! height, @@ -713,12 +775,35 @@ export class ImageEdit extends Component { } export default compose( [ - withDispatch( ( dispatch ) => { - const { toggleSelection } = dispatch( 'core/block-editor' ); + withDispatch( ( dispatch, props ) => { + const { toggleSelection, replaceBlocks } = dispatch( + 'core/block-editor' + ); return { onResizeStart: () => toggleSelection( false ), onResizeStop: () => toggleSelection( true ), + replaceWithMultipleImageBlocks( media ) { + const blocks = filter( + media.map( ( image ) => { + if ( ! image || ! image.url ) { + return null; + } + + const { url, caption } = pickRelevantMediaFiles( + image + ); + + return createBlock( 'core/image', { + url, + caption, + } ); + } ), + ( block ) => !! block + ); + + replaceBlocks( [ props.clientId ], blocks ); + }, }; } ), withSelect( ( select, props ) => { diff --git a/packages/block-library/src/image/editor.scss b/packages/block-library/src/image/editor.scss index db7e48edcd73d8..5d1bfe6c3d537f 100644 --- a/packages/block-library/src/image/editor.scss +++ b/packages/block-library/src/image/editor.scss @@ -5,6 +5,14 @@ opacity: 0.3; } + &.is-uploading-multiple-images .components-spinner { + position: relative; + top: 0; + left: 0; + margin-top: 5px; + margin-left: 11px; + } + figcaption img { display: inline; }