From e686dde9c16a3264cc2b91e84b2f0c0ed16d697e Mon Sep 17 00:00:00 2001 From: Derek Blank Date: Thu, 7 Apr 2022 17:50:07 +1000 Subject: [PATCH 01/21] Add 'Insert from URL' option to Video and Image blocks --- .../src/components/media-upload/index.native.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/media-upload/index.native.js b/packages/block-editor/src/components/media-upload/index.native.js index 05aabd9a9a3cd1..632bfa98c76ccf 100644 --- a/packages/block-editor/src/components/media-upload/index.native.js +++ b/packages/block-editor/src/components/media-upload/index.native.js @@ -124,7 +124,11 @@ export class MediaUpload extends Component { id: URL_MEDIA_SOURCE, value: URL_MEDIA_SOURCE, label: __( 'Insert from URL' ), - types: [ MEDIA_TYPE_AUDIO ], + types: [ + MEDIA_TYPE_AUDIO, + MEDIA_TYPE_IMAGE, + MEDIA_TYPE_VIDEO, + ], icon: globe, }; From cec7316074d9bf8e65619a41482aaf80a091ef52 Mon Sep 17 00:00:00 2001 From: Derek Blank Date: Mon, 11 Apr 2022 16:29:30 +1000 Subject: [PATCH 02/21] Update code style from linting --- .../src/components/media-upload/index.native.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/block-editor/src/components/media-upload/index.native.js b/packages/block-editor/src/components/media-upload/index.native.js index 632bfa98c76ccf..9d286f2bf4aeac 100644 --- a/packages/block-editor/src/components/media-upload/index.native.js +++ b/packages/block-editor/src/components/media-upload/index.native.js @@ -124,11 +124,7 @@ export class MediaUpload extends Component { id: URL_MEDIA_SOURCE, value: URL_MEDIA_SOURCE, label: __( 'Insert from URL' ), - types: [ - MEDIA_TYPE_AUDIO, - MEDIA_TYPE_IMAGE, - MEDIA_TYPE_VIDEO, - ], + types: [ MEDIA_TYPE_AUDIO, MEDIA_TYPE_IMAGE, MEDIA_TYPE_VIDEO ], icon: globe, }; From d56ab563eea1b9af69691d8f66694503633f702e Mon Sep 17 00:00:00 2001 From: Derek Blank Date: Thu, 14 Apr 2022 13:34:24 +1000 Subject: [PATCH 03/21] Improve test cases for Media Upload capture options --- .../components/media-upload/index.native.js | 2 ++ .../media-upload/test/index.native.js | 36 +++++++++++++++---- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/packages/block-editor/src/components/media-upload/index.native.js b/packages/block-editor/src/components/media-upload/index.native.js index 9d286f2bf4aeac..6ef097037164d6 100644 --- a/packages/block-editor/src/components/media-upload/index.native.js +++ b/packages/block-editor/src/components/media-upload/index.native.js @@ -37,8 +37,10 @@ export const MEDIA_TYPE_ANY = 'any'; export const OPTION_TAKE_VIDEO = __( 'Take a Video' ); export const OPTION_TAKE_PHOTO = __( 'Take a Photo' ); +export const OPTION_CHOOSE_FROM_DEVICE = __( 'Choose from Device' ); export const OPTION_TAKE_PHOTO_OR_VIDEO = __( 'Take a Photo or Video' ); export const OPTION_INSERT_FROM_URL = __( 'Insert from URL' ); +export const OPTION_WORDPRESS_MEDIA_LIBRARY = __( 'WordPress Media Library' ); const URL_MEDIA_SOURCE = 'URL'; diff --git a/packages/block-editor/src/components/media-upload/test/index.native.js b/packages/block-editor/src/components/media-upload/test/index.native.js index e54a9f5219321d..1a70a2fb9e93ad 100644 --- a/packages/block-editor/src/components/media-upload/test/index.native.js +++ b/packages/block-editor/src/components/media-upload/test/index.native.js @@ -17,9 +17,11 @@ import { MEDIA_TYPE_IMAGE, MEDIA_TYPE_VIDEO, MEDIA_TYPE_AUDIO, + OPTION_CHOOSE_FROM_DEVICE, OPTION_TAKE_VIDEO, OPTION_TAKE_PHOTO, OPTION_INSERT_FROM_URL, + OPTION_WORDPRESS_MEDIA_LIBRARY, } from '../index'; const MEDIA_URL = 'http://host.media.type'; @@ -33,14 +35,14 @@ describe( 'MediaUpload component', () => { expect( wrapper ).toBeTruthy(); } ); - it( 'shows right media capture option for media type', () => { + describe( 'Media capture options for different media block types', () => { const expectOptionForMediaType = ( mediaType, expectedOption ) => { const wrapper = render( { return ( - <> + <> Open Picker @@ -52,11 +54,33 @@ describe( 'MediaUpload component', () => { ); fireEvent.press( wrapper.getByText( 'Open Picker' ) ); - wrapper.getByText( expectedOption ); + wrapper.findByText( expectedOption ); }; - expectOptionForMediaType( MEDIA_TYPE_IMAGE, OPTION_TAKE_PHOTO ); - expectOptionForMediaType( MEDIA_TYPE_VIDEO, OPTION_TAKE_VIDEO ); - expectOptionForMediaType( MEDIA_TYPE_AUDIO, OPTION_INSERT_FROM_URL ); + + it( 'shows the correct media capture options for the Image block', () => { + expectOptionForMediaType( MEDIA_TYPE_IMAGE, [ + OPTION_CHOOSE_FROM_DEVICE, + OPTION_TAKE_PHOTO, + OPTION_WORDPRESS_MEDIA_LIBRARY, + OPTION_INSERT_FROM_URL, + ] ); + } ); + + it( 'shows the correct media capture options for the Video block', () => { + expectOptionForMediaType( MEDIA_TYPE_VIDEO, [ + OPTION_CHOOSE_FROM_DEVICE, + OPTION_TAKE_VIDEO, + OPTION_WORDPRESS_MEDIA_LIBRARY, + OPTION_INSERT_FROM_URL, + ] ); + } ); + + it( 'shows the correct media capture options for the Audio block', () => { + expectOptionForMediaType( MEDIA_TYPE_AUDIO, [ + OPTION_WORDPRESS_MEDIA_LIBRARY, + OPTION_INSERT_FROM_URL, + ] ); + } ); } ); const expectMediaPickerForOption = ( From 504eabfa79e0bb7b2bff82708bd1d5b3978ade6f Mon Sep 17 00:00:00 2001 From: Derek Blank Date: Thu, 14 Apr 2022 14:40:38 +1000 Subject: [PATCH 04/21] Fix whitespace issue --- .../src/components/media-upload/test/index.native.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/media-upload/test/index.native.js b/packages/block-editor/src/components/media-upload/test/index.native.js index 1a70a2fb9e93ad..b8dd8f6fc676c9 100644 --- a/packages/block-editor/src/components/media-upload/test/index.native.js +++ b/packages/block-editor/src/components/media-upload/test/index.native.js @@ -42,7 +42,7 @@ describe( 'MediaUpload component', () => { allowedTypes={ [ mediaType ] } render={ ( { open, getMediaOptions } ) => { return ( - <> + <> Open Picker From 8b79cf190585b1ff3760750c67c4c43e27115dbc Mon Sep 17 00:00:00 2001 From: Derek Blank Date: Thu, 21 Apr 2022 14:01:08 +1000 Subject: [PATCH 05/21] Update Media Upload option tests to be asynchronous --- .../components/media-upload/test/index.native.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/packages/block-editor/src/components/media-upload/test/index.native.js b/packages/block-editor/src/components/media-upload/test/index.native.js index b8dd8f6fc676c9..9bc27cf5f63bb9 100644 --- a/packages/block-editor/src/components/media-upload/test/index.native.js +++ b/packages/block-editor/src/components/media-upload/test/index.native.js @@ -17,7 +17,6 @@ import { MEDIA_TYPE_IMAGE, MEDIA_TYPE_VIDEO, MEDIA_TYPE_AUDIO, - OPTION_CHOOSE_FROM_DEVICE, OPTION_TAKE_VIDEO, OPTION_TAKE_PHOTO, OPTION_INSERT_FROM_URL, @@ -36,7 +35,10 @@ describe( 'MediaUpload component', () => { } ); describe( 'Media capture options for different media block types', () => { - const expectOptionForMediaType = ( mediaType, expectedOption ) => { + const expectOptionForMediaType = async ( + mediaType, + expectedOptions + ) => { const wrapper = render( { } } /> ); - fireEvent.press( wrapper.getByText( 'Open Picker' ) ); + await fireEvent.press( wrapper.getByText( 'Open Picker' ) ); - wrapper.findByText( expectedOption ); + await expectedOptions.forEach( ( item ) => { + const option = wrapper.getByText( item ); + expect( option ).toBeVisible(); + } ); }; it( 'shows the correct media capture options for the Image block', () => { expectOptionForMediaType( MEDIA_TYPE_IMAGE, [ - OPTION_CHOOSE_FROM_DEVICE, OPTION_TAKE_PHOTO, OPTION_WORDPRESS_MEDIA_LIBRARY, OPTION_INSERT_FROM_URL, @@ -68,7 +72,6 @@ describe( 'MediaUpload component', () => { it( 'shows the correct media capture options for the Video block', () => { expectOptionForMediaType( MEDIA_TYPE_VIDEO, [ - OPTION_CHOOSE_FROM_DEVICE, OPTION_TAKE_VIDEO, OPTION_WORDPRESS_MEDIA_LIBRARY, OPTION_INSERT_FROM_URL, @@ -77,7 +80,6 @@ describe( 'MediaUpload component', () => { it( 'shows the correct media capture options for the Audio block', () => { expectOptionForMediaType( MEDIA_TYPE_AUDIO, [ - OPTION_WORDPRESS_MEDIA_LIBRARY, OPTION_INSERT_FROM_URL, ] ); } ); From 760b9cf80afcf19ed05ebe140b7a281b0036a55d Mon Sep 17 00:00:00 2001 From: Derek Blank Date: Tue, 26 Apr 2022 21:12:55 +1000 Subject: [PATCH 06/21] Update native image block to use correct image URL --- .../block-library/src/image/edit.native.js | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/packages/block-library/src/image/edit.native.js b/packages/block-library/src/image/edit.native.js index 5ebea31f3ad31c..46d7b55d3d8531 100644 --- a/packages/block-library/src/image/edit.native.js +++ b/packages/block-library/src/image/edit.native.js @@ -45,7 +45,7 @@ import { blockSettingsScreens, } from '@wordpress/block-editor'; import { __, _x, sprintf } from '@wordpress/i18n'; -import { getProtocol, hasQueryArg } from '@wordpress/url'; +import { getProtocol, hasQueryArg, isURL } from '@wordpress/url'; import { doAction, hasAction } from '@wordpress/hooks'; import { compose, withPreferredColorScheme } from '@wordpress/compose'; import { withSelect, withDispatch } from '@wordpress/data'; @@ -207,6 +207,7 @@ export class ImageEdit extends Component { this.onImagePressed = this.onImagePressed.bind( this ); this.onSetFeatured = this.onSetFeatured.bind( this ); this.onFocusCaption = this.onFocusCaption.bind( this ); + this.onSelectURL = this.onSelectURL.bind( this ); this.updateAlignment = this.updateAlignment.bind( this ); this.accessibilityLabelCreator = this.accessibilityLabelCreator.bind( this @@ -461,6 +462,19 @@ export class ImageEdit extends Component { } ); } + onSelectURL( newUrl ) { + const { attributes: url, setAttributes } = this.props; + + if ( newUrl !== url ) { + if ( isURL( newUrl ) ) { + setAttributes( { url: newUrl, id: undefined } ); + } else { + // TODO: throw createErrorNotice equivalent error from class component + // console.log( 'Invalid URL. Image file not found.' ); + } + } + } + onFocusCaption() { if ( this.props.onFocus ) { this.props.onFocus(); @@ -716,6 +730,7 @@ export class ImageEdit extends Component { { return getImageComponent( open, getMediaOptions ); } } From b3312b908e74d6b7fff794b91ded0f2d71c86760 Mon Sep 17 00:00:00 2001 From: Derek Blank Date: Thu, 28 Apr 2022 19:56:31 +1000 Subject: [PATCH 07/21] Add error handling for invalid URLs to native Image block --- .../block-library/src/image/edit.native.js | 44 +++++++++++++++---- .../src/image/styles.native.scss | 17 +++++++ 2 files changed, 52 insertions(+), 9 deletions(-) diff --git a/packages/block-library/src/image/edit.native.js b/packages/block-library/src/image/edit.native.js index 46d7b55d3d8531..31db3cfe54de4e 100644 --- a/packages/block-library/src/image/edit.native.js +++ b/packages/block-library/src/image/edit.native.js @@ -41,6 +41,7 @@ import { InspectorControls, BlockAlignmentToolbar, BlockStyles, + PlainText, store as blockEditorStore, blockSettingsScreens, } from '@wordpress/block-editor'; @@ -54,6 +55,7 @@ import { replace, fullscreen, textColor, + warning, } from '@wordpress/icons'; import { store as coreStore } from '@wordpress/core-data'; import { store as editPostStore } from '@wordpress/edit-post'; @@ -185,6 +187,7 @@ export class ImageEdit extends Component { this.state = { isCaptionSelected: false, + isInvalidURL: false, uploadStatus: UPLOAD_STATE_IDLE, }; @@ -345,6 +348,7 @@ export class ImageEdit extends Component { this.setState( { isCaptionSelected: false, + isInvalidURL: false, } ); } @@ -462,15 +466,22 @@ export class ImageEdit extends Component { } ); } - onSelectURL( newUrl ) { - const { attributes: url, setAttributes } = this.props; - - if ( newUrl !== url ) { - if ( isURL( newUrl ) ) { - setAttributes( { url: newUrl, id: undefined } ); + onSelectURL( newURL ) { + const { attributes: url, imageDefaultSize, setAttributes } = this.props; + + if ( newURL !== url ) { + if ( isURL( newURL ) ) { + setAttributes( { + url: newURL, + id: undefined, + width: undefined, + height: undefined, + sizeSlug: imageDefaultSize, + } ); } else { - // TODO: throw createErrorNotice equivalent error from class component - // console.log( 'Invalid URL. Image file not found.' ); + this.setState( { + isInvalidURL: true, + } ); } } } @@ -625,7 +636,7 @@ export class ImageEdit extends Component { } render() { - const { isCaptionSelected } = this.state; + const { isCaptionSelected, isInvalidURL } = this.state; const { attributes, isSelected, @@ -776,6 +787,21 @@ export class ImageEdit extends Component { disabled={ ! isSelected } > + { isInvalidURL && ( + + + + </View> + ) } { isSelected && getInspectorControls() } { isSelected && getMediaOptions() } { ! this.state.isCaptionSelected && diff --git a/packages/block-library/src/image/styles.native.scss b/packages/block-library/src/image/styles.native.scss index 476bb8b2be4716..bb07842c6a7dfd 100644 --- a/packages/block-library/src/image/styles.native.scss +++ b/packages/block-library/src/image/styles.native.scss @@ -57,3 +57,20 @@ .removeFeaturedButton { color: $alert-red; } + +.errorContainer { + flex-direction: row; + align-items: center; + padding-top: 4px; + padding-bottom: 8px; +} + +.errorIcon { + margin-left: -4px; + color: $alert-red; +} + +.errorText { + padding: 0; + color: $alert-red; +} From badb6e15cb9d9b0bba1eb39d43faf900f97218fe Mon Sep 17 00:00:00 2001 From: Derek Blank <derekpblank@gmail.com> Date: Fri, 29 Apr 2022 12:47:36 +1000 Subject: [PATCH 08/21] Clear invalid URL error on Image URL success --- packages/block-library/src/image/edit.native.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/block-library/src/image/edit.native.js b/packages/block-library/src/image/edit.native.js index 31db3cfe54de4e..ecda106a2b9788 100644 --- a/packages/block-library/src/image/edit.native.js +++ b/packages/block-library/src/image/edit.native.js @@ -478,6 +478,9 @@ export class ImageEdit extends Component { height: undefined, sizeSlug: imageDefaultSize, } ); + this.setState( { + isInvalidURL: false, + } ); } else { this.setState( { isInvalidURL: true, From ee5456b6fb2ec230e9a0bdd20e51ffb572a7499b Mon Sep 17 00:00:00 2001 From: Derek Blank <derekpblank@gmail.com> Date: Fri, 29 Apr 2022 12:52:52 +1000 Subject: [PATCH 09/21] Fix synchronicity of Media Upload option tests --- .../src/components/media-upload/test/index.native.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/components/media-upload/test/index.native.js b/packages/block-editor/src/components/media-upload/test/index.native.js index 9bc27cf5f63bb9..8ce3045daef0fb 100644 --- a/packages/block-editor/src/components/media-upload/test/index.native.js +++ b/packages/block-editor/src/components/media-upload/test/index.native.js @@ -54,9 +54,9 @@ describe( 'MediaUpload component', () => { } } /> ); - await fireEvent.press( wrapper.getByText( 'Open Picker' ) ); + fireEvent.press( wrapper.getByText( 'Open Picker' ) ); - await expectedOptions.forEach( ( item ) => { + expectedOptions.forEach( ( item ) => { const option = wrapper.getByText( item ); expect( option ).toBeVisible(); } ); From 0e647c1fdb0b54c8c33cdd5210455b9ba305178b Mon Sep 17 00:00:00 2001 From: Derek Blank <derekpblank@gmail.com> Date: Thu, 5 May 2022 13:28:24 +1000 Subject: [PATCH 10/21] Add check for URL handler to native Image block picker options --- .../src/components/media-upload/index.native.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/media-upload/index.native.js b/packages/block-editor/src/components/media-upload/index.native.js index 6ef097037164d6..4645c217724711 100644 --- a/packages/block-editor/src/components/media-upload/index.native.js +++ b/packages/block-editor/src/components/media-upload/index.native.js @@ -80,6 +80,8 @@ export class MediaUpload extends Component { } getAllSources() { + const { onSelectURL } = this.props; + const cameraImageSource = { id: mediaSources.deviceCamera, // ID is the value sent to native. value: mediaSources.deviceCamera + '-IMAGE', // This is needed to diferenciate image-camera from video-camera sources. @@ -130,12 +132,14 @@ export class MediaUpload extends Component { icon: globe, }; + // Only include `urlSource` option if `onSelectURL` prop is present + // (matches web behavior) const internalSources = [ deviceLibrarySource, cameraImageSource, cameraVideoSource, siteLibrarySource, - urlSource, + ...onSelectURL ? [ urlSource] : [], ]; return internalSources.concat( this.state.otherMediaOptions ); From 4d33bb13c74a7c1d75467f4cdb1b9d7f78e7c5b9 Mon Sep 17 00:00:00 2001 From: Derek Blank <derekpblank@gmail.com> Date: Thu, 5 May 2022 13:29:41 +1000 Subject: [PATCH 11/21] Update code style --- .../block-editor/src/components/media-upload/index.native.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/components/media-upload/index.native.js b/packages/block-editor/src/components/media-upload/index.native.js index 4645c217724711..e4f7f42f558608 100644 --- a/packages/block-editor/src/components/media-upload/index.native.js +++ b/packages/block-editor/src/components/media-upload/index.native.js @@ -81,7 +81,7 @@ export class MediaUpload extends Component { getAllSources() { const { onSelectURL } = this.props; - + const cameraImageSource = { id: mediaSources.deviceCamera, // ID is the value sent to native. value: mediaSources.deviceCamera + '-IMAGE', // This is needed to diferenciate image-camera from video-camera sources. @@ -139,7 +139,7 @@ export class MediaUpload extends Component { cameraImageSource, cameraVideoSource, siteLibrarySource, - ...onSelectURL ? [ urlSource] : [], + ...( onSelectURL ? [ urlSource ] : [] ), ]; return internalSources.concat( this.state.otherMediaOptions ); From aede9d3e38af971877b6b9cf14d595e04ecd3089 Mon Sep 17 00:00:00 2001 From: Derek Blank <derekpblank@gmail.com> Date: Thu, 5 May 2022 13:43:15 +1000 Subject: [PATCH 12/21] Remove Video block from urlSource options Why: to be introduced in a later PR --- .../block-editor/src/components/media-upload/index.native.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/media-upload/index.native.js b/packages/block-editor/src/components/media-upload/index.native.js index e4f7f42f558608..b2427056373c05 100644 --- a/packages/block-editor/src/components/media-upload/index.native.js +++ b/packages/block-editor/src/components/media-upload/index.native.js @@ -128,7 +128,7 @@ export class MediaUpload extends Component { id: URL_MEDIA_SOURCE, value: URL_MEDIA_SOURCE, label: __( 'Insert from URL' ), - types: [ MEDIA_TYPE_AUDIO, MEDIA_TYPE_IMAGE, MEDIA_TYPE_VIDEO ], + types: [ MEDIA_TYPE_AUDIO, MEDIA_TYPE_IMAGE ], icon: globe, }; From dbc6e23339a26e855d9b01f0cd23961c6ce51561 Mon Sep 17 00:00:00 2001 From: Derek Blank <derekpblank@gmail.com> Date: Thu, 5 May 2022 17:10:18 +1000 Subject: [PATCH 13/21] Remove URL option from Video block for Media Upload test --- .../src/components/media-upload/test/index.native.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/block-editor/src/components/media-upload/test/index.native.js b/packages/block-editor/src/components/media-upload/test/index.native.js index 8ce3045daef0fb..73cbf41b7dfc14 100644 --- a/packages/block-editor/src/components/media-upload/test/index.native.js +++ b/packages/block-editor/src/components/media-upload/test/index.native.js @@ -74,7 +74,6 @@ describe( 'MediaUpload component', () => { expectOptionForMediaType( MEDIA_TYPE_VIDEO, [ OPTION_TAKE_VIDEO, OPTION_WORDPRESS_MEDIA_LIBRARY, - OPTION_INSERT_FROM_URL, ] ); } ); From 07ee97dcc49ac97a0bc9d1a543740f8ab80cd28e Mon Sep 17 00:00:00 2001 From: Derek Blank <derekpblank@gmail.com> Date: Fri, 6 May 2022 14:54:39 +1000 Subject: [PATCH 14/21] Use Notice snackbar for native Image block error handling --- .../block-library/src/image/edit.native.js | 42 +++++++------------ .../src/image/styles.native.scss | 17 -------- 2 files changed, 15 insertions(+), 44 deletions(-) diff --git a/packages/block-library/src/image/edit.native.js b/packages/block-library/src/image/edit.native.js index ecda106a2b9788..d830666528113e 100644 --- a/packages/block-library/src/image/edit.native.js +++ b/packages/block-library/src/image/edit.native.js @@ -41,7 +41,6 @@ import { InspectorControls, BlockAlignmentToolbar, BlockStyles, - PlainText, store as blockEditorStore, blockSettingsScreens, } from '@wordpress/block-editor'; @@ -55,10 +54,10 @@ import { replace, fullscreen, textColor, - warning, } from '@wordpress/icons'; import { store as coreStore } from '@wordpress/core-data'; import { store as editPostStore } from '@wordpress/edit-post'; +import { store as noticesStore } from '@wordpress/notices'; /** * Internal dependencies @@ -187,7 +186,6 @@ export class ImageEdit extends Component { this.state = { isCaptionSelected: false, - isInvalidURL: false, uploadStatus: UPLOAD_STATE_IDLE, }; @@ -348,7 +346,6 @@ export class ImageEdit extends Component { this.setState( { isCaptionSelected: false, - isInvalidURL: false, } ); } @@ -467,7 +464,12 @@ export class ImageEdit extends Component { } onSelectURL( newURL ) { - const { attributes: url, imageDefaultSize, setAttributes } = this.props; + const { + attributes: url, + createNotice, + imageDefaultSize, + setAttributes, + } = this.props; if ( newURL !== url ) { if ( isURL( newURL ) ) { @@ -478,13 +480,11 @@ export class ImageEdit extends Component { height: undefined, sizeSlug: imageDefaultSize, } ); - this.setState( { - isInvalidURL: false, - } ); } else { - this.setState( { - isInvalidURL: true, - } ); + createNotice( + 'error', + __( 'Invalid URL. Image file not found.' ) + ); } } } @@ -639,7 +639,7 @@ export class ImageEdit extends Component { } render() { - const { isCaptionSelected, isInvalidURL } = this.state; + const { isCaptionSelected } = this.state; const { attributes, isSelected, @@ -790,21 +790,6 @@ export class ImageEdit extends Component { disabled={ ! isSelected } > <View style={ styles.content }> - { isInvalidURL && ( - <View style={ styles.errorContainer }> - <Icon - icon={ warning } - style={ styles.errorIcon } - /> - <PlainText - editable={ false } - value={ __( - 'Invalid URL. Image file not found.' - ) } - style={ styles.errorText } - /> - </View> - ) } { isSelected && getInspectorControls() } { isSelected && getMediaOptions() } { ! this.state.isCaptionSelected && @@ -927,7 +912,10 @@ export default compose( [ }; } ), withDispatch( ( dispatch ) => { + const { createNotice } = dispatch( noticesStore ); + return { + createNotice, closeSettingsBottomSheet() { dispatch( editPostStore ).closeGeneralSidebar(); }, diff --git a/packages/block-library/src/image/styles.native.scss b/packages/block-library/src/image/styles.native.scss index bb07842c6a7dfd..476bb8b2be4716 100644 --- a/packages/block-library/src/image/styles.native.scss +++ b/packages/block-library/src/image/styles.native.scss @@ -57,20 +57,3 @@ .removeFeaturedButton { color: $alert-red; } - -.errorContainer { - flex-direction: row; - align-items: center; - padding-top: 4px; - padding-bottom: 8px; -} - -.errorIcon { - margin-left: -4px; - color: $alert-red; -} - -.errorText { - padding: 0; - color: $alert-red; -} From 7e8b6cbbe82978e740947f005ed3066c47bca0aa Mon Sep 17 00:00:00 2001 From: Derek Blank <derekpblank@gmail.com> Date: Mon, 9 May 2022 23:23:23 +1000 Subject: [PATCH 15/21] Update Image/Media Upload code style and helpers --- .../src/components/media-upload/index.native.js | 4 +--- packages/block-library/src/image/edit.native.js | 11 ++++------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/packages/block-editor/src/components/media-upload/index.native.js b/packages/block-editor/src/components/media-upload/index.native.js index b2427056373c05..8f793e4c0fa3f6 100644 --- a/packages/block-editor/src/components/media-upload/index.native.js +++ b/packages/block-editor/src/components/media-upload/index.native.js @@ -37,7 +37,6 @@ export const MEDIA_TYPE_ANY = 'any'; export const OPTION_TAKE_VIDEO = __( 'Take a Video' ); export const OPTION_TAKE_PHOTO = __( 'Take a Photo' ); -export const OPTION_CHOOSE_FROM_DEVICE = __( 'Choose from Device' ); export const OPTION_TAKE_PHOTO_OR_VIDEO = __( 'Take a Photo or Video' ); export const OPTION_INSERT_FROM_URL = __( 'Insert from URL' ); export const OPTION_WORDPRESS_MEDIA_LIBRARY = __( 'WordPress Media Library' ); @@ -132,8 +131,7 @@ export class MediaUpload extends Component { icon: globe, }; - // Only include `urlSource` option if `onSelectURL` prop is present - // (matches web behavior) + // Only include `urlSource` option if `onSelectURL` prop is present, in order to match the web behavior. const internalSources = [ deviceLibrarySource, cameraImageSource, diff --git a/packages/block-library/src/image/edit.native.js b/packages/block-library/src/image/edit.native.js index d830666528113e..2af60637a0e6b8 100644 --- a/packages/block-library/src/image/edit.native.js +++ b/packages/block-library/src/image/edit.native.js @@ -466,7 +466,7 @@ export class ImageEdit extends Component { onSelectURL( newURL ) { const { attributes: url, - createNotice, + createErrorNotice, imageDefaultSize, setAttributes, } = this.props; @@ -481,10 +481,7 @@ export class ImageEdit extends Component { sizeSlug: imageDefaultSize, } ); } else { - createNotice( - 'error', - __( 'Invalid URL. Image file not found.' ) - ); + createErrorNotice( __( 'Invalid URL. Image file not found.' ) ); } } } @@ -912,10 +909,10 @@ export default compose( [ }; } ), withDispatch( ( dispatch ) => { - const { createNotice } = dispatch( noticesStore ); + const { createErrorNotice } = dispatch( noticesStore ); return { - createNotice, + createErrorNotice, closeSettingsBottomSheet() { dispatch( editPostStore ).closeGeneralSidebar(); }, From 7995ef9976319757cb865100ea6779fe1c9c7f9b Mon Sep 17 00:00:00 2001 From: Derek Blank <derekpblank@gmail.com> Date: Fri, 13 May 2022 15:52:26 +1000 Subject: [PATCH 16/21] Use getImage to determine if URL is a valid image within Image block --- .../block-library/src/image/edit.native.js | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/packages/block-library/src/image/edit.native.js b/packages/block-library/src/image/edit.native.js index 2af60637a0e6b8..b6b7a9ffb29c16 100644 --- a/packages/block-library/src/image/edit.native.js +++ b/packages/block-library/src/image/edit.native.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import { View, TouchableWithoutFeedback } from 'react-native'; +import { Image as RNImage, View, TouchableWithoutFeedback } from 'react-native'; import { useRoute } from '@react-navigation/native'; /** @@ -45,7 +45,7 @@ import { blockSettingsScreens, } from '@wordpress/block-editor'; import { __, _x, sprintf } from '@wordpress/i18n'; -import { getProtocol, hasQueryArg, isURL } from '@wordpress/url'; +import { getProtocol, hasQueryArg } from '@wordpress/url'; import { doAction, hasAction } from '@wordpress/hooks'; import { compose, withPreferredColorScheme } from '@wordpress/compose'; import { withSelect, withDispatch } from '@wordpress/data'; @@ -465,25 +465,27 @@ export class ImageEdit extends Component { onSelectURL( newURL ) { const { - attributes: url, createErrorNotice, imageDefaultSize, setAttributes, } = this.props; - if ( newURL !== url ) { - if ( isURL( newURL ) ) { + // Use RN's Image.getSize to determine if URL is a valid image + RNImage.getSize( + newURL, + ( width, height ) => { setAttributes( { url: newURL, id: undefined, - width: undefined, - height: undefined, + width, + height, sizeSlug: imageDefaultSize, } ); - } else { + }, + () => { createErrorNotice( __( 'Invalid URL. Image file not found.' ) ); } - } + ); } onFocusCaption() { From 344c3409565bae2a52be6271d0d6008b40199c32 Mon Sep 17 00:00:00 2001 From: Derek Blank <derekpblank@gmail.com> Date: Mon, 16 May 2022 15:49:34 +1000 Subject: [PATCH 17/21] Add loading indicator and isURL check to native Image block URL behavior --- .../block-library/src/image/edit.native.js | 64 +++++++++++++------ .../src/image/styles.native.scss | 11 ++++ 2 files changed, 56 insertions(+), 19 deletions(-) diff --git a/packages/block-library/src/image/edit.native.js b/packages/block-library/src/image/edit.native.js index b6b7a9ffb29c16..bc1431b44e376f 100644 --- a/packages/block-library/src/image/edit.native.js +++ b/packages/block-library/src/image/edit.native.js @@ -1,7 +1,12 @@ /** * External dependencies */ -import { Image as RNImage, View, TouchableWithoutFeedback } from 'react-native'; +import { + ActivityIndicator, + Image as RNImage, + TouchableWithoutFeedback, + View, +} from 'react-native'; import { useRoute } from '@react-navigation/native'; /** @@ -45,7 +50,7 @@ import { blockSettingsScreens, } from '@wordpress/block-editor'; import { __, _x, sprintf } from '@wordpress/i18n'; -import { getProtocol, hasQueryArg } from '@wordpress/url'; +import { getProtocol, hasQueryArg, isURL } from '@wordpress/url'; import { doAction, hasAction } from '@wordpress/hooks'; import { compose, withPreferredColorScheme } from '@wordpress/compose'; import { withSelect, withDispatch } from '@wordpress/data'; @@ -470,22 +475,36 @@ export class ImageEdit extends Component { setAttributes, } = this.props; - // Use RN's Image.getSize to determine if URL is a valid image - RNImage.getSize( - newURL, - ( width, height ) => { - setAttributes( { - url: newURL, - id: undefined, - width, - height, - sizeSlug: imageDefaultSize, - } ); - }, - () => { - createErrorNotice( __( 'Invalid URL. Image file not found.' ) ); - } - ); + if ( isURL( newURL ) ) { + this.setState( { + isFetchingImage: true, + } ); + + // Use RN's Image.getSize to determine if URL is a valid image + RNImage.getSize( + newURL, + ( width, height ) => { + setAttributes( { + url: newURL, + id: undefined, + width, + height, + sizeSlug: imageDefaultSize, + } ); + this.setState( { + isFetchingImage: false, + } ); + }, + () => { + createErrorNotice( __( 'Image file not found.' ) ); + this.setState( { + isFetchingImage: false, + } ); + } + ); + } else { + createErrorNotice( __( 'Invalid URL.' ) ); + } } onFocusCaption() { @@ -638,7 +657,7 @@ export class ImageEdit extends Component { } render() { - const { isCaptionSelected } = this.state; + const { isCaptionSelected, isFetchingImage } = this.state; const { attributes, isSelected, @@ -813,6 +832,13 @@ export class ImageEdit extends Component { } ) => { return ( <View style={ imageContainerStyles }> + { isFetchingImage && ( + <View + style={ styles.image__loading } + > + <ActivityIndicator animating /> + </View> + ) } <Image align={ align && alignToFlex[ align ] diff --git a/packages/block-library/src/image/styles.native.scss b/packages/block-library/src/image/styles.native.scss index 476bb8b2be4716..0bcec21b571893 100644 --- a/packages/block-library/src/image/styles.native.scss +++ b/packages/block-library/src/image/styles.native.scss @@ -57,3 +57,14 @@ .removeFeaturedButton { color: $alert-red; } + +.image__loading { + align-items: center; + background-color: rgba(10, 10, 10, 0.5); + flex: 1; + height: 100%; + justify-content: center; + position: absolute; + width: 100%; + z-index: 1; +} From ee61ccb3b1eabce9dbc32fbd6c47cc64277002e7 Mon Sep 17 00:00:00 2001 From: Derek Blank <derekpblank@gmail.com> Date: Wed, 18 May 2022 18:12:59 +1000 Subject: [PATCH 18/21] Add loading indicator to native Image block media placeholder --- packages/block-library/src/image/edit.native.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/block-library/src/image/edit.native.js b/packages/block-library/src/image/edit.native.js index bc1431b44e376f..97a94e6b970359 100644 --- a/packages/block-library/src/image/edit.native.js +++ b/packages/block-library/src/image/edit.native.js @@ -759,6 +759,13 @@ export class ImageEdit extends Component { if ( ! url ) { return ( <View style={ styles.content }> + { isFetchingImage && ( + <View + style={ styles.image__loading } + > + <ActivityIndicator animating /> + </View> + ) } <MediaPlaceholder allowedTypes={ [ MEDIA_TYPE_IMAGE ] } onSelect={ this.onSelectMediaUploadOption } From a43fce12c6bd88c4b2307283186a1a54a3b2967b Mon Sep 17 00:00:00 2001 From: Derek Blank <derekpblank@gmail.com> Date: Thu, 19 May 2022 15:24:38 +1000 Subject: [PATCH 19/21] Fix whitespace issue in native Image block code style --- packages/block-library/src/image/edit.native.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/block-library/src/image/edit.native.js b/packages/block-library/src/image/edit.native.js index 97a94e6b970359..44f5a31cd6f0ce 100644 --- a/packages/block-library/src/image/edit.native.js +++ b/packages/block-library/src/image/edit.native.js @@ -760,12 +760,10 @@ export class ImageEdit extends Component { return ( <View style={ styles.content }> { isFetchingImage && ( - <View - style={ styles.image__loading } - > + <View style={ styles.image__loading }> <ActivityIndicator animating /> </View> - ) } + ) } <MediaPlaceholder allowedTypes={ [ MEDIA_TYPE_IMAGE ] } onSelect={ this.onSelectMediaUploadOption } From 7b721c0e0cbf927c66fc21401652e440da364e7c Mon Sep 17 00:00:00 2001 From: Derek Blank <derekpblank@gmail.com> Date: Fri, 20 May 2022 15:18:11 +1000 Subject: [PATCH 20/21] Reuse native Image block loading indicator --- .../block-library/src/image/edit.native.js | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/packages/block-library/src/image/edit.native.js b/packages/block-library/src/image/edit.native.js index 44f5a31cd6f0ce..bacb084af4a282 100644 --- a/packages/block-library/src/image/edit.native.js +++ b/packages/block-library/src/image/edit.native.js @@ -530,6 +530,14 @@ export class ImageEdit extends Component { ); } + showLoadingIndicator() { + return ( + <View style={ styles.image__loading }> + <ActivityIndicator animating /> + </View> + ) + } + getWidth() { const { attributes } = this.props; const { align, width } = attributes; @@ -759,11 +767,7 @@ export class ImageEdit extends Component { if ( ! url ) { return ( <View style={ styles.content }> - { isFetchingImage && ( - <View style={ styles.image__loading }> - <ActivityIndicator animating /> - </View> - ) } + { isFetchingImage && this.showLoadingIndicator() } <MediaPlaceholder allowedTypes={ [ MEDIA_TYPE_IMAGE ] } onSelect={ this.onSelectMediaUploadOption } @@ -837,13 +841,7 @@ export class ImageEdit extends Component { } ) => { return ( <View style={ imageContainerStyles }> - { isFetchingImage && ( - <View - style={ styles.image__loading } - > - <ActivityIndicator animating /> - </View> - ) } + { isFetchingImage && this.showLoadingIndicator() } <Image align={ align && alignToFlex[ align ] From ae0276312497617eee578878ffeccc1a7441d976 Mon Sep 17 00:00:00 2001 From: Derek Blank <derekpblank@gmail.com> Date: Fri, 20 May 2022 15:24:14 +1000 Subject: [PATCH 21/21] Use undefined dimension attributes for the native Image block URL behavior --- packages/block-library/src/image/edit.native.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/block-library/src/image/edit.native.js b/packages/block-library/src/image/edit.native.js index bacb084af4a282..6503e2613e1132 100644 --- a/packages/block-library/src/image/edit.native.js +++ b/packages/block-library/src/image/edit.native.js @@ -483,12 +483,12 @@ export class ImageEdit extends Component { // Use RN's Image.getSize to determine if URL is a valid image RNImage.getSize( newURL, - ( width, height ) => { + () => { setAttributes( { url: newURL, id: undefined, - width, - height, + width: undefined, + height: undefined, sizeSlug: imageDefaultSize, } ); this.setState( { @@ -535,7 +535,7 @@ export class ImageEdit extends Component { <View style={ styles.image__loading }> <ActivityIndicator animating /> </View> - ) + ); } getWidth() { @@ -841,7 +841,8 @@ export class ImageEdit extends Component { } ) => { return ( <View style={ imageContainerStyles }> - { isFetchingImage && this.showLoadingIndicator() } + { isFetchingImage && + this.showLoadingIndicator() } <Image align={ align && alignToFlex[ align ]