mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
refactor: move path to core/document
This commit is contained in:
parent
7f92f8988f
commit
b9788bce09
@ -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> {
|
||||
|
@ -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);
|
@ -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'});
|
||||
|
@ -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);
|
||||
});
|
||||
});
|
||||
}
|
@ -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);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -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);
|
||||
});
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user