diff --git a/packages/block-editor/src/components/inserter/hooks/use-patterns-state.js b/packages/block-editor/src/components/inserter/hooks/use-patterns-state.js index 33efedb187651..2a99e637ed123 100644 --- a/packages/block-editor/src/components/inserter/hooks/use-patterns-state.js +++ b/packages/block-editor/src/components/inserter/hooks/use-patterns-state.js @@ -2,7 +2,7 @@ * WordPress dependencies */ import { useCallback, useMemo } from '@wordpress/element'; -import { cloneBlock, parse } from '@wordpress/blocks'; +import { cloneBlock } from '@wordpress/blocks'; import { useDispatch, useSelect } from '@wordpress/data'; import { __, sprintf } from '@wordpress/i18n'; import { store as noticesStore } from '@wordpress/notices'; @@ -12,6 +12,12 @@ import { store as noticesStore } from '@wordpress/notices'; */ import { store as blockEditorStore } from '../../../store'; +const CUSTOM_CATEGORY = { + name: 'custom', + label: __( 'Custom patterns' ), + description: __( 'Custom patterns add by site users' ), +}; + /** * Retrieves the block patterns inserter state. * @@ -21,45 +27,24 @@ import { store as blockEditorStore } from '../../../store'; * @return {Array} Returns the patterns state. (patterns, categories, onSelect handler) */ const usePatternsState = ( onInsert, rootClientId ) => { - const { patternCategories, patterns, unsyncedPatterns } = useSelect( + const { patternCategories, patterns } = useSelect( ( select ) => { - const { - __experimentalGetAllowedPatterns, - getSettings, - getInserterItems, - } = select( blockEditorStore ); + const { __experimentalGetAllowedPatterns, getSettings } = + select( blockEditorStore ); + return { patterns: __experimentalGetAllowedPatterns( rootClientId ), patternCategories: getSettings().__experimentalBlockPatternCategories, - unsyncedPatterns: getInserterItems( rootClientId, 'unsynced' ), }; }, [ rootClientId ] ); - const allPatterns = useMemo( () => { - const parsedUnsyncedPatterns = unsyncedPatterns.map( - ( syncedPattern ) => ( { - title: syncedPattern.title, - name: syncedPattern.id, - categories: [ 'custom' ], - blocks: parse( syncedPattern.content, { - __unstableSkipMigrationLogs: true, - } ), - } ) - ); - return [ ...patterns, ...parsedUnsyncedPatterns ]; - }, [ unsyncedPatterns, patterns ] ); - - const allCategories = useMemo( () => { - const customPatternsCategory = { - name: 'custom', - label: __( 'Custom patterns' ), - description: __( 'Custom patterns add by site users' ), - }; - return [ ...patternCategories, customPatternsCategory ]; - }, [ patternCategories ] ); + const allCategories = useMemo( + () => [ ...patternCategories, CUSTOM_CATEGORY ], + [ patternCategories ] + ); const { createSuccessNotice } = useDispatch( noticesStore ); const onClickPattern = useCallback( @@ -82,7 +67,7 @@ const usePatternsState = ( onInsert, rootClientId ) => { [ createSuccessNotice, onInsert ] ); - return [ allPatterns, allCategories, onClickPattern ]; + return [ patterns, allCategories, onClickPattern ]; }; export default usePatternsState; diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index c51c32d8466c1..660794abba566 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -1945,7 +1945,6 @@ const buildBlockTypeItem = * * @param {Object} state Editor state. * @param {?string} rootClientId Optional root client ID of block list. - * @param {?string} syncStatus Optional sync status to filter pattern blocks by. * * @return {WPEditorInserterItem[]} Items that appear in inserter. * @@ -1962,7 +1961,7 @@ const buildBlockTypeItem = * @property {number} frecency Heuristic that combines frequency and recency. */ export const getInserterItems = createSelector( - ( state, rootClientId = null, syncStatus ) => { + ( state, rootClientId = null ) => { /* * Matches block comment delimiters amid serialized content. * @@ -2027,7 +2026,7 @@ export const getInserterItems = createSelector( }; }; - const reusableBlockInserterItems = canInsertBlockTypeUnmemoized( + const syncedPatternInserterItems = canInsertBlockTypeUnmemoized( state, 'core/block', rootClientId @@ -2035,17 +2034,14 @@ export const getInserterItems = createSelector( ? getReusableBlocks( state ) .filter( ( reusableBlock ) => - syncStatus === reusableBlock.meta?.sync_status || - ( ! syncStatus && - reusableBlock.meta?.sync_status === '' ) + // Filter to either fully synced patterns (sync_status === 'fully'), + // or old school reusable blocks (sync_status === ''). + reusableBlock.meta?.sync_status === 'fully' || + reusableBlock.meta?.sync_status === '' ) .map( buildReusableBlockInserterItem ) : []; - if ( syncStatus === 'unsynced' ) { - return reusableBlockInserterItems; - } - const buildBlockTypeInserterItem = buildBlockTypeItem( state, { buildScope: 'inserter', } ); @@ -2086,7 +2082,7 @@ export const getInserterItems = createSelector( { core: [], noncore: [] } ); const sortedBlockTypes = [ ...coreItems, ...nonCoreItems ]; - return [ ...sortedBlockTypes, ...reusableBlockInserterItems ]; + return [ ...sortedBlockTypes, ...syncedPatternInserterItems ]; }, ( state, rootClientId ) => [ state.blockListSettings[ rootClientId ], @@ -2310,10 +2306,32 @@ const checkAllowListRecursive = ( blocks, allowedBlockTypes ) => { return true; }; +function getUnsyncedPatterns( state ) { + const reusableBlocks = + state?.settings?.__experimentalReusableBlocks ?? EMPTY_ARRAY; + + return reusableBlocks + .filter( + ( reusableBlock ) => reusableBlock.meta?.sync_status === 'unsynced' + ) + .map( ( reusableBlock ) => { + return { + name: `core/block/${ reusableBlock.id }`, + title: reusableBlock.title.raw, + categories: [ 'custom' ], + content: reusableBlock.content.raw, + }; + } ); +} + export const __experimentalGetParsedPattern = createSelector( ( state, patternName ) => { const patterns = state.settings.__experimentalBlockPatterns; - const pattern = patterns.find( ( { name } ) => name === patternName ); + const unsyncedPatterns = getUnsyncedPatterns( state ); + + const pattern = [ ...patterns, ...unsyncedPatterns ].find( + ( { name } ) => name === patternName + ); if ( ! pattern ) { return null; } @@ -2324,14 +2342,20 @@ export const __experimentalGetParsedPattern = createSelector( } ), }; }, - ( state ) => [ state.settings.__experimentalBlockPatterns ] + ( state ) => [ + state.settings.__experimentalBlockPatterns, + state.settings.__experimentalReusableBlocks, + ] ); const getAllAllowedPatterns = createSelector( ( state ) => { const patterns = state.settings.__experimentalBlockPatterns; + const unsyncedPatterns = getUnsyncedPatterns( state ); + const { allowedBlockTypes } = getSettings( state ); - const parsedPatterns = patterns + + const parsedPatterns = [ ...patterns, ...unsyncedPatterns ] .filter( ( { inserter = true } ) => !! inserter ) .map( ( { name } ) => __experimentalGetParsedPattern( state, name ) @@ -2343,6 +2367,7 @@ const getAllAllowedPatterns = createSelector( }, ( state ) => [ state.settings.__experimentalBlockPatterns, + state.settings.__experimentalReusableBlocks, state.settings.allowedBlockTypes, ] ); @@ -2369,6 +2394,7 @@ export const __experimentalGetAllowedPatterns = createSelector( }, ( state, rootClientId ) => [ state.settings.__experimentalBlockPatterns, + state.settings.__experimentalReusableBlocks, state.settings.allowedBlockTypes, state.settings.templateLock, state.blockListSettings[ rootClientId ],