mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
feat: invert delta
This commit is contained in:
parent
b859e2a252
commit
3cbac6f3f9
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flowy_editor/flowy_editor.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:flowy_editor/document/attributes.dart';
|
||||
|
||||
class TextNodeBuilder extends NodeWidgetBuilder {
|
||||
TextNodeBuilder.create({
|
||||
|
@ -0,0 +1,23 @@
|
||||
typedef Attributes = Map<String, dynamic>;
|
||||
|
||||
int hashAttributes(Attributes attributes) {
|
||||
return Object.hashAllUnordered(
|
||||
attributes.entries.map((e) => Object.hash(e.key, e.value)));
|
||||
}
|
||||
|
||||
Attributes invertAttributes(Attributes? attr, Attributes? base) {
|
||||
attr ??= {};
|
||||
base ??= {};
|
||||
final Attributes baseInverted = base.keys.fold({}, (memo, key) {
|
||||
if (base![key] != attr![key] && attr.containsKey(key)) {
|
||||
memo[key] = base[key];
|
||||
}
|
||||
return memo;
|
||||
});
|
||||
return attr.keys.fold(baseInverted, (memo, key) {
|
||||
if (attr![key] != base![key] && base.containsKey(key)) {
|
||||
memo[key] = null;
|
||||
}
|
||||
return memo;
|
||||
});
|
||||
}
|
@ -1,8 +1,7 @@
|
||||
import 'dart:collection';
|
||||
import 'package:flowy_editor/document/path.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
typedef Attributes = Map<String, dynamic>;
|
||||
import './attributes.dart';
|
||||
|
||||
class Node extends ChangeNotifier with LinkedListEntry<Node> {
|
||||
Node? parent;
|
||||
|
@ -1,5 +1,6 @@
|
||||
import 'package:flowy_editor/document/node.dart';
|
||||
import 'package:flowy_editor/document/path.dart';
|
||||
import './attributes.dart';
|
||||
|
||||
class StateTree {
|
||||
final Node root;
|
||||
|
@ -3,7 +3,7 @@ import 'dart:math';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import './node.dart';
|
||||
import './attributes.dart';
|
||||
|
||||
// constant number: 2^53 - 1
|
||||
const int _maxInt = 9007199254740991;
|
||||
@ -22,14 +22,6 @@ class TextOperation {
|
||||
}
|
||||
}
|
||||
|
||||
int _hashAttributes(Attributes attributes) {
|
||||
return Object.hashAllUnordered(
|
||||
attributes.entries.map(
|
||||
(e) => Object.hash(e.key, e.value),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
class TextInsert extends TextOperation {
|
||||
String content;
|
||||
final Attributes? _attributes;
|
||||
@ -60,7 +52,7 @@ class TextInsert extends TextOperation {
|
||||
final contentHash = content.hashCode;
|
||||
final attrs = _attributes;
|
||||
return Object.hash(
|
||||
contentHash, attrs == null ? null : _hashAttributes(attrs));
|
||||
contentHash, attrs == null ? null : hashAttributes(attrs));
|
||||
}
|
||||
}
|
||||
|
||||
@ -104,7 +96,7 @@ class TextRetain extends TextOperation {
|
||||
@override
|
||||
int get hashCode {
|
||||
final attrs = _attributes;
|
||||
return Object.hash(_length, attrs == null ? null : _hashAttributes(attrs));
|
||||
return Object.hash(_length, attrs == null ? null : hashAttributes(attrs));
|
||||
}
|
||||
}
|
||||
|
||||
@ -404,6 +396,32 @@ class Delta {
|
||||
int get hashCode {
|
||||
return hashList(operations);
|
||||
}
|
||||
|
||||
Delta invert(Delta base) {
|
||||
final inverted = Delta();
|
||||
operations.fold(0, (int previousValue, op) {
|
||||
if (op is TextInsert) {
|
||||
inverted.delete(op.length);
|
||||
} else if (op is TextRetain && op.attributes == null) {
|
||||
inverted.retain(op.length);
|
||||
return previousValue + op.length;
|
||||
} else if (op is TextDelete || op is TextRetain) {
|
||||
final length = op.length;
|
||||
final slice = base.slice(previousValue, previousValue + length);
|
||||
for (final baseOp in slice.operations) {
|
||||
if (op is TextDelete) {
|
||||
inverted.add(baseOp);
|
||||
} else if (op is TextRetain && op.attributes != null) {
|
||||
inverted.retain(baseOp.length,
|
||||
invertAttributes(op.attributes, baseOp.attributes));
|
||||
}
|
||||
}
|
||||
return previousValue + length;
|
||||
}
|
||||
return previousValue;
|
||||
});
|
||||
return inverted.chop();
|
||||
}
|
||||
}
|
||||
|
||||
Attributes? _composeMap(Attributes? a, Attributes? b) {
|
||||
|
@ -1,5 +1,7 @@
|
||||
import 'package:flowy_editor/document/path.dart';
|
||||
import 'package:flowy_editor/document/node.dart';
|
||||
import 'package:flowy_editor/document/text_delta.dart';
|
||||
import 'package:flowy_editor/document/attributes.dart';
|
||||
|
||||
abstract class Operation {
|
||||
Operation invert();
|
||||
@ -61,3 +63,18 @@ class DeleteOperation extends Operation {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class TextEditOperation extends Operation {
|
||||
final Path path;
|
||||
final Delta delta;
|
||||
|
||||
TextEditOperation({
|
||||
required this.path,
|
||||
required this.delta,
|
||||
});
|
||||
|
||||
@override
|
||||
Operation invert() {
|
||||
return TextEditOperation(path: path, delta: delta);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user