diff --git a/blocks/library/gallery/index.js b/blocks/library/gallery/index.js index cfc9d107e29ba9..3a73ccb2191364 100644 --- a/blocks/library/gallery/index.js +++ b/blocks/library/gallery/index.js @@ -120,6 +120,7 @@ registerBlockType( 'core/gallery', { onSelect={ setMediaUrl } type="image" multiple="true" + gallery="true" > { __( 'Insert from Media Library' ) } diff --git a/blocks/media-upload-button/index.js b/blocks/media-upload-button/index.js index 013c15707ced4f..f60dfdae2fe035 100644 --- a/blocks/media-upload-button/index.js +++ b/blocks/media-upload-button/index.js @@ -4,12 +4,65 @@ import { Component } from 'element'; import { __ } from 'i18n'; import { Button } from 'components'; +import { pick } from 'lodash'; + +// Getter for the sake of unit tests. +const getGalleryDetailsMediaFrame = () => { + /** + * Custom gallery details frame. + * + * @link https://github.com/xwp/wp-core-media-widgets/blob/905edbccfc2a623b73a93dac803c5335519d7837/wp-admin/js/widgets/media-gallery-widget.js + * @class GalleryDetailsMediaFrame + * @constructor + */ + return wp.media.view.MediaFrame.Post.extend( { + + /** + * Create the default states. + * + * @returns {void} + */ + createStates: function createStates() { + this.states.add( [ + new wp.media.controller.Library( { + id: 'gallery', + title: wp.media.view.l10n.createGalleryTitle, + priority: 40, + toolbar: 'main-gallery', + filterable: 'uploaded', + multiple: 'add', + editable: false, + + library: wp.media.query( _.defaults( { + type: 'image', + }, this.options.library ) ), + } ), + + new wp.media.controller.GalleryEdit( { + library: this.options.selection, + editing: this.options.editing, + menu: 'gallery', + } ), + + new wp.media.controller.GalleryAdd(), + ] ); + }, + } ); +}; + +// the media library image object contains numerous attributes +// we only need this set to display the image in the library +const slimImageObject = ( img ) => { + const attrSet = [ 'sizes', 'mime', 'type', 'subtype', 'id', 'url', 'alt' ]; + return pick( img, attrSet ); +}; class MediaUploadButton extends Component { - constructor( { multiple = false, type } ) { + constructor( { multiple = false, type, gallery = false } ) { super( ...arguments ); this.openModal = this.openModal.bind( this ); this.onSelect = this.onSelect.bind( this ); + this.onUpdate = this.onUpdate.bind( this ); this.onOpen = this.onOpen.bind( this ); const frameConfig = { title: __( 'Select or Upload a media' ), @@ -17,14 +70,27 @@ class MediaUploadButton extends Component { text: __( 'Select' ), }, multiple, + selection: new wp.media.model.Selection( [] ), }; if ( !! type ) { frameConfig.library = { type }; } - this.frame = wp.media( frameConfig ); + + if ( gallery ) { + const GalleryDetailsMediaFrame = getGalleryDetailsMediaFrame(); + this.frame = new GalleryDetailsMediaFrame( { + frame: 'select', + mimeType: type, + state: 'gallery', + } ); + wp.media.frame = this.frame; + } else { + this.frame = wp.media( frameConfig ); + } // When an image is selected in the media frame... this.frame.on( 'select', this.onSelect ); + this.frame.on( 'update', this.onUpdate ); this.frame.on( 'open', this.onOpen ); } @@ -32,6 +98,21 @@ class MediaUploadButton extends Component { this.frame.remove(); } + onUpdate( selections ) { + const { onSelect, multiple = false } = this.props; + const state = this.frame.state(); + const selectedImages = selections || state.get( 'selection' ); + + if ( ! selectedImages || ! selectedImages.models.length ) { + return; + } + if ( multiple ) { + onSelect( selectedImages.models.map( ( model ) => slimImageObject( model.toJSON() ) ) ); + } else { + onSelect( slimImageObject( selectedImages.models[ 0 ].toJSON() ) ); + } + } + onSelect() { const { onSelect, multiple = false } = this.props; // Get media attachment details from the frame state diff --git a/lib/client-assets.php b/lib/client-assets.php index 19a8656a7a3e9f..4247a00c437dae 100644 --- a/lib/client-assets.php +++ b/lib/client-assets.php @@ -103,7 +103,7 @@ function gutenberg_register_scripts_and_styles() { wp_register_script( 'wp-blocks', gutenberg_url( 'blocks/build/index.js' ), - array( 'wp-element', 'wp-components', 'wp-utils', 'tinymce-nightly', 'tinymce-nightly-lists', 'tinymce-nightly-paste', 'tinymce-nightly-table' ), + array( 'wp-element', 'wp-components', 'wp-utils', 'tinymce-nightly', 'tinymce-nightly-lists', 'tinymce-nightly-paste', 'tinymce-nightly-table', 'media-views', 'media-models' ), filemtime( gutenberg_dir_path() . 'blocks/build/index.js' ) );