-
Notifications
You must be signed in to change notification settings - Fork 1k
Description
My issue is about Mobile, i didn't try my code on any other Platform besides Android and IOS.
I tried to adjust the Editor behavior when editing links. The normal behavior when adding a letter inside the links seems to be that the link splits at the location of the letter and both parts of the link keep the Link to the old URL target.
Our customers don't like this behavior so tried to use custom rules to reevaluate the link when an letter is added. If the link is still valid i will create one new link and remove the old one. When the new target is invalid i will remove the old one and replace it with a text.
During this development i noticed that deleting and inserting into the same delta seems to result into a wrong cursor position. To be specific if i remove text the cursor wont move at all as long as there is still text remaining after the current position, so basically the index is identical to before. If i insert text afterwards the cursor does move resulting in a wrong position.
Sample Code
`import 'package:flutter_quill/flutter_quill.dart';
import 'package:flutter_quill/models/rules/insert.dart';
import 'package:moin/helper/helper.dart';
class QuillLinkCustomInsertRule extends InsertRule {
const QuillLinkCustomInsertRule();
@OverRide
Delta? applyRule(Delta document, int index, {int? len, Object? data, Attribute? attribute}) {
if (data is! String || (data != ' ' && data != ".")) {
if (data is String ) {
final itr = DeltaIterator(document);
final prev = itr.skip(index);
final prevAttributes = prev?.attributes ?? <String, dynamic>{};
if (prev != null && prev.data is String && prevAttributes.containsKey(Attribute.link.key)) {
final after = itr.next();
final afterAttributes = after.attributes ?? <String, dynamic>{};
String text = prev.data as String;
int lengthBefore = text.length;
text += data;
if ( afterAttributes.containsKey(Attribute.link.key) ) {
text += after.data as String;
}
print(text);
Delta delta = Delta()
..retain(index - lengthBefore )
..delete(text.length - data.length);
if (Helper.isLink(text)) {
return delta..insert(text,LinkAttribute(text.toString()).toJson());
}
return delta..insert(text);
}
}
return null;
}
final itr = DeltaIterator(document);
final prev = itr.skip(index);
if (prev == null || prev.data is! String) {
return null;
}
try {
final cand = (prev.data as String).split('\n').last.split(' ').last;
final link = Uri.parse(cand);
if (!['https', 'http'].contains(link.scheme)) {// && !Helper.isLink(link.path)) {
return null;
}
final attributes = prev.attributes ?? <String, dynamic>{};
if (attributes.containsKey(Attribute.link.key)) {
return null;
}
attributes.addAll(LinkAttribute(link.toString()).toJson());
return Delta()
..retain(index + (len ?? 0) - cand.length)
..retain(cand.length, attributes)
..insert(data, prev.attributes);
} on FormatException {
return null;
}
}
}`
Expectations:
I would expect the cursor to move only 1 place if only 1 character is inserted. Since i delete and insert nearly same number of letters.
Solutions:
I couldn't find a direct way to fix this issue, the fact that nearly all classes use private constructors makes it kind of hard to try solutions using inheritance. However i did try to overwrite the length of the insert operation with 0 which doesn't help. The order of operations for the delete and insert part doesn't seem to matter for this.
I have the same issue using my custom delete rule which basically does the same as the above code just for removing characters. I can add the code if it helps.

