Skip to content

Commit

Permalink
feat: slice attribute from next position if index is 0 (#911)
Browse files Browse the repository at this point in the history
* feat: slice attribute from next position if index is 0

* test: add slice attributes test
  • Loading branch information
LucasXu0 authored Oct 8, 2024
1 parent 647a53e commit c07f9ef
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 9 deletions.
30 changes: 21 additions & 9 deletions lib/src/core/document/text_delta.dart
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import 'dart:math';

import 'package:appflowy_editor/src/core/document/attributes.dart';
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:collection/collection.dart';
import 'package:diff_match_patch/diff_match_patch.dart' as diff_match_patch;
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';

import '../../editor/block_component/rich_text/appflowy_rich_text_keys.dart';

// constant number: 2^53 - 1
const int _maxInt = 9007199254740991;

Expand Down Expand Up @@ -517,15 +515,29 @@ class Delta extends Iterable<TextOperation> {
}

Attributes? sliceAttributes(int index) {
if (index <= 0) {
if (index < 0) {
return null;
}

final attributes = slice(index - 1, index).first.attributes;
if (attributes == null ||
!attributes.keys.every(
(element) => AppFlowyRichTextKeys.supportSliced.contains(element),
)) {
Attributes? attributes;

// if the index == 0, slice the attributes from the next position.
if (index == 0 && length >= 1) {
attributes = slice(index, index + 1).firstOrNull?.attributes;
} else {
attributes = slice(index - 1, index).firstOrNull?.attributes;
}

if (attributes == null) {
return null;
}

if (!attributes.keys.every(
(element) => AppFlowyRichTextKeys.supportSliced.contains(element),
)) {
AppFlowyEditorLog.editor.info(
'The attributes: $attributes is not supported in sliceAttributes.',
);
return null;
}

Expand Down
59 changes: 59 additions & 0 deletions test/customer/slice_attributes_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,63 @@ void main() async {
},
]);
});

testWidgets('slice attributes from next position if index is 0',
(tester) async {
final editor = tester.editor..addEmptyParagraph();
await editor.startTesting();
await tester.pumpAndSettle();

final selection = Selection.collapsed(Position(path: [0]));
await editor.updateSelection(selection);
const text1 = '**World**';
for (var i = 0; i < text1.length; i++) {
await editor.ime.typeText(text1[i]);
}

// move the cursor to the beginning of the text
await editor.updateSelection(Selection.collapsed(Position(path: [0])));
await editor.ime.typeText('Hello');

final node = editor.editorState.getNodeAtPath([0]);
final delta = node?.delta;
expect(delta?.toJson(), [
{
'insert': 'HelloWorld',
'attributes': {'bold': true},
},
]);
});

testWidgets('don\'t slice attributes from next position if index is not 0',
(tester) async {
final editor = tester.editor..addEmptyParagraph();
await editor.startTesting();
await tester.pumpAndSettle();

final selection = Selection.collapsed(Position(path: [0]));
await editor.updateSelection(selection);
const text1 = 'Hello **World**';
for (var i = 0; i < text1.length; i++) {
await editor.ime.typeText(text1[i]);
}

// move the cursor after Hello: `Hello |`
await editor.updateSelection(
Selection.collapsed(Position(path: [0], offset: 6)),
);
await editor.ime.typeText('Hello');

final node = editor.editorState.getNodeAtPath([0]);
final delta = node?.delta;
expect(delta?.toJson(), [
{
'insert': 'Hello Hello',
},
{
'insert': 'World',
'attributes': {'bold': true},
},
]);
});
}

0 comments on commit c07f9ef

Please sign in to comment.