Skip to content

feat: expose clearHistory() to reset the undo/redo stack#373

Merged
SSShooter merged 6 commits intoSSShooter:masterfrom
DisciplinedSoftware:feat/clear-history
Mar 11, 2026
Merged

feat: expose clearHistory() to reset the undo/redo stack#373
SSShooter merged 6 commits intoSSShooter:masterfrom
DisciplinedSoftware:feat/clear-history

Conversation

@DisciplinedSoftware
Copy link
Copy Markdown
Contributor

Motivation

When an application loads new data into an existing MindElixir instance via refresh(), the internal undo/redo history still contains snapshots from the previous diagram. This lets users press Ctrl+Z and silently travel back into an earlier diagram's state — a confusing and data-loss-prone experience.

A host needs a way to discard that stale history after loading new data.

Changes

src/plugin/operationHistory.ts

Adds mei.clearHistory(), which:

  • clears the history array
  • resets currentIndex to -1
  • re-captures current from mei.getData() so the fresh snapshot is the new undo baseline

src/types/index.ts

Declares clearHistory: () => void on MindElixirInstance with a JSDoc comment explaining its purpose.

Usage

mind.refresh(newData)
mind.clearHistory() // users can no longer undo back into the previous diagram

Adds a clearHistory() method to the operationHistory plugin that
resets the undo/redo stack to an empty state with a fresh baseline
snapshot. This is needed by hosts that load new data into an
existing MindElixir instance (e.g. via refresh()) and want to
prevent users from undoing back into the previous diagram's state.
Copilot AI review requested due to automatic review settings March 10, 2026 05:01
@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses a potential data-loss and confusing user experience when an application refreshes a MindElixir instance with new data. By exposing a new clearHistory() method, it provides a mechanism for applications to reset the undo/redo stack, ensuring that users cannot inadvertently revert to the state of a previously loaded diagram.

Highlights

  • New clearHistory() method: Introduced mei.clearHistory() to allow hosts to discard stale undo/redo history after loading new data, preventing users from undoing into previous diagram states.
  • clearHistory() implementation: The clearHistory() method clears the internal history array, resets currentIndex to -1, and captures the current diagram state as the new undo baseline.
  • Type definition and documentation: Added clearHistory: () => void to the MindElixirInstance interface in src/types/index.ts with a detailed JSDoc comment.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • src/plugin/operationHistory.ts
    • Implemented the clearHistory method on the MindElixirInstance to reset the undo/redo history.
  • src/types/index.ts
    • Added the clearHistory method signature and JSDoc documentation to the MindElixirInstance interface.
Activity
  • No human activity has been recorded for this pull request yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a clearHistory() method to the MindElixir instance, allowing users to reset the undo/redo stack after loading new data. No security vulnerabilities were found. However, there is a type safety concern where the MindElixirInstance interface defines clearHistory as a mandatory method, but its runtime assignment is conditional on the allowUndo option, which could lead to runtime errors if invoked when allowUndo is false.

Comment on lines +124 to +130
/**
* Reset the undo/redo stack and update the internal baseline snapshot to the
* current diagram state. Call this after loading new data into an existing
* instance (e.g. after `refresh()`) to prevent users from undoing back into
* a previously loaded diagram.
*/
clearHistory: () => void
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The clearHistory method is declared as mandatory in the MindElixirInstance interface. However, its implementation in src/plugin/operationHistory.ts is only applied to the instance if the allowUndo option is true (as seen in src/methods.ts, line 94). If allowUndo is false, mei.clearHistory will not be defined at runtime, which could lead to a TypeError if the method is called, despite the type definition indicating its presence. To prevent this type-runtime mismatch, clearHistory should be marked as optional in the interface.

Suggested change
/**
* Reset the undo/redo stack and update the internal baseline snapshot to the
* current diagram state. Call this after loading new data into an existing
* instance (e.g. after `refresh()`) to prevent users from undoing back into
* a previously loaded diagram.
*/
clearHistory: () => void
/**
* Reset the undo/redo stack and update the internal baseline snapshot to the
* current diagram state. Call this after loading new data into an existing
* instance (e.g. after `refresh()`) to prevent users from undoing back into
* a previously loaded diagram.
*/
clearHistory?: () => void

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 15a42c9 — changed to clearHistory?: () => void and updated the JSDoc to note that it is only available when allowUndo is true.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a public API to reset MindElixir’s undo/redo history after loading new data into an existing instance (e.g., via refresh()), preventing users from undoing back into a previously loaded diagram.

Changes:

  • Add mei.clearHistory() to clear the operation history stack and re-baseline the “current” snapshot.
  • Extend MindElixirInstance typings with a documented clearHistory() method.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
