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

Inserter: Update how we compute the actual insertion point for blocks #65490

Merged
merged 7 commits into from
Sep 24, 2024
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 @@ -186,7 +186,7 @@ export function BlockTypesTab(
continue;
}

if ( rootClientId && item.rootClientId === rootClientId ) {
if ( rootClientId && item.isAllowedInCurrentRoot ) {
itemsForCurrentRoot.push( item );
} else {
itemsRemaining.push( item );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,23 @@
* WordPress dependencies
*/
import {
getBlockType,
createBlock,
createBlocksFromInnerBlocksTemplate,
store as blocksStore,
parse,
} from '@wordpress/blocks';
import { useSelect } from '@wordpress/data';
import { useSelect, useDispatch } from '@wordpress/data';
import { useCallback, useMemo } from '@wordpress/element';
import { store as noticesStore } from '@wordpress/notices';
import { __, sprintf } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import { store as blockEditorStore } from '../../../store';
import { withRootClientIdOptionKey } from '../../../store/utils';
import { isFiltered } from '../../../store/utils';
import { unlock } from '../../../lock-unlock';

/**
* Retrieves the block types inserter state.
Expand All @@ -26,7 +30,7 @@ import { withRootClientIdOptionKey } from '../../../store/utils';
*/
const useBlockTypesState = ( rootClientId, onInsert, isQuick ) => {
const options = useMemo(
() => ( { [ withRootClientIdOptionKey ]: ! isQuick } ),
() => ( { [ isFiltered ]: !! isQuick } ),
[ isQuick ]
);
const [ items ] = useSelect(
Expand All @@ -38,6 +42,10 @@ const useBlockTypesState = ( rootClientId, onInsert, isQuick ) => {
],
[ rootClientId, options ]
);
const { getClosestAllowedInsertionPoint } = unlock(
useSelect( blockEditorStore )
);
const { createErrorNotice } = useDispatch( noticesStore );

const [ categories, collections ] = useSelect( ( select ) => {
const { getCategories, getCollections } = select( blocksStore );
Expand All @@ -46,16 +54,29 @@ const useBlockTypesState = ( rootClientId, onInsert, isQuick ) => {

const onSelectItem = useCallback(
(
{
name,
initialAttributes,
innerBlocks,
syncStatus,
content,
rootClientId: _rootClientId,
},
{ name, initialAttributes, innerBlocks, syncStatus, content },
shouldFocusBlock
) => {
const destinationClientId = getClosestAllowedInsertionPoint(
name,
rootClientId
);
if ( destinationClientId === null ) {
const title = getBlockType( name )?.title ?? name;
createErrorNotice(
sprintf(
/* translators: %s: block pattern title. */
__( 'Block "%s" can\'t be inserted.' ),
title
),
{
type: 'snackbar',
id: 'inserter-notice',
}
);
return;
}

const insertedBlock =
syncStatus === 'unsynced'
? parse( content, {
Expand All @@ -66,15 +87,14 @@ const useBlockTypesState = ( rootClientId, onInsert, isQuick ) => {
initialAttributes,
createBlocksFromInnerBlocksTemplate( innerBlocks )
);

onInsert(
insertedBlock,
undefined,
shouldFocusBlock,
_rootClientId
destinationClientId
);
},
[ onInsert ]
[ onInsert, getClosestAllowedInsertionPoint, rootClientId ]
);

return [ items, categories, collections, onSelectItem ];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,11 @@ function useInsertionPoint( {
selectBlockOnInsert = true,
} ) {
const registry = useRegistry();
const { getSelectedBlock } = useSelect( blockEditorStore );
const {
getSelectedBlock,
getClosestAllowedInsertionPoint,
isBlockInsertionPointVisible,
} = unlock( useSelect( blockEditorStore ) );
const { destinationRootClientId, destinationIndex } = useSelect(
( select ) => {
const {
Expand Down Expand Up @@ -193,21 +197,30 @@ function useInsertionPoint( {

const onToggleInsertionPoint = useCallback(
( item ) => {
if ( item?.hasOwnProperty( 'rootClientId' ) ) {
showInsertionPoint(
item.rootClientId,
getIndex( {
destinationRootClientId,
destinationIndex,
rootClientId: item.rootClientId,
registry,
} )
);
if ( item && ! isBlockInsertionPointVisible() ) {
const allowedDestinationRootClientId =
getClosestAllowedInsertionPoint(
item.name,
destinationRootClientId
);
if ( allowedDestinationRootClientId !== null ) {
showInsertionPoint(
allowedDestinationRootClientId,
getIndex( {
destinationRootClientId,
destinationIndex,
rootClientId: allowedDestinationRootClientId,
registry,
} )
);
}
} else {
hideInsertionPoint();
}
},
[
getClosestAllowedInsertionPoint,
isBlockInsertionPointVisible,
showInsertionPoint,
hideInsertionPoint,
destinationRootClientId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ const usePatternsState = ( onInsert, rootClientId, selectedCategory ) => {
),
{
type: 'snackbar',
id: 'block-pattern-inserted-notice',
id: 'inserter-notice',
}
);
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,13 +184,16 @@ export function MediaPreview( { media, onClick, category } ) {
} );
createSuccessNotice(
__( 'Image uploaded and inserted.' ),
{ type: 'snackbar' }
{ type: 'snackbar', id: 'inserter-notice' }
);
setIsInserting( false );
},
allowedTypes: ALLOWED_MEDIA_TYPES,
onError( message ) {
createErrorNotice( message, { type: 'snackbar' } );
createErrorNotice( message, {
type: 'snackbar',
id: 'inserter-notice',
} );
setIsInserting( false );
},
} );
Expand Down Expand Up @@ -281,6 +284,7 @@ export function MediaPreview( { media, onClick, category } ) {
onClick( cloneBlock( block ) );
createSuccessNotice( __( 'Image inserted.' ), {
type: 'snackbar',
id: 'inserter-notice',
} );
setShowExternalUploadModal( false );
} }
Expand Down

This file was deleted.

38 changes: 38 additions & 0 deletions packages/block-editor/src/store/private-selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
getTemplateLock,
getClientIdsWithDescendants,
isNavigationMode,
getBlockRootClientId,
} from './selectors';
import {
checkAllowListRecursive,
Expand Down Expand Up @@ -637,3 +638,40 @@ export function getZoomLevel( state ) {
export function isZoomOut( state ) {
return getZoomLevel( state ) < 100;
}

/**
* Finds the closest block where the block is allowed to be inserted.
*
* @param {Object} state Editor state.
* @param {string} name Block name.
* @param {string} clientId Default insertion point.
*
* @return {string} clientID of the closest container when the block name can be inserted.
*/
export function getClosestAllowedInsertionPoint( state, name, clientId = '' ) {
// If we're trying to insert at the root level and it's not allowed
// Try the section root instead.
if ( ! clientId ) {
if ( canInsertBlockType( state, name, clientId ) ) {
return clientId;
}

const sectionRootClientId = getSectionRootClientId( state );
if (
sectionRootClientId &&
canInsertBlockType( state, name, sectionRootClientId )
) {
return sectionRootClientId;
}
return null;
}

// Traverse the block tree up until we find a place where we can insert.
let current = clientId;
while ( current !== null && ! canInsertBlockType( state, name, current ) ) {
const parentClientId = getBlockRootClientId( state, current );
current = parentClientId;
}

return current;
}
Loading
Loading