[RNMobile] Inner Block Navigate down through hierarchy#17547
[RNMobile] Inner Block Navigate down through hierarchy#17547lukewalczak merged 82 commits intoWordPress:masterfrom
Conversation
|
@pinarol @koke @iamthomasbishop I have pushed changes that we recently discussed and want to summarise the status of the PR once again. I have also update the PR description to cover current styling logic. I have also manage the CI test passed on Apart of one thing described at the bottom I think the PR is ready for re-review. The short summary about the progress:
It is done. However I have noticed issue when click on MediaPlaceholder in e.g. image block. Closing BottomSheet with options which pop-ups brings back selection to previously selectedRichText ( noticed also in 2. This looks new, appender is not working ✅ 3. Selection Loop ✅ 4. Dimmed content after exit app with back button on Android ✅ It happens only in demo app. Details
5. Passing styles in proper way (still discussing that) ✅ I used @koke web version demo and apply the logic to mobile app One more issue that currently can be noticed is when RichText is selected and user change selection by pressing on media placeholder. After close modal the selection will be back to RichText. It is something that is also on current develop branch. Please see GIF: |
|
Thanks a lot for the update @jbinda At this point I'd like to also invite @Tug to give this a look as well as he introduced the InnerBlocks solution on mobile side and this is the next big iteration on top of it.
Correct. This is how it works on develop as well. It is about how modals interact with the block editor on iOS currently, i don't think we should try to solve this within this PR. |
Tug
left a comment
There was a problem hiding this comment.
Approach looks good, I only had a few comments about code clarity. But generally, I would be fine going with this and iterate on the code and UX in a follow up PR.
I'll spend more time reviewing it see if there are other details I missed, would be nice to see the improvements I talked about addressed in the meantime :)
packages/block-editor/src/components/block-list/block.native.js
Outdated
Show resolved
Hide resolved
| const isDescendantSelected = selectedBlockClientId && getBlockParents( selectedBlockClientId ).includes( clientId ); | ||
| const isDescendantOfParentSelected = selectedBlockClientId && getBlockParents( selectedBlockClientId ).includes( parentId ); | ||
| const isTouchable = isSelected || isDescendantSelected || isDescendantOfParentSelected || isParentSelected || parentId === ''; | ||
| const isDimmed = ! isSelected && selectionIsNested && ! isAncestorSelected && ! isDescendantSelected && ( isDescendantOfParentSelected || rootBlockId === clientId ); |
There was a problem hiding this comment.
Those conditions looks quite hard to understand! Could we try to make them more readable? I haven't spent that much time trying to understand it yet so I might have omitted some edge cases, but from the few cases I can think of, the following conditions would be more readable imo:
const isBlockHighlighted = selectionIsNested && ( isSelected || isParentSelected );
const isDimmed = ! isBlockHighlighted;
I'm not sure how isDescendantOfParentSelected could play a role here, is there a case where a component is highlighted when a "sibling" is selected?
There was a problem hiding this comment.
As I understand, isDimmed should only be true for blocks that are outside the selection and its descendants, right? There was a suggestion to do a different think, but as far as I understand we didn't decide to go that way. It's not clear to me if we want to dim other blocks when a top level one is selected (even if it has children), or just when we start going 1+ level deep into nested blocks.
There are some redundant checks:
- If
isDescendantSelected⇒isDescendantOfParentSelected. SoisDescendantSelected || isDescendantOfParentSelected == isDescendantSelected
There was a problem hiding this comment.
I'm not sure how isDescendantOfParentSelected could play a role here, is there a case where a component is highlighted when a "sibling" is selected?
In my version it's the case when you select first child of root block. Without this check the rest of the components stays highlighted.
Next thing is that I need to dim only the bottom most descendant in each branch which should be dimmed to avoid multiplication of opacity applied to block in hierarchy. In other words if I apply opacity to block parent which fits criteria to be dimmed and them apply opacity for the block itself the block will have opacity 0.4 instead of desire 0.2. This opacity increased depending of nesting level. I hope that make sense
There is also edge case that do not dim when RootList block is selected as well.
I gave a shot for what you proposed and it does not works as expected but I will try to refactor original checks to increase clarity and write some comments in the code
There was a problem hiding this comment.
@koke I have noticed your comment now so I want to refer to what you wrote as well
There are some redundant checks:
If isDescendantSelected ⇒ isDescendantOfParentSelected. So isDescendantSelected || isDescendantOfParentSelected == isDescendantSelected
That's true according to same branch.
The case for check 'isDescendantOfParentSelected' according to below image is when we have 1-4 selected (red) and isTouchable should be set to true for 1-2, 1-5. Also 1-4-5 ,1-4-3 should be touchable(green). The blue one circle represents block that should be dimmed.
I agree that we can simplify this:
const isTouchable = isSelected || isDescendantSelected || isDescendantOfParentSelected || isParentSelected || parentId === '';
to this:
const isTouchable = isSelected || isDescendantOfParentSelected || isParentSelected || parentId === '';
1-5 should have isDescendantOfParentSelected true and isDescendantSelected false because 1-4 is not descendant of 1-5 but is descendant of 1-5 parent
There was a problem hiding this comment.
That's right, I knew one of them was redundant but I got my logic backwards 😅
There was a problem hiding this comment.
I'm still not sure about isDimmed and try to check if we can simplify
packages/block-editor/src/components/block-list/block.native.js
Outdated
Show resolved
Hide resolved
|
Hi @Tug Thanks for review. I response on comments you gave and make updates |
Tug
left a comment
There was a problem hiding this comment.
Thank you @jbinda comments really help in that case I think.
I find the dimmed/highlighted condition is still a bit complicated. As you discussed with Koke there are probably simplifications that could be made in that area.
Regarding the general UX I think this is an improvement from what we currently have so even if it could benefit some refinements, I'm all for merging it as it is now!
💯 🎉
koke
left a comment
There was a problem hiding this comment.
I think this is looking pretty good and I'd be happy to merge after addressing the few minor things I commented. 👏 👏 So happy to see this one being ready, it's been quite the effort 😅
Co-Authored-By: Jorge Bernal <jbernal@gmail.com>
Co-Authored-By: Jorge Bernal <jbernal@gmail.com>
Co-Authored-By: Jorge Bernal <jbernal@gmail.com>
|
@koke thank you for approval. I fixed thing you have pointed |
|
gutenberg repoCI pass, but still have some issue with passing gutenberg-mobile PR and will open thread on Slack to solve it |
packages/block-editor/src/components/block-list/block.native.js
Outdated
Show resolved
Hide resolved
packages/block-editor/src/components/block-list/block.native.js
Outdated
Show resolved
Hide resolved
packages/block-editor/src/components/block-list/block.native.js
Outdated
Show resolved
Hide resolved
packages/block-editor/src/components/block-list/block.native.js
Outdated
Show resolved
Hide resolved
| const isSelectedBlockNested = !! getBlockRootClientId( selectedBlockClientId ); | ||
|
|
||
| const isDescendantSelected = selectedBlockClientId && getBlockParents( selectedBlockClientId ).includes( clientId ); | ||
| const isDescendantOfParentSelected = selectedBlockClientId && getBlockParents( selectedBlockClientId ).includes( parentId ); |
There was a problem hiding this comment.
WDYT about create const with getBlockParents( selectedBlockClientId ) and use it instead of calling it 2 times?
There was a problem hiding this comment.
After reading this comment, it did look a bit related to the firstToSelect search, so I think we could have the equivalent (please double check my logic here 😉):
isDescendantSelected: if the selection is one of the descendants, then this must be a parent of the selection, which also means it will be the lowest common ancestor. SoisDescendantSelected = commonAncestor === clientIdisDescendantOfParentSelected: similar to the previous one, if the parent of this block is an ancestor of the selection, but the selection is not one of this block's descendants, then the lowest common ancestor if this block's parent:isDescendantOfParentSelected = commonAncestor === parentId
There was a problem hiding this comment.
@koke I temporary go with @dratwas suggest.
However I agree with this one isDescendantSelected = commonAncestor === clientId
but not sure about this
isDescendantOfParentSelected = commonAncestor === parentId
Shouldn't we check the common ancestor with parent of selected block ?
Then it will look like this:
const commonAncestorParent = getLowestCommonAncestorWithSelectedBlock( parentId );
const isDescendantOfParentSelected = commonAncestorParent === parentId;
There was a problem hiding this comment.
Right, I think that would change the behavior a bit. The commonAncestor == parentId would not include the case where isDescendantSelected == true. It would be more accurate to say isDescendantOfSiblingSelected, which might not be what you had in mind when doing the calculations. I think we can combine both:
const isDescendantSelected = commonAncestor === clientId;
const isDescendantOfParentSelected = isDescendantSelected || commonAncestor === parentId;But at this stage, this feels more like nitpicking, so I'm happy with either approach, we shouldn't block on this one to merge.


Description
PR is connected with #1314 in gutenberg-mobile.
Please also refer to:
Related gutenberg-mobile PR
merge this PR first [RNMobile] FloatingToolbar and [RNMobile] Inner Block Navigate upward through hierarchy
It presents ability to select all parents in cascade way (according to the way how selecting in groups works on web version)
Please also refer to below description of the logic behind the styles which is applied to the blocks
Details
During selection the main rules are:
not selectedgets dimmed if selection is nested (selected block is a child of other block)1. Blocks on RootListLevel
when a block
is selectedand do not have inner blockswhen a block
is selectedand have or could have inner blockswhen a block is
not selectedand do not have inner blockswhen a block is
not selectedand have or could have inner blocks2. Blocks that renders InnerBlock inside (a component that can have inner block inside e.g.
GrouporMediaText)InnerBlock is the only one child of component (e.g.
Group)InnerBlock is not the only one child of component (e.g.
MediaText)3. Block that is a descendant of InnerBlock component
when a parent
is selected:when ancestor
is selectedwhen a block
is selectedLEGEND:
_variables.scss
$block-edge-to-content: 16px;
$block-selected-margin: 3px;
$block-selected-border-width: 1px;
$block-selected-padding: 0;
$block-selected-child-margin: 5px;
$block-selected-child-border-width: 1px;
$block-selected-child-padding: 0;
$block-selected-to-content: $block-edge-to-content - $block-selected-margin - $block-selected-border-width;
$block-selected-child-to-content: $block-selected-to-content - $block-selected-child-margin - $block-selected-child-border-width;
$block-custom-appender-to-content: $block-edge-to-content - $block-selected-margin - $block-selected-child-margin + $block-selected-border-width;
block.native.scss
semi-border:
fully-border:
dashed-border:
neutral:
full:
selectedLeaf:
selectedRootLeaf:
selectedParent:
dimmed:
dimmed:
dimmed:
dimmed:
How has this been tested?
initial-htmlto test nested grouping with applied border styling`initial-html`
Screenshots
Initial GIF
Previous state:
Details
**1:**2:

Current state:
Details
Types of changes
getLowestCommonAncestorWithSelectedBlockselector to get blockId that is common ancestor of given block and currently selected blockonFocushandler to select block in parent hierarchy firstChecklist: