-
Notifications
You must be signed in to change notification settings - Fork 246
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
[SuperEditor] - Make all DocumentNodes immutable (Resolves #2166) #2384
base: main
Are you sure you want to change the base?
Conversation
… a blockquote use-case, and ToggleTextAttributionsCommand
…per_editor/supereditor_text_layout_test.dart
FYI @miguelcmedeiros @brian-superlist @jmatth @Jethro87 - This PR will likely break some things for you. The fixes should be pretty simple and straight forward, but some changes will likely be necessary for you. Changing document nodes to immutable brings us one step closer to capturing snapshots for undo/redo. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM with a single comment.
@@ -375,49 +418,31 @@ abstract class DocumentNode implements ChangeNotifier { | |||
} | |||
|
|||
/// Returns all metadata attached to this [DocumentNode]. | |||
Map<String, dynamic> get metadata => _metadata; | |||
Map<String, dynamic> get metadata => Map.from(_metadata); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we really need to create a new map that copies all items each time? If we just want to prevent modifications, could we use UnmodifiableMapView
instead?
From the docs:
View of a Map that disallow modifying the map.
A wrapper around a Map that forwards all members to the map provided in the constructor, except for operations
that modify the map. Modifying operations throw instead.
[SuperEditor] - Make all DocumentNodes immutable (Resolves #2166)
For undo/redo and edit transactions to be trustable, the document and its nodes need to be immutable from outside the
Editor
. This PR makes that conversion.Replacing nodes
By making nodes immutable, each node can no longer be directly updated for things like changing text, indent, etc. Instead, every time a change is made to a node, the previous node must be replaced by the new node in the document. For that reason, a lot of the changes in this PR is focused on switching from direct node manipulation to document node replacement.
This also means that tests need to re-query nodes throughout the test. We should avoid storing nodes as intermediate values in tests, whenever we can, so that we don't accidentally try to look for changes on the same immutable node.
New copy methods
Moving from direct editing of a node to node replacement, we need the ability to
copyWith()
changes. Unfortunately, there's not a clean solution to this because Dart doesn't support method overloading. As a result, to deal with subclasses, we have to declare things likecopyTextNodeWith()
,copyParagraphWith()
, andcopyTaskWith()
. Moreover, each subclass needs to adjust the superclass copy method so that subclass instances don't lose some of their data when the parent class' copy method is called.