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.
What's wrong
The docs tell apps to keep their UI in sync through the service's events, for example
CommandExecuted += (s, e) => UpdateUI()inREADME.md(~L198),docs/README.md(~L126),docs/best-practices.md(~L451) anddocs/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,CommandRedoneandSaveBoundaryCreated. 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:Each call changed observable state and raised zero events.
Why it matters
An app that follows the documented pattern shows the wrong state:
Clear()), the Undo button stays enabledLoadStateAsync()), the history panel, the Undo/Redo buttons and the "unsaved changes" indicator still describe the previous documentSuggested fix / acceptance criteria
StateChangedevent (orHistoryReset/StateRestored) toIUndoRedoService. Raise it fromClear()and from a successfulRestoreFromState(), which also coversLoadStateAsync(). Ideally also raise it after Execute, Undo, Redo, merge and trim, so a UI only needs to subscribe to one event.Clear(), a successfulLoadStateAsync()and a successfulRestoreFromState()each raise the event exactly once, and a failed load raises nothing.