src/plugin/operationHistory.ts Implements mei.clearHistory() to reset internal history state and baseline snapshot.
src/types/index.ts Exposes clearHistory(): void on the public MindElixirInstance type with JSDoc guidance.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

* instance (e.g. after `refresh()`) to prevent users from undoing back into
* a previously loaded diagram.
*/
clearHistory: () => void
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clearHistory is declared as a required method on MindElixirInstance, but it’s only assigned inside the operationHistory plugin (and that plugin is skipped when allowUndo is false and in lite mode). This makes the type contract unsafe for consumers because mind.clearHistory() can be undefined at runtime. Consider either (a) making clearHistory optional in the interface, or (b) defining a default no-op implementation on the instance/prototype so it always exists regardless of allowUndo/build mode.

Suggested change
clearHistory: () => void
clearHistory?: () => void

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 15a42c9 — changed to clearHistory?: () => void and updated the JSDoc to note that it is only available when allowUndo is true.

mei.clearHistory = function () {
history = []
currentIndex = -1
current = mei.getData()
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clearHistory() clears the history stack but leaves currentSelectedNodes unchanged. Since the intended usage is right after refresh(), selection is typically cleared, and the next operation may incorrectly record the previous diagram’s selected node IDs in currentSelected, which can break selection restoration on undo/redo. Reset currentSelectedNodes inside clearHistory() (e.g., derive it from mei.currentNodes) or update the selection tracking to handle deselection events as well.

Suggested change
current = mei.getData()
current = mei.getData()
// keep cached selection in sync with current diagram state
currentSelectedNodes = mei.currentNodes.map(n => n.nodeObj)

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 601dc4b — added currentSelectedNodes = [] to clearHistory() so stale node IDs from the previous diagram cannot affect selection restoration after refresh() + clearHistory().

Comment on lines +91 to +95
mei.clearHistory = function () {
history = []
currentIndex = -1
current = mei.getData()
}
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No automated test is added for the new clearHistory() behavior. There are existing Playwright specs covering operation history/undo/redo; please add a test that (1) performs some operations, (2) calls refresh(newData) + clearHistory(), then (3) asserts that undo/redo cannot revert into the pre-refresh diagram and that the first undo baseline is the refreshed data.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added in 1e50bf0 — new file tests/clear-history.spec.ts with three Playwright tests:

  1. Undo cannot revert into the pre-refresh diagram — performs ops on diagram A, calls refresh(B) + clearHistory(), then asserts Ctrl+Z/Ctrl+Y are no-ops across the diagram boundary.
  2. Operations after clearHistory() are undoable normally — verifies that new operations on diagram B undo/redo correctly, and that the stack doesn't reach back into diagram A.
  3. First undo baseline is the refreshed state — verifies that undoing the first post-refresh operation lands exactly on the refreshed diagram, not an earlier one.

…iew fixes

- Reset currentSelectedNodes to [] so stale selection IDs from the
  previous diagram cannot corrupt undo/redo selection restoration after
  a refresh + clearHistory() call.
- (types updated in next commit to mark clearHistory as optional)
clearHistory is only registered by the operationHistory plugin, which is
skipped when allowUndo is false. Declaring it as a required method would
be a type-runtime mismatch. Mark it optional and update the JSDoc to
mention the allowUndo prerequisite.
@DisciplinedSoftware
Copy link
Copy Markdown
Contributor Author

Thank you both for the reviews! Fixed in the two follow-up commits:

clearHistory?: () => void (optional) — changed in 15a42c9. The JSDoc now also explicitly notes that clearHistory is only available when allowUndo is true.

currentSelectedNodes reset — added currentSelectedNodes = [] inside clearHistory() in 601dc4b. Without this, stale node IDs from the previous diagram could corrupt selection restoration on the first undo after a refresh() + clearHistory() call.

Tests — noted. The existing Playwright test suite for operation history would be the right place; happy to add a test case if that would help move this forward.

Tests verify:
- Undo cannot revert into a pre-refresh diagram after clearHistory()
- Operations performed after clearHistory() are themselves undoable/redoable
- The first undo baseline is the refreshed diagram state, not a prior one
Copy link
Copy Markdown
Owner

@SSShooter SSShooter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your contribution! This is indeed a design oversight, but a few changes are needed here.

history = []
currentIndex = -1
current = mei.getData()
currentSelectedNodes = []
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

better use mei.clearSelection()

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's indeed better. Done.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the test is failing, please remove it for now.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oups...
The tests should pass now.

Copy link
Copy Markdown
Owner

@SSShooter SSShooter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@SSShooter SSShooter merged commit 14ff39b into SSShooter:master Mar 11, 2026
1 check passed
@DisciplinedSoftware DisciplinedSoftware deleted the feat/clear-history branch March 11, 2026 15:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants