From eed8cb5c3b3cfe3a2adc78491c0065c8e8f3f394 Mon Sep 17 00:00:00 2001 From: ntsekouras Date: Fri, 15 Oct 2021 15:07:01 +0300 Subject: [PATCH 1/2] [Block Editor]: Fix selection by holding shift key for nested blocks --- .../use-block-props/use-multi-selection.js | 24 +++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/packages/block-editor/src/components/block-list/use-block-props/use-multi-selection.js b/packages/block-editor/src/components/block-list/use-block-props/use-multi-selection.js index 93f84ef6067cfd..75e9dca6c322f5 100644 --- a/packages/block-editor/src/components/block-list/use-block-props/use-multi-selection.js +++ b/packages/block-editor/src/components/block-list/use-block-props/use-multi-selection.js @@ -165,15 +165,29 @@ export function useMultiSelection( clientId ) { if ( event.shiftKey ) { const blockSelectionStart = getBlockSelectionStart(); - // Handle the case where we select a single block by - // holding the `shiftKey` and don't mark this action - // as multiselection. + // By checking `blockSelectionStart` to be set, we handle the + // case where we select a single block. We also have to check + // the selectionEnd (clientId) not to be included in the + // `blockSelectionStart`'s parents because the click event is + // propagated. + const startParents = getBlockParents( blockSelectionStart ); if ( blockSelectionStart && - blockSelectionStart !== clientId + blockSelectionStart !== clientId && + ! startParents?.includes( clientId ) ) { toggleRichText( node, false ); - multiSelect( blockSelectionStart, clientId ); + const startPath = [ + ...startParents, + blockSelectionStart, + ]; + const endPath = [ + ...getBlockParents( clientId ), + clientId, + ]; + const depth = + Math.min( startPath.length, endPath.length ) - 1; + multiSelect( startPath[ depth ], endPath[ depth ] ); event.preventDefault(); } } else if ( hasMultiSelection() ) { From c36fafac80f78d96be2e954a30f1d260491c1c92 Mon Sep 17 00:00:00 2001 From: ntsekouras Date: Fri, 15 Oct 2021 18:03:32 +0300 Subject: [PATCH 2/2] add e2e tests --- .../various/multi-block-selection.test.js | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/packages/e2e-tests/specs/editor/various/multi-block-selection.test.js b/packages/e2e-tests/specs/editor/various/multi-block-selection.test.js index 7921ea67c249dd..c87700e23d3e1f 100644 --- a/packages/e2e-tests/specs/editor/various/multi-block-selection.test.js +++ b/packages/e2e-tests/specs/editor/various/multi-block-selection.test.js @@ -11,6 +11,7 @@ import { clickButton, clickMenuItem, saveDraft, + transformBlockTo, } from '@wordpress/e2e-test-utils'; async function getSelectedFlatIndices() { @@ -311,6 +312,58 @@ describe( 'Multi-block selection', () => { ` ); } ); + it( 'should properly select multiple blocks if selected nested blocks belong to different parent', async () => { + await clickBlockAppender(); + await page.keyboard.type( 'first' ); + await page.keyboard.press( 'Enter' ); + await page.keyboard.type( 'group' ); + // Multiselect via keyboard. + await page.keyboard.down( 'Shift' ); + await page.keyboard.press( 'ArrowUp' ); + await page.keyboard.up( 'Shift' ); + await transformBlockTo( 'Group' ); + await page.keyboard.press( 'Enter' ); + await page.keyboard.type( 'second' ); + await page.keyboard.press( 'Enter' ); + await page.keyboard.type( 'group' ); + await page.keyboard.down( 'Shift' ); + await page.keyboard.press( 'ArrowUp' ); + await page.keyboard.up( 'Shift' ); + await transformBlockTo( 'Group' ); + await page.keyboard.press( 'ArrowDown' ); + + // Click the first paragraph in the first Group block while pressing `shift` key. + const firstParagraph = await page.waitForXPath( "//p[text()='first']" ); + await page.keyboard.down( 'Shift' ); + await firstParagraph.click(); + await page.keyboard.up( 'Shift' ); + + await page.waitForSelector( '.is-multi-selected' ); + const selectedBlocks = await page.$$( '.is-multi-selected' ); + expect( selectedBlocks ).toHaveLength( 2 ); + } ); + it( 'should properly select part of nested rich text block while holding shift', async () => { + await clickBlockAppender(); + await page.keyboard.type( 'rich text in group' ); + await transformBlockTo( 'Group' ); + await page.keyboard.press( 'ArrowDown' ); + + await page.keyboard.down( 'Shift' ); + const paragraph = await page.$( '[data-type="core/paragraph"]' ); + const { x, y } = await paragraph.boundingBox(); + await page.mouse.move( x + 20, y ); + await page.mouse.down(); + await page.keyboard.up( 'Shift' ); + await page.keyboard.type( 'hi' ); + expect( await getEditedPostContent() ).toMatchInlineSnapshot( ` + " +
+

hih text in group

+
+ " + ` ); + } ); + it( 'should select by dragging', async () => { await clickBlockAppender(); await page.keyboard.type( '1' );