From 0c8b6d6572b1a0c5864004095b0c3b3f3e841f19 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Date: Fri, 11 Aug 2023 18:06:01 +0200 Subject: [PATCH 01/15] Prevent rendering deeply nested block list --- .../src/components/block-list/index.native.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/packages/block-editor/src/components/block-list/index.native.js b/packages/block-editor/src/components/block-list/index.native.js index 810e23e4c1442..81e4cb037c4b3 100644 --- a/packages/block-editor/src/components/block-list/index.native.js +++ b/packages/block-editor/src/components/block-list/index.native.js @@ -30,6 +30,9 @@ import { import { BlockDraggableWrapper } from '../block-draggable'; import { useEditorWrapperStyles } from '../../hooks/use-editor-wrapper-styles'; import { store as blockEditorStore } from '../../store'; +import Warning from '../warning'; + +const MAX_DEEP_NESTING_LEVEL = 10; const identity = ( x ) => x; @@ -78,9 +81,11 @@ export default function BlockList( { isStackedHorizontally, maxWidth, isRTL, + nestingLevel, } = useSelect( ( select ) => { const { + getBlockParents, getBlockCount, getBlockHierarchyRootClientId, getBlockOrder, @@ -118,6 +123,7 @@ export default function BlockList( { isStackedHorizontally: orientation === 'horizontal', maxWidth: maxWidthSetting, isRTL: isRTLSetting, + nestingLevel: getBlockParents( rootClientId ).length, }; }, [ filterInnerBlocks, orientation, rootClientId ] @@ -228,6 +234,15 @@ export default function BlockList( { blockToolbar.height + ( isFloatingToolbarVisible ? floatingToolbar.height : 0 ); + if ( nestingLevel >= MAX_DEEP_NESTING_LEVEL ) { + return ( + + ); + } return ( Date: Mon, 11 Sep 2023 19:13:29 +0200 Subject: [PATCH 02/15] Add `BlockFallbackWebVersion` component --- .../index.native.js | 207 ++++++++++++++++++ .../style.native.scss | 56 +++++ .../src/components/index.native.js | 1 + 3 files changed, 264 insertions(+) create mode 100644 packages/block-editor/src/components/block-fallback-web-version/index.native.js create mode 100644 packages/block-editor/src/components/block-fallback-web-version/style.native.scss diff --git a/packages/block-editor/src/components/block-fallback-web-version/index.native.js b/packages/block-editor/src/components/block-fallback-web-version/index.native.js new file mode 100644 index 0000000000000..04ef3fdf18e06 --- /dev/null +++ b/packages/block-editor/src/components/block-fallback-web-version/index.native.js @@ -0,0 +1,207 @@ +/** + * External dependencies + */ +import { View, Text } from 'react-native'; + +/** + * WordPress dependencies + */ +import { BottomSheet, Icon, TextControl } from '@wordpress/components'; +import { + requestUnsupportedBlockFallback, + sendActionButtonPressedAction, + actionButtons, +} from '@wordpress/react-native-bridge'; +import { help } from '@wordpress/icons'; +import { __ } from '@wordpress/i18n'; +import { useSelect } from '@wordpress/data'; +import { usePreferredColorSchemeStyle } from '@wordpress/compose'; +import { getBlockType, serialize } from '@wordpress/blocks'; +import { useCallback, useState } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import styles from './style.scss'; +import { store as blockEditorStore } from '../../store'; + +// Blocks that can't be edited through the Unsupported block editor identified by their name. +const UBE_INCOMPATIBLE_BLOCKS = [ 'core/block' ]; +const EMPTY_ARRAY = []; + +const BlockFallbackWebVersion = ( { + clientId, + showSheet, + onCloseSheet, + customBlockTitle = '', + icon, + title, + description, + actionButtonLabel, + customActions = EMPTY_ARRAY, +} ) => { + const [ sendFallbackMessage, setSendFallbackMessage ] = useState( false ); + const [ sendButtonPressMessage, setSendButtonPressMessage ] = + useState( false ); + + const { + blockName, + blockContent, + isUnsupportedBlockEditorSupported, + canEnableUnsupportedBlockEditor, + isEditableInUnsupportedBlockEditor, + } = useSelect( + ( select ) => { + const { getBlock, getSettings } = select( blockEditorStore ); + const { capabilities } = getSettings(); + + const block = getBlock( clientId ); + const blockAttributes = block?.attributes || {}; + + const blockDetails = { + blockName: block?.name, + blockContent: serialize( block ? [ block ] : [] ), + }; + + // If the block is unsupported, use the `original` attributes to identify the block's name. + if ( blockDetails.blockName === 'core/missing' ) { + blockDetails.blockName = blockAttributes.originalName; + blockDetails.blockContent = + blockDetails.blockName === 'core/freeform' + ? blockAttributes.content + : block?.originalContent; + } + + return { + isUnsupportedBlockEditorSupported: + capabilities?.unsupportedBlockEditor === true, + canEnableUnsupportedBlockEditor: + capabilities?.canEnableUnsupportedBlockEditor === true, + isEditableInUnsupportedBlockEditor: + ! UBE_INCOMPATIBLE_BLOCKS.includes( + blockDetails.blockName + ), + ...blockDetails, + }; + }, + [ clientId ] + ); + + // Styles + const textStyle = usePreferredColorSchemeStyle( + styles.sheet__text, + styles[ 'sheet__text--dark' ] + ); + const titleStyle = usePreferredColorSchemeStyle( + styles.sheet__title, + styles[ 'sheet__title--dark' ] + ); + const descriptionStyle = usePreferredColorSchemeStyle( + styles.sheet__description, + styles[ 'sheet__description--dark' ] + ); + const iconStyle = usePreferredColorSchemeStyle( + styles.sheet__icon, + styles[ 'sheet__icon--dark' ] + ); + const actionButtonStyle = usePreferredColorSchemeStyle( + styles[ 'sheet__action-button' ], + styles[ 'sheet__action-button--dark' ] + ); + + const blockTitle = + customBlockTitle || getBlockType( blockName )?.title || blockName; + + const requestFallback = useCallback( () => { + if ( + canEnableUnsupportedBlockEditor && + isUnsupportedBlockEditorSupported === false + ) { + onCloseSheet(); + setSendButtonPressMessage( true ); + } else { + onCloseSheet(); + setSendFallbackMessage( true ); + } + }, [ + canEnableUnsupportedBlockEditor, + isUnsupportedBlockEditorSupported, + onCloseSheet, + ] ); + + const canUseWebEditor = + ( isUnsupportedBlockEditorSupported || + canEnableUnsupportedBlockEditor ) && + isEditableInUnsupportedBlockEditor; + const actions = [ + ...[ + canUseWebEditor && { + label: actionButtonLabel || __( 'Edit using web editor' ), + onPress: requestFallback, + }, + ], + ...customActions, + ].filter( Boolean ); + + return ( + { + 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( () => { + // For the Classic block, the content is kept in the `content` attribute. + requestUnsupportedBlockFallback( + blockContent, + clientId, + blockName, + blockTitle + ); + }, 100 ); + setSendFallbackMessage( false ); + } else if ( sendButtonPressMessage ) { + this.timeout = setTimeout( () => { + sendActionButtonPressedAction( + actionButtons.missingBlockAlertActionButton + ); + }, 100 ); + setSendButtonPressMessage( false ); + } + } } + > + + + { title } + { isEditableInUnsupportedBlockEditor && description && ( + + { description } + + ) } + + { actions.map( ( { label, onPress }, index ) => ( + + ) ) } + + + ); +}; + +export default BlockFallbackWebVersion; diff --git a/packages/block-editor/src/components/block-fallback-web-version/style.native.scss b/packages/block-editor/src/components/block-fallback-web-version/style.native.scss new file mode 100644 index 0000000000000..7e83c4150db9b --- /dev/null +++ b/packages/block-editor/src/components/block-fallback-web-version/style.native.scss @@ -0,0 +1,56 @@ +.sheet__container { + flex-direction: column; + align-items: center; + justify-content: flex-end; +} + +.sheet__icon { + size: 36; + height: 36; + padding-top: 8; + padding-bottom: 8; + color: $gray; +} + +.sheet__icon--dark { + color: $gray-20; +} + +.sheet__text { + text-align: center; + color: $gray-dark; +} + +.sheet__text--dark { + color: $white; +} + +.sheet__title { + padding-top: 8; + padding-bottom: 12; + font-size: 20; + font-weight: bold; + color: $gray-dark; +} + +.sheet__title--dark { + color: $white; +} + +.sheet__description { + padding-bottom: 24; + font-size: 16; + color: $gray-darken-20; +} + +.sheet__description--dark { + color: $gray-20; +} + +.sheet__action-button { + color: $blue-50; +} + +.sheet__action-button--dark { + color: $blue-30; +} diff --git a/packages/block-editor/src/components/index.native.js b/packages/block-editor/src/components/index.native.js index 1f675daaa8ca1..1032590d39677 100644 --- a/packages/block-editor/src/components/index.native.js +++ b/packages/block-editor/src/components/index.native.js @@ -91,6 +91,7 @@ export { default as __unstableEditorStyles } from './editor-styles'; export { default as Inserter } from './inserter'; export { useBlockProps } from './block-list/use-block-props'; export { default as FloatingToolbar } from './floating-toolbar'; +export { default as BlockFallbackWebVersion } from './block-fallback-web-version'; // State Related Components. export { default as BlockEditorProvider } from './provider'; From d61890ba88f1df0d20fe5097fa49cac8146ad98e Mon Sep 17 00:00:00 2001 From: Carlos Garcia Date: Mon, 11 Sep 2023 19:14:25 +0200 Subject: [PATCH 03/15] Add `WarningMaxDepthExceeded` component --- .../warning-max-depth-exceeded.native.js | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 packages/block-editor/src/components/inner-blocks/warning-max-depth-exceeded.native.js diff --git a/packages/block-editor/src/components/inner-blocks/warning-max-depth-exceeded.native.js b/packages/block-editor/src/components/inner-blocks/warning-max-depth-exceeded.native.js new file mode 100644 index 0000000000000..662dd9160b762 --- /dev/null +++ b/packages/block-editor/src/components/inner-blocks/warning-max-depth-exceeded.native.js @@ -0,0 +1,84 @@ +/** + * External dependencies + */ +import { TouchableWithoutFeedback, View } from 'react-native'; + +/** + * WordPress dependencies + */ +import { __, sprintf } from '@wordpress/i18n'; +import { useState } from '@wordpress/element'; +import { useDispatch, useSelect } from '@wordpress/data'; + +/** + * Internal dependencies + */ +import Warning from '../warning'; +import BlockFallbackWebVersion from '../block-fallback-web-version'; +import { store as blockEditorStore } from '../../store'; + +const WarningMaxDepthExceeded = ( { clientId } ) => { + const [ showDetails, setShowDetails ] = useState( false ); + + const { isSelected, innerBlocks } = useSelect( + ( select ) => { + const { getBlock, isBlockSelected } = select( blockEditorStore ); + return { + innerBlocks: getBlock( clientId )?.innerBlocks || [], + isSelected: isBlockSelected( clientId ), + }; + }, + [ clientId ] + ); + const { replaceBlocks } = useDispatch( blockEditorStore ); + + const onUngroup = () => { + if ( ! innerBlocks.length ) { + return; + } + + replaceBlocks( clientId, innerBlocks ); + }; + + /* translators: Warning related to having blocks deeply nested. %d: The deepest nesting level. */ + const descriptionFormat = __( + 'Blocks with inner blocks that are nested deeper than %d levels might not be rendered properly in the native version of the editor. For this reason, we recommend flattening the content by ungrouping the block or editing the block using the web editor.' + ); + const description = sprintf( descriptionFormat, MAX_NESTING_DEPTH ); + + return ( + setShowDetails( true ) } + > + + + setShowDetails( false ) } + title={ __( 'Block deeply nested' ) } + description={ description } + customActions={ [ + { label: __( 'Ungroup block' ), onPress: onUngroup }, + ] } + /> + + + ); +}; + +// Hermes has a limit for the call stack depth to avoid infinite recursion. +// When creating a deep nested structure of inner blocks, the editor might exceed +// this limit and crash. In order to avoid this, we set a maximum depth level where +// we stop rendering blocks. +export const MAX_NESTING_DEPTH = 10; + +export default WarningMaxDepthExceeded; From e028e9ada1c06cb8e31e9b848e492ad37422ba65 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Date: Mon, 11 Sep 2023 19:15:30 +0200 Subject: [PATCH 04/15] Add max depth warning in inner blocks component --- .../src/components/block-list/index.native.js | 15 --------------- .../src/components/inner-blocks/index.native.js | 16 ++++++++++++++++ 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/packages/block-editor/src/components/block-list/index.native.js b/packages/block-editor/src/components/block-list/index.native.js index 81e4cb037c4b3..810e23e4c1442 100644 --- a/packages/block-editor/src/components/block-list/index.native.js +++ b/packages/block-editor/src/components/block-list/index.native.js @@ -30,9 +30,6 @@ import { import { BlockDraggableWrapper } from '../block-draggable'; import { useEditorWrapperStyles } from '../../hooks/use-editor-wrapper-styles'; import { store as blockEditorStore } from '../../store'; -import Warning from '../warning'; - -const MAX_DEEP_NESTING_LEVEL = 10; const identity = ( x ) => x; @@ -81,11 +78,9 @@ export default function BlockList( { isStackedHorizontally, maxWidth, isRTL, - nestingLevel, } = useSelect( ( select ) => { const { - getBlockParents, getBlockCount, getBlockHierarchyRootClientId, getBlockOrder, @@ -123,7 +118,6 @@ export default function BlockList( { isStackedHorizontally: orientation === 'horizontal', maxWidth: maxWidthSetting, isRTL: isRTLSetting, - nestingLevel: getBlockParents( rootClientId ).length, }; }, [ filterInnerBlocks, orientation, rootClientId ] @@ -234,15 +228,6 @@ export default function BlockList( { blockToolbar.height + ( isFloatingToolbarVisible ? floatingToolbar.height : 0 ); - if ( nestingLevel >= MAX_DEEP_NESTING_LEVEL ) { - return ( - - ); - } return ( { + return select( blockEditorStore ).getBlockParents( clientId ) + ?.length; + }, + [ clientId ] + ); + if ( nestingLevel >= MAX_NESTING_DEPTH ) { + return ; + } + return ( From 0f4637cd2e02ddb37c1a81bf56d4eb74fed816a0 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Date: Fri, 15 Sep 2023 15:35:05 +0200 Subject: [PATCH 05/15] Update title of max depth exceeded warning Co-authored-by: David Calhoun --- .../inner-blocks/warning-max-depth-exceeded.native.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/inner-blocks/warning-max-depth-exceeded.native.js b/packages/block-editor/src/components/inner-blocks/warning-max-depth-exceeded.native.js index 662dd9160b762..8f5d9cacdc7e6 100644 --- a/packages/block-editor/src/components/inner-blocks/warning-max-depth-exceeded.native.js +++ b/packages/block-editor/src/components/inner-blocks/warning-max-depth-exceeded.native.js @@ -64,7 +64,7 @@ const WarningMaxDepthExceeded = ( { clientId } ) => { clientId={ clientId } showSheet={ showDetails } onCloseSheet={ () => setShowDetails( false ) } - title={ __( 'Block deeply nested' ) } + title={ __( 'Deeply nested block' ) } description={ description } customActions={ [ { label: __( 'Ungroup block' ), onPress: onUngroup }, From df993f8e2b50618e60e457830fa58a75f9ef520c Mon Sep 17 00:00:00 2001 From: Carlos Garcia Date: Fri, 15 Sep 2023 17:18:38 +0200 Subject: [PATCH 06/15] Update description of max depth exceeded warning --- .../inner-blocks/warning-max-depth-exceeded.native.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/inner-blocks/warning-max-depth-exceeded.native.js b/packages/block-editor/src/components/inner-blocks/warning-max-depth-exceeded.native.js index 8f5d9cacdc7e6..f23308b3c8656 100644 --- a/packages/block-editor/src/components/inner-blocks/warning-max-depth-exceeded.native.js +++ b/packages/block-editor/src/components/inner-blocks/warning-max-depth-exceeded.native.js @@ -42,7 +42,7 @@ const WarningMaxDepthExceeded = ( { clientId } ) => { /* translators: Warning related to having blocks deeply nested. %d: The deepest nesting level. */ const descriptionFormat = __( - 'Blocks with inner blocks that are nested deeper than %d levels might not be rendered properly in the native version of the editor. For this reason, we recommend flattening the content by ungrouping the block or editing the block using the web editor.' + 'Blocks nested deeper than %d levels may not render properly in the mobile editor. For this reason, we recommend flattening the content by ungrouping the block or editing the block using the web editor.' ); const description = sprintf( descriptionFormat, MAX_NESTING_DEPTH ); From a4fc8725b17a34a56640ce1d801746f077f7ca88 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Date: Fri, 15 Sep 2023 17:23:49 +0200 Subject: [PATCH 07/15] Add constants file to `InnerBlocks` component `MAX_NESTING_DEPTH` has been moved to the constants file. --- .../src/components/inner-blocks/constants.native.js | 5 +++++ .../src/components/inner-blocks/index.native.js | 5 ++--- .../inner-blocks/warning-max-depth-exceeded.native.js | 7 +------ 3 files changed, 8 insertions(+), 9 deletions(-) create mode 100644 packages/block-editor/src/components/inner-blocks/constants.native.js diff --git a/packages/block-editor/src/components/inner-blocks/constants.native.js b/packages/block-editor/src/components/inner-blocks/constants.native.js new file mode 100644 index 0000000000000..79962a2373b88 --- /dev/null +++ b/packages/block-editor/src/components/inner-blocks/constants.native.js @@ -0,0 +1,5 @@ +// Hermes has a limit for the call stack depth to avoid infinite recursion. +// When creating a deep nested structure of inner blocks, the editor might exceed +// this limit and crash. In order to avoid this, we set a maximum depth level where +// we stop rendering blocks. +export const MAX_NESTING_DEPTH = 10; diff --git a/packages/block-editor/src/components/inner-blocks/index.native.js b/packages/block-editor/src/components/inner-blocks/index.native.js index 197399a6bc149..e254eff6c9ef1 100644 --- a/packages/block-editor/src/components/inner-blocks/index.native.js +++ b/packages/block-editor/src/components/inner-blocks/index.native.js @@ -23,9 +23,8 @@ import useBlockSync from '../provider/use-block-sync'; import { BlockContextProvider } from '../block-context'; import { defaultLayout, LayoutProvider } from '../block-list/layout'; import { store as blockEditorStore } from '../../store'; -import WarningMaxDepthExceeded, { - MAX_NESTING_DEPTH, -} from './warning-max-depth-exceeded'; +import WarningMaxDepthExceeded from './warning-max-depth-exceeded'; +import { MAX_NESTING_DEPTH } from './constants'; /** * This hook is used to lightly mark an element as an inner blocks wrapper diff --git a/packages/block-editor/src/components/inner-blocks/warning-max-depth-exceeded.native.js b/packages/block-editor/src/components/inner-blocks/warning-max-depth-exceeded.native.js index f23308b3c8656..61e771b81c6dd 100644 --- a/packages/block-editor/src/components/inner-blocks/warning-max-depth-exceeded.native.js +++ b/packages/block-editor/src/components/inner-blocks/warning-max-depth-exceeded.native.js @@ -16,6 +16,7 @@ import { useDispatch, useSelect } from '@wordpress/data'; import Warning from '../warning'; import BlockFallbackWebVersion from '../block-fallback-web-version'; import { store as blockEditorStore } from '../../store'; +import { MAX_NESTING_DEPTH } from './constants'; const WarningMaxDepthExceeded = ( { clientId } ) => { const [ showDetails, setShowDetails ] = useState( false ); @@ -75,10 +76,4 @@ const WarningMaxDepthExceeded = ( { clientId } ) => { ); }; -// Hermes has a limit for the call stack depth to avoid infinite recursion. -// When creating a deep nested structure of inner blocks, the editor might exceed -// this limit and crash. In order to avoid this, we set a maximum depth level where -// we stop rendering blocks. -export const MAX_NESTING_DEPTH = 10; - export default WarningMaxDepthExceeded; From 4ae212b19579900d790496b6ac0db30594551752 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Date: Fri, 15 Sep 2023 17:30:02 +0200 Subject: [PATCH 08/15] Revert `BlockFallbackWebVersion` export --- packages/block-editor/src/components/index.native.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/block-editor/src/components/index.native.js b/packages/block-editor/src/components/index.native.js index 1032590d39677..1f675daaa8ca1 100644 --- a/packages/block-editor/src/components/index.native.js +++ b/packages/block-editor/src/components/index.native.js @@ -91,7 +91,6 @@ export { default as __unstableEditorStyles } from './editor-styles'; export { default as Inserter } from './inserter'; export { useBlockProps } from './block-list/use-block-props'; export { default as FloatingToolbar } from './floating-toolbar'; -export { default as BlockFallbackWebVersion } from './block-fallback-web-version'; // State Related Components. export { default as BlockEditorProvider } from './provider'; From 053a2c83a5726f175448c6a2f41082806aae1f3b Mon Sep 17 00:00:00 2001 From: Carlos Garcia Date: Fri, 15 Sep 2023 17:31:38 +0200 Subject: [PATCH 09/15] Rename `BlockFallbackWebVersion` component to `UnsupportedBlockDetails` --- .../inner-blocks/warning-max-depth-exceeded.native.js | 4 ++-- .../index.native.js | 4 ++-- .../style.native.scss | 0 3 files changed, 4 insertions(+), 4 deletions(-) rename packages/block-editor/src/components/{block-fallback-web-version => unsupported-block-details}/index.native.js (98%) rename packages/block-editor/src/components/{block-fallback-web-version => unsupported-block-details}/style.native.scss (100%) diff --git a/packages/block-editor/src/components/inner-blocks/warning-max-depth-exceeded.native.js b/packages/block-editor/src/components/inner-blocks/warning-max-depth-exceeded.native.js index 61e771b81c6dd..c2707dd7f2321 100644 --- a/packages/block-editor/src/components/inner-blocks/warning-max-depth-exceeded.native.js +++ b/packages/block-editor/src/components/inner-blocks/warning-max-depth-exceeded.native.js @@ -14,7 +14,7 @@ import { useDispatch, useSelect } from '@wordpress/data'; * Internal dependencies */ import Warning from '../warning'; -import BlockFallbackWebVersion from '../block-fallback-web-version'; +import UnsupportedBlockDetails from '../unsupported-block-details'; import { store as blockEditorStore } from '../../store'; import { MAX_NESTING_DEPTH } from './constants'; @@ -61,7 +61,7 @@ const WarningMaxDepthExceeded = ( { clientId } ) => { 'Block cannot be rendered because it is deeply nested. Tap here for more details.' ) } /> - setShowDetails( false ) } diff --git a/packages/block-editor/src/components/block-fallback-web-version/index.native.js b/packages/block-editor/src/components/unsupported-block-details/index.native.js similarity index 98% rename from packages/block-editor/src/components/block-fallback-web-version/index.native.js rename to packages/block-editor/src/components/unsupported-block-details/index.native.js index 04ef3fdf18e06..d535bc146e6b0 100644 --- a/packages/block-editor/src/components/block-fallback-web-version/index.native.js +++ b/packages/block-editor/src/components/unsupported-block-details/index.native.js @@ -29,7 +29,7 @@ import { store as blockEditorStore } from '../../store'; const UBE_INCOMPATIBLE_BLOCKS = [ 'core/block' ]; const EMPTY_ARRAY = []; -const BlockFallbackWebVersion = ( { +const UnsupportedBlockDetails = ( { clientId, showSheet, onCloseSheet, @@ -204,4 +204,4 @@ const BlockFallbackWebVersion = ( { ); }; -export default BlockFallbackWebVersion; +export default UnsupportedBlockDetails; diff --git a/packages/block-editor/src/components/block-fallback-web-version/style.native.scss b/packages/block-editor/src/components/unsupported-block-details/style.native.scss similarity index 100% rename from packages/block-editor/src/components/block-fallback-web-version/style.native.scss rename to packages/block-editor/src/components/unsupported-block-details/style.native.scss From 4c645acf95f7103dc17abf7360fac11fedb64168 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Date: Fri, 15 Sep 2023 17:35:09 +0200 Subject: [PATCH 10/15] Rename `UnsupportedBlockDetails` styles --- .../unsupported-block-details/index.native.js | 22 +++++++++---------- .../style.native.scss | 22 +++++++++---------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/packages/block-editor/src/components/unsupported-block-details/index.native.js b/packages/block-editor/src/components/unsupported-block-details/index.native.js index d535bc146e6b0..429e9f0a35444 100644 --- a/packages/block-editor/src/components/unsupported-block-details/index.native.js +++ b/packages/block-editor/src/components/unsupported-block-details/index.native.js @@ -89,24 +89,24 @@ const UnsupportedBlockDetails = ( { // Styles const textStyle = usePreferredColorSchemeStyle( - styles.sheet__text, - styles[ 'sheet__text--dark' ] + styles[ 'unsupported-block-details__text' ], + styles[ 'unsupported-block-details__text--dark' ] ); const titleStyle = usePreferredColorSchemeStyle( - styles.sheet__title, - styles[ 'sheet__title--dark' ] + styles[ 'unsupported-block-details__title' ], + styles[ 'unsupported-block-details__title--dark' ] ); const descriptionStyle = usePreferredColorSchemeStyle( - styles.sheet__description, - styles[ 'sheet__description--dark' ] + styles[ 'unsupported-block-details__description' ], + styles[ 'unsupported-block-details__description--dark' ] ); const iconStyle = usePreferredColorSchemeStyle( - styles.sheet__icon, - styles[ 'sheet__icon--dark' ] + styles[ 'unsupported-block-details__icon' ], + styles[ 'unsupported-block-details__icon--dark' ] ); const actionButtonStyle = usePreferredColorSchemeStyle( - styles[ 'sheet__action-button' ], - styles[ 'sheet__action-button--dark' ] + styles[ 'unsupported-block-details__action-button' ], + styles[ 'unsupported-block-details__action-button--dark' ] ); const blockTitle = @@ -172,7 +172,7 @@ const UnsupportedBlockDetails = ( { } } } > - + Date: Fri, 15 Sep 2023 18:52:08 +0200 Subject: [PATCH 11/15] Update default web editor action label via WP hooks --- .../components/unsupported-block-details/index.native.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/unsupported-block-details/index.native.js b/packages/block-editor/src/components/unsupported-block-details/index.native.js index 429e9f0a35444..b0b25717df0ff 100644 --- a/packages/block-editor/src/components/unsupported-block-details/index.native.js +++ b/packages/block-editor/src/components/unsupported-block-details/index.native.js @@ -18,6 +18,7 @@ import { useSelect } from '@wordpress/data'; import { usePreferredColorSchemeStyle } from '@wordpress/compose'; import { getBlockType, serialize } from '@wordpress/blocks'; import { useCallback, useState } from '@wordpress/element'; +import { applyFilters } from '@wordpress/hooks'; /** * Internal dependencies @@ -129,6 +130,11 @@ const UnsupportedBlockDetails = ( { onCloseSheet, ] ); + const webEditorDefaultLabel = applyFilters( + 'native.unsupported_block_details_web_editor_action', + __( 'Edit using web editor' ) + ); + const canUseWebEditor = ( isUnsupportedBlockEditorSupported || canEnableUnsupportedBlockEditor ) && @@ -136,7 +142,7 @@ const UnsupportedBlockDetails = ( { const actions = [ ...[ canUseWebEditor && { - label: actionButtonLabel || __( 'Edit using web editor' ), + label: actionButtonLabel || webEditorDefaultLabel, onPress: requestFallback, }, ], From 167418fc621935067d6652e20b0303ae2ed248fc Mon Sep 17 00:00:00 2001 From: Carlos Garcia Date: Fri, 15 Sep 2023 19:02:59 +0200 Subject: [PATCH 12/15] Allow inserting extra notes to description via WP hooks --- .../unsupported-block-details/index.native.js | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/packages/block-editor/src/components/unsupported-block-details/index.native.js b/packages/block-editor/src/components/unsupported-block-details/index.native.js index b0b25717df0ff..a1ac2c8d200a0 100644 --- a/packages/block-editor/src/components/unsupported-block-details/index.native.js +++ b/packages/block-editor/src/components/unsupported-block-details/index.native.js @@ -130,6 +130,13 @@ const UnsupportedBlockDetails = ( { onCloseSheet, ] ); + // The description can include extra notes via WP hooks. + const descriptionWithNotes = applyFilters( + 'native.unsupported_block_details_extra_note', + description, + blockName + ); + const webEditorDefaultLabel = applyFilters( 'native.unsupported_block_details_web_editor_action', __( 'Edit using web editor' ) @@ -185,11 +192,12 @@ const UnsupportedBlockDetails = ( { size={ iconStyle.size } /> { title } - { isEditableInUnsupportedBlockEditor && description && ( - - { description } - - ) } + { isEditableInUnsupportedBlockEditor && + descriptionWithNotes && ( + + { descriptionWithNotes } + + ) } { actions.map( ( { label, onPress }, index ) => ( Date: Fri, 15 Sep 2023 19:27:41 +0200 Subject: [PATCH 13/15] Extract UBE settings fetch to a hook --- .../unsupported-block-details/index.native.js | 44 +------------- .../index.native.js | 59 +++++++++++++++++++ 2 files changed, 62 insertions(+), 41 deletions(-) create mode 100644 packages/block-editor/src/components/use-unsupported-block-editor/index.native.js diff --git a/packages/block-editor/src/components/unsupported-block-details/index.native.js b/packages/block-editor/src/components/unsupported-block-details/index.native.js index a1ac2c8d200a0..a35d96a925676 100644 --- a/packages/block-editor/src/components/unsupported-block-details/index.native.js +++ b/packages/block-editor/src/components/unsupported-block-details/index.native.js @@ -14,9 +14,8 @@ import { } from '@wordpress/react-native-bridge'; import { help } from '@wordpress/icons'; import { __ } from '@wordpress/i18n'; -import { useSelect } from '@wordpress/data'; import { usePreferredColorSchemeStyle } from '@wordpress/compose'; -import { getBlockType, serialize } from '@wordpress/blocks'; +import { getBlockType } from '@wordpress/blocks'; import { useCallback, useState } from '@wordpress/element'; import { applyFilters } from '@wordpress/hooks'; @@ -24,10 +23,8 @@ import { applyFilters } from '@wordpress/hooks'; * Internal dependencies */ import styles from './style.scss'; -import { store as blockEditorStore } from '../../store'; +import useUnsupportedBlockEditor from '../use-unsupported-block-editor'; -// Blocks that can't be edited through the Unsupported block editor identified by their name. -const UBE_INCOMPATIBLE_BLOCKS = [ 'core/block' ]; const EMPTY_ARRAY = []; const UnsupportedBlockDetails = ( { @@ -51,42 +48,7 @@ const UnsupportedBlockDetails = ( { isUnsupportedBlockEditorSupported, canEnableUnsupportedBlockEditor, isEditableInUnsupportedBlockEditor, - } = useSelect( - ( select ) => { - const { getBlock, getSettings } = select( blockEditorStore ); - const { capabilities } = getSettings(); - - const block = getBlock( clientId ); - const blockAttributes = block?.attributes || {}; - - const blockDetails = { - blockName: block?.name, - blockContent: serialize( block ? [ block ] : [] ), - }; - - // If the block is unsupported, use the `original` attributes to identify the block's name. - if ( blockDetails.blockName === 'core/missing' ) { - blockDetails.blockName = blockAttributes.originalName; - blockDetails.blockContent = - blockDetails.blockName === 'core/freeform' - ? blockAttributes.content - : block?.originalContent; - } - - return { - isUnsupportedBlockEditorSupported: - capabilities?.unsupportedBlockEditor === true, - canEnableUnsupportedBlockEditor: - capabilities?.canEnableUnsupportedBlockEditor === true, - isEditableInUnsupportedBlockEditor: - ! UBE_INCOMPATIBLE_BLOCKS.includes( - blockDetails.blockName - ), - ...blockDetails, - }; - }, - [ clientId ] - ); + } = useUnsupportedBlockEditor( clientId ); // Styles const textStyle = usePreferredColorSchemeStyle( diff --git a/packages/block-editor/src/components/use-unsupported-block-editor/index.native.js b/packages/block-editor/src/components/use-unsupported-block-editor/index.native.js new file mode 100644 index 0000000000000..4b5bbe65857b2 --- /dev/null +++ b/packages/block-editor/src/components/use-unsupported-block-editor/index.native.js @@ -0,0 +1,59 @@ +/** + * WordPress dependencies + */ +import { useSelect } from '@wordpress/data'; +import { serialize } from '@wordpress/blocks'; + +/** + * Internal dependencies + */ +import { store as blockEditorStore } from '../../store'; + +// Blocks that can't be edited through the Unsupported block editor identified by their name. +const UBE_INCOMPATIBLE_BLOCKS = [ 'core/block' ]; + +/** + * Hook that retrieves the settings to determine if the + * Unsupported Block Editor can be used in a specific block. + * + * @param {string} clientId Client ID of block. + * @return {Object} Unsupported block editor settings. + */ +export default function useUnsupportedBlockEditor( clientId ) { + return useSelect( + ( select ) => { + const { getBlock, getSettings } = select( blockEditorStore ); + const { capabilities } = getSettings(); + + const block = getBlock( clientId ); + const blockAttributes = block?.attributes || {}; + + const blockDetails = { + blockName: block?.name, + blockContent: serialize( block ? [ block ] : [] ), + }; + + // If the block is unsupported, use the `original` attributes to identify the block's name. + if ( blockDetails.blockName === 'core/missing' ) { + blockDetails.blockName = blockAttributes.originalName; + blockDetails.blockContent = + blockDetails.blockName === 'core/freeform' + ? blockAttributes.content + : block?.originalContent; + } + + return { + isUnsupportedBlockEditorSupported: + capabilities?.unsupportedBlockEditor === true, + canEnableUnsupportedBlockEditor: + capabilities?.canEnableUnsupportedBlockEditor === true, + isEditableInUnsupportedBlockEditor: + ! UBE_INCOMPATIBLE_BLOCKS.includes( + blockDetails.blockName + ), + ...blockDetails, + }; + }, + [ clientId ] + ); +} From 87fbea640ef5863bc9e79318b7f958b4d836c5de Mon Sep 17 00:00:00 2001 From: Carlos Garcia Date: Fri, 15 Sep 2023 19:28:24 +0200 Subject: [PATCH 14/15] Update description of max depth exceeded warning based on UBE support --- .../warning-max-depth-exceeded.native.js | 31 ++++++++++++++++--- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/packages/block-editor/src/components/inner-blocks/warning-max-depth-exceeded.native.js b/packages/block-editor/src/components/inner-blocks/warning-max-depth-exceeded.native.js index c2707dd7f2321..57a7b7a60483c 100644 --- a/packages/block-editor/src/components/inner-blocks/warning-max-depth-exceeded.native.js +++ b/packages/block-editor/src/components/inner-blocks/warning-max-depth-exceeded.native.js @@ -17,6 +17,7 @@ import Warning from '../warning'; import UnsupportedBlockDetails from '../unsupported-block-details'; import { store as blockEditorStore } from '../../store'; import { MAX_NESTING_DEPTH } from './constants'; +import useUnsupportedBlockEditor from '../use-unsupported-block-editor'; const WarningMaxDepthExceeded = ( { clientId } ) => { const [ showDetails, setShowDetails ] = useState( false ); @@ -33,6 +34,11 @@ const WarningMaxDepthExceeded = ( { clientId } ) => { ); const { replaceBlocks } = useDispatch( blockEditorStore ); + const { + isUnsupportedBlockEditorSupported, + canEnableUnsupportedBlockEditor, + } = useUnsupportedBlockEditor( clientId ); + const onUngroup = () => { if ( ! innerBlocks.length ) { return; @@ -41,11 +47,26 @@ const WarningMaxDepthExceeded = ( { clientId } ) => { replaceBlocks( clientId, innerBlocks ); }; - /* translators: Warning related to having blocks deeply nested. %d: The deepest nesting level. */ - const descriptionFormat = __( - 'Blocks nested deeper than %d levels may not render properly in the mobile editor. For this reason, we recommend flattening the content by ungrouping the block or editing the block using the web editor.' - ); - const description = sprintf( descriptionFormat, MAX_NESTING_DEPTH ); + let description; + // When UBE can't be used, the description mentions using the web browser to edit the block. + if ( + ! isUnsupportedBlockEditorSupported && + ! canEnableUnsupportedBlockEditor + ) { + /* translators: Warning related to having blocks deeply nested. %d: The deepest nesting level. */ + const descriptionFormat = __( + 'Blocks nested deeper than %d levels may not render properly in the mobile editor. For this reason, we recommend flattening the content by ungrouping the block or editing the block using your web browser.' + ); + description = sprintf( descriptionFormat, MAX_NESTING_DEPTH ); + } + // Otherwise, the description mentions using the web editor (i.e. UBE). + else { + /* translators: Warning related to having blocks deeply nested. %d: The deepest nesting level. */ + const descriptionFormat = __( + 'Blocks nested deeper than %d levels may not render properly in the mobile editor. For this reason, we recommend flattening the content by ungrouping the block or editing the block using the web editor.' + ); + description = sprintf( descriptionFormat, MAX_NESTING_DEPTH ); + } return ( Date: Mon, 25 Sep 2023 19:01:29 +0200 Subject: [PATCH 15/15] 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 1debe8fbaad8e..70f0605599add 100644 --- a/packages/react-native-editor/CHANGELOG.md +++ b/packages/react-native-editor/CHANGELOG.md @@ -10,6 +10,7 @@ For each user feature we should also add a importance categorization label to i --> ## Unreleased +- [*] Limit inner blocks nesting depth to avoid call stack size exceeded crash [#54382] ## 1.104.0 - [*] Fix the obscurred "Insert from URL" input for media blocks when using a device in landscape orientation. [#54096]