From 036f60afbecfc7d65a5a3b6d0efb70b5e0fbf75e Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Fri, 19 Jan 2018 14:34:17 +0100 Subject: [PATCH] Blocks: Showing a preview of the block immediately after drag and drop (#4567) --- blocks/library/gallery/editor.scss | 4 ++++ blocks/library/gallery/gallery-image.js | 1 + blocks/library/gallery/index.js | 28 +++++++++++++++------- blocks/library/image/index.js | 20 ++++++++++------ editor/components/block-drop-zone/index.js | 10 ++++---- utils/mediaupload.js | 16 +++++++++++++ 6 files changed, 57 insertions(+), 22 deletions(-) diff --git a/blocks/library/gallery/editor.scss b/blocks/library/gallery/editor.scss index c6a8d2fa6933b7..86eb072132be1b 100644 --- a/blocks/library/gallery/editor.scss +++ b/blocks/library/gallery/editor.scss @@ -9,6 +9,10 @@ outline: 4px solid $blue-medium-500; outline-offset: -4px; } + + &.is-transient img { + @include loading_fade; + } } .blocks-gallery-item__inline-menu { diff --git a/blocks/library/gallery/gallery-image.js b/blocks/library/gallery/gallery-image.js index 78b538c9d14e1e..fdad5b678869ce 100644 --- a/blocks/library/gallery/gallery-image.js +++ b/blocks/library/gallery/gallery-image.js @@ -38,6 +38,7 @@ class GalleryImage extends Component { const className = classnames( { 'is-selected': isSelected, + 'is-transient': 0 === url.indexOf( 'blob:' ), } ); // Disable reason: Each block can be selected by clicking on it and we should keep the same saved markup diff --git a/blocks/library/gallery/index.js b/blocks/library/gallery/index.js index a891e21969de1e..48912f4e780fb2 100644 --- a/blocks/library/gallery/index.js +++ b/blocks/library/gallery/index.js @@ -7,7 +7,7 @@ import { filter, every } from 'lodash'; * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { createMediaFromFile } from '@wordpress/utils'; +import { createMediaFromFile, preloadImage } from '@wordpress/utils'; /** * Internal dependencies @@ -115,14 +115,24 @@ registerBlockType( 'core/gallery', { isMatch( files ) { return files.length !== 1 && every( files, ( file ) => file.type.indexOf( 'image/' ) === 0 ); }, - transform( files ) { - return Promise.all( files.map( ( file ) => createMediaFromFile( file ) ) ) - .then( ( medias ) => createBlock( 'core/gallery', { - images: medias.map( media => ( { - id: media.id, - url: media.source_url, - } ) ), - } ) ); + transform( files, onChange ) { + const block = createBlock( 'core/gallery', { + images: files.map( ( file ) => ( { + url: window.URL.createObjectURL( file ), + } ) ), + } ); + + Promise.all( files.map( ( file ) => + createMediaFromFile( file ) + .then( ( media ) => preloadImage( media.source_url ).then( () => media ) ) + ) ).then( ( medias ) => onChange( block.uid, { + images: medias.map( media => ( { + id: media.id, + url: media.source_url, + } ) ), + } ) ); + + return block; }, }, ], diff --git a/blocks/library/image/index.js b/blocks/library/image/index.js index dbabc408dcd316..150c9c3f137509 100644 --- a/blocks/library/image/index.js +++ b/blocks/library/image/index.js @@ -2,7 +2,7 @@ * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { createMediaFromFile } from '@wordpress/utils'; +import { createMediaFromFile, preloadImage } from '@wordpress/utils'; /** * Internal dependencies @@ -88,12 +88,18 @@ registerBlockType( 'core/image', { isMatch( files ) { return files.length === 1 && files[ 0 ].type.indexOf( 'image/' ) === 0; }, - transform( files ) { - return createMediaFromFile( files[ 0 ] ) - .then( ( media ) => createBlock( 'core/image', { - id: media.id, - url: media.source_url, - } ) ); + transform( files, onChange ) { + const file = files[ 0 ]; + const block = createBlock( 'core/image', { + url: window.URL.createObjectURL( file ), + } ); + + createMediaFromFile( file ) + .then( ( media ) => preloadImage( media.source_url ).then( + () => onChange( block.uid, { id: media.id, url: media.source_url } ) + ) ); + + return block; }, }, { diff --git a/editor/components/block-drop-zone/index.js b/editor/components/block-drop-zone/index.js index d3836f32f98f7c..29f76029940b14 100644 --- a/editor/components/block-drop-zone/index.js +++ b/editor/components/block-drop-zone/index.js @@ -14,7 +14,7 @@ import { compose } from '@wordpress/element'; /** * Internal dependencies */ -import { insertBlocks } from '../../store/actions'; +import { insertBlocks, updateBlockAttributes } from '../../store/actions'; function BlockDropZone( { index, isLocked, ...props } ) { if ( isLocked ) { @@ -40,10 +40,8 @@ function BlockDropZone( { index, isLocked, ...props } ) { if ( transformation ) { const insertPosition = getInsertPosition( position ); - - transformation.transform( files ).then( ( blocks ) => { - props.insertBlocks( blocks, insertPosition ); - } ); + const blocks = transformation.transform( files, props.updateBlockAttributes ); + props.insertBlocks( blocks, insertPosition ); } }; @@ -66,7 +64,7 @@ function BlockDropZone( { index, isLocked, ...props } ) { export default compose( connect( undefined, - { insertBlocks } + { insertBlocks, updateBlockAttributes } ), withContext( 'editor' )( ( settings ) => { const { templateLock } = settings; diff --git a/utils/mediaupload.js b/utils/mediaupload.js index fbf85adaf24f99..bef56184a04d11 100644 --- a/utils/mediaupload.js +++ b/utils/mediaupload.js @@ -60,3 +60,19 @@ export function createMediaFromFile( file ) { contentType: false, } ); } + +/** + * Utility used to preload an image before displaying it. + * + * @param {string} url Image Url. + * @returns {Promise} Pormise resolved once the image is preloaded. + */ +export function preloadImage( url ) { + return new Promise( resolve => { + const newImg = new window.Image(); + newImg.onload = function() { + resolve( url ); + }; + newImg.src = url; + } ); +}