-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
[Writing Flow]: Try to fix multi-selection with shift+click
#40687
Changes from all commits
da13a02
ca3c961
f32b326
d3e9c7a
a661620
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -76,43 +76,81 @@ export default function useSelectionObserver() { | |
const { multiSelect, selectBlock, selectionChange } = useDispatch( | ||
blockEditorStore | ||
); | ||
const { getBlockParents } = useSelect( blockEditorStore ); | ||
const { getBlockParents, getBlockSelectionStart } = useSelect( | ||
blockEditorStore | ||
); | ||
return useRefEffect( | ||
( node ) => { | ||
const { ownerDocument } = node; | ||
const { defaultView } = ownerDocument; | ||
|
||
function onSelectionChange() { | ||
function onSelectionChange( event ) { | ||
const selection = defaultView.getSelection(); | ||
|
||
// If no selection is found, end multi selection and disable the | ||
// contentEditable wrapper. | ||
if ( ! selection.rangeCount || selection.isCollapsed ) { | ||
if ( ! selection.rangeCount ) { | ||
setContentEditableWrapper( node, false ); | ||
return; | ||
} | ||
// If selection is collapsed and we haven't used `shift+click`, | ||
// end multi selection and disable the contentEditable wrapper. | ||
// We have to check about `shift+click` case because elements | ||
// that don't support text selection might be involved, and we might | ||
// update the clientIds to multi-select blocks. | ||
// For now we check if the event is a `mouse` event. | ||
const isClickShift = event.shiftKey && event.type === 'mouseup'; | ||
if ( selection.isCollapsed && ! isClickShift ) { | ||
setContentEditableWrapper( node, false ); | ||
return; | ||
} | ||
|
||
const clientId = getBlockClientId( | ||
let startClientId = getBlockClientId( | ||
extractSelectionStartNode( selection ) | ||
); | ||
const endClientId = getBlockClientId( | ||
let endClientId = getBlockClientId( | ||
extractSelectionEndNode( selection ) | ||
); | ||
// If the selection has changed and we had pressed `shift+click`, | ||
// we need to check if in an element that doesn't support | ||
// text selection has been clicked. | ||
if ( isClickShift ) { | ||
const selectedClientId = getBlockSelectionStart(); | ||
const clickedClientId = getBlockClientId( event.target ); | ||
// `endClientId` is not defined if we end the selection by clicking a non-selectable block. | ||
// We need to check if there was already a selection with a non-selectable focusNode. | ||
const focusNodeIsNonSelectable = | ||
clickedClientId !== endClientId; | ||
if ( | ||
( startClientId === endClientId && | ||
selection.isCollapsed ) || | ||
! endClientId || | ||
focusNodeIsNonSelectable | ||
) { | ||
endClientId = clickedClientId; | ||
} | ||
// Handle the case when we have a non-selectable block | ||
// selected and click another one. | ||
if ( startClientId !== selectedClientId ) { | ||
startClientId = selectedClientId; | ||
} | ||
Comment on lines
+131
to
+135
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This block could just as well be refactored to: startClientId = selectedClientId; … as there is no cost nor any side effect to the assignment. And this brings me to asking the broader question: couldn't we simplify the logic here into something more straightforward, with fewer conditionals, as close as possible to: if ( isClickShift ) { // This is the only branching that matters
startClientId = getBlockSelectionStart();
endClientId = getBlockClientId( event.target );
} wdyt, @ntsekouras? |
||
} | ||
|
||
// If the selection did not involve a block, return early. | ||
if ( clientId === undefined && endClientId === undefined ) { | ||
// If the selection did not involve a block, return. | ||
if ( | ||
startClientId === undefined && | ||
endClientId === undefined | ||
) { | ||
setContentEditableWrapper( node, false ); | ||
return; | ||
} | ||
|
||
const isSingularSelection = clientId === endClientId; | ||
|
||
const isSingularSelection = startClientId === endClientId; | ||
if ( isSingularSelection ) { | ||
selectBlock( clientId ); | ||
selectBlock( startClientId ); | ||
} else { | ||
const startPath = [ | ||
...getBlockParents( clientId ), | ||
clientId, | ||
...getBlockParents( startClientId ), | ||
startClientId, | ||
]; | ||
const endPath = [ | ||
...getBlockParents( endClientId ), | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These changes are unrelated - just some cleaning up.