From 349a252112f73ce656472a60cf96859303ab589d Mon Sep 17 00:00:00 2001 From: Ella Date: Wed, 27 Mar 2024 18:31:51 +0200 Subject: [PATCH] Avoid fetching ALL reusable blocks (user patterns) on post/site editor load --- packages/block-editor/src/private-apis.js | 6 +- .../block-editor/src/store/private-keys.js | 1 + .../src/store/private-selectors.js | 57 ++-- packages/block-editor/src/store/selectors.js | 298 +++++++++--------- .../block-editor/src/store/test/selectors.js | 290 ++++++----------- packages/block-editor/src/store/utils.js | 3 + .../provider/use-block-editor-settings.js | 22 +- 7 files changed, 303 insertions(+), 374 deletions(-) diff --git a/packages/block-editor/src/private-apis.js b/packages/block-editor/src/private-apis.js index 90aa19682a40e..b51c019e79178 100644 --- a/packages/block-editor/src/private-apis.js +++ b/packages/block-editor/src/private-apis.js @@ -31,7 +31,10 @@ import { usesContextKey } from './components/rich-text/format-edit'; import { ExperimentalBlockCanvas } from './components/block-canvas'; import { getDuotoneFilter } from './components/duotone/utils'; import { useFlashEditableBlocks } from './components/use-flash-editable-blocks'; -import { selectBlockPatternsKey } from './store/private-keys'; +import { + selectBlockPatternsKey, + reusableBlocksSelectKey, +} from './store/private-keys'; import { requiresWrapperOnCopy } from './components/writing-flow/utils'; import { PrivateRichText } from './components/rich-text/'; @@ -70,4 +73,5 @@ lock( privateApis, { selectBlockPatternsKey, requiresWrapperOnCopy, PrivateRichText, + reusableBlocksSelectKey, } ); diff --git a/packages/block-editor/src/store/private-keys.js b/packages/block-editor/src/store/private-keys.js index 8bfa4bb68297f..f48612e7491c9 100644 --- a/packages/block-editor/src/store/private-keys.js +++ b/packages/block-editor/src/store/private-keys.js @@ -1 +1,2 @@ export const selectBlockPatternsKey = Symbol( 'selectBlockPatternsKey' ); +export const reusableBlocksSelectKey = Symbol( 'reusableBlocksSelect' ); diff --git a/packages/block-editor/src/store/private-selectors.js b/packages/block-editor/src/store/private-selectors.js index 4351aea15f416..75163273008c4 100644 --- a/packages/block-editor/src/store/private-selectors.js +++ b/packages/block-editor/src/store/private-selectors.js @@ -26,7 +26,10 @@ import { import { INSERTER_PATTERN_TYPES } from '../components/inserter/block-patterns-tab/utils'; import { STORE_NAME } from './constants'; import { unlock } from '../lock-unlock'; -import { selectBlockPatternsKey } from './private-keys'; +import { + selectBlockPatternsKey, + reusableBlocksSelectKey, +} from './private-keys'; export { getBlockSettings } from './get-block-settings'; @@ -300,26 +303,27 @@ export const getAllPatterns = createRegistrySelector( ( select ) => __experimentalUserPatternCategories = [], __experimentalReusableBlocks = [], } = state.settings; - const userPatterns = ( __experimentalReusableBlocks ?? [] ).map( - ( userPattern ) => { - return { - name: `core/block/${ userPattern.id }`, - id: userPattern.id, - type: INSERTER_PATTERN_TYPES.user, - title: userPattern.title.raw, - categories: userPattern.wp_pattern_category.map( - ( catId ) => { - const category = ( - __experimentalUserPatternCategories ?? [] - ).find( ( { id } ) => id === catId ); - return category ? category.slug : catId; - } - ), - content: userPattern.content.raw, - syncStatus: userPattern.wp_pattern_sync_status, - }; - } - ); + const reusableBlocksSelect = state.settings[ reusableBlocksSelectKey ]; + const userPatterns = ( + reusableBlocksSelect + ? reusableBlocksSelect( select ) + : __experimentalReusableBlocks ?? [] + ).map( ( userPattern ) => { + return { + name: `core/block/${ userPattern.id }`, + id: userPattern.id, + type: INSERTER_PATTERN_TYPES.user, + title: userPattern.title.raw, + categories: userPattern.wp_pattern_category.map( ( catId ) => { + const category = ( + __experimentalUserPatternCategories ?? [] + ).find( ( { id } ) => id === catId ); + return category ? category.slug : catId; + } ), + content: userPattern.content.raw, + syncStatus: userPattern.wp_pattern_sync_status, + }; + } ); return [ ...userPatterns, ...__experimentalBlockPatterns, @@ -331,6 +335,17 @@ export const getAllPatterns = createRegistrySelector( ( select ) => }, getAllPatternsDependants( select ) ) ); +const EMPTY_ARRAY = []; + +export const getReusableBlocks = createRegistrySelector( + ( select ) => ( state ) => { + const reusableBlocksSelect = state.settings[ reusableBlocksSelectKey ]; + return reusableBlocksSelect + ? reusableBlocksSelect( select ) + : state.settings.__experimentalReusableBlocks ?? EMPTY_ARRAY; + } +); + /** * Returns the element of the last element that had focus when focus left the editor canvas. * diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index d696f3dc14df4..d1a52ab8cb6a0 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -1973,92 +1973,108 @@ const buildBlockTypeItem = * this item. * @property {number} frecency Heuristic that combines frequency and recency. */ -export const getInserterItems = createSelector( - ( state, rootClientId = null ) => { - const buildReusableBlockInserterItem = ( reusableBlock ) => { - const icon = ! reusableBlock.wp_pattern_sync_status - ? { - src: symbol, - foreground: 'var(--wp-block-synced-color)', - } - : symbol; - const id = `core/block/${ reusableBlock.id }`; - const { time, count = 0 } = getInsertUsage( state, id ) || {}; - const frecency = calculateFrecency( time, count ); - - return { - id, - name: 'core/block', - initialAttributes: { ref: reusableBlock.id }, - title: reusableBlock.title?.raw, - icon, - category: 'reusable', - keywords: [ 'reusable' ], - isDisabled: false, - utility: 1, // Deprecated. - frecency, - content: reusableBlock.content?.raw, - syncStatus: reusableBlock.wp_pattern_sync_status, +export const getInserterItems = createRegistrySelector( ( select ) => + createSelector( + ( state, rootClientId = null ) => { + const buildReusableBlockInserterItem = ( reusableBlock ) => { + const icon = ! reusableBlock.wp_pattern_sync_status + ? { + src: symbol, + foreground: 'var(--wp-block-synced-color)', + } + : symbol; + const id = `core/block/${ reusableBlock.id }`; + const { time, count = 0 } = getInsertUsage( state, id ) || {}; + const frecency = calculateFrecency( time, count ); + + return { + id, + name: 'core/block', + initialAttributes: { ref: reusableBlock.id }, + title: reusableBlock.title?.raw, + icon, + category: 'reusable', + keywords: [ 'reusable' ], + isDisabled: false, + utility: 1, // Deprecated. + frecency, + content: reusableBlock.content?.raw, + syncStatus: reusableBlock.wp_pattern_sync_status, + }; }; - }; - - const syncedPatternInserterItems = canInsertBlockTypeUnmemoized( - state, - 'core/block', - rootClientId - ) - ? getReusableBlocks( state ).map( buildReusableBlockInserterItem ) - : []; - - const buildBlockTypeInserterItem = buildBlockTypeItem( state, { - buildScope: 'inserter', - } ); - const blockTypeInserterItems = getBlockTypes() - .filter( ( blockType ) => - canIncludeBlockTypeInInserter( state, blockType, rootClientId ) + const syncedPatternInserterItems = canInsertBlockTypeUnmemoized( + state, + 'core/block', + rootClientId ) - .map( buildBlockTypeInserterItem ); + ? unlock( select( STORE_NAME ) ) + .getReusableBlocks() + .map( buildReusableBlockInserterItem ) + : []; - const items = blockTypeInserterItems.reduce( ( accumulator, item ) => { - const { variations = [] } = item; - // Exclude any block type item that is to be replaced by a default variation. - if ( ! variations.some( ( { isDefault } ) => isDefault ) ) { - accumulator.push( item ); - } - if ( variations.length ) { - const variationMapper = getItemFromVariation( state, item ); - accumulator.push( ...variations.map( variationMapper ) ); - } - return accumulator; - }, [] ); + const buildBlockTypeInserterItem = buildBlockTypeItem( state, { + buildScope: 'inserter', + } ); - // Ensure core blocks are prioritized in the returned results, - // because third party blocks can be registered earlier than - // the core blocks (usually by using the `init` action), - // thus affecting the display order. - // We don't sort reusable blocks as they are handled differently. - const groupByType = ( blocks, block ) => { - const { core, noncore } = blocks; - const type = block.name.startsWith( 'core/' ) ? core : noncore; - - type.push( block ); - return blocks; - }; - const { core: coreItems, noncore: nonCoreItems } = items.reduce( - groupByType, - { core: [], noncore: [] } - ); - const sortedBlockTypes = [ ...coreItems, ...nonCoreItems ]; - return [ ...sortedBlockTypes, ...syncedPatternInserterItems ]; - }, - ( state, rootClientId ) => [ - getBlockTypes(), - getReusableBlocks( state ), - state.blocks.order, - state.preferences.insertUsage, - ...getInsertBlockTypeDependants( state, rootClientId ), - ] + const blockTypeInserterItems = getBlockTypes() + .filter( ( blockType ) => + canIncludeBlockTypeInInserter( + state, + blockType, + rootClientId + ) + ) + .map( buildBlockTypeInserterItem ); + + const items = blockTypeInserterItems.reduce( + ( accumulator, item ) => { + const { variations = [] } = item; + // Exclude any block type item that is to be replaced by a default variation. + if ( ! variations.some( ( { isDefault } ) => isDefault ) ) { + accumulator.push( item ); + } + if ( variations.length ) { + const variationMapper = getItemFromVariation( + state, + item + ); + accumulator.push( + ...variations.map( variationMapper ) + ); + } + return accumulator; + }, + [] + ); + + // Ensure core blocks are prioritized in the returned results, + // because third party blocks can be registered earlier than + // the core blocks (usually by using the `init` action), + // thus affecting the display order. + // We don't sort reusable blocks as they are handled differently. + const groupByType = ( blocks, block ) => { + const { core, noncore } = blocks; + const type = block.name.startsWith( 'core/' ) ? core : noncore; + + type.push( block ); + return blocks; + }; + const { core: coreItems, noncore: nonCoreItems } = items.reduce( + groupByType, + { core: [], noncore: [] } + ); + const sortedBlockTypes = [ ...coreItems, ...nonCoreItems ]; + return [ ...sortedBlockTypes, ...syncedPatternInserterItems ]; + }, + ( state, rootClientId ) => [ + getBlockTypes(), + unlock( select( STORE_NAME ) ).getReusableBlocks(), + state.blocks.order, + state.preferences.insertUsage, + ...getInsertBlockTypeDependants( state, rootClientId ), + ] + ) ); /** @@ -2135,25 +2151,25 @@ export const getBlockTransformItems = createSelector( * * @return {boolean} Items that appear in inserter. */ -export const hasInserterItems = createSelector( - ( state, rootClientId = null ) => { - const hasBlockType = getBlockTypes().some( ( blockType ) => - canIncludeBlockTypeInInserter( state, blockType, rootClientId ) - ); - if ( hasBlockType ) { - return true; - } - const hasReusableBlock = - canInsertBlockTypeUnmemoized( state, 'core/block', rootClientId ) && - getReusableBlocks( state ).length > 0; +export const hasInserterItems = createRegistrySelector( + ( select ) => + ( state, rootClientId = null ) => { + const hasBlockType = getBlockTypes().some( ( blockType ) => + canIncludeBlockTypeInInserter( state, blockType, rootClientId ) + ); + if ( hasBlockType ) { + return true; + } + const hasReusableBlock = + canInsertBlockTypeUnmemoized( + state, + 'core/block', + rootClientId + ) && + unlock( select( STORE_NAME ) ).getReusableBlocks().length > 0; - return hasReusableBlock; - }, - ( state, rootClientId ) => [ - getBlockTypes(), - getReusableBlocks( state ), - ...getInsertBlockTypeDependants( state, rootClientId ), - ] + return hasReusableBlock; + } ); /** @@ -2164,31 +2180,37 @@ export const hasInserterItems = createSelector( * * @return {Array?} The list of allowed block types. */ -export const getAllowedBlocks = createSelector( - ( state, rootClientId = null ) => { - if ( ! rootClientId ) { - return; - } +export const getAllowedBlocks = createRegistrySelector( ( select ) => + createSelector( + ( state, rootClientId = null ) => { + if ( ! rootClientId ) { + return; + } - const blockTypes = getBlockTypes().filter( ( blockType ) => - canIncludeBlockTypeInInserter( state, blockType, rootClientId ) - ); + const blockTypes = getBlockTypes().filter( ( blockType ) => + canIncludeBlockTypeInInserter( state, blockType, rootClientId ) + ); - const hasReusableBlock = - canInsertBlockTypeUnmemoized( state, 'core/block', rootClientId ) && - getReusableBlocks( state ).length > 0; + const hasReusableBlock = + canInsertBlockTypeUnmemoized( + state, + 'core/block', + rootClientId + ) && + unlock( select( STORE_NAME ) ).getReusableBlocks().length > 0; - if ( hasReusableBlock ) { - blockTypes.push( 'core/block' ); - } + if ( hasReusableBlock ) { + blockTypes.push( 'core/block' ); + } - return blockTypes; - }, - ( state, rootClientId ) => [ - getBlockTypes(), - getReusableBlocks( state ), - ...getInsertBlockTypeDependants( state, rootClientId ), - ] + return blockTypes; + }, + ( state, rootClientId ) => [ + getBlockTypes(), + unlock( select( STORE_NAME ) ).getReusableBlocks(), + ...getInsertBlockTypeDependants( state, rootClientId ), + ] + ) ); export const __experimentalGetAllowedBlocks = createSelector( @@ -2508,18 +2530,21 @@ export const __experimentalGetBlockListSettingsForBlocks = createSelector( * * @return {string} The reusable block saved title. */ -export const __experimentalGetReusableBlockTitle = createSelector( - ( state, ref ) => { - const reusableBlock = getReusableBlocks( state ).find( - ( block ) => block.id === ref - ); - if ( ! reusableBlock ) { - return null; - } +export const __experimentalGetReusableBlockTitle = createRegistrySelector( + ( select ) => + createSelector( + ( state, ref ) => { + const reusableBlock = unlock( select( STORE_NAME ) ) + .getReusableBlocks() + .find( ( block ) => block.id === ref ); + if ( ! reusableBlock ) { + return null; + } - return reusableBlock.title?.raw; - }, - ( state ) => [ getReusableBlocks( state ) ] + return reusableBlock.title?.raw; + }, + () => [ unlock( select( STORE_NAME ) ).getReusableBlocks() ] + ) ); /** @@ -2553,17 +2578,6 @@ export function __experimentalGetLastBlockAttributeChanges( state ) { return state.lastBlockAttributesChange; } -/** - * Returns the available reusable blocks - * - * @param {Object} state Global application state. - * - * @return {Array} Reusable blocks - */ -function getReusableBlocks( state ) { - return state.settings.__experimentalReusableBlocks ?? EMPTY_ARRAY; -} - /** * Returns whether the navigation mode is enabled. * diff --git a/packages/block-editor/src/store/test/selectors.js b/packages/block-editor/src/store/test/selectors.js index 29833611b17f4..27f9042bd87ff 100644 --- a/packages/block-editor/src/store/test/selectors.js +++ b/packages/block-editor/src/store/test/selectors.js @@ -8,11 +8,13 @@ import { } from '@wordpress/blocks'; import { RawHTML } from '@wordpress/element'; import { symbol } from '@wordpress/icons'; +import { select, dispatch } from '@wordpress/data'; /** * Internal dependencies */ import * as selectors from '../selectors'; +import { store } from '../'; const { getBlockName, @@ -55,7 +57,6 @@ const { isSelectionEnabled, canInsertBlockType, canInsertBlocks, - getInserterItems, getBlockTransformItems, isValidTemplate, getTemplate, @@ -3286,41 +3287,26 @@ describe( 'selectors', () => { } ); describe( 'getInserterItems', () => { - it( 'should properly list block type and reusable block items', () => { - const state = { - blocks: { - byClientId: new Map(), - attributes: new Map(), - order: new Map(), - parents: new Map(), - tree: new Map( - Object.entries( { - '': { - innerBlocks: [], - }, - } ) - ), - }, - settings: { - __experimentalReusableBlocks: [ - { - id: 1, - isTemporary: false, - clientId: 'block1', - title: { raw: 'Reusable Block 1' }, - content: { raw: '' }, - }, - ], - }, - // Intentionally include a test case which considers - // `insertUsage` as not present within preferences. - // - // See: https://github.com/WordPress/gutenberg/issues/14580 - preferences: {}, - blockListSettings: {}, - blockEditingModes: new Map(), - }; - const items = getInserterItems( state ); + afterAll( async () => { + await dispatch( store ).updateSettings( { + __experimentalReusableBlocks: [], + } ); + await dispatch( store ).resetBlocks( [] ); + } ); + + it( 'should properly list block type and reusable block items', async () => { + await dispatch( store ).updateSettings( { + __experimentalReusableBlocks: [ + { + id: 1, + isTemporary: false, + clientId: 'block1', + title: { raw: 'Reusable Block 1' }, + content: { raw: '' }, + }, + ], + } ); + const items = select( store ).getInserterItems(); const testBlockAItem = items.find( ( item ) => item.id === 'core/test-block-a' ); @@ -3361,93 +3347,48 @@ describe( 'selectors', () => { } ); } ); - it( 'should correctly cache the return values', () => { - const state = { - blocks: { - byClientId: new Map( - Object.entries( { - block3: { name: 'core/test-block-a' }, - block4: { name: 'core/test-block-a' }, - } ) - ), - attributes: new Map( - Object.entries( { - block3: {}, - block4: {}, - } ) - ), - order: new Map( - Object.entries( { - '': [ 'block3', 'block4' ], - } ) - ), - parents: new Map( - Object.entries( { - block3: '', - block4: '', - } ) - ), - tree: new Map( - Object.entries( { - block3: { - clientId: 'block3', - name: 'core/test-block-a', - attributes: {}, - innerBlocks: [], - }, - block4: { - clientId: 'block4', - name: 'core/test-block-a', - attributes: {}, - innerBlocks: [], - }, - } ) - ), - controlledInnerBlocks: {}, - }, - settings: { - __experimentalReusableBlocks: [ - { - id: 1, - isTemporary: false, - clientId: 'block1', - title: { raw: 'Reusable Block 1' }, - content: { raw: '' }, - }, - { - id: 2, - isTemporary: false, - clientId: 'block2', - title: { raw: 'Reusable Block 2' }, - content: { raw: '' }, - }, - ], - }, - preferences: { - insertUsage: {}, - }, - blockListSettings: { - block3: {}, - block4: {}, - }, - blockEditingModes: new Map(), - }; - - const stateSecondBlockRestricted = { - ...state, - blockListSettings: { - ...state.blockListSettings, - block4: { - allowedBlocks: [ 'core/test-block-b' ], + it( 'should correctly cache the return values', async () => { + await dispatch( store ).updateSettings( { + __experimentalReusableBlocks: [ + { + id: 1, + isTemporary: false, + clientId: 'block1', + title: { raw: 'Reusable Block 1' }, + content: { raw: '' }, + }, + { + id: 2, + isTemporary: false, + clientId: 'block2', + title: { raw: 'Reusable Block 2' }, + content: { raw: '' }, }, + ], + } ); + await dispatch( store ).resetBlocks( [ + { + clientId: 'block3', + name: 'core/test-block-a', + innerBlocks: [], }, - }; + { + clientId: 'block4', + name: 'core/test-block-b', + innerBlocks: [], + }, + ] ); + await dispatch( store ).updateBlockListSettings( 'block3', {} ); + await dispatch( store ).updateBlockListSettings( 'block4', {} ); - const firstBlockFirstCall = getInserterItems( state, 'block3' ); - const firstBlockSecondCall = getInserterItems( - stateSecondBlockRestricted, - 'block3' - ); + const firstBlockFirstCall = + select( store ).getInserterItems( 'block3' ); + await dispatch( store ).updateBlockListSettings( 'block4', { + allowedBlocks: [ 'core/test-block-b' ], + } ); + const firstBlockSecondCall = + select( store ).getInserterItems( 'block3' ); + await dispatch( store ).updateBlockListSettings( 'block4', {} ); expect( firstBlockFirstCall ).toBe( firstBlockSecondCall ); expect( firstBlockFirstCall.map( ( item ) => item.id ) ).toEqual( [ 'core/test-block-a', @@ -3459,15 +3400,19 @@ describe( 'selectors', () => { 'core/block/2', ] ); - const secondBlockFirstCall = getInserterItems( state, 'block4' ); - const secondBlockSecondCall = getInserterItems( - stateSecondBlockRestricted, - 'block4' - ); + const secondBlockFirstCall = + select( store ).getInserterItems( 'block4' ); + await dispatch( store ).updateBlockListSettings( 'block4', { + allowedBlocks: [ 'core/test-block-b' ], + } ); + const secondBlockSecondCall = + select( store ).getInserterItems( 'block4' ); + await dispatch( store ).updateBlockListSettings( 'block4', {} ); expect( secondBlockFirstCall ).not.toBe( secondBlockSecondCall ); expect( secondBlockFirstCall.map( ( item ) => item.id ) ).toEqual( [ 'core/test-block-a', 'core/test-block-b', + 'core/test-block-c', 'core/freeform', 'core/test-block-ancestor', 'core/test-block-parent', @@ -3479,77 +3424,37 @@ describe( 'selectors', () => { ); } ); - it( 'should set isDisabled when a block with `multiple: false` has been used', () => { - const state = { - blocks: { - byClientId: new Map( - Object.entries( { - block1: { - clientId: 'block1', - name: 'core/test-block-b', - }, - } ) - ), - attributes: new Map( - Object.entries( { - block1: { attribute: {} }, - } ) - ), - order: new Map( - Object.entries( { - '': [ 'block1' ], - } ) - ), - tree: new Map( - Object.entries( { - block1: { - clientId: 'block1', - name: 'core/test-block-b', - attributes: {}, - innerBlocks: [], - }, - } ) - ), - controlledInnerBlocks: {}, - parents: new Map(), - }, - preferences: { - insertUsage: {}, + it( 'should set isDisabled when a block with `multiple: false` has been used', async () => { + await dispatch( store ).resetBlocks( [ + { + clientId: 'block1', + name: 'core/test-block-b', + innerBlocks: [], }, - blockListSettings: {}, - settings: {}, - blockEditingModes: new Map(), - }; - const items = getInserterItems( state ); + ] ); + const items = select( store ).getInserterItems(); const testBlockBItem = items.find( ( item ) => item.id === 'core/test-block-b' ); expect( testBlockBItem.isDisabled ).toBe( true ); } ); - it( 'should set a frecency', () => { - const state = { - blocks: { - byClientId: new Map(), - attributes: new Map(), - order: new Map(), - parents: new Map(), - cache: {}, - }, - preferences: { - insertUsage: { - 'core/test-block-b': { count: 10, time: 1000 }, + it( 'should set a frecency', async () => { + for ( let i = 0; i < 10; i++ ) { + await dispatch( store ).insertBlocks( [ + { + clientId: 'block1', + name: 'core/test-block-b', + innerBlocks: [], }, - }, - blockListSettings: {}, - settings: {}, - blockEditingModes: new Map(), - }; - const items = getInserterItems( state ); + ] ); + } + + const items = select( store ).getInserterItems(); const reusableBlock2Item = items.find( ( item ) => item.id === 'core/test-block-b' ); - expect( reusableBlock2Item.frecency ).toBe( 2.5 ); + expect( reusableBlock2Item.frecency ).toBe( 40 ); } ); } ); @@ -4304,20 +4209,7 @@ describe( 'getInserterItems with core blocks prioritization', () => { ].forEach( unregisterBlockType ); } ); it( 'should prioritize core blocks by sorting them at the top of the returned list', () => { - const state = { - blocks: { - byClientId: new Map(), - attributes: new Map(), - order: new Map(), - parents: new Map(), - cache: {}, - }, - settings: {}, - preferences: {}, - blockListSettings: {}, - blockEditingModes: new Map(), - }; - const items = getInserterItems( state ); + const items = select( store ).getInserterItems(); const expectedResult = [ 'core/block', 'core/test-block-a', diff --git a/packages/block-editor/src/store/utils.js b/packages/block-editor/src/store/utils.js index 34a6e04556be4..f236c4a7e56eb 100644 --- a/packages/block-editor/src/store/utils.js +++ b/packages/block-editor/src/store/utils.js @@ -2,6 +2,8 @@ * Internal dependencies */ import { selectBlockPatternsKey } from './private-keys'; +import { unlock } from '../lock-unlock'; +import { STORE_NAME } from './constants'; export const checkAllowList = ( list, item, defaultResult = null ) => { if ( typeof list === 'boolean' ) { @@ -52,6 +54,7 @@ export const getAllPatternsDependants = ( select ) => ( state ) => { state.settings.__experimentalReusableBlocks, state.settings[ selectBlockPatternsKey ]?.( select ), state.blockPatterns, + unlock( select( STORE_NAME ) ).getReusableBlocks(), ]; }; diff --git a/packages/editor/src/components/provider/use-block-editor-settings.js b/packages/editor/src/components/provider/use-block-editor-settings.js index c7540645328f7..2f8bf920a4829 100644 --- a/packages/editor/src/components/provider/use-block-editor-settings.js +++ b/packages/editor/src/components/provider/use-block-editor-settings.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { Platform, useMemo, useCallback } from '@wordpress/element'; +import { useMemo, useCallback } from '@wordpress/element'; import { useDispatch, useSelect } from '@wordpress/data'; import { store as coreStore, @@ -24,6 +24,14 @@ import { unlock } from '../../lock-unlock'; const EMPTY_BLOCKS_LIST = []; +function __experimentalReusableBlocksSelect( select ) { + return ( + select( coreStore ).getEntityRecords( 'postType', 'wp_block', { + per_page: -1, + } ) ?? EMPTY_BLOCKS_LIST + ); +} + const BLOCK_EDITOR_SETTINGS = [ '__experimentalBlockDirectory', '__experimentalDiscussionSettings', @@ -92,7 +100,6 @@ function useBlockEditorSettings( settings, postType, postId ) { hasFixedToolbar, isDistractionFree, keepCaretInsideBlock, - reusableBlocks, hasUploadPermissions, hiddenBlockTypes, canUseUnfilteredHTML, @@ -103,13 +110,11 @@ function useBlockEditorSettings( settings, postType, postId ) { restBlockPatternCategories, } = useSelect( ( select ) => { - const isWeb = Platform.OS === 'web'; const { canUser, getRawEntityRecord, getEntityRecord, getUserPatternCategories, - getEntityRecords, getBlockPatternCategories, } = select( coreStore ); const { get } = select( preferencesStore ); @@ -135,11 +140,6 @@ function useBlockEditorSettings( settings, postType, postId ) { hiddenBlockTypes: get( 'core', 'hiddenBlockTypes' ), isDistractionFree: get( 'core', 'distractionFree' ), keepCaretInsideBlock: get( 'core', 'keepCaretInsideBlock' ), - reusableBlocks: isWeb - ? getEntityRecords( 'postType', 'wp_block', { - per_page: -1, - } ) - : EMPTY_BLOCKS_LIST, // Reusable blocks are fetched in the native version of this hook. hasUploadPermissions: canUser( 'create', 'media' ) ?? true, userCanCreatePages: canUser( 'create', 'pages' ), pageOnFront: siteSettings?.page_on_front, @@ -249,7 +249,8 @@ function useBlockEditorSettings( settings, postType, postId ) { unlock( select( coreStore ) ).getBlockPatternsForPostType( postType ), - __experimentalReusableBlocks: reusableBlocks, + [ unlock( privateApis ).reusableBlocksSelectKey ]: + __experimentalReusableBlocksSelect, __experimentalBlockPatternCategories: blockPatternCategories, __experimentalUserPatternCategories: userPatternCategories, __experimentalFetchLinkSuggestions: ( search, searchOptions ) => @@ -288,7 +289,6 @@ function useBlockEditorSettings( settings, postType, postId ) { keepCaretInsideBlock, settings, hasUploadPermissions, - reusableBlocks, userPatternCategories, blockPatterns, blockPatternCategories,