refactor: move path to core/document

This commit is contained in:
Lucas.Xu 2022-10-09 23:53:18 +08:00
parent 7f92f8988f
commit b9788bce09
24 changed files with 108 additions and 56 deletions

View File

@ -4,7 +4,7 @@ library appflowy_editor;
export 'src/infra/log.dart';
export 'src/render/style/editor_style.dart';
export 'src/core/document/node.dart';
export 'src/document/path.dart';
export 'src/core/document/path.dart';
export 'src/document/position.dart';
export 'src/document/selection.dart';
export 'src/document/state_tree.dart';
@ -28,7 +28,6 @@ export 'src/service/shortcut_event/keybinding.dart';
export 'src/service/shortcut_event/shortcut_event.dart';
export 'src/service/shortcut_event/shortcut_event_handler.dart';
export 'src/extensions/attributes_extension.dart';
export 'src/extensions/path_extensions.dart';
export 'src/render/rich_text/default_selectable.dart';
export 'src/render/rich_text/flowy_rich_text.dart';
export 'src/render/selection_menu/selection_menu_widget.dart';

View File

@ -2,7 +2,7 @@ import 'dart:async';
import 'package:appflowy_editor/src/commands/text_command_infra.dart';
import 'package:appflowy_editor/src/core/document/node.dart';
import 'package:appflowy_editor/src/document/path.dart';
import 'package:appflowy_editor/src/core/document/path.dart';
import 'package:appflowy_editor/src/editor_state.dart';
import 'package:appflowy_editor/src/operation/transaction_builder.dart';
import 'package:flutter/widgets.dart';

View File

@ -3,7 +3,7 @@ import 'package:appflowy_editor/src/commands/text_command_infra.dart';
import 'package:appflowy_editor/src/core/document/attributes.dart';
import 'package:appflowy_editor/src/document/built_in_attribute_keys.dart';
import 'package:appflowy_editor/src/core/document/node.dart';
import 'package:appflowy_editor/src/document/path.dart';
import 'package:appflowy_editor/src/core/document/path.dart';
import 'package:appflowy_editor/src/document/selection.dart';
import 'package:appflowy_editor/src/editor_state.dart';

View File

@ -3,7 +3,7 @@ import 'dart:async';
import 'package:appflowy_editor/src/commands/text_command_infra.dart';
import 'package:appflowy_editor/src/core/document/attributes.dart';
import 'package:appflowy_editor/src/core/document/node.dart';
import 'package:appflowy_editor/src/document/path.dart';
import 'package:appflowy_editor/src/core/document/path.dart';
import 'package:appflowy_editor/src/document/selection.dart';
import 'package:appflowy_editor/src/editor_state.dart';
import 'package:appflowy_editor/src/operation/transaction_builder.dart';

View File

@ -1,5 +1,5 @@
import 'package:appflowy_editor/src/core/document/node.dart';
import 'package:appflowy_editor/src/document/path.dart';
import 'package:appflowy_editor/src/core/document/path.dart';
import 'package:appflowy_editor/src/document/selection.dart';
import 'package:appflowy_editor/src/editor_state.dart';

View File

