From aef7830bc052e7b1356d37eb3a21273af52d581d Mon Sep 17 00:00:00 2001 From: Carlos Garcia Date: Thu, 10 Sep 2020 20:42:18 +0200 Subject: [PATCH 01/40] Add support for required reusable blocks API paths --- packages/react-native-editor/src/api-fetch-setup.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-native-editor/src/api-fetch-setup.js b/packages/react-native-editor/src/api-fetch-setup.js index ee2a15e1a3f8af..afabecdf0a878e 100644 --- a/packages/react-native-editor/src/api-fetch-setup.js +++ b/packages/react-native-editor/src/api-fetch-setup.js @@ -6,7 +6,7 @@ import apiFetch from '@wordpress/api-fetch'; // Please add only wp.org API paths here! const SUPPORTED_ENDPOINTS = [ - /wp\/v2\/(media|categories)\/?\d*?.*/i, + /wp\/v2\/(media|categories|types|posts|blocks)\/?\d*?.*/i, /wp\/v2\/search\?.*/i, ]; From 3481cdb6a9960a8bdc618d37368fc4bdd646d68c Mon Sep 17 00:00:00 2001 From: Carlos Garcia Date: Thu, 10 Sep 2020 20:43:00 +0200 Subject: [PATCH 02/40] Add native version of Disable component --- packages/components/src/disabled/index.native.js | 10 ++++++++++ packages/components/src/index.native.js | 1 + 2 files changed, 11 insertions(+) create mode 100644 packages/components/src/disabled/index.native.js diff --git a/packages/components/src/disabled/index.native.js b/packages/components/src/disabled/index.native.js new file mode 100644 index 00000000000000..8cd36f5788911d --- /dev/null +++ b/packages/components/src/disabled/index.native.js @@ -0,0 +1,10 @@ +/** + * External dependencies + */ +import { View } from 'react-native'; + +function Disabled( { children } ) { + return { children }; +} + +export default Disabled; diff --git a/packages/components/src/index.native.js b/packages/components/src/index.native.js index f03892096361fd..43d56524787506 100644 --- a/packages/components/src/index.native.js +++ b/packages/components/src/index.native.js @@ -46,6 +46,7 @@ export { default as Notice } from './notice'; export { default as NoticeList } from './notice/list'; export { default as RadioControl } from './radio-control'; export { default as UnitControl } from './unit-control'; +export { default as Disabled } from './disabled'; // Higher-Order Components export { default as withConstrainedTabbing } from './higher-order/with-constrained-tabbing'; From c42f0dba78310cc7b55b08ac9b959cb53d208472 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Date: Thu, 10 Sep 2020 20:46:28 +0200 Subject: [PATCH 03/40] Add native version of Reusable block (only preview) --- .../block-library/src/block/edit.native.js | 155 ++++++++++++++++++ .../src/block/editor.native.scss | 3 + 2 files changed, 158 insertions(+) create mode 100644 packages/block-library/src/block/edit.native.js create mode 100644 packages/block-library/src/block/editor.native.scss diff --git a/packages/block-library/src/block/edit.native.js b/packages/block-library/src/block/edit.native.js new file mode 100644 index 00000000000000..1c22cd6b6c8c9e --- /dev/null +++ b/packages/block-library/src/block/edit.native.js @@ -0,0 +1,155 @@ +/** + * External dependencies + */ +import { Text, View } from 'react-native'; +import { partial } from 'lodash'; + +/** + * WordPress dependencies + */ +import { Component } from '@wordpress/element'; +import { Spinner, Disabled } from '@wordpress/components'; +import { withSelect, withDispatch } from '@wordpress/data'; +import { __ } from '@wordpress/i18n'; +import { BlockEditorProvider, BlockList } from '@wordpress/block-editor'; +import { compose } from '@wordpress/compose'; +import { parse } from '@wordpress/blocks'; + +/** + * Internal dependencies + */ +import styles from './editor.scss'; + +class ReusableBlockEdit extends Component { + constructor( { reusableBlock } ) { + super( ...arguments ); + + this.setBlocks = this.setBlocks.bind( this ); + + if ( reusableBlock ) { + // Start in edit mode when we're working with a newly created reusable block + this.state = { + // Since edition is not supported yet isEditing is always false + isEditing: false, + title: reusableBlock.title, + blocks: parse( reusableBlock.content ), + }; + } else { + // Start in preview mode when we're working with an existing reusable block + this.state = { + isEditing: false, + title: null, + blocks: [], + }; + } + } + + componentDidMount() { + if ( ! this.props.reusableBlock ) { + this.props.fetchReusableBlock(); + } + } + + componentDidUpdate( prevProps ) { + if ( + prevProps.reusableBlock !== this.props.reusableBlock && + this.state.title === null + ) { + this.setState( { + title: this.props.reusableBlock.title, + blocks: parse( this.props.reusableBlock.content ), + } ); + } + } + + setBlocks( blocks ) { + this.setState( { blocks } ); + } + + render() { + const { isSelected, reusableBlock, isFetching, settings } = this.props; + const { isEditing, title, blocks } = this.state; + + if ( ! reusableBlock && isFetching ) { + return ; + } + + if ( ! reusableBlock ) { + return ( + + { __( 'Block has been deleted or is unavailable.' ) } + + ); + } + + let element = ( + + + + ); + + if ( ! isEditing ) { + element = { element }; + } + + return ( + + { isSelected && { title } } + { element } + + ); + } +} + +export default compose( [ + withSelect( ( select, ownProps ) => { + const { + __experimentalGetReusableBlock: getReusableBlock, + __experimentalIsFetchingReusableBlock: isFetchingReusableBlock, + __experimentalIsSavingReusableBlock: isSavingReusableBlock, + } = select( 'core/editor' ); + const { canUser } = select( 'core' ); + const { __experimentalGetParsedReusableBlock, getSettings } = select( + 'core/block-editor' + ); + const { ref } = ownProps.attributes; + const reusableBlock = getReusableBlock( ref ); + + return { + reusableBlock, + isFetching: isFetchingReusableBlock( ref ), + isSaving: isSavingReusableBlock( ref ), + blocks: reusableBlock + ? __experimentalGetParsedReusableBlock( reusableBlock.id ) + : null, + canUpdateBlock: + !! reusableBlock && + ! reusableBlock.isTemporary && + !! canUser( 'update', 'blocks', ref ), + settings: getSettings(), + }; + } ), + withDispatch( ( dispatch, ownProps ) => { + const { + __experimentalConvertBlockToStatic: convertBlockToStatic, + __experimentalFetchReusableBlocks: fetchReusableBlocks, + __experimentalUpdateReusableBlock: updateReusableBlock, + __experimentalSaveReusableBlock: saveReusableBlock, + } = dispatch( 'core/editor' ); + const { ref } = ownProps.attributes; + + return { + fetchReusableBlock: partial( fetchReusableBlocks, ref ), + onChange: partial( updateReusableBlock, ref ), + onSave: partial( saveReusableBlock, ref ), + convertToStatic() { + convertBlockToStatic( ownProps.clientId ); + }, + }; + } ), +] )( ReusableBlockEdit ); diff --git a/packages/block-library/src/block/editor.native.scss b/packages/block-library/src/block/editor.native.scss new file mode 100644 index 00000000000000..1fbcfaf370c9f2 --- /dev/null +++ b/packages/block-library/src/block/editor.native.scss @@ -0,0 +1,3 @@ +.title { + font-weight: bold; +} From c13151b9bc08cfd1b0d408687f5be8df8cf3b438 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Date: Thu, 10 Sep 2020 20:47:55 +0200 Subject: [PATCH 04/40] Add Reusable block to mobile registered core blocks --- packages/block-library/src/index.native.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/block-library/src/index.native.js b/packages/block-library/src/index.native.js index 65785c7f3fb378..b38e6977aa7320 100644 --- a/packages/block-library/src/index.native.js +++ b/packages/block-library/src/index.native.js @@ -224,6 +224,7 @@ export const registerCoreBlocks = () => { socialLinks, pullquote, file, + reusableBlock, ].forEach( registerBlock ); registerBlockVariations( socialLink ); From 0e738321d1db1fb0a3133236329cfd936f1e09b7 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Date: Fri, 11 Sep 2020 20:31:28 +0200 Subject: [PATCH 05/40] Fix undefined progress in Spinner component --- packages/components/src/spinner/index.native.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/src/spinner/index.native.js b/packages/components/src/spinner/index.native.js index 263703486a5789..5b25cf7945c079 100644 --- a/packages/components/src/spinner/index.native.js +++ b/packages/components/src/spinner/index.native.js @@ -9,7 +9,7 @@ import { View } from 'react-native'; import style from './style.scss'; export default function Spinner( props ) { - const { progress } = props; + const { progress = 0 } = props; const width = progress + '%'; From 56201525795e84862924d3e0f89def559e426e0e Mon Sep 17 00:00:00 2001 From: Carlos Garcia Date: Wed, 16 Sep 2020 21:24:18 +0200 Subject: [PATCH 06/40] api-fetch-setup unit test updated with new paths --- packages/react-native-editor/src/test/api-fetch-setup.test.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/react-native-editor/src/test/api-fetch-setup.test.js b/packages/react-native-editor/src/test/api-fetch-setup.test.js index c7d5b230fbf8fd..4b19ad592d0099 100644 --- a/packages/react-native-editor/src/test/api-fetch-setup.test.js +++ b/packages/react-native-editor/src/test/api-fetch-setup.test.js @@ -10,6 +10,9 @@ const supportedPaths = [ 'wp/v2/media/', 'wp/v2/media?context=edit&_locale=user', 'wp/v2/categories/', + 'wp/v2/types/wp_block?_locale=user', + 'wp/v2/posts/1?context=edit&_locale=user', + 'wp/v2/blocks/28?_locale=user', ]; const unsupportedPaths = [ From 9bd67ce0f1a11f4ec0938e74d586add4de61fdf5 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Date: Thu, 24 Sep 2020 19:59:23 +0200 Subject: [PATCH 07/40] Posts removed from supported endpoints It's not required by Reusable blocks fetch. --- packages/react-native-editor/src/api-fetch-setup.js | 2 +- packages/react-native-editor/src/test/api-fetch-setup.test.js | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/react-native-editor/src/api-fetch-setup.js b/packages/react-native-editor/src/api-fetch-setup.js index afabecdf0a878e..ab6ee377051577 100644 --- a/packages/react-native-editor/src/api-fetch-setup.js +++ b/packages/react-native-editor/src/api-fetch-setup.js @@ -6,7 +6,7 @@ import apiFetch from '@wordpress/api-fetch'; // Please add only wp.org API paths here! const SUPPORTED_ENDPOINTS = [ - /wp\/v2\/(media|categories|types|posts|blocks)\/?\d*?.*/i, + /wp\/v2\/(media|categories|types|blocks)\/?\d*?.*/i, /wp\/v2\/search\?.*/i, ]; diff --git a/packages/react-native-editor/src/test/api-fetch-setup.test.js b/packages/react-native-editor/src/test/api-fetch-setup.test.js index 4b19ad592d0099..48c8ed258c626c 100644 --- a/packages/react-native-editor/src/test/api-fetch-setup.test.js +++ b/packages/react-native-editor/src/test/api-fetch-setup.test.js @@ -11,7 +11,6 @@ const supportedPaths = [ 'wp/v2/media?context=edit&_locale=user', 'wp/v2/categories/', 'wp/v2/types/wp_block?_locale=user', - 'wp/v2/posts/1?context=edit&_locale=user', 'wp/v2/blocks/28?_locale=user', ]; From 73157357f4fc8f50fcbfd86e1d7ac9692b741978 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Date: Fri, 25 Sep 2020 21:20:32 +0200 Subject: [PATCH 08/40] Add Lock icon --- packages/icons/src/index.js | 1 + packages/icons/src/library/lock.js | 12 ++++++++++++ 2 files changed, 13 insertions(+) create mode 100644 packages/icons/src/library/lock.js diff --git a/packages/icons/src/index.js b/packages/icons/src/index.js index 7140f8a9a3d94d..cc539f05a42f33 100644 --- a/packages/icons/src/index.js +++ b/packages/icons/src/index.js @@ -99,6 +99,7 @@ export { default as lifesaver } from './library/lifesaver'; export { default as link } from './library/link'; export { default as linkOff } from './library/link-off'; export { default as list } from './library/list'; +export { default as lock } from './library/lock'; export { default as loop } from './library/loop'; export { default as mapMarker } from './library/map-marker'; export { default as media } from './library/media'; diff --git a/packages/icons/src/library/lock.js b/packages/icons/src/library/lock.js new file mode 100644 index 00000000000000..6503093111a03b --- /dev/null +++ b/packages/icons/src/library/lock.js @@ -0,0 +1,12 @@ +/** + * WordPress dependencies + */ +import { SVG, Path } from '@wordpress/primitives'; + +const lock = ( + + + +); + +export default lock; From 665cd25b60e09a570836e6a4957debca810a8042 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Date: Fri, 25 Sep 2020 21:24:53 +0200 Subject: [PATCH 09/40] Add Reusable block edit title --- .../src/block/edit-title.native.js | 63 +++++++++++++++++++ .../block-library/src/block/edit.native.js | 5 +- .../src/block/editor.native.scss | 49 +++++++++++++++ 3 files changed, 115 insertions(+), 2 deletions(-) create mode 100644 packages/block-library/src/block/edit-title.native.js diff --git a/packages/block-library/src/block/edit-title.native.js b/packages/block-library/src/block/edit-title.native.js new file mode 100644 index 00000000000000..e9355ef0021931 --- /dev/null +++ b/packages/block-library/src/block/edit-title.native.js @@ -0,0 +1,63 @@ +/** + * External dependencies + */ +import { Text, View } from 'react-native'; + +/** + * WordPress dependencies + */ +import { Icon } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; +import { withPreferredColorScheme } from '@wordpress/compose'; +import { help, lock } from '@wordpress/icons'; + +/** + * Internal dependencies + */ +import styles from './editor.scss'; + +function EditTitle( { getStylesFromColorScheme, title } ) { + const lockIconStyle = getStylesFromColorScheme( + styles.lockIcon, + styles.lockIconDark + ); + const titleStyle = getStylesFromColorScheme( + styles.title, + styles.titleDark + ); + const infoIconStyle = getStylesFromColorScheme( + styles.infoIcon, + styles.infoIconDark + ); + const separatorStyle = getStylesFromColorScheme( + styles.separator, + styles.separatorDark + ); + + return ( + <> + + + + + { title } + + + + + + + ); +} + +export default withPreferredColorScheme( EditTitle ); diff --git a/packages/block-library/src/block/edit.native.js b/packages/block-library/src/block/edit.native.js index 1c22cd6b6c8c9e..de4cb51e277633 100644 --- a/packages/block-library/src/block/edit.native.js +++ b/packages/block-library/src/block/edit.native.js @@ -19,6 +19,7 @@ import { parse } from '@wordpress/blocks'; * Internal dependencies */ import styles from './editor.scss'; +import EditTitle from './edit-title'; class ReusableBlockEdit extends Component { constructor( { reusableBlock } ) { @@ -89,7 +90,7 @@ class ReusableBlockEdit extends Component { onChange={ this.setBlocks } onInput={ this.setBlocks } > - + ); @@ -99,7 +100,7 @@ class ReusableBlockEdit extends Component { return ( - { isSelected && { title } } + { isSelected && } { element } ); diff --git a/packages/block-library/src/block/editor.native.scss b/packages/block-library/src/block/editor.native.scss index 1fbcfaf370c9f2..2782037c50ca97 100644 --- a/packages/block-library/src/block/editor.native.scss +++ b/packages/block-library/src/block/editor.native.scss @@ -1,3 +1,52 @@ +.titleContainer { + flex-direction: row; + align-items: center; + padding-bottom: 12; +} + .title { font-weight: bold; + color: $light-secondary; + flex-grow: 1; +} + +.titleDark { + color: $dark-secondary; +} + +.separator { + background-color: $light-gray-400; + height: 1px; + width: 100%; +} + +.separatorDark { + background-color: $gray-70; +} + +.lockIconContainer { + justify-content: flex-start; + align-items: flex-end; + padding-right: 8; +} + +.lockIcon { + color: $light-secondary; +} + +.lockIconDark { + color: $dark-secondary; +} + +.helpIconContainer { + justify-content: flex-start; + align-items: flex-end; +} + +.infoIcon { + color: $light-secondary; } + +.infoIconDark { + color: $dark-secondary; +} \ No newline at end of file From 2309ac77bdcf95496af7527eda17d8eeb82ebd94 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Date: Tue, 29 Sep 2020 20:04:59 +0200 Subject: [PATCH 10/40] Extend Reusable block title separator --- .../src/block/edit-title.native.js | 38 +++++++++---------- .../src/block/editor.native.scss | 5 ++- 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/packages/block-library/src/block/edit-title.native.js b/packages/block-library/src/block/edit-title.native.js index e9355ef0021931..e0285958a66310 100644 --- a/packages/block-library/src/block/edit-title.native.js +++ b/packages/block-library/src/block/edit-title.native.js @@ -35,28 +35,26 @@ function EditTitle( { getStylesFromColorScheme, title } ) { ); return ( - <> - - - - - { title } - - - + + + + + { title } + + - + ); } diff --git a/packages/block-library/src/block/editor.native.scss b/packages/block-library/src/block/editor.native.scss index 2782037c50ca97..a449ce05d3c62b 100644 --- a/packages/block-library/src/block/editor.native.scss +++ b/packages/block-library/src/block/editor.native.scss @@ -17,7 +17,10 @@ .separator { background-color: $light-gray-400; height: 1px; - width: 100%; + position: absolute; + left: -$block-selected-to-content + $block-selected-border-width; + right: -$block-selected-to-content + $block-selected-border-width; + bottom: 0; } .separatorDark { From f9b45160cddf353be460568489e53451006d9c77 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Date: Tue, 29 Sep 2020 21:22:16 +0200 Subject: [PATCH 11/40] Add bottom sheet to Reusable blocks --- .../block-library/src/block/edit.native.js | 121 +++++++++++++++++- .../src/block/editor.native.scss | 49 ++++++- 2 files changed, 162 insertions(+), 8 deletions(-) diff --git a/packages/block-library/src/block/edit.native.js b/packages/block-library/src/block/edit.native.js index de4cb51e277633..1708dca8697b47 100644 --- a/packages/block-library/src/block/edit.native.js +++ b/packages/block-library/src/block/edit.native.js @@ -1,19 +1,21 @@ /** * External dependencies */ -import { Text, View } from 'react-native'; +import { Platform, Text, TouchableWithoutFeedback, View } from 'react-native'; import { partial } from 'lodash'; /** * WordPress dependencies */ import { Component } from '@wordpress/element'; -import { Spinner, Disabled } from '@wordpress/components'; +import { BottomSheet, Icon, Spinner, Disabled } from '@wordpress/components'; import { withSelect, withDispatch } from '@wordpress/data'; import { __ } from '@wordpress/i18n'; import { BlockEditorProvider, BlockList } from '@wordpress/block-editor'; -import { compose } from '@wordpress/compose'; +import { compose, withPreferredColorScheme } from '@wordpress/compose'; import { parse } from '@wordpress/blocks'; +import { help } from '@wordpress/icons'; +import { requestUnsupportedBlockFallback } from '@wordpress/react-native-bridge'; /** * Internal dependencies @@ -26,6 +28,8 @@ class ReusableBlockEdit extends Component { super( ...arguments ); this.setBlocks = this.setBlocks.bind( this ); + this.toggleSheet = this.toggleSheet.bind( this ); + this.requestFallback = this.requestFallback.bind( this ); if ( reusableBlock ) { // Start in edit mode when we're working with a newly created reusable block @@ -34,6 +38,8 @@ class ReusableBlockEdit extends Component { isEditing: false, title: reusableBlock.title, blocks: parse( reusableBlock.content ), + showHelp: false, + sendFallbackMessage: false, }; } else { // Start in preview mode when we're working with an existing reusable block @@ -41,6 +47,8 @@ class ReusableBlockEdit extends Component { isEditing: false, title: null, blocks: [], + showHelp: false, + sendFallbackMessage: false, }; } } @@ -63,10 +71,99 @@ class ReusableBlockEdit extends Component { } } + toggleSheet() { + this.setState( { + showHelp: ! this.state.showHelp, + } ); + } + + requestFallback() { + this.toggleSheet(); + this.setState( { sendFallbackMessage: true } ); + } + setBlocks( blocks ) { this.setState( { blocks } ); } + renderSheet() { + const { name, reusableBlock } = this.props; + const { showHelp, title } = this.state; + + const { getStylesFromColorScheme, clientId } = this.props; + const infoTextStyle = getStylesFromColorScheme( + styles.infoText, + styles.infoTextDark + ); + const infoTitleStyle = getStylesFromColorScheme( + styles.infoTitle, + styles.infoTitleDark + ); + const infoSheetIconStyle = getStylesFromColorScheme( + styles.infoSheetIcon, + styles.infoSheetIconDark + ); + const actionButtonStyle = getStylesFromColorScheme( + styles.actionButton, + styles.actionButtonDark + ); + + const infoTitle = + Platform.OS === 'android' + ? __( + "'Reusable blocks aren't editable on WordPress for Android" + ) + : __( "Reusable blocks aren't editable on WordPress for iOS" ); + + return ( + { + if ( this.state.sendFallbackMessage ) { + // On iOS, onModalHide is called when the controller is still part of the hierarchy. + // A small delay will ensure that the controller has already been removed. + this.timeout = setTimeout( () => { + requestUnsupportedBlockFallback( + reusableBlock.content, + clientId, + name, + title + ); + }, 100 ); + this.setState( { sendFallbackMessage: false } ); + } + } } + > + + + + { infoTitle } + + + <> + + + + + ); + } + render() { const { isSelected, reusableBlock, isFetching, settings } = this.props; const { isEditing, title, blocks } = this.state; @@ -99,10 +196,19 @@ class ReusableBlockEdit extends Component { } return ( - - { isSelected && } - { element } - + + + { isSelected && } + { element } + { this.renderSheet( title ) } + + ); } } @@ -153,4 +259,5 @@ export default compose( [ }, }; } ), + withPreferredColorScheme, ] )( ReusableBlockEdit ); diff --git a/packages/block-library/src/block/editor.native.scss b/packages/block-library/src/block/editor.native.scss index a449ce05d3c62b..b6e21175273167 100644 --- a/packages/block-library/src/block/editor.native.scss +++ b/packages/block-library/src/block/editor.native.scss @@ -52,4 +52,51 @@ .infoIconDark { color: $dark-secondary; -} \ No newline at end of file +} + +.infoContainer { + flex-direction: column; + align-items: center; + justify-content: flex-end; +} + +.infoSheetIcon { + size: 36; + height: 36; + padding-top: 8; + padding-bottom: 8; + color: $gray; +} + +.infoSheetIconDark { + color: $gray-20; +} + +.infoText { + text-align: center; + color: $gray-dark; +} + +.infoTextDark { + color: $white; +} + +.infoTitle { + padding-top: 8; + padding-bottom: 12; + font-size: 20; + font-weight: bold; + color: $gray-dark; +} + +.infoTitleDark { + color: $white; +} + +.actionButton { + color: $blue-50; +} + +.actionButtonDark { + color: $blue-30; +} From 7ab4a4cff27fa1d262b809840aae022a04604933 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Date: Wed, 30 Sep 2020 21:24:21 +0200 Subject: [PATCH 12/40] Fix reusable blocks use of UBE --- .../block-library/src/block/edit.native.js | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/packages/block-library/src/block/edit.native.js b/packages/block-library/src/block/edit.native.js index 1708dca8697b47..6afa1e26ae63a2 100644 --- a/packages/block-library/src/block/edit.native.js +++ b/packages/block-library/src/block/edit.native.js @@ -36,7 +36,6 @@ class ReusableBlockEdit extends Component { this.state = { // Since edition is not supported yet isEditing is always false isEditing: false, - title: reusableBlock.title, blocks: parse( reusableBlock.content ), showHelp: false, sendFallbackMessage: false, @@ -45,7 +44,6 @@ class ReusableBlockEdit extends Component { // Start in preview mode when we're working with an existing reusable block this.state = { isEditing: false, - title: null, blocks: [], showHelp: false, sendFallbackMessage: false, @@ -54,18 +52,18 @@ class ReusableBlockEdit extends Component { } componentDidMount() { - if ( ! this.props.reusableBlock ) { - this.props.fetchReusableBlock(); - } + this.props.fetchReusableBlock(); } componentDidUpdate( prevProps ) { - if ( - prevProps.reusableBlock !== this.props.reusableBlock && - this.state.title === null - ) { + const hasBlockFetchCompleted = + ! prevProps.reusableBlock && this.props.reusableBlock; + const hasBlockContentChanged = + prevProps.reusableBlock?.content !== + this.props.reusableBlock?.content; + + if ( hasBlockFetchCompleted || hasBlockContentChanged ) { this.setState( { - title: this.props.reusableBlock.title, blocks: parse( this.props.reusableBlock.content ), } ); } @@ -87,8 +85,8 @@ class ReusableBlockEdit extends Component { } renderSheet() { - const { name, reusableBlock } = this.props; - const { showHelp, title } = this.state; + const { reusableBlock } = this.props; + const { showHelp } = this.state; const { getStylesFromColorScheme, clientId } = this.props; const infoTextStyle = getStylesFromColorScheme( @@ -126,10 +124,10 @@ class ReusableBlockEdit extends Component { // A small delay will ensure that the controller has already been removed. this.timeout = setTimeout( () => { requestUnsupportedBlockFallback( - reusableBlock.content, + ``, clientId, name, - title + reusableBlock.title ); }, 100 ); this.setState( { sendFallbackMessage: false } ); @@ -166,7 +164,7 @@ class ReusableBlockEdit extends Component { render() { const { isSelected, reusableBlock, isFetching, settings } = this.props; - const { isEditing, title, blocks } = this.state; + const { isEditing, blocks } = this.state; if ( ! reusableBlock && isFetching ) { return ; @@ -180,6 +178,7 @@ class ReusableBlockEdit extends Component { ); } + const { title } = reusableBlock; let element = ( Date: Wed, 30 Sep 2020 21:38:05 +0200 Subject: [PATCH 13/40] Fix reusable block render bottom sheet --- packages/block-library/src/block/edit.native.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/block-library/src/block/edit.native.js b/packages/block-library/src/block/edit.native.js index 6afa1e26ae63a2..c4b6df3f74e995 100644 --- a/packages/block-library/src/block/edit.native.js +++ b/packages/block-library/src/block/edit.native.js @@ -85,7 +85,7 @@ class ReusableBlockEdit extends Component { } renderSheet() { - const { reusableBlock } = this.props; + const { name, reusableBlock } = this.props; const { showHelp } = this.state; const { getStylesFromColorScheme, clientId } = this.props; @@ -109,7 +109,7 @@ class ReusableBlockEdit extends Component { const infoTitle = Platform.OS === 'android' ? __( - "'Reusable blocks aren't editable on WordPress for Android" + "Reusable blocks aren't editable on WordPress for Android" ) : __( "Reusable blocks aren't editable on WordPress for iOS" ); From 76709809e187980b66c51830894ff5314fe0ca51 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Date: Thu, 1 Oct 2020 20:49:12 +0200 Subject: [PATCH 14/40] Fix title in reusable block when using UBE --- packages/block-library/src/block/edit.native.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/block-library/src/block/edit.native.js b/packages/block-library/src/block/edit.native.js index c4b6df3f74e995..ce5125e37160cd 100644 --- a/packages/block-library/src/block/edit.native.js +++ b/packages/block-library/src/block/edit.native.js @@ -8,7 +8,7 @@ import { partial } from 'lodash'; * WordPress dependencies */ import { Component } from '@wordpress/element'; -import { BottomSheet, Icon, Spinner, Disabled } from '@wordpress/components'; +import { BottomSheet, Icon, Disabled } from '@wordpress/components'; import { withSelect, withDispatch } from '@wordpress/data'; import { __ } from '@wordpress/i18n'; import { BlockEditorProvider, BlockList } from '@wordpress/block-editor'; @@ -85,7 +85,7 @@ class ReusableBlockEdit extends Component { } renderSheet() { - const { name, reusableBlock } = this.props; + const { reusableBlock } = this.props; const { showHelp } = this.state; const { getStylesFromColorScheme, clientId } = this.props; @@ -126,7 +126,7 @@ class ReusableBlockEdit extends Component { requestUnsupportedBlockFallback( ``, clientId, - name, + reusableBlock.name, reusableBlock.title ); }, 100 ); @@ -167,7 +167,7 @@ class ReusableBlockEdit extends Component { const { isEditing, blocks } = this.state; if ( ! reusableBlock && isFetching ) { - return ; + return null; } if ( ! reusableBlock ) { From 002e6907b3f988b32d491861dfe8e9e98f6dcdcd Mon Sep 17 00:00:00 2001 From: Carlos Garcia Date: Fri, 2 Oct 2020 21:49:47 +0200 Subject: [PATCH 15/40] Add closeSheet handler for bottom sheet in Reusable block --- packages/block-library/src/block/edit.native.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/block-library/src/block/edit.native.js b/packages/block-library/src/block/edit.native.js index ce5125e37160cd..2ad8d0207529ba 100644 --- a/packages/block-library/src/block/edit.native.js +++ b/packages/block-library/src/block/edit.native.js @@ -29,6 +29,7 @@ class ReusableBlockEdit extends Component { this.setBlocks = this.setBlocks.bind( this ); this.toggleSheet = this.toggleSheet.bind( this ); + this.closeSheet = this.closeSheet.bind( this ); this.requestFallback = this.requestFallback.bind( this ); if ( reusableBlock ) { @@ -75,6 +76,10 @@ class ReusableBlockEdit extends Component { } ); } + closeSheet() { + this.setState( { showHelp: false } ); + } + requestFallback() { this.toggleSheet(); this.setState( { sendFallbackMessage: true } ); @@ -117,7 +122,7 @@ class ReusableBlockEdit extends Component { { if ( this.state.sendFallbackMessage ) { // On iOS, onModalHide is called when the controller is still part of the hierarchy. From 9fcb36057e49fceece26d3e8e16b7a981f872aa7 Mon Sep 17 00:00:00 2001 From: fluiddot Date: Wed, 23 Dec 2020 14:27:59 +0100 Subject: [PATCH 16/40] Transform Reusable block edit to functional component --- .../block-library/src/block/edit.native.js | 312 ++++++++---------- 1 file changed, 129 insertions(+), 183 deletions(-) diff --git a/packages/block-library/src/block/edit.native.js b/packages/block-library/src/block/edit.native.js index 2ad8d0207529ba..34506d2ad59285 100644 --- a/packages/block-library/src/block/edit.native.js +++ b/packages/block-library/src/block/edit.native.js @@ -2,20 +2,20 @@ * External dependencies */ import { Platform, Text, TouchableWithoutFeedback, View } from 'react-native'; -import { partial } from 'lodash'; /** * WordPress dependencies */ -import { Component } from '@wordpress/element'; +import { useEffect, useRef, useState } from '@wordpress/element'; +import { useEntityBlockEditor } from '@wordpress/core-data'; import { BottomSheet, Icon, Disabled } from '@wordpress/components'; -import { withSelect, withDispatch } from '@wordpress/data'; +import { useSelect, useDispatch } from '@wordpress/data'; import { __ } from '@wordpress/i18n'; import { BlockEditorProvider, BlockList } from '@wordpress/block-editor'; -import { compose, withPreferredColorScheme } from '@wordpress/compose'; -import { parse } from '@wordpress/blocks'; +import { usePreferredColorSchemeStyle } from '@wordpress/compose'; import { help } from '@wordpress/icons'; import { requestUnsupportedBlockFallback } from '@wordpress/react-native-bridge'; +import { store as reusableBlocksStore } from '@wordpress/reusable-blocks'; /** * Internal dependencies @@ -23,94 +23,92 @@ import { requestUnsupportedBlockFallback } from '@wordpress/react-native-bridge' import styles from './editor.scss'; import EditTitle from './edit-title'; -class ReusableBlockEdit extends Component { - constructor( { reusableBlock } ) { - super( ...arguments ); - - this.setBlocks = this.setBlocks.bind( this ); - this.toggleSheet = this.toggleSheet.bind( this ); - this.closeSheet = this.closeSheet.bind( this ); - this.requestFallback = this.requestFallback.bind( this ); - - if ( reusableBlock ) { - // Start in edit mode when we're working with a newly created reusable block - this.state = { - // Since edition is not supported yet isEditing is always false - isEditing: false, - blocks: parse( reusableBlock.content ), - showHelp: false, - sendFallbackMessage: false, - }; - } else { - // Start in preview mode when we're working with an existing reusable block - this.state = { - isEditing: false, - blocks: [], - showHelp: false, - sendFallbackMessage: false, +export default function ReusableBlockEdit( { + attributes: { ref }, + clientId, + isSelected, +} ) { + const recordArgs = [ 'postType', 'wp_block', ref ]; + + const [ showHelp, setShowHelp ] = useState( false ); + const [ sendFallbackMessage, setSendFallbackMessage ] = useState( false ); + const timeoutId = useRef(); + const infoTextStyle = usePreferredColorSchemeStyle( + styles.infoText, + styles.infoTextDark + ); + const infoTitleStyle = usePreferredColorSchemeStyle( + styles.infoTitle, + styles.infoTitleDark + ); + const infoSheetIconStyle = usePreferredColorSchemeStyle( + styles.infoSheetIcon, + styles.infoSheetIconDark + ); + const actionButtonStyle = usePreferredColorSchemeStyle( + styles.actionButton, + styles.actionButtonDark + ); + + const { reusableBlock, hasResolved, isEditing, settings } = useSelect( + ( select ) => { + return { + reusableBlock: select( 'core' ).getEditedEntityRecord( + ...recordArgs + ), + hasResolved: select( 'core' ).hasFinishedResolution( + 'getEditedEntityRecord', + recordArgs + ), + isSaving: select( 'core' ).isSavingEntityRecord( + ...recordArgs + ), + canUserUpdate: select( 'core' ).canUser( + 'update', + 'blocks', + ref + ), + isEditing: select( + reusableBlocksStore + ).__experimentalIsEditingReusableBlock( clientId ), + settings: select( 'core/block-editor' ).getSettings(), }; - } - } - - componentDidMount() { - this.props.fetchReusableBlock(); - } - - componentDidUpdate( prevProps ) { - const hasBlockFetchCompleted = - ! prevProps.reusableBlock && this.props.reusableBlock; - const hasBlockContentChanged = - prevProps.reusableBlock?.content !== - this.props.reusableBlock?.content; - - if ( hasBlockFetchCompleted || hasBlockContentChanged ) { - this.setState( { - blocks: parse( this.props.reusableBlock.content ), - } ); - } - } - - toggleSheet() { - this.setState( { - showHelp: ! this.state.showHelp, - } ); - } + }, + [ ref, clientId ] + ); + + const { invalidateResolution } = useDispatch( 'core' ); + + const [ blocks, onInput, onChange ] = useEntityBlockEditor( + 'postType', + 'wp_block', + { id: ref } + ); + + useEffect( () => { + return () => { + /** + * Invalidate entity record upon unmount to keep the reusable block udpated + * in case it's modified through UBE + */ + invalidateResolution( 'getEntityRecord', recordArgs ); + }; + }, [] ); - closeSheet() { - this.setState( { showHelp: false } ); + function toggleSheet() { + setShowHelp( ! showHelp ); } - requestFallback() { - this.toggleSheet(); - this.setState( { sendFallbackMessage: true } ); + function closeSheet() { + setShowHelp( false ); } - setBlocks( blocks ) { - this.setState( { blocks } ); + function requestFallback() { + toggleSheet(); + setSendFallbackMessage( true ); } - renderSheet() { - const { reusableBlock } = this.props; - const { showHelp } = this.state; - - const { getStylesFromColorScheme, clientId } = this.props; - const infoTextStyle = getStylesFromColorScheme( - styles.infoText, - styles.infoTextDark - ); - const infoTitleStyle = getStylesFromColorScheme( - styles.infoTitle, - styles.infoTitleDark - ); - const infoSheetIconStyle = getStylesFromColorScheme( - styles.infoSheetIcon, - styles.infoSheetIconDark - ); - const actionButtonStyle = getStylesFromColorScheme( - styles.actionButton, - styles.actionButtonDark - ); - + function renderSheet() { const infoTitle = Platform.OS === 'android' ? __( @@ -122,20 +120,24 @@ class ReusableBlockEdit extends Component { { - if ( this.state.sendFallbackMessage ) { + if ( sendFallbackMessage ) { // On iOS, onModalHide is called when the controller is still part of the hierarchy. // A small delay will ensure that the controller has already been removed. - this.timeout = setTimeout( () => { + timeoutId.current = setTimeout( () => { requestUnsupportedBlockFallback( ``, clientId, reusableBlock.name, reusableBlock.title ); + invalidateResolution( + 'getEntityRecord', + recordArgs + ); }, 100 ); - this.setState( { sendFallbackMessage: false } ); + setSendFallbackMessage( false ); } } } > @@ -153,13 +155,13 @@ class ReusableBlockEdit extends Component { @@ -167,101 +169,45 @@ class ReusableBlockEdit extends Component { ); } - render() { - const { isSelected, reusableBlock, isFetching, settings } = this.props; - const { isEditing, blocks } = this.state; - - if ( ! reusableBlock && isFetching ) { - return null; - } - - if ( ! reusableBlock ) { - return ( - - { __( 'Block has been deleted or is unavailable.' ) } - - ); - } - - const { title } = reusableBlock; - let element = ( - - - - ); - - if ( ! isEditing ) { - element = { element }; - } + if ( ! hasResolved ) { + return null; + } + if ( ! reusableBlock ) { return ( - - - { isSelected && } - { element } - { this.renderSheet( title ) } - - + { __( 'Block has been deleted or is unavailable.' ) } ); } -} - -export default compose( [ - withSelect( ( select, ownProps ) => { - const { - __experimentalGetReusableBlock: getReusableBlock, - __experimentalIsFetchingReusableBlock: isFetchingReusableBlock, - __experimentalIsSavingReusableBlock: isSavingReusableBlock, - } = select( 'core/editor' ); - const { canUser } = select( 'core' ); - const { __experimentalGetParsedReusableBlock, getSettings } = select( - 'core/block-editor' - ); - const { ref } = ownProps.attributes; - const reusableBlock = getReusableBlock( ref ); - return { - reusableBlock, - isFetching: isFetchingReusableBlock( ref ), - isSaving: isSavingReusableBlock( ref ), - blocks: reusableBlock - ? __experimentalGetParsedReusableBlock( reusableBlock.id ) - : null, - canUpdateBlock: - !! reusableBlock && - ! reusableBlock.isTemporary && - !! canUser( 'update', 'blocks', ref ), - settings: getSettings(), - }; - } ), - withDispatch( ( dispatch, ownProps ) => { - const { - __experimentalConvertBlockToStatic: convertBlockToStatic, - __experimentalFetchReusableBlocks: fetchReusableBlocks, - __experimentalUpdateReusableBlock: updateReusableBlock, - __experimentalSaveReusableBlock: saveReusableBlock, - } = dispatch( 'core/editor' ); - const { ref } = ownProps.attributes; + const { title } = reusableBlock; + let element = ( + + + + ); + + if ( ! isEditing ) { + element = { element }; + } - return { - fetchReusableBlock: partial( fetchReusableBlocks, ref ), - onChange: partial( updateReusableBlock, ref ), - onSave: partial( saveReusableBlock, ref ), - convertToStatic() { - convertBlockToStatic( ownProps.clientId ); - }, - }; - } ), - withPreferredColorScheme, -] )( ReusableBlockEdit ); + return ( + + + { isSelected && } + { element } + { renderSheet() } + + + ); +} From 26e7b710bdcbad1671079b7dde5aa310a4fa7c97 Mon Sep 17 00:00:00 2001 From: fluiddot Date: Wed, 23 Dec 2020 14:30:39 +0100 Subject: [PATCH 17/40] Fix long texts on Reusable block title --- packages/block-library/src/block/edit-title.native.js | 4 +++- packages/block-library/src/block/editor.native.scss | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/block-library/src/block/edit-title.native.js b/packages/block-library/src/block/edit-title.native.js index e0285958a66310..0a574f2f0cfa83 100644 --- a/packages/block-library/src/block/edit-title.native.js +++ b/packages/block-library/src/block/edit-title.native.js @@ -44,7 +44,9 @@ function EditTitle( { getStylesFromColorScheme, title } ) { style={ lockIconStyle } /> - { title } + + { title } + Date: Wed, 23 Dec 2020 14:32:21 +0100 Subject: [PATCH 18/40] Filter out reusable blocks in inserter menu --- .../block-editor/src/components/inserter/menu.native.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/inserter/menu.native.js b/packages/block-editor/src/components/inserter/menu.native.js index 44cc04f428afd4..1e466713e5bb95 100644 --- a/packages/block-editor/src/components/inserter/menu.native.js +++ b/packages/block-editor/src/components/inserter/menu.native.js @@ -123,12 +123,17 @@ export class InserterMenu extends Component { */ getItems() { const { - items, + items: initialItems, canInsertBlockType, destinationRootClientId, getBlockType, } = this.props; + // Filter out reusable blocks (they will be added in another tab) + const items = initialItems.filter( + ( { name } ) => name !== 'core/block' + ); + const clipboard = getClipboard(); const clipboardBlock = clipboard && rawHandler( { HTML: clipboard } )[ 0 ]; From 1dcfe4637cfd7812568db575005e4a3a67340244 Mon Sep 17 00:00:00 2001 From: fluiddot Date: Wed, 23 Dec 2020 16:31:44 +0100 Subject: [PATCH 19/40] Clear timeout when reusable block edit is unmounted --- packages/block-library/src/block/edit.native.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/block-library/src/block/edit.native.js b/packages/block-library/src/block/edit.native.js index 34506d2ad59285..8358a5f2301955 100644 --- a/packages/block-library/src/block/edit.native.js +++ b/packages/block-library/src/block/edit.native.js @@ -87,6 +87,7 @@ export default function ReusableBlockEdit( { useEffect( () => { return () => { + clearTimeout( timeoutId.current ); /** * Invalidate entity record upon unmount to keep the reusable block udpated * in case it's modified through UBE From 6b58641000e7a8b9a77e27d26aba4224551a5645 Mon Sep 17 00:00:00 2001 From: fluiddot Date: Wed, 23 Dec 2020 16:33:52 +0100 Subject: [PATCH 20/40] Change toggleSheet to openSheet in reusable block edit --- packages/block-library/src/block/edit.native.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/block-library/src/block/edit.native.js b/packages/block-library/src/block/edit.native.js index 8358a5f2301955..2b2e097eef3d2a 100644 --- a/packages/block-library/src/block/edit.native.js +++ b/packages/block-library/src/block/edit.native.js @@ -96,8 +96,8 @@ export default function ReusableBlockEdit( { }; }, [] ); - function toggleSheet() { - setShowHelp( ! showHelp ); + function openSheet() { + setShowHelp( true ); } function closeSheet() { @@ -105,7 +105,7 @@ export default function ReusableBlockEdit( { } function requestFallback() { - toggleSheet(); + closeSheet(); setSendFallbackMessage( true ); } @@ -162,7 +162,7 @@ export default function ReusableBlockEdit( { @@ -202,7 +202,7 @@ export default function ReusableBlockEdit( { accessibilityLabel={ __( 'Help button' ) } accessibilityRole={ 'button' } accessibilityHint={ __( 'Tap here to show help' ) } - onPress={ toggleSheet } + onPress={ openSheet } > { isSelected && } From 753e27b589c28981885ab8ae66fa377a44e25659 Mon Sep 17 00:00:00 2001 From: fluiddot Date: Wed, 30 Dec 2020 16:44:52 +0100 Subject: [PATCH 21/40] Rename edit block in web browser label of reusable block The value is now the same as the missing component since they behave the same, this way the UI tests can follow the same flow. --- packages/block-library/src/block/edit.native.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-library/src/block/edit.native.js b/packages/block-library/src/block/edit.native.js index 2b2e097eef3d2a..0b1a075461ffe3 100644 --- a/packages/block-library/src/block/edit.native.js +++ b/packages/block-library/src/block/edit.native.js @@ -154,7 +154,7 @@ export default function ReusableBlockEdit( { <> Date: Mon, 4 Jan 2021 12:07:21 +0100 Subject: [PATCH 22/40] Update react-native-editor CHANGELOG --- packages/react-native-editor/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/react-native-editor/CHANGELOG.md b/packages/react-native-editor/CHANGELOG.md index 095ed5bbc8fd57..21228a19aa070a 100644 --- a/packages/react-native-editor/CHANGELOG.md +++ b/packages/react-native-editor/CHANGELOG.md @@ -12,6 +12,7 @@ For each user feature we should also add a importance categorization label to i ## Unreleased * [***] Full-width and wide alignment support for Columns +* [**] Add Support to Insert Existing Reusable Blocks from the Editor ## 1.43.0 * [***] New Block: File [#27228] From c419923777ca3adba6b470f0af941a14636a2f07 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Date: Thu, 10 Sep 2020 21:47:38 +0200 Subject: [PATCH 23/40] Add custom header to BottomSheet --- .../src/mobile/bottom-sheet/index.native.js | 34 +++++++++++-------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/packages/components/src/mobile/bottom-sheet/index.native.js b/packages/components/src/mobile/bottom-sheet/index.native.js index c937aad9773e43..6c651427f8af2d 100644 --- a/packages/components/src/mobile/bottom-sheet/index.native.js +++ b/packages/components/src/mobile/bottom-sheet/index.native.js @@ -279,6 +279,7 @@ class BottomSheet extends Component { isVisible, leftButton, rightButton, + header, hideHeader, style = {}, contentStyle = {}, @@ -353,21 +354,24 @@ class BottomSheet extends Component { const WrapperView = hasNavigation ? View : ScrollView; - const getHeader = () => ( - <> - - { leftButton } - - { title } - - { rightButton } - - { withHeaderSeparator && } - - ); + const getHeader = () => + header || ( + <> + + { leftButton } + + { title } + + { rightButton } + + { withHeaderSeparator && ( + + ) } + + ); return ( Date: Thu, 10 Sep 2020 21:48:29 +0200 Subject: [PATCH 24/40] SegmentedControl mobile component exported --- packages/components/src/index.native.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/components/src/index.native.js b/packages/components/src/index.native.js index 43d56524787506..88ae545bac4eb3 100644 --- a/packages/components/src/index.native.js +++ b/packages/components/src/index.native.js @@ -79,6 +79,7 @@ export { default as LinkPickerScreen } from './mobile/link-picker/link-picker-sc export { default as LinkSettings } from './mobile/link-settings'; export { default as LinkSettingsScreen } from './mobile/link-settings/link-settings-screen'; export { default as LinkSettingsNavigation } from './mobile/link-settings/link-settings-navigation'; +export { default as SegmentedControl } from './mobile/segmented-control'; export { default as Image, IMAGE_DEFAULT_FOCAL_POINT } from './mobile/image'; export { default as ImageEditingButton } from './mobile/image/image-editing-button'; export { default as InserterButton } from './mobile/inserter-button'; From 5fc495b370b91cafcdbfb5e13e9d2faefae61f47 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Date: Thu, 10 Sep 2020 21:56:27 +0200 Subject: [PATCH 25/40] Add Reusable blocks to inserter menu with tabs --- .../src/components/inserter/menu.native.js | 132 +++++++++++++----- .../src/components/inserter/style.native.scss | 1 + 2 files changed, 98 insertions(+), 35 deletions(-) diff --git a/packages/block-editor/src/components/inserter/menu.native.js b/packages/block-editor/src/components/inserter/menu.native.js index 1e466713e5bb95..9d38883052affa 100644 --- a/packages/block-editor/src/components/inserter/menu.native.js +++ b/packages/block-editor/src/components/inserter/menu.native.js @@ -1,3 +1,8 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; + /** * External dependencies */ @@ -26,6 +31,7 @@ import { BottomSheetConsumer, InserterButton, getClipboard, + SegmentedControl, } from '@wordpress/components'; /** @@ -34,6 +40,7 @@ import { import styles from './style.scss'; const MIN_COL_NUM = 3; +const TABS = [ __( 'Child Blocks' ), __( 'Reusable blocks' ) ]; export class InserterMenu extends Component { constructor() { @@ -41,9 +48,15 @@ export class InserterMenu extends Component { this.onClose = this.onClose.bind( this ); this.onLayout = this.onLayout.bind( this ); + this.onChangeTab = this.onChangeTab.bind( this ); this.renderItem = this.renderItem.bind( this ); + this.renderBlocksTab = this.renderBlocksTab.bind( this ); + this.renderReusableBlocksTab = this.renderReusableBlocksTab.bind( + this + ); this.state = { numberOfColumns: MIN_COL_NUM, + tab: 0, }; Dimensions.addEventListener( 'change', this.onLayout ); @@ -116,21 +129,25 @@ export class InserterMenu extends Component { this.setState( { numberOfColumns, itemWidth, maxWidth } ); } + onChangeTab( tab ) { + this.setState( { tab: TABS.indexOf( tab ) } ); + } + /** * Processes the inserter items to check * if there's any copied block in the clipboard * to add it as an extra item */ - getItems() { + getBlockItems() { const { - items: initialItems, + items, canInsertBlockType, destinationRootClientId, getBlockType, } = this.props; // Filter out reusable blocks (they will be added in another tab) - const items = initialItems.filter( + const blockItems = items.filter( ( { name } ) => name !== 'core/block' ); @@ -152,9 +169,15 @@ export class InserterMenu extends Component { initialAttributes: clipboardBlock.attributes, innerBlocks: clipboardBlock.innerBlocks, }, - ...items, + ...blockItems, ] - : items; + : blockItems; + } + + getReusableBlockItems() { + const { items } = this.props; + + return items.filter( ( { name } ) => name === 'core/block' ); } renderItem( { item } ) { @@ -170,46 +193,85 @@ export class InserterMenu extends Component { ); } - render() { + renderBlocksTab( listProps ) { const { numberOfColumns } = this.state; - const items = this.getItems(); + const items = this.getBlockItems(); + + return ( + ( + + + + ) } + keyExtractor={ ( item ) => item.name } + renderItem={ this.renderItem } + { ...listProps } + /> + ); + } + + renderReusableBlocksTab( listProps ) { + const { numberOfColumns } = this.state; + const items = this.getReusableBlockItems(); + + return ( + ( + + + + ) } + keyExtractor={ ( item ) => item.name } + renderItem={ this.renderItem } + { ...listProps } + /> + ); + } + + render() { + const { tab } = this.state; + const reusableBlockItems = this.getReusableBlockItems(); + + const hideHeader = reusableBlockItems.length === 0; return ( + } + hideHeader={ hideHeader } hasNavigation + contentStyle={ styles.list } + isChildrenScrollable > - { ( { listProps, safeAreaBottomInset } ) => ( - ( - - - - ) } - keyExtractor={ ( item ) => item.name } - renderItem={ this.renderItem } - { ...listProps } - contentContainerStyle={ [ - ...listProps.contentContainerStyle, - { - paddingBottom: - safeAreaBottomInset || - styles.list.paddingBottom, - }, - ] } - /> - ) } + { ( { listProps } ) => { + switch ( tab ) { + case 0: + return this.renderBlocksTab( listProps ); + case 1: + return this.renderReusableBlocksTab( + listProps + ); + } + } } diff --git a/packages/block-editor/src/components/inserter/style.native.scss b/packages/block-editor/src/components/inserter/style.native.scss index 77456c9587d1dd..5a1fe9ded51382 100644 --- a/packages/block-editor/src/components/inserter/style.native.scss +++ b/packages/block-editor/src/components/inserter/style.native.scss @@ -18,4 +18,5 @@ .list { padding-bottom: 20; + padding-top: 8; } From 8c25354b0132e6370a697e8ef5fdef7e0987b9b0 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Date: Mon, 14 Sep 2020 22:10:51 +0200 Subject: [PATCH 26/40] Add native version of inserter-list-item --- .../inserter-list-item/index.native.js | 84 +++++++++++++++++++ .../inserter-list-item/style.native.scss | 63 ++++++++++++++ 2 files changed, 147 insertions(+) create mode 100644 packages/block-editor/src/components/inserter-list-item/index.native.js create mode 100644 packages/block-editor/src/components/inserter-list-item/style.native.scss diff --git a/packages/block-editor/src/components/inserter-list-item/index.native.js b/packages/block-editor/src/components/inserter-list-item/index.native.js new file mode 100644 index 00000000000000..185d97963e4ae4 --- /dev/null +++ b/packages/block-editor/src/components/inserter-list-item/index.native.js @@ -0,0 +1,84 @@ +/** + * External dependencies + */ +import { View, TouchableHighlight, Text } from 'react-native'; + +/** + * WordPress dependencies + */ +import { Component } from '@wordpress/element'; +import { Icon } from '@wordpress/components'; +import { withPreferredColorScheme } from '@wordpress/compose'; +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import styles from './style.scss'; + +function InserterListItem( { + getStylesFromColorScheme, + item, + itemWidth, + maxWidth, + onSelect, +} ) { + const onPress = () => { + onSelect( item ); + }; + + const modalIconWrapperStyle = getStylesFromColorScheme( + styles.modalIconWrapper, + styles.modalIconWrapperDark + ); + const modalIconStyle = getStylesFromColorScheme( + styles.modalIcon, + styles.modalIconDark + ); + const modalItemLabelStyle = getStylesFromColorScheme( + styles.modalItemLabel, + styles.modalItemLabelDark + ); + + const clipboardBlockStyles = getStylesFromColorScheme( + styles.clipboardBlock, + styles.clipboardBlockDark + ); + + const isClipboardBlock = item.id === 'clipboard'; + + return ( + + + + + + + + + { isClipboardBlock ? __( 'Copied block' ) : item.title } + + + + ); +} + +export default withPreferredColorScheme( InserterListItem ); diff --git a/packages/block-editor/src/components/inserter-list-item/style.native.scss b/packages/block-editor/src/components/inserter-list-item/style.native.scss new file mode 100644 index 00000000000000..48836bf4888475 --- /dev/null +++ b/packages/block-editor/src/components/inserter-list-item/style.native.scss @@ -0,0 +1,63 @@ +.touchableArea { + border-radius: 8px 8px 8px 8px; +} + +.modalItem { + flex-direction: column; + justify-content: flex-start; + align-items: center; + padding-left: $grid-unit-20 / 2; + padding-right: $grid-unit-20 / 2; + padding-top: 0; + padding-bottom: 0; +} + +.modalIconWrapper { + width: 104px; + height: 64px; + background-color: $gray-light; //#f3f6f8 + border-radius: 8px 8px 8px 8px; + justify-content: center; + align-items: center; +} + +.modalIconWrapperDark { + background-color: rgba( $white, 0.07 ); +} + +.modalIcon { + width: 32px; + height: 32px; + justify-content: center; + align-items: center; + fill: $gray-dark; +} + +.modalIconDark { + fill: $white; +} + +.modalItemLabel { + background-color: transparent; + padding-left: 2; + padding-right: 2; + padding-top: 4; + padding-bottom: 0; + justify-content: center; + font-size: 12; + color: $gray-dark; +} + +.modalItemLabelDark { + color: $white; +} + +.clipboardBlock { + background-color: transparent; + border-width: 1px; + border-color: $light-gray-400; +} + +.clipboardBlockDark { + border-color: $gray-70; +} From d98b527900990a122cce409c8e083275f977394a Mon Sep 17 00:00:00 2001 From: Carlos Garcia Date: Tue, 15 Sep 2020 21:23:03 +0200 Subject: [PATCH 27/40] Add mobile version of block-types-list component --- .../block-types-list/index.native.js | 120 ++++++++++++++++++ .../block-types-list/style.native.scss | 7 + 2 files changed, 127 insertions(+) create mode 100644 packages/block-editor/src/components/block-types-list/index.native.js create mode 100644 packages/block-editor/src/components/block-types-list/style.native.scss diff --git a/packages/block-editor/src/components/block-types-list/index.native.js b/packages/block-editor/src/components/block-types-list/index.native.js new file mode 100644 index 00000000000000..fecd0986fa0b95 --- /dev/null +++ b/packages/block-editor/src/components/block-types-list/index.native.js @@ -0,0 +1,120 @@ +/** + * External dependencies + */ +import { + FlatList, + View, + TouchableWithoutFeedback, + Dimensions, +} from 'react-native'; + +/** + * WordPress dependencies + */ +import { Component } from '@wordpress/element'; +import { BottomSheet } from '@wordpress/components'; + +/** + * Internal dependencies + */ +import InserterListItem from '../inserter-list-item'; +import styles from './style.scss'; + +const MIN_COL_NUM = 3; + +export class BlockTypesList extends Component { + constructor() { + super( ...arguments ); + + this.onLayout = this.onLayout.bind( this ); + this.renderItem = this.renderItem.bind( this ); + + this.state = { + numberOfColumns: MIN_COL_NUM, + }; + + Dimensions.addEventListener( 'change', this.onLayout ); + } + + componentWillUnmount() { + Dimensions.removeEventListener( 'change', this.onLayout ); + } + + calculateMinItemWidth( bottomSheetWidth ) { + const { paddingLeft, paddingRight } = styles.columnPadding; + return ( + ( bottomSheetWidth - 2 * ( paddingLeft + paddingRight ) ) / + MIN_COL_NUM + ); + } + + calculateColumnsProperties() { + const bottomSheetWidth = BottomSheet.getWidth(); + const { paddingLeft, paddingRight } = styles.columnPadding; + const itemTotalWidth = InserterListItem.getWidth(); + const containerTotalWidth = + bottomSheetWidth - ( paddingLeft + paddingRight ); + const numofColumns = Math.floor( containerTotalWidth / itemTotalWidth ); + + if ( numofColumns < MIN_COL_NUM ) { + return { + numOfColumns: MIN_COL_NUM, + itemWidth: this.calculateMinItemWidth( bottomSheetWidth ), + maxWidth: containerTotalWidth / MIN_COL_NUM, + }; + } + return { + numOfColumns: numofColumns, + maxWidth: containerTotalWidth / numofColumns, + }; + } + + onLayout() { + const { + numOfColumns, + itemWidth, + maxWidth, + } = this.calculateColumnsProperties(); + const numberOfColumns = numOfColumns; + + this.setState( { numberOfColumns, itemWidth, maxWidth } ); + } + + renderItem( { item } ) { + const { onSelect } = this.props; + const { itemWidth, maxWidth } = this.state; + return ( + + ); + } + + render() { + const { name, items, listProps } = this.props; + const { numberOfColumns } = this.state; + + return ( + ( + + + + ) } + keyExtractor={ ( item ) => item.name } + renderItem={ this.renderItem } + { ...listProps } + /> + ); + } +} + +export default BlockTypesList; diff --git a/packages/block-editor/src/components/block-types-list/style.native.scss b/packages/block-editor/src/components/block-types-list/style.native.scss new file mode 100644 index 00000000000000..2499c0ff55dbc5 --- /dev/null +++ b/packages/block-editor/src/components/block-types-list/style.native.scss @@ -0,0 +1,7 @@ +.rowSeparator { + height: 12px; +} + +.columnPadding { + padding: $grid-unit-20; +} From 7c09b4ef70726123ec9487ba0ad6a0be3e572d5c Mon Sep 17 00:00:00 2001 From: Carlos Garcia Date: Tue, 15 Sep 2020 21:24:07 +0200 Subject: [PATCH 28/40] Add getWidth to mobile version of inserter-list-item component --- .../components/inserter-list-item/index.native.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/inserter-list-item/index.native.js b/packages/block-editor/src/components/inserter-list-item/index.native.js index 185d97963e4ae4..9d48c9db143c19 100644 --- a/packages/block-editor/src/components/inserter-list-item/index.native.js +++ b/packages/block-editor/src/components/inserter-list-item/index.native.js @@ -81,4 +81,17 @@ function InserterListItem( { ); } -export default withPreferredColorScheme( InserterListItem ); +function getWidth() { + const { + paddingLeft: itemPaddingLeft, + paddingRight: itemPaddingRight, + } = styles.modalItem; + const { width: itemWidth } = styles.modalIconWrapper; + return itemWidth + itemPaddingLeft + itemPaddingRight; +} + +const ThemedInserterListItem = withPreferredColorScheme( InserterListItem ); + +ThemedInserterListItem.getWidth = getWidth; + +export default ThemedInserterListItem; From 00f70370a4204f745b5aa2526e2a16666a25108d Mon Sep 17 00:00:00 2001 From: Carlos Garcia Date: Tue, 15 Sep 2020 21:36:03 +0200 Subject: [PATCH 29/40] Add blocks-tab mobile version to inserter component --- .../components/inserter/blocks-tab.native.js | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 packages/block-editor/src/components/inserter/blocks-tab.native.js diff --git a/packages/block-editor/src/components/inserter/blocks-tab.native.js b/packages/block-editor/src/components/inserter/blocks-tab.native.js new file mode 100644 index 00000000000000..c87794df258f50 --- /dev/null +++ b/packages/block-editor/src/components/inserter/blocks-tab.native.js @@ -0,0 +1,72 @@ +/** + * External dependencies + */ +import { pick } from 'lodash'; + +/** + * WordPress dependencies + */ +import { rawHandler } from '@wordpress/blocks'; +import { useSelect } from '@wordpress/data'; + +/** + * Internal dependencies + */ +import BlockTypesList from '../block-types-list'; + +const NON_BLOCK_CATEGORIES = [ 'reusable' ]; + +function BlocksTab( { onSelect, rootClientId, listProps } ) { + const { items } = useSelect( + ( select ) => { + const { + getInserterItems, + getSettings, + canInsertBlockType, + } = select( 'core/block-editor' ); + const { getBlockType } = select( 'core/blocks' ); + const { getClipboard } = select( 'core/editor' ); + + const clipboard = getClipboard(); + const clipboardBlock = + clipboard && rawHandler( { HTML: clipboard } )[ 0 ]; + const shouldAddClipboardBlock = + clipboardBlock && + canInsertBlockType( clipboardBlock.name, rootClientId ); + + const allItems = getInserterItems( rootClientId ); + const items = allItems.filter( + ( { category } ) => ! NON_BLOCK_CATEGORIES.includes( category ) + ); + + const itemsWithClipboard = shouldAddClipboardBlock + ? [ + { + ...pick( getBlockType( clipboardBlock.name ), [ + 'name', + 'icon', + ] ), + id: 'clipboard', + initialAttributes: clipboardBlock.attributes, + innerBlocks: clipboardBlock.innerBlocks, + }, + ...items, + ] + : items; + + return { items: itemsWithClipboard }; + }, + [ rootClientId ] + ); + + return ( + + ); +} + +export default BlocksTab; From f3dcfa413554b6eb7d08a66b70a50dacc7c95911 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Date: Tue, 15 Sep 2020 21:36:16 +0200 Subject: [PATCH 30/40] Add reusable-blocks-tab mobile version to inserter component --- .../inserter/reusable-blocks-tab.native.js | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 packages/block-editor/src/components/inserter/reusable-blocks-tab.native.js diff --git a/packages/block-editor/src/components/inserter/reusable-blocks-tab.native.js b/packages/block-editor/src/components/inserter/reusable-blocks-tab.native.js new file mode 100644 index 00000000000000..02ca18dc14f05d --- /dev/null +++ b/packages/block-editor/src/components/inserter/reusable-blocks-tab.native.js @@ -0,0 +1,50 @@ +/** + * WordPress dependencies + */ +import { useEffect } from '@wordpress/element'; +import { useSelect } from '@wordpress/data'; + +/** + * Internal dependencies + */ +import BlockTypesList from '../block-types-list'; + +const REUSABLE_BLOCKS_CATEGORY = 'reusable'; + +function ReusableBlocksTab( { onSelect, rootClientId, listProps } ) { + const { items, fetchReusableBlocks } = useSelect( + ( select ) => { + const { getInserterItems, getSettings } = select( + 'core/block-editor' + ); + const { __experimentalFetchReusableBlocks } = getSettings(); + const allItems = getInserterItems( rootClientId ); + const items = allItems.filter( + ( { category } ) => category === REUSABLE_BLOCKS_CATEGORY + ); + + return { + items, + fetchReusableBlocks: __experimentalFetchReusableBlocks, + }; + }, + [ rootClientId ] + ); + + useEffect( () => { + if ( fetchReusableBlocks ) { + fetchReusableBlocks(); + } + }, [] ); + + return ( + + ); +} + +export default ReusableBlocksTab; From 19ab89e0ca049cad5a5945ecfcdf1fe3cdab61a3 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Date: Tue, 15 Sep 2020 21:38:42 +0200 Subject: [PATCH 31/40] Inserter menu mobile version refactor to use new tabs --- .../block-types-list/index.native.js | 17 +- .../components/inserter/blocks-tab.native.js | 17 +- .../src/components/inserter/menu.native.js | 228 +++--------------- .../inserter/reusable-blocks-tab.native.js | 21 +- 4 files changed, 57 insertions(+), 226 deletions(-) diff --git a/packages/block-editor/src/components/block-types-list/index.native.js b/packages/block-editor/src/components/block-types-list/index.native.js index fecd0986fa0b95..67f4a6c42a7ba6 100644 --- a/packages/block-editor/src/components/block-types-list/index.native.js +++ b/packages/block-editor/src/components/block-types-list/index.native.js @@ -12,7 +12,7 @@ import { * WordPress dependencies */ import { Component } from '@wordpress/element'; -import { BottomSheet } from '@wordpress/components'; +import { BottomSheet, InserterButton } from '@wordpress/components'; /** * Internal dependencies @@ -48,10 +48,19 @@ export class BlockTypesList extends Component { ); } + calculateItemWidth() { + const { + paddingLeft: itemPaddingLeft, + paddingRight: itemPaddingRight, + } = InserterButton.Styles.modalItem; + const { width: itemWidth } = InserterButton.Styles.modalIconWrapper; + return itemWidth + itemPaddingLeft + itemPaddingRight; + } + calculateColumnsProperties() { const bottomSheetWidth = BottomSheet.getWidth(); const { paddingLeft, paddingRight } = styles.columnPadding; - const itemTotalWidth = InserterListItem.getWidth(); + const itemTotalWidth = this.calculateItemWidth(); const containerTotalWidth = bottomSheetWidth - ( paddingLeft + paddingRight ); const numofColumns = Math.floor( containerTotalWidth / itemTotalWidth ); @@ -81,10 +90,10 @@ export class BlockTypesList extends Component { } renderItem( { item } ) { - const { onSelect } = this.props; const { itemWidth, maxWidth } = this.state; + const { onSelect } = this.props; return ( - { - const { - getInserterItems, - getSettings, - canInsertBlockType, - } = select( 'core/block-editor' ); + const { getInserterItems, canInsertBlockType } = select( + 'core/block-editor' + ); const { getBlockType } = select( 'core/blocks' ); - const { getClipboard } = select( 'core/editor' ); const clipboard = getClipboard(); const clipboardBlock = @@ -35,10 +33,11 @@ function BlocksTab( { onSelect, rootClientId, listProps } ) { canInsertBlockType( clipboardBlock.name, rootClientId ); const allItems = getInserterItems( rootClientId ); - const items = allItems.filter( + const blockItems = allItems.filter( ( { category } ) => ! NON_BLOCK_CATEGORIES.includes( category ) ); + // Add copied blocks in the clipboard as extra items const itemsWithClipboard = shouldAddClipboardBlock ? [ { @@ -50,9 +49,9 @@ function BlocksTab( { onSelect, rootClientId, listProps } ) { initialAttributes: clipboardBlock.attributes, innerBlocks: clipboardBlock.innerBlocks, }, - ...items, + ...blockItems, ] - : items; + : blockItems; return { items: itemsWithClipboard }; }, diff --git a/packages/block-editor/src/components/inserter/menu.native.js b/packages/block-editor/src/components/inserter/menu.native.js index 9d38883052affa..46db69fc3c40c8 100644 --- a/packages/block-editor/src/components/inserter/menu.native.js +++ b/packages/block-editor/src/components/inserter/menu.native.js @@ -6,60 +6,41 @@ import { __ } from '@wordpress/i18n'; /** * External dependencies */ -import { - FlatList, - View, - TouchableHighlight, - TouchableWithoutFeedback, - Dimensions, -} from 'react-native'; -import { pick } from 'lodash'; +import { TouchableHighlight } from 'react-native'; /** * WordPress dependencies */ import { Component } from '@wordpress/element'; -import { - createBlock, - rawHandler, - store as blocksStore, -} from '@wordpress/blocks'; +import { createBlock, store as blocksStore } from '@wordpress/blocks'; import { withDispatch, withSelect } from '@wordpress/data'; import { withInstanceId, compose } from '@wordpress/compose'; import { BottomSheet, BottomSheetConsumer, - InserterButton, - getClipboard, SegmentedControl, } from '@wordpress/components'; /** * Internal dependencies */ +import BlocksTab from './blocks-tab'; +import ReusableBlocksTab from './reusable-blocks-tab'; import styles from './style.scss'; -const MIN_COL_NUM = 3; -const TABS = [ __( 'Child Blocks' ), __( 'Reusable blocks' ) ]; +const TABS = [ __( 'Blocks' ), __( 'Reusable' ) ]; +const REUSABLE_BLOCKS_CATEGORY = 'reusable'; export class InserterMenu extends Component { constructor() { super( ...arguments ); this.onClose = this.onClose.bind( this ); - this.onLayout = this.onLayout.bind( this ); this.onChangeTab = this.onChangeTab.bind( this ); - this.renderItem = this.renderItem.bind( this ); - this.renderBlocksTab = this.renderBlocksTab.bind( this ); - this.renderReusableBlocksTab = this.renderReusableBlocksTab.bind( - this - ); + this.renderTabs = this.renderTabs.bind( this ); this.state = { - numberOfColumns: MIN_COL_NUM, tab: 0, }; - - Dimensions.addEventListener( 'change', this.onLayout ); } componentDidMount() { @@ -68,45 +49,6 @@ export class InserterMenu extends Component { componentWillUnmount() { this.props.hideInsertionPoint(); - Dimensions.removeEventListener( 'change', this.onLayout ); - } - - calculateMinItemWidth( bottomSheetWidth ) { - const { paddingLeft, paddingRight } = styles.columnPadding; - return ( - ( bottomSheetWidth - 2 * ( paddingLeft + paddingRight ) ) / - MIN_COL_NUM - ); - } - - calculateItemWidth() { - const { - paddingLeft: itemPaddingLeft, - paddingRight: itemPaddingRight, - } = InserterButton.Styles.modalItem; - const { width: itemWidth } = InserterButton.Styles.modalIconWrapper; - return itemWidth + itemPaddingLeft + itemPaddingRight; - } - - calculateColumnsProperties() { - const bottomSheetWidth = BottomSheet.getWidth(); - const { paddingLeft, paddingRight } = styles.columnPadding; - const itemTotalWidth = this.calculateItemWidth(); - const containerTotalWidth = - bottomSheetWidth - ( paddingLeft + paddingRight ); - const numofColumns = Math.floor( containerTotalWidth / itemTotalWidth ); - - if ( numofColumns < MIN_COL_NUM ) { - return { - numOfColumns: MIN_COL_NUM, - itemWidth: this.calculateMinItemWidth( bottomSheetWidth ), - maxWidth: containerTotalWidth / MIN_COL_NUM, - }; - } - return { - numOfColumns: numofColumns, - maxWidth: containerTotalWidth / numofColumns, - }; } onClose() { @@ -118,132 +60,32 @@ export class InserterMenu extends Component { this.props.onDismiss(); } - onLayout() { - const { - numOfColumns, - itemWidth, - maxWidth, - } = this.calculateColumnsProperties(); - const numberOfColumns = numOfColumns; - - this.setState( { numberOfColumns, itemWidth, maxWidth } ); - } - onChangeTab( tab ) { this.setState( { tab: TABS.indexOf( tab ) } ); } - /** - * Processes the inserter items to check - * if there's any copied block in the clipboard - * to add it as an extra item - */ - getBlockItems() { - const { - items, - canInsertBlockType, - destinationRootClientId, - getBlockType, - } = this.props; - - // Filter out reusable blocks (they will be added in another tab) - const blockItems = items.filter( - ( { name } ) => name !== 'core/block' - ); - - const clipboard = getClipboard(); - const clipboardBlock = - clipboard && rawHandler( { HTML: clipboard } )[ 0 ]; - const shouldAddClipboardBlock = - clipboardBlock && - canInsertBlockType( clipboardBlock.name, destinationRootClientId ); - - return shouldAddClipboardBlock - ? [ - { - ...pick( getBlockType( clipboardBlock.name ), [ - 'name', - 'icon', - ] ), - id: 'clipboard', - initialAttributes: clipboardBlock.attributes, - innerBlocks: clipboardBlock.innerBlocks, - }, - ...blockItems, - ] - : blockItems; - } - - getReusableBlockItems() { - const { items } = this.props; - - return items.filter( ( { name } ) => name === 'core/block' ); - } - - renderItem( { item } ) { - const { itemWidth, maxWidth } = this.state; - const { onSelect } = this.props; - return ( - - ); - } - - renderBlocksTab( listProps ) { - const { numberOfColumns } = this.state; - const items = this.getBlockItems(); - - return ( - ( - - - - ) } - keyExtractor={ ( item ) => item.name } - renderItem={ this.renderItem } - { ...listProps } - /> - ); - } + renderTabs( { listProps } ) { + const { onSelect, destinationRootClientId } = this.props; + const { tab } = this.state; - renderReusableBlocksTab( listProps ) { - const { numberOfColumns } = this.state; - const items = this.getReusableBlockItems(); + const tabProps = { + rootClientId: destinationRootClientId, + onSelect, + listProps, + }; - return ( - ( - - - - ) } - keyExtractor={ ( item ) => item.name } - renderItem={ this.renderItem } - { ...listProps } - /> - ); + switch ( tab ) { + case 0: + return ; + case 1: + return ; + } } render() { - const { tab } = this.state; - const reusableBlockItems = this.getReusableBlockItems(); + const { hasReusableBlocks } = this.props; - const hideHeader = reusableBlockItems.length === 0; + const hideHeader = ! hasReusableBlocks; return ( - { ( { listProps } ) => { - switch ( tab ) { - case 0: - return this.renderBlocksTab( listProps ); - case 1: - return this.renderReusableBlocksTab( - listProps - ); - } - } } + { this.renderTabs } @@ -287,9 +120,8 @@ export default compose( getBlockRootClientId, getBlockSelectionEnd, getSettings, - canInsertBlockType, } = select( 'core/block-editor' ); - const { getChildBlockNames, getBlockType } = select( blocksStore ); + const { getChildBlockNames } = select( blocksStore ); let destinationRootClientId = rootClientId; if ( ! destinationRootClientId && ! clientId && ! isAppender ) { @@ -307,13 +139,17 @@ export default compose( __experimentalShouldInsertAtTheTop: shouldInsertAtTheTop, } = getSettings(); + const items = getInserterItems( destinationRootClientId ); + const reusableBlockItems = items.filter( + ( { category } ) => category === REUSABLE_BLOCKS_CATEGORY + ); + return { rootChildBlocks: getChildBlockNames( destinationRootBlockName ), - items: getInserterItems( destinationRootClientId ), + items, + hasReusableBlocks: !! reusableBlockItems.length, destinationRootClientId, shouldInsertAtTheTop, - getBlockType, - canInsertBlockType, }; } ), withDispatch( ( dispatch, ownProps, { select } ) => { diff --git a/packages/block-editor/src/components/inserter/reusable-blocks-tab.native.js b/packages/block-editor/src/components/inserter/reusable-blocks-tab.native.js index 02ca18dc14f05d..e5fb79717af021 100644 --- a/packages/block-editor/src/components/inserter/reusable-blocks-tab.native.js +++ b/packages/block-editor/src/components/inserter/reusable-blocks-tab.native.js @@ -1,7 +1,6 @@ /** * WordPress dependencies */ -import { useEffect } from '@wordpress/element'; import { useSelect } from '@wordpress/data'; /** @@ -12,31 +11,19 @@ import BlockTypesList from '../block-types-list'; const REUSABLE_BLOCKS_CATEGORY = 'reusable'; function ReusableBlocksTab( { onSelect, rootClientId, listProps } ) { - const { items, fetchReusableBlocks } = useSelect( + const { items } = useSelect( ( select ) => { - const { getInserterItems, getSettings } = select( - 'core/block-editor' - ); - const { __experimentalFetchReusableBlocks } = getSettings(); + const { getInserterItems } = select( 'core/block-editor' ); const allItems = getInserterItems( rootClientId ); - const items = allItems.filter( + const reusableBlockItems = allItems.filter( ( { category } ) => category === REUSABLE_BLOCKS_CATEGORY ); - return { - items, - fetchReusableBlocks: __experimentalFetchReusableBlocks, - }; + return { items: reusableBlockItems }; }, [ rootClientId ] ); - useEffect( () => { - if ( fetchReusableBlocks ) { - fetchReusableBlocks(); - } - }, [] ); - return ( Date: Fri, 18 Sep 2020 21:30:14 +0200 Subject: [PATCH 32/40] Lint fixes in inserter menu components --- .../src/components/inserter-list-item/index.native.js | 1 - .../block-editor/src/components/inserter/blocks-tab.native.js | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/block-editor/src/components/inserter-list-item/index.native.js b/packages/block-editor/src/components/inserter-list-item/index.native.js index 9d48c9db143c19..c69912f1ae4ed4 100644 --- a/packages/block-editor/src/components/inserter-list-item/index.native.js +++ b/packages/block-editor/src/components/inserter-list-item/index.native.js @@ -6,7 +6,6 @@ import { View, TouchableHighlight, Text } from 'react-native'; /** * WordPress dependencies */ -import { Component } from '@wordpress/element'; import { Icon } from '@wordpress/components'; import { withPreferredColorScheme } from '@wordpress/compose'; import { __ } from '@wordpress/i18n'; diff --git a/packages/block-editor/src/components/inserter/blocks-tab.native.js b/packages/block-editor/src/components/inserter/blocks-tab.native.js index 0da95cb6b00d01..d00683d5ad10cf 100644 --- a/packages/block-editor/src/components/inserter/blocks-tab.native.js +++ b/packages/block-editor/src/components/inserter/blocks-tab.native.js @@ -38,7 +38,7 @@ function BlocksTab( { onSelect, rootClientId, listProps } ) { ); // Add copied blocks in the clipboard as extra items - const itemsWithClipboard = shouldAddClipboardBlock + const blockItemsWithClipboard = shouldAddClipboardBlock ? [ { ...pick( getBlockType( clipboardBlock.name ), [ @@ -53,7 +53,7 @@ function BlocksTab( { onSelect, rootClientId, listProps } ) { ] : blockItems; - return { items: itemsWithClipboard }; + return { items: blockItemsWithClipboard }; }, [ rootClientId ] ); From 6e04f7c2cf775da58dd9dd97499d6c09f986cef4 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Date: Mon, 21 Sep 2020 20:08:48 +0200 Subject: [PATCH 33/40] README of block-types-list component updated with mobile changes --- .../src/components/block-types-list/README.md | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/block-types-list/README.md b/packages/block-editor/src/components/block-types-list/README.md index a074d730b73284..07f41ae154dbde 100644 --- a/packages/block-editor/src/components/block-types-list/README.md +++ b/packages/block-editor/src/components/block-types-list/README.md @@ -24,7 +24,7 @@ Renders a list of blocks types. ```jsx import { BlockTypesList } from '@wordpress/block-editor'; -const MyBlockTypesList = () => ;; +const MyBlockTypesList = () => ; ``` ### Props @@ -35,6 +35,25 @@ The blocks that will be displayed in the block list. - Type: `Array` - Required: Yes +- Platform: Web | Mobile + +#### name + +Name of the list to be used as part of component's key. + +- Type: `String` +- Required: Yes +- Platform: Mobile + +#### listProps + +Extra `FlatList` props for customizing the list. + +On Mobile usually this component is rendered inside `BottomSheet` component, which already [generates these props](<(https://github.com/WordPress/gutenberg/blob/c3c514ba1123be5a7cf881c223c038cfc31b3f59/packages/components/src/mobile/bottom-sheet/index.native.js#L335-L354)>) for this component. + +- Type: `String` +- Required: No +- Platform: Mobile ## Related components From f3ef8323c2d0e4317f94181f52c25975b36e55ca Mon Sep 17 00:00:00 2001 From: Carlos Garcia Date: Mon, 21 Sep 2020 20:20:54 +0200 Subject: [PATCH 34/40] modal prefix removed from inserter-list-item style names --- .../inserter-list-item/index.native.js | 33 +++++++++---------- .../inserter-list-item/style.native.scss | 12 +++---- 2 files changed, 21 insertions(+), 24 deletions(-) diff --git a/packages/block-editor/src/components/inserter-list-item/index.native.js b/packages/block-editor/src/components/inserter-list-item/index.native.js index c69912f1ae4ed4..9bda34d3c8f558 100644 --- a/packages/block-editor/src/components/inserter-list-item/index.native.js +++ b/packages/block-editor/src/components/inserter-list-item/index.native.js @@ -26,17 +26,14 @@ function InserterListItem( { onSelect( item ); }; - const modalIconWrapperStyle = getStylesFromColorScheme( - styles.modalIconWrapper, - styles.modalIconWrapperDark + const iconWrapperStyle = getStylesFromColorScheme( + styles.iconWrapper, + styles.iconWrapperDark ); - const modalIconStyle = getStylesFromColorScheme( - styles.modalIcon, - styles.modalIconDark - ); - const modalItemLabelStyle = getStylesFromColorScheme( - styles.modalItemLabel, - styles.modalItemLabelDark + const iconStyle = getStylesFromColorScheme( styles.icon, styles.iconDark ); + const itemLabelStyle = getStylesFromColorScheme( + styles.itemLabel, + styles.itemLabelDark ); const clipboardBlockStyles = getStylesFromColorScheme( @@ -54,25 +51,25 @@ function InserterListItem( { accessibilityLabel={ item.title } onPress={ onPress } > - + - + - + { isClipboardBlock ? __( 'Copied block' ) : item.title } @@ -84,8 +81,8 @@ function getWidth() { const { paddingLeft: itemPaddingLeft, paddingRight: itemPaddingRight, - } = styles.modalItem; - const { width: itemWidth } = styles.modalIconWrapper; + } = styles.item; + const { width: itemWidth } = styles.iconWrapper; return itemWidth + itemPaddingLeft + itemPaddingRight; } diff --git a/packages/block-editor/src/components/inserter-list-item/style.native.scss b/packages/block-editor/src/components/inserter-list-item/style.native.scss index 48836bf4888475..425a29eddc7cf2 100644 --- a/packages/block-editor/src/components/inserter-list-item/style.native.scss +++ b/packages/block-editor/src/components/inserter-list-item/style.native.scss @@ -2,7 +2,7 @@ border-radius: 8px 8px 8px 8px; } -.modalItem { +.item { flex-direction: column; justify-content: flex-start; align-items: center; @@ -12,7 +12,7 @@ padding-bottom: 0; } -.modalIconWrapper { +.iconWrapper { width: 104px; height: 64px; background-color: $gray-light; //#f3f6f8 @@ -25,7 +25,7 @@ background-color: rgba( $white, 0.07 ); } -.modalIcon { +.icon { width: 32px; height: 32px; justify-content: center; @@ -33,11 +33,11 @@ fill: $gray-dark; } -.modalIconDark { +.iconDark { fill: $white; } -.modalItemLabel { +.itemLabel { background-color: transparent; padding-left: 2; padding-right: 2; @@ -48,7 +48,7 @@ color: $gray-dark; } -.modalItemLabelDark { +.itemLabelDark { color: $white; } From 0839f54d041e6ff2e2662a20d32959ef1325c550 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Date: Mon, 21 Sep 2020 20:24:26 +0200 Subject: [PATCH 35/40] blocks-tab renamed to block-types-tab in inserter menu --- .../{blocks-tab.native.js => blocks-types-tab.native.js} | 0 packages/block-editor/src/components/inserter/menu.native.js | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) rename packages/block-editor/src/components/inserter/{blocks-tab.native.js => blocks-types-tab.native.js} (100%) diff --git a/packages/block-editor/src/components/inserter/blocks-tab.native.js b/packages/block-editor/src/components/inserter/blocks-types-tab.native.js similarity index 100% rename from packages/block-editor/src/components/inserter/blocks-tab.native.js rename to packages/block-editor/src/components/inserter/blocks-types-tab.native.js diff --git a/packages/block-editor/src/components/inserter/menu.native.js b/packages/block-editor/src/components/inserter/menu.native.js index 46db69fc3c40c8..6f9f7073e974a9 100644 --- a/packages/block-editor/src/components/inserter/menu.native.js +++ b/packages/block-editor/src/components/inserter/menu.native.js @@ -24,7 +24,7 @@ import { /** * Internal dependencies */ -import BlocksTab from './blocks-tab'; +import BlocksTypesTab from './blocks-types-tab'; import ReusableBlocksTab from './reusable-blocks-tab'; import styles from './style.scss'; @@ -76,7 +76,7 @@ export class InserterMenu extends Component { switch ( tab ) { case 0: - return ; + return ; case 1: return ; } From 035bd156a2d11a6cd15872c35a0a2d3f12eeeee2 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Date: Mon, 21 Sep 2020 21:18:35 +0200 Subject: [PATCH 36/40] add block-types-tab UI test --- .../inserter/test/block-types-tab.native.js | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 packages/block-editor/src/components/inserter/test/block-types-tab.native.js diff --git a/packages/block-editor/src/components/inserter/test/block-types-tab.native.js b/packages/block-editor/src/components/inserter/test/block-types-tab.native.js new file mode 100644 index 00000000000000..4992e3f8a99fde --- /dev/null +++ b/packages/block-editor/src/components/inserter/test/block-types-tab.native.js @@ -0,0 +1,63 @@ +/** + * External dependencies + */ +import { shallow } from 'enzyme'; + +/** + * WordPress dependencies + */ +import { useSelect } from '@wordpress/data'; + +/** + * Internal dependencies + */ +import items from './fixtures'; +import BlocksTypesTab from '../blocks-types-tab'; +import BlocksTypesList from '../../block-types-list'; + +jest.mock( '../../block-types-list' ); +jest.mock( '@wordpress/data/src/components/use-select' ); + +const selectMock = { + getInserterItems: jest.fn().mockReturnValue( [] ), + canInsertBlockType: jest.fn(), + getBlockType: jest.fn(), + getClipboard: jest.fn(), +}; + +describe( 'BlocksTypesTab component', () => { + beforeEach( () => { + useSelect.mockImplementation( ( callback ) => + callback( () => selectMock ) + ); + } ); + + it( 'renders without crashing', () => { + const component = shallow( + + ); + expect( component ).toBeTruthy(); + } ); + + it( 'shows block items', () => { + selectMock.getInserterItems.mockReturnValue( items ); + + const blockItems = items.filter( + ( { category } ) => category !== 'reusable' + ); + const component = shallow( + + ); + expect( component.find( BlocksTypesList ).prop( 'items' ) ).toEqual( + blockItems + ); + } ); +} ); From 0358fa27463aee0ed63411ef53471cb5106740b3 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Date: Tue, 22 Sep 2020 21:04:23 +0200 Subject: [PATCH 37/40] Add reusable-blocks-tab UI test --- .../test/reusable-blocks-tab.native.js | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 packages/block-editor/src/components/inserter/test/reusable-blocks-tab.native.js diff --git a/packages/block-editor/src/components/inserter/test/reusable-blocks-tab.native.js b/packages/block-editor/src/components/inserter/test/reusable-blocks-tab.native.js new file mode 100644 index 00000000000000..d8eac0853060f8 --- /dev/null +++ b/packages/block-editor/src/components/inserter/test/reusable-blocks-tab.native.js @@ -0,0 +1,64 @@ +/** + * External dependencies + */ +import { shallow } from 'enzyme'; + +/** + * WordPress dependencies + */ +import { useSelect } from '@wordpress/data'; + +/** + * Internal dependencies + */ +import items from './fixtures'; +import ReusableBlocksTab from '../reusable-blocks-tab'; +import BlocksTypesList from '../../block-types-list'; + +jest.mock( '../../block-types-list' ); +jest.mock( '@wordpress/data/src/components/use-select' ); + +const fetchReusableBlocks = jest.fn(); +const selectMock = { + getInserterItems: jest.fn().mockReturnValue( [] ), + getSettings: jest.fn().mockReturnValue( { + __experimentalFetchReusableBlocks: fetchReusableBlocks, + } ), +}; + +describe( 'ReusableBlocksTab component', () => { + beforeEach( () => { + useSelect.mockImplementation( ( callback ) => + callback( () => selectMock ) + ); + } ); + + it( 'renders without crashing', () => { + const component = shallow( + + ); + expect( component ).toBeTruthy(); + } ); + + it( 'shows reusable block items', () => { + selectMock.getInserterItems.mockReturnValue( items ); + + const reusableBlockItems = items.filter( + ( { category } ) => category === 'reusable' + ); + const component = shallow( + + ); + expect( component.find( BlocksTypesList ).prop( 'items' ) ).toEqual( + reusableBlockItems + ); + } ); +} ); From e53c31ce594923c5c946711b7dd2c0363e5c526a Mon Sep 17 00:00:00 2001 From: Carlos Garcia Date: Fri, 2 Oct 2020 21:54:08 +0200 Subject: [PATCH 38/40] Remove unused import from block types list --- .../block-editor/src/components/block-types-list/index.native.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/block-editor/src/components/block-types-list/index.native.js b/packages/block-editor/src/components/block-types-list/index.native.js index 67f4a6c42a7ba6..dcf58cab118ebd 100644 --- a/packages/block-editor/src/components/block-types-list/index.native.js +++ b/packages/block-editor/src/components/block-types-list/index.native.js @@ -17,7 +17,6 @@ import { BottomSheet, InserterButton } from '@wordpress/components'; /** * Internal dependencies */ -import InserterListItem from '../inserter-list-item'; import styles from './style.scss'; const MIN_COL_NUM = 3; From 135e06bd6c5b2f3c20070b41d51866db4cc93bb9 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Date: Mon, 4 Jan 2021 16:45:51 +0100 Subject: [PATCH 39/40] Change key calculation for block types list component Block name's field was being used which is not unique so it has been changed to id field. --- .../src/components/block-types-list/index.native.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/block-types-list/index.native.js b/packages/block-editor/src/components/block-types-list/index.native.js index dcf58cab118ebd..249a8a74db1304 100644 --- a/packages/block-editor/src/components/block-types-list/index.native.js +++ b/packages/block-editor/src/components/block-types-list/index.native.js @@ -117,7 +117,7 @@ export class BlockTypesList extends Component { ) } - keyExtractor={ ( item ) => item.name } + keyExtractor={ ( item ) => item.id } renderItem={ this.renderItem } { ...listProps } /> From f1c8224a1be5e42dffa30025bdaabfcf83794845 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Date: Mon, 4 Jan 2021 16:50:34 +0100 Subject: [PATCH 40/40] Fix style format issue in inserter list item --- .../src/components/inserter-list-item/style.native.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/inserter-list-item/style.native.scss b/packages/block-editor/src/components/inserter-list-item/style.native.scss index 425a29eddc7cf2..2b00725f63c3f5 100644 --- a/packages/block-editor/src/components/inserter-list-item/style.native.scss +++ b/packages/block-editor/src/components/inserter-list-item/style.native.scss @@ -22,7 +22,7 @@ } .modalIconWrapperDark { - background-color: rgba( $white, 0.07 ); + background-color: rgba($white, 0.07); } .icon {