-
Notifications
You must be signed in to change notification settings - Fork 4.6k
Refactor: Content only template locking block editing modes to reducer #67606
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
Changes from all commits
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 |
|---|---|---|
|
|
@@ -3076,62 +3076,36 @@ export function __unstableIsWithinBlockOverlay( state, clientId ) { | |
| * @return {BlockEditingMode} The block editing mode. One of `'disabled'`, | ||
| * `'contentOnly'`, or `'default'`. | ||
| */ | ||
| export const getBlockEditingMode = createRegistrySelector( | ||
| ( select ) => | ||
| ( state, clientId = '' ) => { | ||
| // Some selectors that call this provide `null` as the default | ||
| // rootClientId, but the default rootClientId is actually `''`. | ||
| if ( clientId === null ) { | ||
| clientId = ''; | ||
| } | ||
| export function getBlockEditingMode( state, clientId = '' ) { | ||
| // Some selectors that call this provide `null` as the default | ||
| // rootClientId, but the default rootClientId is actually `''`. | ||
| if ( clientId === null ) { | ||
| clientId = ''; | ||
| } | ||
|
|
||
| const isNavMode = isNavigationMode( state ); | ||
|
|
||
| // If the editor is currently not in navigation mode, check if the clientId | ||
| // has an editing mode set in the regular derived map. | ||
| // There may be an editing mode set here for synced patterns or in zoomed out | ||
| // mode. | ||
| if ( | ||
| ! isNavMode && | ||
| state.derivedBlockEditingModes?.has( clientId ) | ||
| ) { | ||
| return state.derivedBlockEditingModes.get( clientId ); | ||
| } | ||
| const isNavMode = isNavigationMode( state ); | ||
|
Member
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.
Contributor
Author
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. It is related and not. Write Mode has now taken that tool's place, but the API used is still the same. So navigation mode === write mode.
Member
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. My brain hurts. |
||
|
|
||
| // If the editor *is* in navigation mode, the block editing mode states | ||
| // are stored in the derivedNavModeBlockEditingModes map. | ||
| if ( | ||
| isNavMode && | ||
| state.derivedNavModeBlockEditingModes?.has( clientId ) | ||
| ) { | ||
| return state.derivedNavModeBlockEditingModes.get( clientId ); | ||
| } | ||
| // If the editor is currently not in navigation mode, check if the clientId | ||
| // has an editing mode set in the regular derived map. | ||
| // There may be an editing mode set here for synced patterns or in zoomed out | ||
| // mode. | ||
| if ( ! isNavMode && state.derivedBlockEditingModes?.has( clientId ) ) { | ||
| return state.derivedBlockEditingModes.get( clientId ); | ||
| } | ||
|
|
||
| // In normal mode, consider that an explicitly set editing mode takes over. | ||
| const blockEditingMode = state.blockEditingModes.get( clientId ); | ||
| if ( blockEditingMode ) { | ||
| return blockEditingMode; | ||
| } | ||
| // If the editor *is* in navigation mode, the block editing mode states | ||
| // are stored in the derivedNavModeBlockEditingModes map. | ||
| if ( isNavMode && state.derivedNavModeBlockEditingModes?.has( clientId ) ) { | ||
| return state.derivedNavModeBlockEditingModes.get( clientId ); | ||
| } | ||
|
Comment on lines
+3096
to
+3100
Contributor
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. Should we only have
Contributor
Author
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. I guess there are no cases where If so, I think what you suggest is probably a good idea, though perhaps
Contributor
Author
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. Lets handle it in a separate PR given the code for this is already in trunk. |
||
|
|
||
| // In normal mode, top level is default mode. | ||
| if ( clientId === '' ) { | ||
| return 'default'; | ||
| } | ||
| // In normal mode, consider that an explicitly set editing mode takes over. | ||
| if ( state.blockEditingModes.has( clientId ) ) { | ||
| return state.blockEditingModes.get( clientId ); | ||
| } | ||
|
|
||
| const rootClientId = getBlockRootClientId( state, clientId ); | ||
| const templateLock = getTemplateLock( state, rootClientId ); | ||
| // If the parent of the block is contentOnly locked, check whether it's a content block. | ||
| if ( templateLock === 'contentOnly' ) { | ||
| const name = getBlockName( state, clientId ); | ||
| const { hasContentRoleAttribute } = unlock( | ||
| select( blocksStore ) | ||
| ); | ||
| const isContent = hasContentRoleAttribute( name ); | ||
| return isContent ? 'contentOnly' : 'disabled'; | ||
| } | ||
| return 'default'; | ||
| } | ||
|
Comment on lines
-3121
to
-3133
Contributor
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. I really like the refactor to move this logic to the reducer rather than spreading it out within the getter.
Member
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. Just so I understand, is the selling point that previously, every call to getBlockEditingMode would traverse the entire block tree and recalculate. Now it's computed once per state change?
Contributor
Author
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. The history is that some time ago Synced Patterns didn't work properly in Write Mode. I tried fixing that by adding extra code to the I had to buy some more performance in order to be able to fix that bug, and so I've done that by moving code from the selector. I think the code is still far from good, but it's a tough problem to solve, and I think it's reflective of how complicated the features that use blockEditingModes are. We should try to simplify both the features and the code where we can. |
||
| ); | ||
| return 'default'; | ||
| } | ||
|
|
||
| /** | ||
| * Indicates if a block is ungroupable. | ||
|
|
||

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.
Do you think it's worth adding performance tests later?
I could be totally barking up the wrong tree, but let's say we have a document with 10,000 blocks, does this mean we're storing 10,000 block editing modes entries in memory?
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.
I did a very crude js heap comparision using
window.performance.memoryand I couldn't see any memory degradation comparing trunk with this PR based on aderivedNavModeBlockEditingModescount of 40. Total heap size hovered around200-280 MBUh oh!
There was an error while loading. Please reload this page.
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.
We do already have performance tests in CI, but then I don't think they test these modes.
Not really, not every block gets a block editing mode. Only
contentOnlyordisabledblocks are given one. Most of the time blocks will just bedefaultand then they have no mode set.But anyway, if we have 10,000 blocks in the post, we'd be storing other state for those blocks, so why not a block editing mode? It is only a short string.
I think the issue is more about whether we update 10,000 blocks on every state change, and we don't.
Here's some of the performance related checks the reducer does:
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.
Thanks for the explainer! 🙇🏻