Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Try integrating unsynced patterns directly into pattern selectors #51955

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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.
*
Expand All @@ -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(
Expand All @@ -82,7 +67,7 @@ const usePatternsState = ( onInsert, rootClientId ) => {
[ createSuccessNotice, onInsert ]
);

return [ allPatterns, allCategories, onClickPattern ];
return [ patterns, allCategories, onClickPattern ];
};

export default usePatternsState;
54 changes: 40 additions & 14 deletions packages/block-editor/src/store/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand All @@ -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.
*
Expand Down Expand Up @@ -2027,25 +2026,22 @@ export const getInserterItems = createSelector(
};
};

const reusableBlockInserterItems = canInsertBlockTypeUnmemoized(
const syncedPatternInserterItems = canInsertBlockTypeUnmemoized(
state,
'core/block',
rootClientId
)
? 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',
} );
Expand Down Expand Up @@ -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 ],
Expand Down Expand Up @@ -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;
}
Expand All @@ -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 )
Expand All @@ -2343,6 +2367,7 @@ const getAllAllowedPatterns = createSelector(
},
( state ) => [
state.settings.__experimentalBlockPatterns,
state.settings.__experimentalReusableBlocks,
state.settings.allowedBlockTypes,
]
);
Expand All @@ -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 ],
Expand Down