refactor: move path to core/document
This commit is contained in:
parent
fe7b9e384a
commit
e9f3954005
24 changed files with 108 additions and 56 deletions
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
||||
|
|
|
|||
|
|
@ -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> {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,72 @@
|
|||
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 (equals(other)) {
|
||||
return true;
|
||||
}
|
||||
return this > other;
|
||||
}
|
||||
|
||||
bool operator >(Path other) {
|
||||
if (equals(other)) {
|
||||
return false;
|
||||
}
|
||||
final length = min(this.length, other.length);
|
||||
for (var i = 0; i < length; i++) {
|
||||
if (this[i] < other[i]) {
|
||||
return false;
|
||||
} else if (this[i] > other[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (this.length < other.length) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator <=(Path other) {
|
||||
if (equals(other)) {
|
||||
return true;
|
||||
}
|
||||
return this < other;
|
||||
}
|
||||
|
||||
bool operator <(Path other) {
|
||||
if (equals(other)) {
|
||||
return false;
|
||||
}
|
||||
final length = min(this.length, other.length);
|
||||
for (var i = 0; i < length; i++) {
|
||||
if (this[i] > other[i]) {
|
||||
return false;
|
||||
} else if (this[i] < other[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (this.length > other.length) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Path get next {
|
||||
Path nextPath = Path.from(this, growable: true);
|
||||
if (isEmpty) {
|
||||
return nextPath;
|
||||
}
|
||||
final last = nextPath.last;
|
||||
return nextPath
|
||||
..removeLast()
|
||||
..add(last + 1);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
|
||||
typedef Path = List<int>;
|
||||
|
||||
bool pathEquals(Path path1, Path path2) {
|
||||
return listEquals(path1, path2);
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 =>
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ void main() async {
|
|||
expect(nodes.current.type, 'node_${i}_$j');
|
||||
}
|
||||
}
|
||||
expect(nodes.moveNext(), false);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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'});
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue