From 4a2d044be60547086f57581dd8fa74e36ca486fa Mon Sep 17 00:00:00 2001 From: "Lucas.Xu" Date: Thu, 26 Sep 2024 15:49:56 +0800 Subject: [PATCH 1/3] feat: skip slicing the next inserted text if the previous text has been formatted --- lib/src/core/transform/transaction.dart | 5 ++++- .../service/ime/delta_input_on_insert_impl.dart | 6 +++++- lib/src/editor_state.dart | 6 ++++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/lib/src/core/transform/transaction.dart b/lib/src/core/transform/transaction.dart index b8fb5968a..05d171b2d 100644 --- a/lib/src/core/transform/transaction.dart +++ b/lib/src/core/transform/transaction.dart @@ -197,6 +197,7 @@ extension TextTransaction on Transaction { String text, { Attributes? attributes, Attributes? toggledAttributes, + bool sliceAttributes = true, }) { final delta = node.delta; if (delta == null) { @@ -210,7 +211,9 @@ extension TextTransaction on Transaction { return; } - final newAttributes = attributes ?? delta.sliceAttributes(index) ?? {}; + final newAttributes = attributes ?? + (sliceAttributes ? delta.sliceAttributes(index) : {}) ?? + {}; if (toggledAttributes != null) { newAttributes.addAll(toggledAttributes); diff --git a/lib/src/editor/editor_component/service/ime/delta_input_on_insert_impl.dart b/lib/src/editor/editor_component/service/ime/delta_input_on_insert_impl.dart index 0ab26dd13..367ef00dd 100644 --- a/lib/src/editor/editor_component/service/ime/delta_input_on_insert_impl.dart +++ b/lib/src/editor/editor_component/service/ime/delta_input_on_insert_impl.dart @@ -24,6 +24,7 @@ Future onInsert( ); if (execution) { + editorState.sliceUpcomingAttributes = false; return; } } @@ -76,7 +77,10 @@ Future onInsert( selection.startIndex, textInserted, toggledAttributes: editorState.toggledStyle, + sliceAttributes: editorState.sliceUpcomingAttributes, ) ..afterSelection = afterSelection; - return editorState.apply(transaction); + await editorState.apply(transaction); + + editorState.sliceUpcomingAttributes = true; } diff --git a/lib/src/editor_state.dart b/lib/src/editor_state.dart index 8c24e5bbb..4d988d45a 100644 --- a/lib/src/editor_state.dart +++ b/lib/src/editor_state.dart @@ -183,6 +183,12 @@ class EditorState { toggledStyleNotifier.value = {..._toggledStyle}; } + /// Whether the upcoming attributes should be sliced. + /// + /// If the value is true, the upcoming attributes will be sliced. + /// If the value is false, the upcoming attributes will be skipped. + bool sliceUpcomingAttributes = true; + final UndoManager undoManager = UndoManager(); Transaction get transaction { From 7a2d36a51ab24f3fa92ce7f2a6aa3b17b5ed242f Mon Sep 17 00:00:00 2001 From: "Lucas.Xu" Date: Thu, 26 Sep 2024 16:01:47 +0800 Subject: [PATCH 2/3] test: skip slicing attribute test --- test/customer/slice_attributes_test.dart | 66 ++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 test/customer/slice_attributes_test.dart diff --git a/test/customer/slice_attributes_test.dart b/test/customer/slice_attributes_test.dart new file mode 100644 index 000000000..4e9c145c1 --- /dev/null +++ b/test/customer/slice_attributes_test.dart @@ -0,0 +1,66 @@ +import 'package:appflowy_editor/appflowy_editor.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../new/infra/testable_editor.dart'; + +void main() async { + setUpAll(() { + TestWidgetsFlutterBinding.ensureInitialized(); + }); + + // input `Hello` World + // only the `Hello` has the code style + testWidgets('skip attributes if pressing space', (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 text = '`Hello` World'; + for (var i = 0; i < text.length; i++) { + await editor.ime.typeText(text[i]); + } + + final node = editor.editorState.getNodeAtPath([0]); + final delta = node?.delta; + expect(delta?.toPlainText(), 'Hello World'); + expect(delta?.toJson(), [ + { + 'insert': 'Hello', + 'attributes': {'code': true}, + }, + {'insert': ' World'}, + ]); + }); + + testWidgets('keep attributes if pressing backspace', (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` '; + for (var i = 0; i < text1.length; i++) { + await editor.ime.typeText(text1[i]); + } + + await tester.editor.pressKey(key: LogicalKeyboardKey.backspace); + + const text2 = 'World'; + for (var i = 0; i < text2.length; i++) { + await editor.ime.typeText(text2[i]); + } + + final node = editor.editorState.getNodeAtPath([0]); + final delta = node?.delta; + expect(delta?.toJson(), [ + { + 'insert': 'HelloWorld', + 'attributes': {'code': true}, + }, + ]); + }); +} From e4f0d0cd291e35bbcaf642c880cb7ea7e9add636 Mon Sep 17 00:00:00 2001 From: "Lucas.Xu" Date: Thu, 26 Sep 2024 16:13:54 +0800 Subject: [PATCH 3/3] feat: reset slice flag when updating selection --- .../service/ime/delta_input_on_insert_impl.dart | 2 -- lib/src/editor_state.dart | 3 +++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/src/editor/editor_component/service/ime/delta_input_on_insert_impl.dart b/lib/src/editor/editor_component/service/ime/delta_input_on_insert_impl.dart index 367ef00dd..4d8bac3f8 100644 --- a/lib/src/editor/editor_component/service/ime/delta_input_on_insert_impl.dart +++ b/lib/src/editor/editor_component/service/ime/delta_input_on_insert_impl.dart @@ -81,6 +81,4 @@ Future onInsert( ) ..afterSelection = afterSelection; await editorState.apply(transaction); - - editorState.sliceUpcomingAttributes = true; } diff --git a/lib/src/editor_state.dart b/lib/src/editor_state.dart index 4d988d45a..9b13bbf9e 100644 --- a/lib/src/editor_state.dart +++ b/lib/src/editor_state.dart @@ -123,6 +123,9 @@ class EditorState { _toggledStyle.clear(); } + // reset slice flag + sliceUpcomingAttributes = true; + selectionNotifier.value = value; }