diff --git a/frontend/app_flowy/packages/appflowy_editor/lib/src/document/node_iterator.dart b/frontend/app_flowy/packages/appflowy_editor/lib/src/core/document/node_iterator.dart similarity index 74% rename from frontend/app_flowy/packages/appflowy_editor/lib/src/document/node_iterator.dart rename to frontend/app_flowy/packages/appflowy_editor/lib/src/core/document/node_iterator.dart index 8028ec1752..345bda3eda 100644 --- a/frontend/app_flowy/packages/appflowy_editor/lib/src/document/node_iterator.dart +++ b/frontend/app_flowy/packages/appflowy_editor/lib/src/core/document/node_iterator.dart @@ -1,23 +1,28 @@ import 'package:appflowy_editor/src/core/document/node.dart'; - -import './state_tree.dart'; +import 'package:appflowy_editor/src/document/state_tree.dart'; /// [NodeIterator] is used to traverse the nodes in visual order. class NodeIterator implements Iterator { + NodeIterator({ + required this.stateTree, + required this.startNode, + this.endNode, + }); + final StateTree stateTree; - final Node _startNode; - final Node? _endNode; + final Node startNode; + final Node? endNode; + Node? _currentNode; bool _began = false; - NodeIterator(this.stateTree, Node startNode, [Node? endNode]) - : _startNode = startNode, - _endNode = endNode; + @override + Node get current => _currentNode!; @override bool moveNext() { if (!_began) { - _currentNode = _startNode; + _currentNode = startNode; _began = true; return true; } @@ -27,7 +32,7 @@ class NodeIterator implements Iterator { return false; } - if (_endNode != null && _endNode == node) { + if (endNode != null && endNode == node) { _currentNode = null; return false; } @@ -42,32 +47,25 @@ class NodeIterator implements Iterator { if (nextOfParent == null) { _currentNode = null; } else { - _currentNode = _findLeadingChild(nextOfParent); + _currentNode = nextOfParent; } } return _currentNode != null; } + List toList() { + final result = []; + while (moveNext()) { + result.add(current); + } + return result; + } + Node _findLeadingChild(Node node) { while (node.children.isNotEmpty) { node = node.children.first; } return node; } - - @override - Node get current { - return _currentNode!; - } - - List toList() { - final result = []; - - while (moveNext()) { - result.add(current); - } - - return result; - } } diff --git a/frontend/app_flowy/packages/appflowy_editor/lib/src/service/internal_key_event_handlers/copy_paste_handler.dart b/frontend/app_flowy/packages/appflowy_editor/lib/src/service/internal_key_event_handlers/copy_paste_handler.dart index c87dc3e91d..8672464b2d 100644 --- a/frontend/app_flowy/packages/appflowy_editor/lib/src/service/internal_key_event_handlers/copy_paste_handler.dart +++ b/frontend/app_flowy/packages/appflowy_editor/lib/src/service/internal_key_event_handlers/copy_paste_handler.dart @@ -1,6 +1,6 @@ import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:appflowy_editor/src/infra/html_converter.dart'; -import 'package:appflowy_editor/src/document/node_iterator.dart'; +import 'package:appflowy_editor/src/core/document/node_iterator.dart'; import 'package:appflowy_editor/src/service/internal_key_event_handlers/number_list_helper.dart'; import 'package:flutter/material.dart'; import 'package:rich_clipboard/rich_clipboard.dart'; @@ -49,7 +49,11 @@ void _handleCopy(EditorState editorState) async { final beginNode = editorState.document.nodeAtPath(selection.start.path)!; final endNode = editorState.document.nodeAtPath(selection.end.path)!; - final nodes = NodeIterator(editorState.document, beginNode, endNode).toList(); + final nodes = NodeIterator( + stateTree: editorState.document, + startNode: beginNode, + endNode: endNode, + ).toList(); final copyString = NodesToHTMLConverter( nodes: nodes, @@ -316,8 +320,11 @@ void _deleteSelectedContent(EditorState editorState) { tb.commit(); return; } - final traverser = NodeIterator(editorState.document, beginNode, endNode); - + final traverser = NodeIterator( + stateTree: editorState.document, + startNode: beginNode, + endNode: endNode, + ); final tb = TransactionBuilder(editorState); while (traverser.moveNext()) { final item = traverser.current; diff --git a/frontend/app_flowy/packages/appflowy_editor/lib/src/service/selection_service.dart b/frontend/app_flowy/packages/appflowy_editor/lib/src/service/selection_service.dart index 5fcd3cfafb..4f7909223b 100644 --- a/frontend/app_flowy/packages/appflowy_editor/lib/src/service/selection_service.dart +++ b/frontend/app_flowy/packages/appflowy_editor/lib/src/service/selection_service.dart @@ -2,7 +2,7 @@ import 'package:appflowy_editor/src/infra/log.dart'; import 'package:flutter/material.dart'; import 'package:appflowy_editor/src/core/document/node.dart'; -import 'package:appflowy_editor/src/document/node_iterator.dart'; +import 'package:appflowy_editor/src/core/document/node_iterator.dart'; import 'package:appflowy_editor/src/document/position.dart'; import 'package:appflowy_editor/src/document/selection.dart'; import 'package:appflowy_editor/src/editor_state.dart'; @@ -179,8 +179,11 @@ class _AppFlowySelectionState extends State final startNode = editorState.document.nodeAtPath(start); final endNode = editorState.document.nodeAtPath(end); if (startNode != null && endNode != null) { - final nodes = - NodeIterator(editorState.document, startNode, endNode).toList(); + final nodes = NodeIterator( + stateTree: editorState.document, + startNode: startNode, + endNode: endNode, + ).toList(); if (selection.isBackward) { return nodes; } else { diff --git a/frontend/app_flowy/packages/appflowy_editor/test/core/document/node_iterator_test.dart b/frontend/app_flowy/packages/appflowy_editor/test/core/document/node_iterator_test.dart new file mode 100644 index 0000000000..1b89f4d729 --- /dev/null +++ b/frontend/app_flowy/packages/appflowy_editor/test/core/document/node_iterator_test.dart @@ -0,0 +1,32 @@ +import 'package:appflowy_editor/appflowy_editor.dart'; +import 'package:appflowy_editor/src/core/document/node_iterator.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() async { + group('node_iterator.dart', () { + test('', () { + final root = Node(type: 'root'); + for (var i = 1; i <= 10; i++) { + final node = Node(type: 'node_$i'); + for (var j = 1; j <= i; j++) { + node.insert(Node(type: 'node_${i}_$j')); + } + root.insert(node); + } + final nodes = NodeIterator( + stateTree: StateTree(root: root), + startNode: root.childAtPath([0])!, + endNode: root.childAtPath([10, 10]), + ); + + for (var i = 1; i <= 10; i++) { + nodes.moveNext(); + expect(nodes.current.type, 'node_$i'); + for (var j = 1; j <= i; j++) { + nodes.moveNext(); + expect(nodes.current.type, 'node_${i}_$j'); + } + } + }); + }); +} diff --git a/frontend/app_flowy/packages/appflowy_editor/test/core/document/node_test.dart b/frontend/app_flowy/packages/appflowy_editor/test/core/document/node_test.dart index aa78bf7a7c..43940f76f9 100644 --- a/frontend/app_flowy/packages/appflowy_editor/test/core/document/node_test.dart +++ b/frontend/app_flowy/packages/appflowy_editor/test/core/document/node_test.dart @@ -4,10 +4,6 @@ import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:flutter_test/flutter_test.dart'; void main() async { - setUpAll(() { - TestWidgetsFlutterBinding.ensureInitialized(); - }); - group('node.dart', () { test('test node copyWith', () { final node = Node(