Skip to content

Keep a reloaded command's navigation context and metadata [patch] - #135

Merged
matt-edmondson merged 1 commit into
mainfrom
fix/94-restore-serialized-command-state
Oct 7, 2026
Merged

matt-edmondson merged 1 commit into
mainfrom
fix/94-restore-serialized-command-state

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Fixes #94

Problem

JsonUndoRedoSerializer writes NavigationContext and Metadata for every command. On load, only the PlaceholderCommand fallback read them back. A command that implements ISerializableCommand was rebuilt with Activator.CreateInstance and DeserializeData, so it kept whatever its parameterless constructor set:

  • no navigation context
  • change size 1
  • a timestamp equal to the load time
  • no custom data

As a result, UndoAsync and RedoAsync stopped navigating after LoadStateAsync.

Change

  • BaseCommand gains an internal RestoreSerializedState(string? navigationContext, ChangeMetadata metadata), which uses the existing protected set setters. The public API does not change.
  • ConvertFromSerializableCommand calls it after DeserializeData whenever the rebuilt instance is a BaseCommand.

Tests

  • New test UndoRedoService_LoadStateSerializableCommand_RestoresNavigationContextAndMetadata round-trips an ISerializableCommand through SaveStateAsync and LoadStateAsync. It checks the navigation context and every metadata field: change type, affected items, size, timestamp and custom data. It then checks that UndoAsync calls the navigation provider with line:42.
  • With the serializer change reverted, the new test fails on Assert.AreEqual("line:42", reloaded.NavigationContext).
  • Full suite with the fix: 122 of 122 pass on net10.0.

🤖 Generated with Claude Code

https://claude.ai/code/session_017crwGv42t1FV1Sp9QxoQNe


Generated by Claude Code

A command that implements ISerializableCommand is rebuilt with its
parameterless constructor and DeserializeData, so it came back with no
NavigationContext and default metadata (size 1, timestamp at load time).
UndoAsync and RedoAsync then stopped navigating after LoadStateAsync.

BaseCommand gains an internal RestoreSerializedState hook, which the JSON
serializer calls after DeserializeData to put back the saved navigation
context and metadata.

Fixes #94

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017crwGv42t1FV1Sp9QxoQNe
@sonarqubecloud

sonarqubecloud Bot commented Oct 7, 2026

Copy link
Copy Markdown

@matt-edmondson
matt-edmondson merged commit 4de68c2 into main Oct 7, 2026
14 checks passed
@matt-edmondson
matt-edmondson deleted the fix/94-restore-serialized-command-state branch October 7, 2026 08:57
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.

A reloaded ISerializableCommand loses its NavigationContext and ChangeMetadata, so UndoAsync/RedoAsync no longer navigate after LoadStateAsync

2 participants