mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
refactor: flutter style optional chaining
This commit is contained in:
parent
eb519f4e11
commit
45556ae015
@ -276,14 +276,13 @@ class Delta extends Iterable<TextOperation> {
|
||||
|
||||
Delta([List<TextOperation>? ops]) : _operations = ops ?? <TextOperation>[];
|
||||
|
||||
Delta addAll(Iterable<TextOperation> textOps) {
|
||||
void addAll(Iterable<TextOperation> textOps) {
|
||||
textOps.forEach(add);
|
||||
return this;
|
||||
}
|
||||
|
||||
Delta add(TextOperation textOp) {
|
||||
void add(TextOperation textOp) {
|
||||
if (textOp.isEmpty) {
|
||||
return this;
|
||||
return;
|
||||
}
|
||||
_rawString = null;
|
||||
|
||||
@ -291,12 +290,12 @@ class Delta extends Iterable<TextOperation> {
|
||||
final lastOp = _operations.last;
|
||||
if (lastOp is TextDelete && textOp is TextDelete) {
|
||||
lastOp.length += textOp.length;
|
||||
return this;
|
||||
return;
|
||||
}
|
||||
if (mapEquals(lastOp.attributes, textOp.attributes)) {
|
||||
if (lastOp is TextInsert && textOp is TextInsert) {
|
||||
lastOp.content += textOp.content;
|
||||
return this;
|
||||
return;
|
||||
}
|
||||
// if there is an delete before the insert
|
||||
// swap the order
|
||||
@ -304,17 +303,16 @@ class Delta extends Iterable<TextOperation> {
|
||||
_operations.removeLast();
|
||||
_operations.add(textOp);
|
||||
_operations.add(lastOp);
|
||||
return this;
|
||||
return;
|
||||
}
|
||||
if (lastOp is TextRetain && textOp is TextRetain) {
|
||||
lastOp.length += textOp.length;
|
||||
return this;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_operations.add(textOp);
|
||||
return this;
|
||||
}
|
||||
|
||||
Delta slice(int start, [int? end]) {
|
||||
@ -337,20 +335,13 @@ class Delta extends Iterable<TextOperation> {
|
||||
return result;
|
||||
}
|
||||
|
||||
Delta insert(String content, [Attributes? attributes]) {
|
||||
final op = TextInsert(content, attributes);
|
||||
return add(op);
|
||||
}
|
||||
void insert(String content, [Attributes? attributes]) =>
|
||||
add(TextInsert(content, attributes));
|
||||
|
||||
Delta retain(int length, [Attributes? attributes]) {
|
||||
final op = TextRetain(length, attributes);
|
||||
return add(op);
|
||||
}
|
||||
void retain(int length, [Attributes? attributes]) =>
|
||||
add(TextRetain(length, attributes));
|
||||
|
||||
Delta delete(int length) {
|
||||
final op = TextDelete(length);
|
||||
return add(op);
|
||||
}
|
||||
void delete(int length) => add(TextDelete(length));
|
||||
|
||||
int get length {
|
||||
return _operations.fold(
|
||||
@ -409,7 +400,7 @@ class Delta extends Iterable<TextOperation> {
|
||||
if (!otherIter.hasNext &&
|
||||
delta._operations[delta._operations.length - 1] == newOp) {
|
||||
final rest = Delta(thisIter.rest());
|
||||
return delta.concat(rest).chop();
|
||||
return (delta + rest)..chop();
|
||||
}
|
||||
} else if (otherOp is TextDelete && (thisOp is TextRetain)) {
|
||||
delta.add(otherOp);
|
||||
@ -417,10 +408,10 @@ class Delta extends Iterable<TextOperation> {
|
||||
}
|
||||
}
|
||||
|
||||
return delta.chop();
|
||||
return delta..chop();
|
||||
}
|
||||
|
||||
Delta concat(Delta other) {
|
||||
Delta operator +(Delta other) {
|
||||
var ops = [..._operations];
|
||||
if (other._operations.isNotEmpty) {
|
||||
ops.add(other._operations[0]);
|
||||
@ -429,16 +420,15 @@ class Delta extends Iterable<TextOperation> {
|
||||
return Delta(ops);
|
||||
}
|
||||
|
||||
Delta chop() {
|
||||
void chop() {
|
||||
if (_operations.isEmpty) {
|
||||
return this;
|
||||
return;
|
||||
}
|
||||
_rawString = null;
|
||||
final lastOp = _operations.last;
|
||||
if (lastOp is TextRetain && (lastOp.attributes?.length ?? 0) == 0) {
|
||||
_operations.removeLast();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@override
|
||||
@ -477,7 +467,7 @@ class Delta extends Iterable<TextOperation> {
|
||||
}
|
||||
return previousValue;
|
||||
});
|
||||
return inverted.chop();
|
||||
return inverted..chop();
|
||||
}
|
||||
|
||||
List<dynamic> toJson() {
|
||||
|
@ -113,22 +113,32 @@ class TransactionBuilder {
|
||||
}
|
||||
textEdit(
|
||||
node,
|
||||
() => Delta().retain(index).insert(
|
||||
content,
|
||||
newAttributes,
|
||||
),
|
||||
() => Delta()
|
||||
..retain(index)
|
||||
..insert(
|
||||
content,
|
||||
newAttributes,
|
||||
),
|
||||
);
|
||||
afterSelection = Selection.collapsed(
|
||||
Position(path: node.path, offset: index + content.length));
|
||||
}
|
||||
|
||||
formatText(TextNode node, int index, int length, Attributes attributes) {
|
||||
textEdit(node, () => Delta().retain(index).retain(length, attributes));
|
||||
textEdit(
|
||||
node,
|
||||
() => Delta()
|
||||
..retain(index)
|
||||
..retain(length, attributes));
|
||||
afterSelection = beforeSelection;
|
||||
}
|
||||
|
||||
deleteText(TextNode node, int index, int length) {
|
||||
textEdit(node, () => Delta().retain(index).delete(length));
|
||||
textEdit(
|
||||
node,
|
||||
() => Delta()
|
||||
..retain(index)
|
||||
..delete(length));
|
||||
afterSelection =
|
||||
Selection.collapsed(Position(path: node.path, offset: index));
|
||||
}
|
||||
@ -144,7 +154,10 @@ class TransactionBuilder {
|
||||
}
|
||||
textEdit(
|
||||
node,
|
||||
() => Delta().retain(index).delete(length).insert(content, newAttributes),
|
||||
() => Delta()
|
||||
..retain(index)
|
||||
..delete(length)
|
||||
..insert(content, newAttributes),
|
||||
);
|
||||
afterSelection = Selection.collapsed(
|
||||
Position(
|
||||
|
@ -67,7 +67,7 @@ _pasteHTML(EditorState editorState, String html) {
|
||||
final textNodeAtPath = nodeAtPath as TextNode;
|
||||
final firstTextNode = firstNode as TextNode;
|
||||
tb.textEdit(textNodeAtPath,
|
||||
() => Delta().retain(startOffset).concat(firstTextNode.delta));
|
||||
() => (Delta()..retain(startOffset)) + firstTextNode.delta);
|
||||
tb.setAfterSelection(Selection.collapsed(Position(
|
||||
path: path, offset: startOffset + firstTextNode.delta.length)));
|
||||
tb.commit();
|
||||
@ -93,17 +93,18 @@ _pasteMultipleLinesInText(
|
||||
|
||||
tb.textEdit(
|
||||
textNodeAtPath,
|
||||
() => Delta()
|
||||
.retain(offset)
|
||||
.delete(remain.length)
|
||||
.concat(firstTextNode.delta));
|
||||
() =>
|
||||
(Delta()
|
||||
..retain(offset)
|
||||
..delete(remain.length)) +
|
||||
firstTextNode.delta);
|
||||
|
||||
final tailNodes = nodes.sublist(1);
|
||||
path[path.length - 1]++;
|
||||
if (tailNodes.isNotEmpty) {
|
||||
if (tailNodes.last.type == "text") {
|
||||
final tailTextNode = tailNodes.last as TextNode;
|
||||
tailTextNode.delta = tailTextNode.delta.concat(remain);
|
||||
tailTextNode.delta = tailTextNode.delta + remain;
|
||||
} else if (remain.length > 0) {
|
||||
tailNodes.add(TextNode(type: "text", delta: remain));
|
||||
}
|
||||
@ -151,7 +152,11 @@ _handlePastePlainText(EditorState editorState, String plainText) {
|
||||
editorState.document.nodeAtPath(selection.end.path)! as TextNode;
|
||||
final beginOffset = selection.end.offset;
|
||||
TransactionBuilder(editorState)
|
||||
..textEdit(node, () => Delta().retain(beginOffset).insert(lines[0]))
|
||||
..textEdit(
|
||||
node,
|
||||
() => Delta()
|
||||
..retain(beginOffset)
|
||||
..insert(lines[0]))
|
||||
..setAfterSelection(Selection.collapsed(Position(
|
||||
path: selection.end.path, offset: beginOffset + lines[0].length)))
|
||||
..commit();
|
||||
@ -175,17 +180,20 @@ _handlePastePlainText(EditorState editorState, String plainText) {
|
||||
final nodes = remains.map((e) {
|
||||
if (index++ == remains.length - 1) {
|
||||
return TextNode(
|
||||
type: "text", delta: Delta().insert(e).addAll(insertedLineSuffix));
|
||||
type: "text",
|
||||
delta: Delta()
|
||||
..insert(e)
|
||||
..addAll(insertedLineSuffix));
|
||||
}
|
||||
return TextNode(type: "text", delta: Delta().insert(e));
|
||||
return TextNode(type: "text", delta: Delta()..insert(e));
|
||||
}).toList();
|
||||
// insert first line
|
||||
tb.textEdit(
|
||||
node,
|
||||
() => Delta()
|
||||
.retain(beginOffset)
|
||||
.insert(firstLine)
|
||||
.delete(node.delta.length - beginOffset));
|
||||
..retain(beginOffset)
|
||||
..insert(firstLine)
|
||||
..delete(node.delta.length - beginOffset));
|
||||
// insert remains
|
||||
tb.insertNodes(path, nodes);
|
||||
tb.commit();
|
||||
@ -226,7 +234,10 @@ _deleteSelectedContent(EditorState editorState) {
|
||||
final tb = TransactionBuilder(editorState);
|
||||
final len = selection.end.offset - selection.start.offset;
|
||||
tb.textEdit(
|
||||
textItem, () => Delta().retain(selection.start.offset).delete(len));
|
||||
textItem,
|
||||
() => Delta()
|
||||
..retain(selection.start.offset)
|
||||
..delete(len));
|
||||
tb.setAfterSelection(Selection.collapsed(selection.start));
|
||||
tb.commit();
|
||||
return;
|
||||
@ -240,8 +251,9 @@ _deleteSelectedContent(EditorState editorState) {
|
||||
final textItem = item as TextNode;
|
||||
final deleteLen = textItem.delta.length - selection.start.offset;
|
||||
tb.textEdit(textItem, () {
|
||||
final delta = Delta();
|
||||
delta.retain(selection.start.offset).delete(deleteLen);
|
||||
final delta = Delta()
|
||||
..retain(selection.start.offset)
|
||||
..delete(deleteLen);
|
||||
|
||||
if (endNode is TextNode) {
|
||||
final remain = endNode.delta.slice(selection.end.offset);
|
||||
|
@ -14,9 +14,12 @@ void main() {
|
||||
})
|
||||
]);
|
||||
|
||||
final death = Delta().retain(12).insert("White", {
|
||||
'color': '#fff',
|
||||
}).delete(4);
|
||||
final death = Delta()
|
||||
..retain(12)
|
||||
..insert("White", {
|
||||
'color': '#fff',
|
||||
})
|
||||
..delete(4);
|
||||
|
||||
final restores = delta.compose(death);
|
||||
expect(restores.toList(), <TextOperation>[
|
||||
@ -26,164 +29,203 @@ void main() {
|
||||
]);
|
||||
});
|
||||
test('compose()', () {
|
||||
final a = Delta().insert('A');
|
||||
final b = Delta().insert('B');
|
||||
final expected = Delta().insert('B').insert('A');
|
||||
final a = Delta()..insert('A');
|
||||
final b = Delta()..insert('B');
|
||||
final expected = Delta()
|
||||
..insert('B')
|
||||
..insert('A');
|
||||
expect(a.compose(b), expected);
|
||||
});
|
||||
test('insert + retain', () {
|
||||
final a = Delta().insert('A');
|
||||
final b = Delta().retain(1, {
|
||||
'bold': true,
|
||||
'color': 'red',
|
||||
});
|
||||
final expected = Delta().insert('A', {
|
||||
'bold': true,
|
||||
'color': 'red',
|
||||
});
|
||||
final a = Delta()..insert('A');
|
||||
final b = Delta()
|
||||
..retain(1, {
|
||||
'bold': true,
|
||||
'color': 'red',
|
||||
});
|
||||
final expected = Delta()
|
||||
..insert('A', {
|
||||
'bold': true,
|
||||
'color': 'red',
|
||||
});
|
||||
expect(a.compose(b), expected);
|
||||
});
|
||||
test('insert + delete', () {
|
||||
final a = Delta().insert('A');
|
||||
final b = Delta().delete(1);
|
||||
final a = Delta()..insert('A');
|
||||
final b = Delta()..delete(1);
|
||||
final expected = Delta();
|
||||
expect(a.compose(b), expected);
|
||||
});
|
||||
test('delete + insert', () {
|
||||
final a = Delta().delete(1);
|
||||
final b = Delta().insert('B');
|
||||
final expected = Delta().insert('B').delete(1);
|
||||
final a = Delta()..delete(1);
|
||||
final b = Delta()..insert('B');
|
||||
final expected = Delta()
|
||||
..insert('B')
|
||||
..delete(1);
|
||||
expect(a.compose(b), expected);
|
||||
});
|
||||
test('delete + retain', () {
|
||||
final a = Delta().delete(1);
|
||||
final b = Delta().retain(1, {
|
||||
'bold': true,
|
||||
'color': 'red',
|
||||
});
|
||||
final expected = Delta().delete(1).retain(1, {
|
||||
'bold': true,
|
||||
'color': 'red',
|
||||
});
|
||||
final a = Delta()..delete(1);
|
||||
final b = Delta()
|
||||
..retain(1, {
|
||||
'bold': true,
|
||||
'color': 'red',
|
||||
});
|
||||
final expected = Delta()
|
||||
..delete(1)
|
||||
..retain(1, {
|
||||
'bold': true,
|
||||
'color': 'red',
|
||||
});
|
||||
expect(a.compose(b), expected);
|
||||
});
|
||||
test('delete + delete', () {
|
||||
final a = Delta().delete(1);
|
||||
final b = Delta().delete(1);
|
||||
final expected = Delta().delete(2);
|
||||
final a = Delta()..delete(1);
|
||||
final b = Delta()..delete(1);
|
||||
final expected = Delta()..delete(2);
|
||||
expect(a.compose(b), expected);
|
||||
});
|
||||
test('retain + insert', () {
|
||||
final a = Delta().retain(1, {'color': 'blue'});
|
||||
final b = Delta().insert('B');
|
||||
final expected = Delta().insert('B').retain(1, {
|
||||
'color': 'blue',
|
||||
});
|
||||
final a = Delta()..retain(1, {'color': 'blue'});
|
||||
final b = Delta()..insert('B');
|
||||
final expected = Delta()
|
||||
..insert('B')
|
||||
..retain(1, {
|
||||
'color': 'blue',
|
||||
});
|
||||
expect(a.compose(b), expected);
|
||||
});
|
||||
test('retain + retain', () {
|
||||
final a = Delta().retain(1, {
|
||||
'color': 'blue',
|
||||
});
|
||||
final b = Delta().retain(1, {
|
||||
'bold': true,
|
||||
'color': 'red',
|
||||
});
|
||||
final expected = Delta().retain(1, {
|
||||
'bold': true,
|
||||
'color': 'red',
|
||||
});
|
||||
final a = Delta()
|
||||
..retain(1, {
|
||||
'color': 'blue',
|
||||
});
|
||||
final b = Delta()
|
||||
..retain(1, {
|
||||
'bold': true,
|
||||
'color': 'red',
|
||||
});
|
||||
final expected = Delta()
|
||||
..retain(1, {
|
||||
'bold': true,
|
||||
'color': 'red',
|
||||
});
|
||||
expect(a.compose(b), expected);
|
||||
});
|
||||
test('retain + delete', () {
|
||||
final a = Delta().retain(1, {
|
||||
'color': 'blue',
|
||||
});
|
||||
final b = Delta().delete(1);
|
||||
final expected = Delta().delete(1);
|
||||
final a = Delta()
|
||||
..retain(1, {
|
||||
'color': 'blue',
|
||||
});
|
||||
final b = Delta()..delete(1);
|
||||
final expected = Delta()..delete(1);
|
||||
expect(a.compose(b), expected);
|
||||
});
|
||||
test('insert in middle of text', () {
|
||||
final a = Delta().insert('Hello');
|
||||
final b = Delta().retain(3).insert('X');
|
||||
final expected = Delta().insert('HelXlo');
|
||||
final a = Delta()..insert('Hello');
|
||||
final b = Delta()
|
||||
..retain(3)
|
||||
..insert('X');
|
||||
final expected = Delta()..insert('HelXlo');
|
||||
expect(a.compose(b), expected);
|
||||
});
|
||||
test('insert and delete ordering', () {
|
||||
final a = Delta().insert('Hello');
|
||||
final b = Delta().insert('Hello');
|
||||
final insertFirst = Delta().retain(3).insert('X').delete(1);
|
||||
final deleteFirst = Delta().retain(3).delete(1).insert('X');
|
||||
final expected = Delta().insert('HelXo');
|
||||
final a = Delta()..insert('Hello');
|
||||
final b = Delta()..insert('Hello');
|
||||
final insertFirst = Delta()
|
||||
..retain(3)
|
||||
..insert('X')
|
||||
..delete(1);
|
||||
final deleteFirst = Delta()
|
||||
..retain(3)
|
||||
..delete(1)
|
||||
..insert('X');
|
||||
final expected = Delta()..insert('HelXo');
|
||||
expect(a.compose(insertFirst), expected);
|
||||
expect(b.compose(deleteFirst), expected);
|
||||
});
|
||||
test('delete entire text', () {
|
||||
final a = Delta().retain(4).insert('Hello');
|
||||
final b = Delta().delete(9);
|
||||
final expected = Delta().delete(4);
|
||||
final a = Delta()
|
||||
..retain(4)
|
||||
..insert('Hello');
|
||||
final b = Delta()..delete(9);
|
||||
final expected = Delta()..delete(4);
|
||||
expect(a.compose(b), expected);
|
||||
});
|
||||
test('retain more than length of text', () {
|
||||
final a = Delta().insert('Hello');
|
||||
final b = Delta().retain(10);
|
||||
final expected = Delta().insert('Hello');
|
||||
final a = Delta()..insert('Hello');
|
||||
final b = Delta()..retain(10);
|
||||
final expected = Delta()..insert('Hello');
|
||||
expect(a.compose(b), expected);
|
||||
});
|
||||
test('retain start optimization', () {
|
||||
final a = Delta()
|
||||
.insert('A', {'bold': true})
|
||||
.insert('B')
|
||||
.insert('C', {'bold': true})
|
||||
.delete(1);
|
||||
final b = Delta().retain(3).insert('D');
|
||||
..insert('A', {'bold': true})
|
||||
..insert('B')
|
||||
..insert('C', {'bold': true})
|
||||
..delete(1);
|
||||
final b = Delta()
|
||||
..retain(3)
|
||||
..insert('D');
|
||||
final expected = Delta()
|
||||
.insert('A', {'bold': true})
|
||||
.insert('B')
|
||||
.insert('C', {'bold': true})
|
||||
.insert('D')
|
||||
.delete(1);
|
||||
..insert('A', {'bold': true})
|
||||
..insert('B')
|
||||
..insert('C', {'bold': true})
|
||||
..insert('D')
|
||||
..delete(1);
|
||||
expect(a.compose(b), expected);
|
||||
});
|
||||
test('retain end optimization', () {
|
||||
final a = Delta()
|
||||
.insert('A', {'bold': true})
|
||||
.insert('B')
|
||||
.insert('C', {'bold': true});
|
||||
final b = Delta().delete(1);
|
||||
final expected = Delta().insert('B').insert('C', {'bold': true});
|
||||
..insert('A', {'bold': true})
|
||||
..insert('B')
|
||||
..insert('C', {'bold': true});
|
||||
final b = Delta()..delete(1);
|
||||
final expected = Delta()
|
||||
..insert('B')
|
||||
..insert('C', {'bold': true});
|
||||
expect(a.compose(b), expected);
|
||||
});
|
||||
test('retain end optimization join', () {
|
||||
final a = Delta()
|
||||
.insert('A', {'bold': true})
|
||||
.insert('B')
|
||||
.insert('C', {'bold': true})
|
||||
.insert('D')
|
||||
.insert('E', {'bold': true})
|
||||
.insert('F');
|
||||
final b = Delta().retain(1).delete(1);
|
||||
..insert('A', {'bold': true})
|
||||
..insert('B')
|
||||
..insert('C', {'bold': true})
|
||||
..insert('D')
|
||||
..insert('E', {'bold': true})
|
||||
..insert('F');
|
||||
final b = Delta()
|
||||
..retain(1)
|
||||
..delete(1);
|
||||
final expected = Delta()
|
||||
.insert('AC', {'bold': true})
|
||||
.insert('D')
|
||||
.insert('E', {'bold': true})
|
||||
.insert('F');
|
||||
..insert('AC', {'bold': true})
|
||||
..insert('D')
|
||||
..insert('E', {'bold': true})
|
||||
..insert('F');
|
||||
expect(a.compose(b), expected);
|
||||
});
|
||||
});
|
||||
group('invert', () {
|
||||
test('insert', () {
|
||||
final delta = Delta().retain(2).insert('A');
|
||||
final base = Delta().insert('12346');
|
||||
final expected = Delta().retain(2).delete(1);
|
||||
final delta = Delta()
|
||||
..retain(2)
|
||||
..insert('A');
|
||||
final base = Delta()..insert('12346');
|
||||
final expected = Delta()
|
||||
..retain(2)
|
||||
..delete(1);
|
||||
final inverted = delta.invert(base);
|
||||
expect(expected, inverted);
|
||||
expect(base.compose(delta).compose(inverted), base);
|
||||
});
|
||||
test('delete', () {
|
||||
final delta = Delta().retain(2).delete(3);
|
||||
final base = Delta().insert('123456');
|
||||
final expected = Delta().retain(2).insert('345');
|
||||
final delta = Delta()
|
||||
..retain(2)
|
||||
..delete(3);
|
||||
final base = Delta()..insert('123456');
|
||||
final expected = Delta()
|
||||
..retain(2)
|
||||
..insert('345');
|
||||
final inverted = delta.invert(base);
|
||||
expect(expected, inverted);
|
||||
expect(base.compose(delta).compose(inverted), base);
|
||||
@ -199,7 +241,10 @@ void main() {
|
||||
});
|
||||
group('json', () {
|
||||
test('toJson()', () {
|
||||
final delta = Delta().retain(2).insert('A').delete(3);
|
||||
final delta = Delta()
|
||||
..retain(2)
|
||||
..insert('A')
|
||||
..delete(3);
|
||||
expect(delta.toJson(), [
|
||||
{'retain': 2},
|
||||
{'insert': 'A'},
|
||||
@ -207,8 +252,9 @@ void main() {
|
||||
]);
|
||||
});
|
||||
test('attributes', () {
|
||||
final delta =
|
||||
Delta().retain(2, {'bold': true}).insert('A', {'italic': true});
|
||||
final delta = Delta()
|
||||
..retain(2, {'bold': true})
|
||||
..insert('A', {'italic': true});
|
||||
expect(delta.toJson(), [
|
||||
{
|
||||
'retain': 2,
|
||||
@ -226,7 +272,10 @@ void main() {
|
||||
{'insert': 'A'},
|
||||
{'delete': 3},
|
||||
]);
|
||||
final expected = Delta().retain(2).insert('A').delete(3);
|
||||
final expected = Delta()
|
||||
..retain(2)
|
||||
..insert('A')
|
||||
..delete(3);
|
||||
expect(delta, expected);
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user