diff --git a/lib/src/service/internal_key_event_handlers/enter_without_shift_in_text_node_handler.dart b/lib/src/service/internal_key_event_handlers/enter_without_shift_in_text_node_handler.dart index 69c041007..e62d8e39d 100644 --- a/lib/src/service/internal_key_event_handlers/enter_without_shift_in_text_node_handler.dart +++ b/lib/src/service/internal_key_event_handlers/enter_without_shift_in_text_node_handler.dart @@ -77,15 +77,27 @@ ShortcutEventHandler enterWithoutShiftInTextNodesHandler = // insert a empty text node before. if (selection.isCollapsed && selection.start.offset == 0) { if (textNode.toPlainText().isEmpty && textNode.subtype != null) { + final path = + textNode.path.length > 1 ? [++textNode.path.first] : textNode.path; + final afterSelection = Selection.collapsed( - Position(path: textNode.path, offset: 0), + Position(path: path, offset: 0), ); - final transaction = editorState.transaction - ..updateNode(textNode, { - BuiltInAttributeKey.subtype: null, - textNode.subtype!: null, - }) - ..afterSelection = afterSelection; + + final transaction = editorState.transaction; + if (textNode.path.length > 1) { + transaction + ..deleteNode(textNode) + ..insertNode(path, textNode) + ..afterSelection = afterSelection; + } else { + transaction + ..updateNode(textNode, { + BuiltInAttributeKey.subtype: null, + textNode.subtype!: null, + }) + ..afterSelection = afterSelection; + } editorState.apply(transaction); final nextNode = textNode.next; diff --git a/test/service/internal_key_event_handlers/enter_without_shift_in_text_node_handler_test.dart b/test/service/internal_key_event_handlers/enter_without_shift_in_text_node_handler_test.dart index 5b7e8d84f..74605f86c 100644 --- a/test/service/internal_key_event_handlers/enter_without_shift_in_text_node_handler_test.dart +++ b/test/service/internal_key_event_handlers/enter_without_shift_in_text_node_handler_test.dart @@ -102,12 +102,23 @@ void main() async { testWidgets('Presses enter key in bulleted list', (tester) async { await _testStyleNeedToBeCopy(tester, BuiltInAttributeKey.bulletedList); }); + testWidgets('Presses enter key in numbered list', (tester) async { await _testStyleNeedToBeCopy(tester, BuiltInAttributeKey.numberList); }); + testWidgets('Presses enter key in checkbox styled text', (tester) async { await _testStyleNeedToBeCopy(tester, BuiltInAttributeKey.checkbox); }); + + testWidgets('Presses enter key in checkbox list indented', (tester) async { + await _testListOutdent(tester, BuiltInAttributeKey.checkbox); + }); + + testWidgets('Presses enter key in bulleted list indented', (tester) async { + await _testListOutdent(tester, BuiltInAttributeKey.bulletedList); + }); + testWidgets('Presses enter key in quoted text', (tester) async { await _testStyleNeedToBeCopy(tester, BuiltInAttributeKey.quote); }); @@ -203,6 +214,50 @@ Future _testStyleNeedToBeCopy(WidgetTester tester, String style) async { } } +Future _testListOutdent(WidgetTester tester, String style) async { + const text = 'Welcome to Appflowy 😁'; + final Attributes attributes = { + BuiltInAttributeKey.subtype: style, + style: true, + }; + + final editor = tester.editor + ..insertTextNode(text) + ..insertTextNode(text, attributes: attributes) + ..insertTextNode('', attributes: attributes); + + await editor.startTesting(); + await editor.updateSelection( + Selection.single(path: [2], startOffset: 0), + ); + await editor.pressLogicKey( + key: LogicalKeyboardKey.tab, + ); + expect( + editor.documentSelection, + Selection.single(path: [1, 0], startOffset: 0), + ); + + await editor.pressLogicKey( + key: LogicalKeyboardKey.enter, + ); + expect( + editor.documentSelection, + Selection.single(path: [2], startOffset: 0), + ); + expect(editor.nodeAtPath([2])?.subtype, style); + + await editor.pressLogicKey( + key: LogicalKeyboardKey.enter, + ); + expect( + editor.documentSelection, + Selection.single(path: [2], startOffset: 0), + ); + + expect(editor.nodeAtPath([2])?.subtype, null); +} + Future _testMultipleSelection( WidgetTester tester, bool isBackwardSelection,