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

Drag & Drop: Fix unexpected row/gallery creation logic #64241

Merged
merged 4 commits into from
Aug 6, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
92 changes: 78 additions & 14 deletions packages/block-editor/src/components/use-block-drop-zone/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,27 @@ export function isDropTargetValid(
return areBlocksAllowed && targetMatchesDraggedBlockParents;
}

/**
* Check if the Row or the Gallery can be created with the dragged
* blocks and the target block.
* @param {boolean} areAllImages
* @param {boolean} canInsertGalleryBlock
* @param {boolean} areGroupableBlocks
* @param {boolean} canInsertRow
* @return {boolean} Whether Row block or Gallery can be created.
*/
function canCreateRowOrGallery(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This process might not even need to be made into a function.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Either or" I think.

It doesn't abstract much and could be inline and just as neat. Unless it needs unit testing.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same. Since it's only used in one place, I'd lean slightly toward inlining unless it needs unit testing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed the function and inlined it here 👍

areAllImages,
canInsertGalleryBlock,
areGroupableBlocks,
canInsertRow
) {
if ( areAllImages ) {
return canInsertGalleryBlock || ( areGroupableBlocks && canInsertRow );
}
return areGroupableBlocks && canInsertRow;
}

/**
* @typedef {Object} WPBlockDropZoneConfig
* @property {?HTMLElement} dropZoneElement Optional element to be used as the drop zone.
Expand Down Expand Up @@ -301,15 +322,18 @@ export default function useBlockDropZone( {
operation: 'insert',
} );

const { getBlockType } = useSelect( blocksStore );
const { getBlockType, getBlockVariations, getGroupingBlockName } =
useSelect( blocksStore );
const {
canInsertBlockType,
getBlockListSettings,
getBlocks,
getBlockIndex,
getDraggedBlockClientIds,
getBlockNamesByClientId,
getAllowedBlocks,
isDragging,
isGroupable,
} = unlock( useSelect( blockEditorStore ) );
const {
showInsertionPoint,
Expand Down Expand Up @@ -385,21 +409,57 @@ export default function useBlockDropZone( {
};
} );

const dropTargetPosition = getDropTargetPosition(
blocksData,
{ x: event.clientX, y: event.clientY },
getBlockListSettings( targetRootClientId )?.orientation,
{
dropZoneElement,
parentBlockClientId,
parentBlockOrientation: parentBlockClientId
? getBlockListSettings( parentBlockClientId )
?.orientation
: undefined,
rootBlockIndex: getBlockIndex( targetRootClientId ),
}
);

const [ targetIndex, operation, nearestSide ] =
getDropTargetPosition(
blocksData,
{ x: event.clientX, y: event.clientY },
getBlockListSettings( targetRootClientId )?.orientation,
{
dropZoneElement,
parentBlockClientId,
parentBlockOrientation: parentBlockClientId
? getBlockListSettings( parentBlockClientId )
?.orientation
: undefined,
rootBlockIndex: getBlockIndex( targetRootClientId ),
}
dropTargetPosition;

if ( operation === 'group' ) {
const targetBlock = blocks[ targetIndex ];
const areAllImages = [
targetBlock.name,
...draggedBlockNames,
].every( ( name ) => name === 'core/image' );
const canInsertGalleryBlock = canInsertBlockType(
'core/gallery',
targetRootClientId
);
const areGroupableBlocks = isGroupable( [
targetBlock.clientId,
getDraggedBlockClientIds(),
] );
const groupBlockVariations = getBlockVariations(
getGroupingBlockName(),
'block'
);
const canInsertRow =
groupBlockVariations &&
groupBlockVariations.find(
( { name } ) => name === 'group-row'
);
const _canCreateRowOrGallery = canCreateRowOrGallery(
areAllImages,
canInsertGalleryBlock,
areGroupableBlocks,
canInsertRow
);
if ( ! _canCreateRowOrGallery ) {
return;
}
}

registry.batch( () => {
setDropTarget( {
Expand Down Expand Up @@ -436,6 +496,10 @@ export default function useBlockDropZone( {
showInsertionPoint,
isDragging,
startDragging,
canInsertBlockType,
getBlockVariations,
getGroupingBlockName,
isGroupable,
]
),
200
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,6 @@ export default function useOnBlockDrop(
getBlocksByClientId,
getSettings,
getBlock,
isGroupable,
} = useSelect( blockEditorStore );
const { getGroupingBlockName } = useSelect( blocksStore );
const {
Expand All @@ -255,17 +254,11 @@ export default function useOnBlockDrop(
if ( ! Array.isArray( blocks ) ) {
blocks = [ blocks ];
}

const clientIds = getBlockOrder( targetRootClientId );
const clientId = clientIds[ targetBlockIndex ];
const blocksClientIds = blocks.map( ( block ) => block.clientId );
const areGroupableBlocks = isGroupable( [
...blocksClientIds,
clientId,
] );
if ( operation === 'replace' ) {
replaceBlocks( clientId, blocks, undefined, initialPosition );
} else if ( operation === 'group' && areGroupableBlocks ) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At this point, it is guaranteed that at least one of the Row block or Gallery block can be created, so areGroupableBlocks is not necessary.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just double-checking, is that because this check is now happening in the throttle'd function instead, prior to displaying the drop indicator and setting the drop target?

It looks like that other code also calls isGroupable, too 👍. From memory the other thing we needed to check was that the hovered over block can be removed, so as long as the check is happening somewhere that sounds good to me!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just double-checking, is that because this check is now happening in the "throttle"'d function instead, prior to displaying the drop indicator and setting the drop target?

Yes. If the areGroupableBlocks check is present here, the gallery block will not be created when the following conditions are met:

  • The Group block is unregistered
  • he dragged blocks and the target block are all images

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for clarifying!

} else if ( operation === 'group' ) {
const targetBlock = getBlock( clientId );
if ( nearestSide === 'left' ) {
blocks.push( targetBlock );
Expand Down Expand Up @@ -325,7 +318,6 @@ export default function useOnBlockDrop(
getBlockOrder,
targetRootClientId,
targetBlockIndex,
isGroupable,
operation,
replaceBlocks,
getBlock,
Expand Down
Loading