Skip to content

Clear(), LoadStateAsync() and RestoreFromState() raise no event, so UIs synced through events show stale CanUndo/CanRedo/unsaved state #114

Description

@matt-edmondson

What's wrong

The docs tell apps to keep their UI in sync through the service's events, for example CommandExecuted += (s, e) => UpdateUI() in README.md (~L198), docs/README.md (~L126), docs/best-practices.md (~L451) and docs/getting-started.md (~L212). But three methods replace the whole history (stack, position and save boundaries) without raising any event:

  • UndoRedoService.Clear() (UndoRedo/Services/UndoRedoService.cs ~L213)
  • LoadStateAsync() (~L359)
  • RestoreFromState() (~L387)

The only events are CommandExecuted, CommandUndone, CommandRedone and SaveBoundaryCreated. None of them fires on these paths, and there's no general "state changed" event an app could subscribe to instead.

Reproduction

A counter is subscribed to all four events. The steps are Execute(A), SaveStateAsync, Execute(B), then reset the counter:

after Clear:   events=0 CanUndo=False Count=0
after Load:    ok=True events=0 Count=1
after Restore: ok=True events=0 CanUndo=False

Each call changed observable state and raised zero events.

Why it matters

An app that follows the documented pattern shows the wrong state:

  • after "New document" (Clear()), the Undo button stays enabled
  • after opening a document (LoadStateAsync()), the history panel, the Undo/Redo buttons and the "unsaved changes" indicator still describe the previous document
  • clicking the stale Undo button does nothing, or behaves unexpectedly

Suggested fix / acceptance criteria

  • Add a StateChanged event (or HistoryReset / StateRestored) to IUndoRedoService. Raise it from Clear() and from a successful RestoreFromState(), which also covers LoadStateAsync(). Ideally also raise it after Execute, Undo, Redo, merge and trim, so a UI only needs to subscribe to one event.
  • Tests: Clear(), a successful LoadStateAsync() and a successful RestoreFromState() each raise the event exactly once, and a failed load raises nothing.
  • Update the UI-sync examples in the docs to use the new event.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions