-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
Block Editor: Fix undo level inconsistencies. #17259
Conversation
@epiqueras I added some e2e tests that should pass, and do pass before #16932. They are still failing with these changes though. I think one undo level has been removed, but for some reason there's still one being created with the first letter. |
That's because the Block Editor is marking it as persistent (calling |
Sure. Where is it doing that? |
When you type that first character. |
@epiqueras I meant in the code :) |
No idea, I thought you might know, because of your |
@epiqueras RichText doesn't mark the first character as persistent. It continuously calls |
So, the issue is probably coming from somewhere else in the block editor. In your tests, you are also seeing the first character passed through |
Well, it follows this logic: gutenberg/packages/block-editor/src/store/reducer.js Lines 341 to 350 in dd7782a
The first character's edit is not updating the same attribute as the last edit right? How should we go about this? I think the logic behind Also, do you have an example of a release where this worked correctly? |
|
Should we not make sure this all works before the last Gutenberg release of WP 5.3? |
d195dae
to
a40ce33
Compare
@ellatrix I think we can merge this now with the latest changes? |
… against the last action in the persistent block change HOR.
a40ce33
to
e816e71
Compare
Rebased the branch as I was getting some PHP errors with the current checkout of WP core. |
Looks way better now. Still seeing some inconsistencies.
|
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.
Functionally it looks good. Would be great if the last e2e test case that I added could be fixed. Codewise I don't have any objections, but would be great if someone familiar with the core-data
package could provide a second review.
} ); | ||
|
||
const comparisonUndoEdits = Object.values( action.meta.undo.edits ).filter( ( edit ) => typeof edit !== 'function' ); |
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 is this checking for? Would be great to inline comment.
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.
That the last two edits are not the same.
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'm more wondering what the filter is for. :)
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.
When an edit is a function it's an optimization to avoid running some expensive operation. We can't rely on the function references being the same so we opt out of comparing them here.
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.
That could use an inline comment.
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'm working on it with another fix.
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.
edits && | ||
Object.keys( edits ).some( | ||
( key ) => | ||
edits[ key ] !== ( has( post, [ key, 'raw' ] ) ? post[ key ].raw : post[ key ] ) |
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 raw
key seems very API specific. Given all the API abstractions, is this the right place to check for the raw
key?
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.
Yeah, it's not ideal. I think we should deprecate initial edits if possible.
So this is all fine in the end? Anything that should be changed? |
Since this seems more or less ready, and fixing important issues, I'd suggest we include it in Gutenberg 6.5. |
420ead2 adds a test case for the third item listed in this comment: #16932 (comment). This PR fixes the issue. |
For the demo content being dirty. That was a decision we made on purpose after some discussions with @jasmussen and @epiqueras |
Ok sure, I agree, that's just a minor thing. |
I'm fine with reverting the test case introduced in d1817b6 for now if it would take too long to fix. It's good to have the other fixes merged. |
With that test case I meant the first item in #17259 (comment), not the demo content one. Would still be great to fix for 5.3 separately. |
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 opinion, feel free to merge. :)
Description
This PR fixes a couple of undo level related inconsistencies that surfaced after merging #16932.
In the Block Editor,
withPersistentBlockChange
marks any change to an attribute different than the last, as persistent. However, it considers all actions for this comparison, so an explicit persistence change triggered by a timeout like the one that fires after not typing for a while, would break this "chain of comparison", and the next change would be marked as persistent even if targeted at the same attribute as the one before the explicit persistence change. This resulted in scenarios where typing "Hello", waiting a bit, then typing "World", would result in 4 undo levels instead of 3. Namely, there would be an extra unnecessary undo level in the middle, requiring an extra click to undo. This PR fixes this by ignoring explicit persistence changes when comparing the last two attribute changes.In the Editor, the decision was made to consider initial edits as dirtying operations that create an undo level and enable saving functionality. For some reason, the server sends an empty initial edit with empty strings for the title, excerpt, and content of new posts. This results in another unnecessary undo level. This PR fixes this by ignoring initial edits that would not change any values of the post.
How has this been tested?
It was verified that typing two words with a pause in between does not create an undo level and that new posts don't load with an undo level.
Types of Changes
Bug Fix: Stop inserting unnecessary undo levels between words an on empty posts.
Checklist: