From c75c5bd3e491a5cb48a15af9613adef6137aca56 Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Thu, 11 Apr 2024 22:28:49 +0300 Subject: [PATCH] Pattern block: avoid fetching all reusable blocks on mount (#60310) Co-authored-by: ellatrix Co-authored-by: jsnajdr --- .../src/store/private-selectors.js | 103 +++++++++++++----- packages/block-editor/src/store/selectors.js | 61 ++++++----- 2 files changed, 106 insertions(+), 58 deletions(-) diff --git a/packages/block-editor/src/store/private-selectors.js b/packages/block-editor/src/store/private-selectors.js index bc4a3ba1a797c5..126c116ac97f84 100644 --- a/packages/block-editor/src/store/private-selectors.js +++ b/packages/block-editor/src/store/private-selectors.js @@ -290,38 +290,83 @@ export const hasAllowedPatterns = createRegistrySelector( ( select ) => ) ); +function mapUserPattern( + userPattern, + __experimentalUserPatternCategories = [] +) { + 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, + }; +} + +export const getPatternBySlug = createRegistrySelector( ( select ) => + createSelector( + ( state, patternName ) => { + // Only fetch reusable blocks if we know we need them. To do: maybe + // use the entity record API to retrieve the block by slug. + if ( patternName?.startsWith( 'core/block/' ) ) { + const _id = parseInt( + patternName.slice( 'core/block/'.length ), + 10 + ); + const block = unlock( select( STORE_NAME ) ) + .getReusableBlocks() + .find( ( { id } ) => id === _id ); + + if ( ! block ) { + return null; + } + + return mapUserPattern( + block, + state.settings.__experimentalUserPatternCategories + ); + } + + return [ + // This setting is left for back compat. + ...( state.settings.__experimentalBlockPatterns ?? [] ), + ...( state.settings[ selectBlockPatternsKey ]?.( select ) ?? + [] ), + ].find( ( { name } ) => name === patternName ); + }, + ( state, patternName ) => + patternName?.startsWith( 'core/block/' ) + ? [ + unlock( select( STORE_NAME ) ).getReusableBlocks(), + state.settings.__experimentalReusableBlocks, + ] + : [ + state.settings.__experimentalBlockPatterns, + state.settings[ selectBlockPatternsKey ]?.( select ), + ] + ) +); + export const getAllPatterns = createRegistrySelector( ( select ) => createSelector( ( state ) => { - // This setting is left for back compat. - const { - __experimentalBlockPatterns = [], - __experimentalUserPatternCategories = [], - __experimentalReusableBlocks = [], - } = state.settings; - 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, + ...unlock( select( STORE_NAME ) ) + .getReusableBlocks() + .map( ( userPattern ) => + mapUserPattern( + userPattern, + state.settings.__experimentalUserPatternCategories + ) + ), + // This setting is left for back compat. + ...( state.settings.__experimentalBlockPatterns ?? [] ), ...( state.settings[ selectBlockPatternsKey ]?.( select ) ?? [] ), ].filter( ( x, index, arr ) => diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index ccb4ca8b602ebc..43b1990e3f17b4 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -2280,36 +2280,39 @@ export function __experimentalGetDirectInsertBlock( export const __experimentalGetParsedPattern = createRegistrySelector( ( select ) => - createSelector( ( state, patternName ) => { - const { getAllPatterns } = unlock( select( STORE_NAME ) ); - const patterns = getAllPatterns(); - const pattern = patterns.find( - ( { name } ) => name === patternName - ); - if ( ! pattern ) { - return null; - } - const blocks = parse( pattern.content, { - __unstableSkipMigrationLogs: true, - } ); - if ( blocks.length === 1 ) { - blocks[ 0 ].attributes = { - ...blocks[ 0 ].attributes, - metadata: { - ...( blocks[ 0 ].attributes.metadata || {} ), - categories: pattern.categories, - patternName: pattern.name, - name: - blocks[ 0 ].attributes.metadata?.name || - pattern.title, - }, + createSelector( + ( state, patternName ) => { + const pattern = unlock( select( STORE_NAME ) ).getPatternBySlug( + patternName + ); + if ( ! pattern ) { + return null; + } + const blocks = parse( pattern.content, { + __unstableSkipMigrationLogs: true, + } ); + if ( blocks.length === 1 ) { + blocks[ 0 ].attributes = { + ...blocks[ 0 ].attributes, + metadata: { + ...( blocks[ 0 ].attributes.metadata || {} ), + categories: pattern.categories, + patternName: pattern.name, + name: + blocks[ 0 ].attributes.metadata?.name || + pattern.title, + }, + }; + } + return { + ...pattern, + blocks, }; - } - return { - ...pattern, - blocks, - }; - }, getAllPatternsDependants( select ) ) + }, + ( state, patternName ) => [ + unlock( select( STORE_NAME ) ).getPatternBySlug( patternName ), + ] + ) ); const getAllowedPatternsDependants = ( select ) => ( state, rootClientId ) => [