Skip to content
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

Table of Contents: fix undo history quirk #41031

Open
ZebulanStanphill opened this issue May 12, 2022 · 4 comments
Open

Table of Contents: fix undo history quirk #41031

ZebulanStanphill opened this issue May 12, 2022 · 4 comments
Labels
[Block] Table of contents (experimental) Affects the Table of contents Block [Feature] History History, undo, redo, revisions, autosave. [Type] Bug An existing feature does not function as intended

Comments

@ZebulanStanphill
Copy link
Member

Description

As noted in #29739, there is an undesirable quirk with the current implementation of the Table of Contents block:

When a Table of Contents block is present, every letter typed in a Heading block counts as a separate undo step, in contrast to the default behavior of multiple letters typed in sequence being combined into a single undo step. This only affects typing in Heading blocks; other blocks continue to behave as expected, with whole strings of sequentially typed text counted as a single undo step as expected.

Unfortunately, I am not aware of any way to fix this, so I could use some expert technical help here.

Step-by-step reproduction instructions

  1. Insert a Table of Contents block.
  2. Insert a Heading block.
  3. Type "Hello world" into the Heading block.
  4. Click the "Undo" button in the main toolbar of the editor.
  5. Notice that each undo step removes a single character, instead of the entire sequence of typed text.

Screenshots, screen recording, code snippet

No response

Environment info

  • WP 6.0-alpha-52828
  • Gutenberg trunk as of ff56d57

Please confirm that you have searched existing issues in the repo.

Yes

Please confirm that you have tested with all plugins deactivated except Gutenberg.

Yes

@ZebulanStanphill ZebulanStanphill added [Type] Bug An existing feature does not function as intended Needs Dev Ready for, and needs developer efforts [Feature] History History, undo, redo, revisions, autosave. [Block] Table of contents (experimental) Affects the Table of contents Block labels May 12, 2022
@kevin940726
Copy link
Member

I believe this issue is caused by having to do setAttributes in useEffect on changes of some external data.

As I mentioned in this comment of how and why "undo trap" is an issue, although this issue is technically not that kind of issue, they are similar in a way that most practices still apply.

If we edit a Heading block character-on-character, (I think) this happens:

  1. Type in H, the block calls setAttributes({ content: 'H' }).
  2. Type in i, the block calls setAttributes({ content: 'Hi' }), isUpdatingSameBlockAttribute is true, not pushing to the undo stack (not persistent).
  3. Stop typing, push Hi to the undo stack. Results in only one undo level.

However, if we add a ToC block to the post, something changes because of the useEffect we have:

  1. Type in H, the Heading block calls setAttributes({ content: 'H' }), the Heading block is updated to H.
  2. The useEffect in the ToC block picks up the change and updates itself with setAttributes({ headings }). This breaks the isUpdatingSameBlockAttribute check in the original flow, thus creating a new undo level.
  3. Type in i, the Heading block calls setAttributes({ content: 'Hi' }), the same thing happens again from (1).

I'm not sure if there's an easy solution for this, but one possible solution might be refactoring the block into a dynamic block so that it doesn't have to call setAttributes inside useEffect at the wrong time.

Note: A more general way to think about this is to "derive the state" rather than setting them in useEffect. However, since we can't call useSelect in Save, the architecture makes it extremely hard to do so. The official doc even recommends us to store derived states in attributes. I think we might need a new API or data type for the derived states, but that's for a bigger conversation.

@kevin940726
Copy link
Member

kevin940726 commented Jul 19, 2022

I'm not sure if there's an easy solution for this

Well, I think we can listen to isTyping and only update the ToC block when the user stops typing. The ToC block will update itself with a delay though, but I think it's acceptable in most cases. I'll put up a draft PR using this method.

Scratch that, I don't think isTyping is the right property to listen to. But the idea is the same: defer the update. I'll keep looking.

Scratch that too 😅, I don't think delaying the update is the right approach, it'll still break the undo history. We might have to go for the dynamic block approach in the current architecture.

@priethor priethor added the [Priority] High Used to indicate top priority items that need quick attention label Aug 29, 2022
@richtabor
Copy link
Member

richtabor commented Jun 29, 2023

I don't think this is a big enough deal to block.

Sure, if the block needs to go dynamic to better support identifying headings within the post content, wherever the block is rendered on the page (#41173 (comment)), it's fine to dive in after—but otherwise it's hardly noticeable.

@github-actions github-actions bot added the [Status] In Progress Tracking issues with work in progress label Sep 6, 2023
@Mamaduka Mamaduka removed the Needs Dev Ready for, and needs developer efforts label Sep 6, 2023
@Mamaduka Mamaduka removed their assignment Nov 28, 2023
@Mamaduka Mamaduka removed the [Status] In Progress Tracking issues with work in progress label Nov 28, 2023
@annezazu annezazu removed the [Priority] High Used to indicate top priority items that need quick attention label Dec 19, 2023
@annezazu
Copy link
Contributor

👋🏼 I'm doing a sweep of high priority issues to keep this label relevant and actionable. This effort has clearly stalled so the label has been removed as it was added in a release specific window. If you believe this should be added back in, please comment with some context. I am making my best estimates across the project and want to get this right!

P.S. there's a current effort underway that might nicely address this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Block] Table of contents (experimental) Affects the Table of contents Block [Feature] History History, undo, redo, revisions, autosave. [Type] Bug An existing feature does not function as intended
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants