feat: integrate awesome_lints and upgrade to Flutter 3.38 (#1173)

* chore: update Flutter SDK to version 3.38.5

Upgrade Flutter from 3.32.4 to 3.38.5 to meet awesome_lints
requirement for Dart SDK 3.10.0+. Update CI workflow to use
the new Flutter version and add custom_lint verification step.

* chore: integrate awesome_lints with custom lint rules

Add awesome_lints and custom_lint dependencies, configure
analysis_options.yaml to enable newline lint rules: newline_before_case,
newline_before_constructor, newline_before_method, and newline_before_return.

* style: apply newline formatting per awesome_lints rules

Add blank lines before case clauses, return statements, method
declarations, and constructors throughout the codebase to comply
with awesome_lints newline rules.

* fix: replace deprecated translate with leftTranslateByDouble

Update Matrix4.translate() calls to use the new leftTranslateByDouble()
API to resolve deprecation warnings in Flutter SDK 3.38.5.

* chore: improve code readability with blank line formatting
This commit is contained in:
Lucas 2025-12-23 15:12:57 +08:00 • committed by GitHub
commit f882d958d9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
229 changed files with 850 additions and 5 deletions

2
.fvmrc
View file

@ -1,3 +1,3 @@
{ {
"flutter": "3.32.4" "flutter": "3.38.5"
} }

View file

@ -33,7 +33,7 @@ jobs:
- uses: subosito/flutter-action@v2 - uses: subosito/flutter-action@v2
with: with:
channel: "stable" channel: "stable"
flutter-version: "3.32.4" flutter-version: "3.38.5"
cache: true cache: true
- name: Run tests - name: Run tests
@ -42,6 +42,7 @@ jobs:
flutter pub get flutter pub get
flutter analyze . flutter analyze .
dart format --set-exit-if-changed . dart format --set-exit-if-changed .
dart run custom_lint
flutter test --coverage flutter test --coverage
- name: Upload coverage to Codecov - name: Upload coverage to Codecov

View file

@ -12,3 +12,13 @@ linter:
analyzer: analyzer:
exclude: exclude:
- lib/src/l10n/** - lib/src/l10n/**
plugins:
- custom_lint
custom_lint:
enable_all_lint_rules: false
rules:
- newline_before_case
- newline_before_constructor
- newline_before_method
- newline_before_return

View file

@ -22,6 +22,7 @@ class DocumentV0 {
final document = Map<String, Object>.from(json['document'] as Map); final document = Map<String, Object>.from(json['document'] as Map);
final root = NodeV0.fromJson(document); final root = NodeV0.fromJson(document);
return DocumentV0(root: root); return DocumentV0(root: root);
} }
@ -31,6 +32,7 @@ class DocumentV0 {
type: 'editor', type: 'editor',
children: LinkedList<NodeV0>()..add(TextNodeV0.empty()), children: LinkedList<NodeV0>()..add(TextNodeV0.empty()),
); );
return DocumentV0( return DocumentV0(
root: root, root: root,
); );
@ -54,6 +56,7 @@ class DocumentV0 {
for (final node in nodes) { for (final node in nodes) {
target.insertBefore(node); target.insertBefore(node);
} }
return true; return true;
} }
@ -62,6 +65,7 @@ class DocumentV0 {
for (var i = 0; i < nodes.length; i++) { for (var i = 0; i < nodes.length; i++) {
parent.insert(nodes.elementAt(i), index: path.last + i); parent.insert(nodes.elementAt(i), index: path.last + i);
} }
return true; return true;
} }
@ -83,6 +87,7 @@ class DocumentV0 {
target = next; target = next;
length--; length--;
} }
return true; return true;
} }
@ -96,6 +101,7 @@ class DocumentV0 {
return false; return false;
} }
target.updateAttributes(attributes); target.updateAttributes(attributes);
return true; return true;
} }
@ -109,6 +115,7 @@ class DocumentV0 {
return false; return false;
} }
target.delta = target.delta.compose(delta); target.delta = target.delta.compose(delta);
return true; return true;
} }

View file

@ -87,6 +87,7 @@ final class NodeV0 extends ChangeNotifier with LinkedListEntry<NodeV0> {
if (subtype != null) { if (subtype != null) {
return '$type/$subtype'; return '$type/$subtype';
} }
return type; return type;
} }
@ -94,6 +95,7 @@ final class NodeV0 extends ChangeNotifier with LinkedListEntry<NodeV0> {
if (attributes[BuiltInAttributeKey.subtype] is String) { if (attributes[BuiltInAttributeKey.subtype] is String) {
return attributes[BuiltInAttributeKey.subtype] as String; return attributes[BuiltInAttributeKey.subtype] as String;
} }
return null; return null;
} }
@ -136,6 +138,7 @@ final class NodeV0 extends ChangeNotifier with LinkedListEntry<NodeV0> {
entry.parent = this; entry.parent = this;
children.add(entry); children.add(entry);
notifyListeners(); notifyListeners();
return; return;
} }
@ -188,6 +191,7 @@ final class NodeV0 extends ChangeNotifier with LinkedListEntry<NodeV0> {
if (attributes.isNotEmpty) { if (attributes.isNotEmpty) {
map['attributes'] = attributes; map['attributes'] = attributes;
} }
return map; return map;
} }
@ -208,6 +212,7 @@ final class NodeV0 extends ChangeNotifier with LinkedListEntry<NodeV0> {
); );
} }
} }
return node; return node;
} }
@ -222,6 +227,7 @@ final class NodeV0 extends ChangeNotifier with LinkedListEntry<NodeV0> {
} }
index += 1; index += 1;
} }
return parent!._computePath([index, ...previous]); return parent!._computePath([index, ...previous]);
} }
} }
@ -245,7 +251,9 @@ final class TextNodeV0 extends NodeV0 {
); );
Delta _delta; Delta _delta;
Delta get delta => _delta; Delta get delta => _delta;
set delta(Delta v) { set delta(Delta v) {
_delta = v; _delta = v;
notifyListeners(); notifyListeners();
@ -255,6 +263,7 @@ final class TextNodeV0 extends NodeV0 {
Map<String, Object> toJson() { Map<String, Object> toJson() {
final map = super.toJson(); final map = super.toJson();
map['delta'] = delta.toJson(); map['delta'] = delta.toJson();
return map; return map;
} }
@ -277,6 +286,7 @@ final class TextNodeV0 extends NodeV0 {
); );
} }
} }
return textNode; return textNode;
} }
@ -293,6 +303,7 @@ extension NodeV0Equality on Iterable<NodeV0> {
return false; return false;
} }
} }
return true; return true;
} }

View file

@ -71,6 +71,7 @@ List<Operation> diffNodes(Node oldNode, Node newNode) {
} }
} }
} }
return combinedOperations; return combinedOperations;
} }
@ -99,6 +100,7 @@ List<Operation> diffNodes(Node oldNode, Node newNode) {
} }
} }
} }
return combinedOperations; return combinedOperations;
} }

View file

@ -41,6 +41,7 @@ class Document {
final document = Map<String, Object>.from(json['document'] as Map); final document = Map<String, Object>.from(json['document'] as Map);
final root = Node.fromJson(document); final root = Node.fromJson(document);
return Document(root: root); return Document(root: root);
} }
@ -51,6 +52,7 @@ class Document {
type: 'document', type: 'document',
children: LinkedList<Node>()..add(TextNode.empty()), children: LinkedList<Node>()..add(TextNode.empty()),
); );
return Document( return Document(
root: root, root: root,
); );
@ -66,6 +68,7 @@ class Document {
type: 'page', type: 'page',
children: withInitialText ? [paragraphNode()] : [], children: withInitialText ? [paragraphNode()] : [],
); );
return Document( return Document(
root: root, root: root,
); );
@ -83,6 +86,7 @@ class Document {
while (current != null && current.children.isNotEmpty) { while (current != null && current.children.isNotEmpty) {
current = current.children.last; current = current.children.last;
} }
return current; return current;
} }
@ -110,6 +114,7 @@ class Document {
for (final node in nodes) { for (final node in nodes) {
target.insertBefore(node); target.insertBefore(node);
} }
return true; return true;
} }
@ -118,6 +123,7 @@ class Document {
for (var i = 0; i < nodes.length; i++) { for (var i = 0; i < nodes.length; i++) {
parent.insert(nodes.elementAt(i), index: path.last + i); parent.insert(nodes.elementAt(i), index: path.last + i);
} }
return true; return true;
} }
@ -139,6 +145,7 @@ class Document {
target = next; target = next;
length--; length--;
} }
return true; return true;
} }
@ -147,6 +154,7 @@ class Document {
// if the path is empty, it means the root node. // if the path is empty, it means the root node.
if (path.isEmpty) { if (path.isEmpty) {
root.updateAttributes(attributes); root.updateAttributes(attributes);
return true; return true;
} }
final target = nodeAtPath(path); final target = nodeAtPath(path);
@ -154,6 +162,7 @@ class Document {
return false; return false;
} }
target.updateAttributes(attributes); target.updateAttributes(attributes);
return true; return true;
} }
@ -168,6 +177,7 @@ class Document {
return false; return false;
} }
target.updateAttributes({'delta': (targetDelta.compose(delta)).toJson()}); target.updateAttributes({'delta': (targetDelta.compose(delta)).toJson()});
return true; return true;
} }

View file

@ -84,8 +84,10 @@ final class Node extends ChangeNotifier with LinkedListEntry<Node> {
/// The children of the node. /// The children of the node.
final LinkedList<Node> _children; final LinkedList<Node> _children;
List<Node> get children { List<Node> get children {
_cacheChildren ??= _children.toList(growable: false); _cacheChildren ??= _children.toList(growable: false);
return _cacheChildren!; return _cacheChildren!;
} }
@ -93,6 +95,7 @@ final class Node extends ChangeNotifier with LinkedListEntry<Node> {
/// The attributes of the node. /// The attributes of the node.
Attributes _attributes; Attributes _attributes;
Attributes get attributes => {..._attributes}; Attributes get attributes => {..._attributes};
/// The path of the node. /// The path of the node.
@ -138,6 +141,7 @@ final class Node extends ChangeNotifier with LinkedListEntry<Node> {
final index = path.first; final index = path.first;
final child = childAtIndexOrNull(index); final child = childAtIndexOrNull(index);
return child?.childAtPath(path.sublist(1)); return child?.childAtPath(path.sublist(1));
} }
@ -161,6 +165,7 @@ final class Node extends ChangeNotifier with LinkedListEntry<Node> {
if (_children.isEmpty) { if (_children.isEmpty) {
_children.add(entry); _children.add(entry);
notifyListeners(); notifyListeners();
return; return;
} }
@ -213,6 +218,7 @@ final class Node extends ChangeNotifier with LinkedListEntry<Node> {
parent?.notifyListeners(); parent?.notifyListeners();
parent = null; parent = null;
return true; return true;
} }
@ -235,6 +241,7 @@ final class Node extends ChangeNotifier with LinkedListEntry<Node> {
if (attributes['delta'] is List) { if (attributes['delta'] is List) {
return Delta.fromJson(attributes['delta']); return Delta.fromJson(attributes['delta']);
} }
return null; return null;
} }
@ -253,6 +260,7 @@ final class Node extends ChangeNotifier with LinkedListEntry<Node> {
// filter the null value // filter the null value
map['data'] = attributes..removeWhere((_, value) => value == null); map['data'] = attributes..removeWhere((_, value) => value == null);
} }
return map; return map;
} }
@ -281,6 +289,7 @@ final class Node extends ChangeNotifier with LinkedListEntry<Node> {
} }
node.externalValues = externalValues; node.externalValues = externalValues;
node.extraInfos = extraInfos; node.extraInfos = extraInfos;
return node; return node;
} }
@ -297,6 +306,7 @@ final class Node extends ChangeNotifier with LinkedListEntry<Node> {
return previous; return previous;
} }
final index = parent.children.indexOf(this); final index = parent.children.indexOf(this);
return parent._computePath([index, ...previous]); return parent._computePath([index, ...previous]);
} }
@ -351,8 +361,10 @@ final class TextNode extends Node {
String get subtype => ''; String get subtype => '';
Delta _delta; Delta _delta;
@override @override
Delta get delta => _delta; Delta get delta => _delta;
set delta(Delta v) { set delta(Delta v) {
_delta = v; _delta = v;
notifyListeners(); notifyListeners();
@ -362,6 +374,7 @@ final class TextNode extends Node {
Map<String, Object> toJson() { Map<String, Object> toJson() {
final map = super.toJson(); final map = super.toJson();
map['delta'] = delta.toJson(); map['delta'] = delta.toJson();
return map; return map;
} }
@ -385,6 +398,7 @@ final class TextNode extends Node {
); );
} }
} }
return textNode; return textNode;
} }
@ -401,6 +415,7 @@ extension NodeEquality on Iterable<Node> {
return false; return false;
} }
} }
return true; return true;
} }

View file

@ -30,6 +30,7 @@ class NodeIterator implements Iterator<Node> {
if (!_began) { if (!_began) {
_currentNode = startNode; _currentNode = startNode;
_began = true; _began = true;
return true; return true;
} }
@ -40,6 +41,7 @@ class NodeIterator implements Iterator<Node> {
if (endNode != null && endNode == node) { if (endNode != null && endNode == node) {
_currentNode = null; _currentNode = null;
return false; return false;
} }
@ -49,6 +51,7 @@ class NodeIterator implements Iterator<Node> {
_currentNode = node.next!; _currentNode = node.next!;
} else if (node.parent == null) { } else if (node.parent == null) {
_currentNode = null; _currentNode = null;
return false; return false;
} else { } else {
while (node.parent != null) { while (node.parent != null) {
@ -74,6 +77,7 @@ class NodeIterator implements Iterator<Node> {
while (moveNext()) { while (moveNext()) {
result.add(current); result.add(current);
} }
return result; return result;
} }
} }

View file

@ -14,6 +14,7 @@ extension PathExtensions on Path {
if (equals(other)) { if (equals(other)) {
return true; return true;
} }
return this > other; return this > other;
} }
@ -32,6 +33,7 @@ extension PathExtensions on Path {
if (this.length < other.length) { if (this.length < other.length) {
return false; return false;
} }
return true; return true;
} }
@ -39,6 +41,7 @@ extension PathExtensions on Path {
if (equals(other)) { if (equals(other)) {
return true; return true;
} }
return this < other; return this < other;
} }
@ -57,6 +60,7 @@ extension PathExtensions on Path {
if (this.length > other.length) { if (this.length > other.length) {
return false; return false;
} }
return true; return true;
} }
@ -66,6 +70,7 @@ extension PathExtensions on Path {
return nextPath; return nextPath;
} }
final last = nextPath.last; final last = nextPath.last;
return nextPath return nextPath
..removeLast() ..removeLast()
..add(last + 1); ..add(last + 1);
@ -77,6 +82,7 @@ extension PathExtensions on Path {
return nextPath; return nextPath;
} }
final last = nextPath.last; final last = nextPath.last;
return nextPath return nextPath
..removeLast() ..removeLast()
..add(last + n); ..add(last + n);
@ -92,6 +98,7 @@ extension PathExtensions on Path {
return previousPath; return previousPath;
} }
final last = previousPath.last; final last = previousPath.last;
return previousPath return previousPath
..removeLast() ..removeLast()
..add(max(0, last - 1)); ..add(max(0, last - 1));
@ -103,6 +110,7 @@ extension PathExtensions on Path {
return previousPath; return previousPath;
} }
final last = previousPath.last; final last = previousPath.last;
return previousPath return previousPath
..removeLast() ..removeLast()
..add(max(0, last - n)); ..add(max(0, last - n));
@ -112,6 +120,7 @@ extension PathExtensions on Path {
if (isEmpty) { if (isEmpty) {
return this; return this;
} }
return Path.from(this, growable: true)..removeLast(); return Path.from(this, growable: true)..removeLast();
} }
@ -130,6 +139,7 @@ extension PathExtensions on Path {
return false; return false;
} }
} }
return true; return true;
} }
@ -145,6 +155,7 @@ extension PathExtensions on Path {
if (isSameDepth) { if (isSameDepth) {
return result && selection.start.path.length == length; return result && selection.start.path.length == length;
} }
return result; return result;
} }
} }

View file

@ -5,6 +5,7 @@ import 'package:appflowy_editor/appflowy_editor.dart';
/// If the document is empty, it will create a new paragraph node. /// If the document is empty, it will create a new paragraph node.
class AtLeastOneEditableNodeRule extends DocumentRule { class AtLeastOneEditableNodeRule extends DocumentRule {
const AtLeastOneEditableNodeRule(); const AtLeastOneEditableNodeRule();
@override @override
bool shouldApply({ bool shouldApply({
required EditorState editorState, required EditorState editorState,
@ -15,6 +16,7 @@ class AtLeastOneEditableNodeRule extends DocumentRule {
return false; return false;
} }
final document = editorState.document; final document = editorState.document;
return document.root.children.isEmpty; return document.root.children.isEmpty;
} }

View file

@ -131,6 +131,7 @@ class TextInsert extends TextOperation {
if (_attributes != null && _attributes.isNotEmpty) { if (_attributes != null && _attributes.isNotEmpty) {
result['attributes'] = attributes; result['attributes'] = attributes;
} }
return result; return result;
} }
@ -168,6 +169,7 @@ class TextRetain extends TextOperation {
if (_attributes != null && _attributes.isNotEmpty) { if (_attributes != null && _attributes.isNotEmpty) {
result['attributes'] = attributes; result['attributes'] = attributes;
} }
return result; return result;
} }
@ -256,11 +258,13 @@ class Delta extends Iterable<TextOperation> {
final lastOp = _operations.last; final lastOp = _operations.last;
if (lastOp is TextDelete && textOperation is TextDelete) { if (lastOp is TextDelete && textOperation is TextDelete) {
lastOp.length += textOperation.length; lastOp.length += textOperation.length;
return; return;
} }
if (_mapEquals(lastOp.attributes, textOperation.attributes)) { if (_mapEquals(lastOp.attributes, textOperation.attributes)) {
if (lastOp is TextInsert && textOperation is TextInsert) { if (lastOp is TextInsert && textOperation is TextInsert) {
lastOp.text += textOperation.text; lastOp.text += textOperation.text;
return; return;
} }
// if there is an delete before the insert // if there is an delete before the insert
@ -269,10 +273,12 @@ class Delta extends Iterable<TextOperation> {
_operations.removeLast(); _operations.removeLast();
_operations.add(textOperation); _operations.add(textOperation);
_operations.add(lastOp); _operations.add(lastOp);
return; return;
} }
if (lastOp is TextRetain && textOperation is TextRetain) { if (lastOp is TextRetain && textOperation is TextRetain) {
lastOp.length += textOperation.length; lastOp.length += textOperation.length;
return; return;
} }
} }
@ -387,6 +393,7 @@ class Delta extends Iterable<TextOperation> {
delta._operations.isNotEmpty && delta._operations.isNotEmpty &&
delta._operations.last == newOp) { delta._operations.last == newOp) {
final rest = Delta(operations: thisIter.rest()); final rest = Delta(operations: thisIter.rest());
return (delta + rest)..chop(); return (delta + rest)..chop();
} }
} else if (otherOp is TextDelete && (thisOp is TextRetain)) { } else if (otherOp is TextDelete && (thisOp is TextRetain)) {
@ -409,8 +416,10 @@ class Delta extends Iterable<TextOperation> {
return op.text; return op.text;
} }
assert(false, 'diff() called with non-insert operations'); assert(false, 'diff() called with non-insert operations');
return ''; return '';
}).join(); }).join();
return text; return text;
}).toList(); }).toList();
@ -430,11 +439,13 @@ class Delta extends Iterable<TextOperation> {
opLength = min(otherIter.peekLength(), length); opLength = min(otherIter.peekLength(), length);
retDelta.add(otherIter.next(opLength)); retDelta.add(otherIter.next(opLength));
break; break;
case diff_match_patch.DIFF_DELETE: case diff_match_patch.DIFF_DELETE:
opLength = min(length, thisIter.peekLength()); opLength = min(length, thisIter.peekLength());
thisIter.next(opLength); thisIter.next(opLength);
retDelta.delete(opLength); retDelta.delete(opLength);
break; break;
case diff_match_patch.DIFF_EQUAL: case diff_match_patch.DIFF_EQUAL:
opLength = min( opLength = min(
min(thisIter.peekLength(), otherIter.peekLength()), min(thisIter.peekLength(), otherIter.peekLength()),
@ -460,6 +471,7 @@ class Delta extends Iterable<TextOperation> {
length -= opLength; length -= opLength;
} }
} }
return retDelta..trim(); return retDelta..trim();
} }
@ -480,6 +492,7 @@ class Delta extends Iterable<TextOperation> {
operations.add(other._operations[0]); operations.add(other._operations[0]);
operations.addAll(other._operations.sublist(1)); operations.addAll(other._operations.sublist(1));
} }
return Delta(operations: operations); return Delta(operations: operations);
} }
@ -499,6 +512,7 @@ class Delta extends Iterable<TextOperation> {
if (other is! Delta) { if (other is! Delta) {
return false; return false;
} }
return listEquals(_operations, other._operations); return listEquals(_operations, other._operations);
} }
@ -515,6 +529,7 @@ class Delta extends Iterable<TextOperation> {
inverted.delete(op.length); inverted.delete(op.length);
} else if (op is TextRetain && op.attributes == null) { } else if (op is TextRetain && op.attributes == null) {
inverted.retain(op.length); inverted.retain(op.length);
return previousValue + op.length; return previousValue + op.length;
} else if (op is TextDelete || op is TextRetain) { } else if (op is TextDelete || op is TextRetain) {
final length = op.length; final length = op.length;
@ -529,10 +544,13 @@ class Delta extends Iterable<TextOperation> {
); );
} }
} }
return previousValue + length; return previousValue + length;
} }
return previousValue; return previousValue;
}); });
return inverted..chop(); return inverted..chop();
} }
@ -554,6 +572,7 @@ class Delta extends Iterable<TextOperation> {
final content = toPlainText(); final content = toPlainText();
final boundary = CharacterBoundary(content); final boundary = CharacterBoundary(content);
final index = boundary.getLeadingTextBoundaryAt(pos - 1); final index = boundary.getLeadingTextBoundaryAt(pos - 1);
return index ?? 0; return index ?? 0;
} }
@ -571,12 +590,14 @@ class Delta extends Iterable<TextOperation> {
} }
final boundary = CharacterBoundary(content); final boundary = CharacterBoundary(content);
final index = boundary.getTrailingTextBoundaryAt(pos); final index = boundary.getTrailingTextBoundaryAt(pos);
return index ?? content.length; return index ?? content.length;
} }
String toPlainText() { String toPlainText() {
_plainText ??= _plainText ??=
_operations.whereType<TextInsert>().map((op) => op.text).join(); _operations.whereType<TextInsert>().map((op) => op.text).join();
return _plainText!; return _plainText!;
} }
@ -634,8 +655,10 @@ class _OpIterator {
int peekLength() { int peekLength() {
if (_index < _operations.length) { if (_index < _operations.length) {
final op = _operations[_index]; final op = _operations[_index];
return op.length - _offset; return op.length - _offset;
} }
return _maxInt; return _maxInt;
} }
@ -661,8 +684,10 @@ class _OpIterator {
switch (nextOp) { switch (nextOp) {
case TextDelete _: case TextDelete _:
return TextDelete(length: length); return TextDelete(length: length);
case TextRetain _: case TextRetain _:
return TextRetain(length, attributes: nextOp.attributes); return TextRetain(length, attributes: nextOp.attributes);
case TextInsert _: case TextInsert _:
return TextInsert( return TextInsert(
nextOp.text.substring(offset, offset + length), nextOp.text.substring(offset, offset + length),
@ -683,6 +708,7 @@ class _OpIterator {
final rest = _operations.sublist(_index); final rest = _operations.sublist(_index);
_offset = offset; _offset = offset;
_index = index; _index = index;
return [next] + rest; return [next] + rest;
} }
} }
@ -692,5 +718,6 @@ bool _mapEquals<T, U>(Map<T, U>? a, Map<T, U>? b) {
if ((a == null || a.isEmpty) && (b == null || b.isEmpty)) { if ((a == null || a.isEmpty) && (b == null || b.isEmpty)) {
return true; return true;
} }
return mapEquals(a, b); return mapEquals(a, b);
} }

View file

@ -34,6 +34,7 @@ class InsertOperation extends Operation {
final nodes = (json['nodes'] as List) final nodes = (json['nodes'] as List)
.map((n) => Node.fromJson(n)) .map((n) => Node.fromJson(n))
.toList(growable: false); .toList(growable: false);
return InsertOperation(path, nodes); return InsertOperation(path, nodes);
} }
@ -81,6 +82,7 @@ class DeleteOperation extends Operation {
final nodes = (json['nodes'] as List) final nodes = (json['nodes'] as List)
.map((n) => Node.fromJson(n)) .map((n) => Node.fromJson(n))
.toList(growable: false); .toList(growable: false);
return DeleteOperation(path, nodes); return DeleteOperation(path, nodes);
} }
@ -128,6 +130,7 @@ class UpdateOperation extends Operation {
final path = json['path'] as Path; final path = json['path'] as Path;
final oldAttributes = json['oldAttributes'] as Attributes; final oldAttributes = json['oldAttributes'] as Attributes;
final attributes = json['attributes'] as Attributes; final attributes = json['attributes'] as Attributes;
return UpdateOperation( return UpdateOperation(
path, path,
attributes, attributes,
@ -191,6 +194,7 @@ class UpdateTextOperation extends Operation {
final path = json['path'] as Path; final path = json['path'] as Path;
final delta = Delta.fromJson(json['delta']); final delta = Delta.fromJson(json['delta']);
final inverted = Delta.fromJson(json['inverted']); final inverted = Delta.fromJson(json['inverted']);
return UpdateTextOperation(path, delta, inverted); return UpdateTextOperation(path, delta, inverted);
} }
@ -255,6 +259,7 @@ Path transformPath(Path preInsertPath, Path b, [int delta = 1]) {
Operation? transformOperation(Operation a, Operation b) { Operation? transformOperation(Operation a, Operation b) {
if (a is InsertOperation) { if (a is InsertOperation) {
final newPath = transformPath(a.path, b.path, a.nodes.length); final newPath = transformPath(a.path, b.path, a.nodes.length);
return b.copyWith(path: newPath); return b.copyWith(path: newPath);
} else if (a is DeleteOperation) { } else if (a is DeleteOperation) {
if (b is DeleteOperation) { if (b is DeleteOperation) {
@ -265,6 +270,7 @@ Operation? transformOperation(Operation a, Operation b) {
} }
} }
final newPath = transformPath(a.path, b.path, -1 * a.nodes.length); final newPath = transformPath(a.path, b.path, -1 * a.nodes.length);
return b.copyWith(path: newPath); return b.copyWith(path: newPath);
} }

View file

@ -22,6 +22,7 @@ class Transaction {
compose(); compose();
markNeedsComposing = false; markNeedsComposing = false;
} }
return _operations; return _operations;
} }
@ -144,6 +145,7 @@ class Transaction {
if (beforeSelection != null) { if (beforeSelection != null) {
json['before_selection'] = beforeSelection!.toJson(); json['before_selection'] = beforeSelection!.toJson();
} }
return json; return json;
} }
@ -165,6 +167,7 @@ class Transaction {
op.inverted.compose(last.inverted), op.inverted.compose(last.inverted),
); );
operations[_operations.length - 1] = newOp; operations[_operations.length - 1] = newOp;
return; return;
} }
} }
@ -208,12 +211,14 @@ extension TextTransaction on Transaction {
final delta = node.delta; final delta = node.delta;
if (delta == null) { if (delta == null) {
assert(false, 'The node must have a delta.'); assert(false, 'The node must have a delta.');
return; return;
} }
if (index < 0 || index > delta.length) { if (index < 0 || index > delta.length) {
AppFlowyEditorLog.editor AppFlowyEditorLog.editor
.info('The index($index) is out of range or negative.'); .info('The index($index) is out of range or negative.');
return; return;
} }
@ -244,6 +249,7 @@ extension TextTransaction on Transaction {
final delta = node.delta; final delta = node.delta;
if (delta == null) { if (delta == null) {
assert(false, 'The node must have a delta.'); assert(false, 'The node must have a delta.');
return; return;
} }
@ -272,6 +278,7 @@ extension TextTransaction on Transaction {
final delta = node.delta; final delta = node.delta;
if (delta == null) { if (delta == null) {
assert(false, 'The node must have a delta.'); assert(false, 'The node must have a delta.');
return; return;
} }
@ -416,6 +423,7 @@ extension TextTransaction on Transaction {
void compose() { void compose() {
if (_composeMap.isEmpty) { if (_composeMap.isEmpty) {
markNeedsComposing = false; markNeedsComposing = false;
return; return;
} }
for (final entry in _composeMap.entries) { for (final entry in _composeMap.entries) {
@ -460,6 +468,7 @@ extension TextTransaction on Transaction {
selection.endIndex - selection.startIndex, selection.endIndex - selection.startIndex,
texts.first, texts.first,
); );
return; return;
} }

View file

@ -9,10 +9,13 @@ mixin BlockComponentAlignMixin {
switch (alignString) { switch (alignString) {
case 'center': case 'center':
return Alignment.center; return Alignment.center;
case 'right': case 'right':
return Alignment.centerRight; return Alignment.centerRight;
case 'left': case 'left':
return Alignment.centerLeft; return Alignment.centerLeft;
default: default:
return null; return null;
} }

View file

@ -39,7 +39,9 @@ class _BlockComponentActionWrapperState
bool isDisposed = false; bool isDisposed = false;
bool _alwaysShowActions = false; bool _alwaysShowActions = false;
bool get alwaysShowActions => _alwaysShowActions; bool get alwaysShowActions => _alwaysShowActions;
@override @override
set alwaysShowActions(bool alwaysShowActions) { set alwaysShowActions(bool alwaysShowActions) {
if (isDisposed) { if (isDisposed) {

View file

@ -98,6 +98,7 @@ EdgeInsets _indentPadding(Node node, TextDirection textDirection) {
switch (textDirection) { switch (textDirection) {
case TextDirection.ltr: case TextDirection.ltr:
return const EdgeInsets.only(left: 24.0); return const EdgeInsets.only(left: 24.0);
case TextDirection.rtl: case TextDirection.rtl:
return const EdgeInsets.only(right: 24.0); return const EdgeInsets.only(right: 24.0);
} }

View file

@ -57,5 +57,6 @@ CommandShortcutEventHandler _convertToParagraphCommandHandler = (editorState) {
..deleteNode(node) ..deleteNode(node)
..afterSelection = transaction.beforeSelection; ..afterSelection = transaction.beforeSelection;
editorState.apply(transaction); editorState.apply(transaction);
return KeyEventResult.handled; return KeyEventResult.handled;
}; };

View file

@ -29,6 +29,7 @@ Future<bool> insertNewLineInType(
if (node != null && node.path.length > 1) { if (node != null && node.path.length > 1) {
return KeyEventResult.ignored != outdentCommand.execute(editorState); return KeyEventResult.ignored != outdentCommand.execute(editorState);
} }
return KeyEventResult.ignored != return KeyEventResult.ignored !=
convertToParagraphCommand.execute(editorState); convertToParagraphCommand.execute(editorState);
} }
@ -42,5 +43,6 @@ Future<bool> insertNewLineInType(
}, },
), ),
); );
return true; return true;
} }

View file

@ -72,5 +72,6 @@ Future<bool> formatMarkdownSymbol(
..afterSelection = afterSelection; ..afterSelection = afterSelection;
await editorState.apply(transaction); await editorState.apply(transaction);
return true; return true;
} }

Some files were not shown because too many files have changed in this diff Show more