-
Notifications
You must be signed in to change notification settings - Fork 4.1k
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
Add inserterInsertionPoint state to enable updating block insertion point on block selection change #65098
base: trunk
Are you sure you want to change the base?
Conversation
Size Change: +2.52 kB (+0.14%) Total Size: 1.77 MB
ℹ️ View Unchanged
|
I was also trying to find the right solution for this issue and came to a similar conclusion. We should probably fully revert #64048 and work on an alternative fix for #63866. Why revert? Zoom-out mode is still experimental (behind the settings flag); experimental features should hinder stable ones. |
@Mamaduka - I'm fine reverting #64048 as well. I've been looking at this most of the day and feel like there's a deeper issue at play. The insertion point is bound to the editor, and gets set when the inserter opens. The idea of the inserter staying open and the insertion point changing wasn’t a thing when this was designed, because the inserter was supposed to close and reset when focus was moved out of it. Now that it stays open and you can interact with the canvas, we have this muddling of states where the insertion point can change while the inserter is open. |
I worked more on this today to move the insertion point into the block editor package. It's working correctly for the zoom out inserters. I really dislike the naming of all the things as it's so hard to untangle which insertion point means what :/ |
cc @WordPress/gutenberg-core |
* @param {string} value.filterValue A query to filter the inserter results. | ||
* @param {Function} value.onSelect A callback when an item is selected. | ||
* @param {string} value.tab The tab to open in the inserter. | ||
* @param {string} value.category The category to initialize in the inserter. |
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 are not new, just adding the documentation for things already in use.
- _value.filterValue_ `string`: A query to filter the inserter results. | ||
- _value.onSelect_ `Function`: A callback when an item is selected. | ||
- _value.tab_ `string`: The tab to open in the inserter. | ||
- _value.category_ `string`: The category to initialize in the inserter. |
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 are not new, just adding the documentation for things already in use.
} else if ( | ||
insertionPoint?.insertionIndex && | ||
insertionPoint?.rootClientId | ||
) { | ||
_destinationRootClientId = insertionPoint.rootClientId; | ||
_destinationIndex = insertionPoint.insertionIndex; |
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.
Putting this after the insertionIndex
or clientId
to preserve the existing API. This lets anyone who passes these values in via the props to still have full control.
export function setInserterInsertionPoint( value ) { | ||
return { | ||
type: 'SET_INSERTER_INSERTION_POINT', | ||
value, | ||
}; | ||
} | ||
|
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 don't like this naming, but it's at least clear 🤷🏻 I'm concerned that this assumes only one instance of the inserter, while the editor package way passes it in. That said, it's still possible to manually pass the inserter the root block and index and it will be respected.
case 'SELECT_BLOCK': | ||
return null; |
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.
Clear the insertion point after a new block selection.
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.
In my testing, the vertical displacement is still visible after selecting a different block.
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.
To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
This reverts commit df849a9.
392038a
to
a90bb7f
Compare
Flaky tests detected in 6e858a6. 🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/10819186444
|
Performance charts after the revert PR was merged. We should monitor "Inserter Hovering Items" results while working on the fix. Screenshot |
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 noticed something weird that I can't reproduce on trunk. I'm not sure if it's related to this PR nor what's going on. The testing environment is Playground.
Kapture.2024-09-11.at.16.29.35.mp4
Notice how sometimes selecting the pattern will insert it at the wrong place. And some other times hover over sections will rerender the patterns inserter.
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 taking this one. Some things I noticed.
_destinationRootClientId = insertionPoint?.rootClientId | ||
? insertionPoint.rootClientId | ||
: rootClientId; | ||
_destinationIndex = insertionPoint.insertionIndex; |
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.
The other conditions have comments to explain them. Could we add one here?
setInserterIsOpened( { | ||
rootClientId, | ||
insertionIndex, | ||
filterValue, | ||
onSelect, | ||
} ); | ||
setInserterInsertionPoint( { rootClientId, insertionIndex } ); |
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 could have the editor stores setInserterIsOpened
dispatch the setInserterInsertionPoint
to the block editor store as part of the action. That said it might be clearer this way as the "set inserter is opened" communicates "toggling" rather than "setting an insertion point".
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 think we might want to setInserterInsertionPoint
without setInserterIsOpened
as well - for example if you're using the quick inserter.
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.
But what about backwards compat on the setInserterIsOpened
API?
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.
What I mean is that I think its good to have the flexibility of calling these independently rather than tying one to the other.
* @param {string} value.rootClientId The root client ID to insert at. | ||
* @param {number} value.insertionIndex The index to insert at. |
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 could continue to make this backwards compatible by dispatching the new action to the block editor store if the rootClientId
or the insertionIndex
are provided as part of value
. You could also fire a deprecated notice in the console.
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 like this idea.
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.
This API has changed. It's a public API. We have to ensure it's backwards compatible.
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.
You can still pass these things, they just don't do anything within our implementation of the block editor. I'll add a deprecation and fire that though.
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.
...they just don't do anything
That was the bit I was concerned about because if a public API used to do something it needs to continue to do that.
Looks like you fixed it up now 👍
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 can’t deprecate a public API/feature and suggest to use a private API instead.
It would be non-actionable for consumers.
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 think it would also be fine to not deprecate any of it. You can still pass it those props, it just won't do anything in our codebase 🤷🏻
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.
Yeh actually we don't need to deprecate it do we? @Mamaduka is right that we can't point to a private API - great spot there.
I have a couple of surface notes:
Screenshot |
From memory, there's a difference between Would it work to create a new action called |
@Mamaduka - I agree, but I don't see another way to address this without blurring the boundaries of the block-editor and editor package further, as we really need I think we can make this simpler by improving the naming and docs around it. For example, it's already confusing that |
@kevin940726 - Thanks for catching that! The zoom out mode inserters and zoom out mode separators were relying on I think this also fixed the pattern rerendering. |
@kevin940726 - Ok - the pattern list reloading is a deeper issue. It does happen on trunk too. I haven't found the exact reproduction route yet, but it happens when using the zoom out inserters to insert some patterns. Enter them around in various places and eventually you'll get the pattern list reloading when hovering into/out of a section. Seems to be caused by something within So, it should be addressed, but outside the scope of this PR. |
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 tried to break this and I couldn't. I think it's ready!
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 can't land this until the changes to public APIs have been handled. From what I see they haven't been yet.
* @param {string} value.rootClientId The root client ID to insert at. | ||
* @param {number} value.insertionIndex The index to insert at. |
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.
This API has changed. It's a public API. We have to ensure it's backwards compatible.
If the Zoom out mode stays experimental for WP 6.7, then I think we should delay merging until last Gutenberg RC is released (probably next week). |
I'm very fine not implementing this change before 6.7 unless necessary :) I'd like to do a larger refactor of the insertion api, as I think it needs it. Idea and issue overview forthcoming. Draft PR here: #65282 |
Public API has now been handled for backwards compat and has a deprecated warning
Is that because there could be unexpected sideeffects? |
* @param {Object} state | ||
* @return {Object} Of where the insertion point in the block editor is or null if none is set. | ||
*/ | ||
export function getInserterInsertionPoint( state ) { |
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.
Could we name this getInsertionPoint
instead? The same name is in the editor package. I would much prefer getInsertionPoint
as it could be set without the inserter and we don't really want the block-editor to know about the editor package.
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.
If there's no name clash, then set/getInsertionPoint
sounds much better.
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.
There isn't a name clash if I change enough names 😉 😅 I changed quite a bit of naming in 64dcd1f. The main source of confusion for it will be the naming of getBlockInsertionPoint
, but at least now when you look at it it's more obvious that it's returning the state of insertionCue
. So, while still confusing, maybe it'll be easier to understand the flow.
@scruffian, yes. We can be more cautious if a feature/fix isn't required for the next major release. |
- old block-editor insertionPoint becomes insertionCue (for the reducer and state value) - which opens up insertionPoint to be the real insertion point - so we can change getInserterInsertionPoint to getInsertionPoint - rename editor private getInsertionPoint to getInserter to more accurately describe its state - remove unnecessary deprecation
What?
Add inserterInsertionPoint global state to the block editor package.
Why?/How
Now that the inserter can remain open while interacting with the block canvas, it is expected that when you select a new block, the insertion will occur after the selected block.
The insertion point is handled by the editor package via
setIsInserterOpened( value )
, which can take an object to open the inserter to a certain tab panel and also provide the place where the insertion should happen. We want to change this insertion point when selecting a new block on the canvas. Block selection is handled via the block editor package. Since the block editor should not know about the editor, and we can't rely on theSELECTION_CHANGE
action to clear the insertion point within the editor store, I've moved the insertion point data to be within the block editor package.I think the inserter tab and category settings could also be moved, but we can wait on that part.
How?
setInserterInsertionPoint( { rootClientId, insertionIndex } );
in the places we were also opening the inserter from the canvas inserters.SELECT_BLOCK
Testing Instructions
For pattern insertion points in Zoom Out
Default Editing
Testing Instructions for Keyboard
Screenshots or screencast