@ -3,8 +3,8 @@ import 'dart:collection';
import 'package:flutter/material.dart';
import 'package:appflowy_editor/src/core/document/attributes.dart';
import 'package:appflowy_editor/src/core/document/path.dart';
import 'package:appflowy_editor/src/document/built_in_attribute_keys.dart';
import 'package:appflowy_editor/src/document/path.dart';
import 'package:appflowy_editor/src/document/text_delta.dart';
class Node extends ChangeNotifier with LinkedListEntry<Node> {

View File

@ -1,17 +1,23 @@
import 'package:appflowy_editor/src/document/path.dart';
import 'dart:math';
import 'package:flutter/foundation.dart';
typedef Path = List<int>;
extension PathExtensions on Path {
bool equals(Path other) {
return listEquals(this, other);
}
bool operator >=(Path other) {
if (pathEquals(this, other)) {
if (equals(other)) {
return true;
}
return this > other;
}
bool operator >(Path other) {
if (pathEquals(this, other)) {
if (equals(other)) {
return false;
}
final length = min(this.length, other.length);
@ -29,14 +35,14 @@ extension PathExtensions on Path {
}
bool operator <=(Path other) {
if (pathEquals(this, other)) {
if (equals(other)) {
return true;
}
return this < other;
}
bool operator <(Path other) {
if (pathEquals(this, other)) {
if (equals(other)) {
return false;
}
final length = min(this.length, other.length);

View File

@ -1,7 +0,0 @@
import 'package:flutter/foundation.dart';
typedef Path = List<int>;
bool pathEquals(Path path1, Path path2) {
return listEquals(path1, path2);
}

View File

@ -1,4 +1,4 @@
import './path.dart';
import 'package:appflowy_editor/src/core/document/path.dart';
class Position {
final Path path;
@ -14,7 +14,7 @@ class Position {
if (other is! Position) {
return false;
}
return pathEquals(path, other.path) && offset == other.offset;
return path.equals(other.path) && offset == other.offset;
}
@override

View File

@ -1,6 +1,5 @@
import 'package:appflowy_editor/src/document/path.dart';
import 'package:appflowy_editor/src/core/document/path.dart';
import 'package:appflowy_editor/src/document/position.dart';
import 'package:appflowy_editor/src/extensions/path_extensions.dart';
/// Selection represents the selected area or the cursor area in the editor.
///
@ -38,7 +37,7 @@ class Selection {
final Position end;
bool get isCollapsed => start == end;
bool get isSingle => pathEquals(start.path, end.path);
bool get isSingle => start.path.equals(end.path);
bool get isForward =>
(start.path > end.path) || (isSingle && start.offset > end.offset);
bool get isBackward =>

View File

@ -1,7 +1,7 @@
import 'dart:math';
import 'package:appflowy_editor/src/core/document/node.dart';
import 'package:appflowy_editor/src/document/path.dart';
import 'package:appflowy_editor/src/core/document/path.dart';
import 'package:appflowy_editor/src/document/text_delta.dart';
import '../core/document/attributes.dart';

View File

@ -1,7 +1,7 @@
import 'package:appflowy_editor/src/core/document/node.dart';
import 'package:appflowy_editor/src/core/document/path.dart';
import 'package:appflowy_editor/src/document/selection.dart';
import 'package:appflowy_editor/src/extensions/object_extensions.dart';
import 'package:appflowy_editor/src/extensions/path_extensions.dart';
import 'package:appflowy_editor/src/render/selection/selectable.dart';
import 'package:flutter/material.dart';

View File

@ -1,5 +1,5 @@
import 'package:appflowy_editor/src/core/document/node.dart';
import 'package:appflowy_editor/src/document/path.dart';
import 'package:appflowy_editor/src/core/document/path.dart';
import 'package:appflowy_editor/src/document/position.dart';
import 'package:appflowy_editor/src/document/selection.dart';
import 'package:appflowy_editor/src/document/text_delta.dart';
@ -168,7 +168,7 @@ extension TextNodesExtension on List<TextNode> {
for (var i = 0; i < length; i++) {
final node = this[i];
final Selection newSelection;
if (i == 0 && pathEquals(node.path, selection.start.path)) {
if (i == 0 && node.path.equals(selection.start.path)) {
if (selection.isBackward) {
newSelection = selection.copyWith(
end: Position(path: node.path, offset: node.toPlainText().length),
@ -178,8 +178,7 @@ extension TextNodesExtension on List<TextNode> {
end: Position(path: node.path, offset: 0),
);
}
} else if (i == length - 1 &&
pathEquals(node.path, selection.end.path)) {
} else if (i == length - 1 && node.path.equals(selection.end.path)) {
if (selection.isBackward) {
newSelection = selection.copyWith(
start: Position(path: node.path, offset: 0),

View File

@ -3,7 +3,7 @@ import 'dart:math';
import 'package:appflowy_editor/src/core/document/attributes.dart';
import 'package:appflowy_editor/src/core/document/node.dart';
import 'package:appflowy_editor/src/document/path.dart';
import 'package:appflowy_editor/src/core/document/path.dart';
import 'package:appflowy_editor/src/document/position.dart';
import 'package:appflowy_editor/src/document/selection.dart';
import 'package:appflowy_editor/src/document/text_delta.dart';
@ -197,7 +197,7 @@ class TransactionBuilder {
if (last != null) {
if (op is TextEditOperation &&
last is TextEditOperation &&
pathEquals(op.path, last.path)) {
op.path.equals(last.path)) {
final newOp = TextEditOperation(
op.path,
last.delta.compose(op.delta),

View File

@ -6,7 +6,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:appflowy_editor/src/core/document/node.dart';
import 'package:appflowy_editor/src/document/path.dart';
import 'package:appflowy_editor/src/core/document/path.dart';
import 'package:appflowy_editor/src/document/position.dart';
import 'package:appflowy_editor/src/document/selection.dart';
import 'package:appflowy_editor/src/document/text_delta.dart';
@ -123,7 +123,7 @@ class _FlowyRichTextState extends State<FlowyRichText> with SelectableMixin {
@override
List<Rect> getRectsInSelection(Selection selection) {
assert(selection.isSingle &&
pathEquals(selection.start.path, widget.textNode.path));
selection.start.path.equals(widget.textNode.path));
final textSelection = TextSelection(
baseOffset: selection.start.offset,

View File

@ -1,10 +1,10 @@
import 'package:appflowy_editor/src/core/document/attributes.dart';
import 'package:appflowy_editor/src/core/document/node.dart';
import 'package:appflowy_editor/src/core/document/path.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';
import 'package:appflowy_editor/src/extensions/text_node_extensions.dart';
import 'package:appflowy_editor/src/extensions/path_extensions.dart';
import 'package:appflowy_editor/src/operation/transaction_builder.dart';
import 'package:appflowy_editor/src/document/built_in_attribute_keys.dart';

View File

@ -29,7 +29,7 @@ void _handleCopy(EditorState editorState) async {
if (selection == null || selection.isCollapsed) {
return;
}
if (pathEquals(selection.start.path, selection.end.path)) {
if (selection.start.path.equals(selection.end.path)) {
final nodeAtPath = editorState.document.nodeAtPath(selection.end.path)!;
if (nodeAtPath.type == "text") {
final textNode = nodeAtPath as TextNode;
@ -306,7 +306,7 @@ void _deleteSelectedContent(EditorState editorState) {
}
final beginNode = editorState.document.nodeAtPath(selection.start.path)!;
final endNode = editorState.document.nodeAtPath(selection.end.path)!;
if (pathEquals(selection.start.path, selection.end.path) &&
if (selection.start.path.equals(selection.end.path) &&
beginNode.type == "text") {
final textItem = beginNode as TextNode;
final tb = TransactionBuilder(editorState);

View File

@ -3,12 +3,12 @@ import 'package:flutter/material.dart';
import 'package:appflowy_editor/src/core/document/node.dart';
import 'package:appflowy_editor/src/core/document/node_iterator.dart';
import 'package:appflowy_editor/src/core/document/path.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';
import 'package:appflowy_editor/src/extensions/node_extensions.dart';
import 'package:appflowy_editor/src/extensions/object_extensions.dart';
import 'package:appflowy_editor/src/extensions/path_extensions.dart';
import 'package:appflowy_editor/src/render/selection/cursor_widget.dart';
import 'package:appflowy_editor/src/render/selection/selectable.dart';
import 'package:appflowy_editor/src/render/selection/selection_widget.dart';

View File

@ -27,6 +27,7 @@ void main() async {
expect(nodes.current.type, 'node_${i}_$j');
}
}
expect(nodes.moveNext(), false);
});
});
}

View File

@ -149,23 +149,23 @@ void main() async {
type: 'base',
);
// insert at the front
// insert at the front when node's children is empty
final childA = Node(
type: 'child',
);
base.insert(childA, index: -1);
base.insert(childA);
expect(
identical(base.childAtIndex(0), childA),
true,
);
// insert at the last
// insert at the front
final childB = Node(
type: 'child',
);
base.insert(childB, index: 1000);
base.insert(childB, index: -1);
expect(
identical(base.childAtIndex(base.children.length - 1), childB),
identical(base.childAtIndex(0), childB),
true,
);
@ -173,19 +173,39 @@ void main() async {
final childC = Node(
type: 'child',
);
base.insert(childC);
base.insert(childC, index: 1000);
expect(
identical(base.childAtIndex(base.children.length - 1), childC),
true,
);
// insert at the last
final childD = Node(
type: 'child',
);
base.insert(childD);
expect(
identical(base.childAtIndex(base.children.length - 1), childD),
true,
);
// insert at the second
final childE = Node(
type: 'child',
);
base.insert(childE, index: 1);
expect(
identical(base.childAtIndex(1), childE),
true,
);
});
test('test fromJson', () {
final node = Node.fromJson({
'type': 'example',
'attributes': {
'example': 'example',
},
'type': 'text',
'delta': [
{'insert': 'example'},
],
'children': [
{
'type': 'example',
@ -195,8 +215,10 @@ void main() async {
},
],
});
expect(node.type, 'example');
expect(node.attributes, {'example': 'example'});
expect(node.type, 'text');
expect(node is TextNode, true);
expect((node as TextNode).delta.toPlainText(), 'example');
expect(node.attributes, {});
expect(node.children.length, 1);
expect(node.children.first.type, 'example');
expect(node.children.first.attributes, {'example': 'example'});

View File

@ -0,0 +1,33 @@
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:flutter_test/flutter_test.dart';
void main() async {
group('path.dart', () {
test('test path equality', () {
var p1 = [0, 0];
var p2 = [0];
expect(p1 > p2, true);
expect(p1 >= p2, true);
expect(p1 < p2, false);
expect(p1 <= p2, false);
p1 = [1, 1, 2];
p2 = [1, 1, 3];
expect(p2 > p1, true);
expect(p2 >= p1, true);
expect(p2 < p1, false);
expect(p2 <= p1, false);
p1 = [2, 0, 1];
p2 = [2, 0, 1];
expect(p2 > p1, false);
expect(p1 > p2, false);
expect(p2 >= p1, true);
expect(p2 <= p1, true);
expect(p1.equals(p2), true);
});
});
}

View File

@ -31,7 +31,7 @@ void main() async {
expect(p1 > p2, false);
expect(p2 >= p1, true);
expect(p2 <= p1, true);
expect(pathEquals(p1, p2), true);
expect(p1.equals(p2), true);
});
});
}

View File

@ -1,4 +1,4 @@
import 'package:appflowy_editor/src/document/path.dart';
import 'package:appflowy_editor/src/core/document/path.dart';
import 'package:appflowy_editor/src/document/position.dart';
import 'package:appflowy_editor/src/document/selection.dart';
import 'package:flutter_test/flutter_test.dart';
@ -72,7 +72,7 @@ void main() {
test('test path utils 1', () {
final path1 = <int>[1];
final path2 = <int>[1];
expect(pathEquals(path1, path2), true);
expect(path1.equals(path2), true);
expect(Object.hashAll(path1), Object.hashAll(path2));
});
@ -80,7 +80,7 @@ void main() {
test('test path utils 2', () {
final path1 = <int>[1];
final path2 = <int>[2];
expect(pathEquals(path1, path2), false);
expect(path1.equals(path2), false);
expect(Object.hashAll(path1) != Object.hashAll(path2), true);
});

View File

@ -59,7 +59,7 @@ bool isInsertAndPathEqual(Operation operation, Path path, [String? content]) {
return false;
}
if (!pathEquals(operation.path, path)) {
if (!operation.path.equals(path)) {
return false;
}