diff --git a/frontend/app_flowy/packages/appflowy_editor/lib/src/service/internal_key_event_handlers/enter_without_shift_in_text_node_handler.dart b/frontend/app_flowy/packages/appflowy_editor/lib/src/service/internal_key_event_handlers/enter_without_shift_in_text_node_handler.dart index 8f12dbb9e6..bef42cc521 100644 --- a/frontend/app_flowy/packages/appflowy_editor/lib/src/service/internal_key_event_handlers/enter_without_shift_in_text_node_handler.dart +++ b/frontend/app_flowy/packages/appflowy_editor/lib/src/service/internal_key_event_handlers/enter_without_shift_in_text_node_handler.dart @@ -1,14 +1,9 @@ +import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:appflowy_editor/src/document/attributes.dart'; -import 'package:appflowy_editor/src/document/node.dart'; -import 'package:appflowy_editor/src/document/position.dart'; -import 'package:appflowy_editor/src/document/selection.dart'; import 'package:appflowy_editor/src/extensions/path_extensions.dart'; -import 'package:appflowy_editor/src/operation/transaction_builder.dart'; import 'package:appflowy_editor/src/render/rich_text/rich_text_style.dart'; -import 'package:appflowy_editor/src/service/shortcut_event/shortcut_event_handler.dart'; /// Handle some cases where enter is pressed and shift is not pressed. /// @@ -104,19 +99,12 @@ ShortcutEventHandler enterWithoutShiftInTextNodesHandler = // Otherwise, // split the node into two nodes with style - final needCopyAttributes = StyleKey.globalStyleKeys - .where((key) => key != StyleKey.heading) - .contains(textNode.subtype); - Attributes attributes = {}; - if (needCopyAttributes) { - attributes = Attributes.from(textNode.attributes); - if (attributes.check) { - attributes[StyleKey.checkbox] = false; - } - } + Attributes attributes = _attributesFromPreviousLine(textNode); + final afterSelection = Selection.collapsed( Position(path: textNode.path.next, offset: 0), ); + TransactionBuilder(editorState) ..insertNode( textNode.path.next, @@ -132,5 +120,44 @@ ShortcutEventHandler enterWithoutShiftInTextNodesHandler = ) ..afterSelection = afterSelection ..commit(); + + // If the new type of a text node is number list, + // the numbers of the following nodes should be incremental. + if (textNode.subtype == StyleKey.numberList) { + _makeFollowingNodeIncremental(editorState, textNode); + } + return KeyEventResult.handled; }; + +Attributes _attributesFromPreviousLine(TextNode textNode) { + final prevAttributes = textNode.attributes; + final subType = textNode.subtype; + if (subType == null || subType == StyleKey.heading) { + return {}; + } + + final copy = Attributes.from(prevAttributes); + if (subType == StyleKey.numberList) { + return _nextNumberAttributesFromPreviousLine(copy, textNode); + } + + if (subType == StyleKey.checkbox) { + copy[StyleKey.checkbox] = false; + return copy; + } + + return copy; +} + +Attributes _nextNumberAttributesFromPreviousLine( + Attributes copy, TextNode textNode) { + final prevNum = textNode.attributes[StyleKey.number] as int?; + copy[StyleKey.number] = prevNum == null ? 1 : prevNum + 1; + return copy; +} + +void _makeFollowingNodeIncremental(EditorState editorState, TextNode textNode) { + debugPrint("following nodes"); + TransactionBuilder(editorState).commit(); +} diff --git a/frontend/app_flowy/packages/appflowy_editor/lib/src/service/internal_key_event_handlers/whitespace_handler.dart b/frontend/app_flowy/packages/appflowy_editor/lib/src/service/internal_key_event_handlers/whitespace_handler.dart index c6046ba6dd..b667f0c100 100644 --- a/frontend/app_flowy/packages/appflowy_editor/lib/src/service/internal_key_event_handlers/whitespace_handler.dart +++ b/frontend/app_flowy/packages/appflowy_editor/lib/src/service/internal_key_event_handlers/whitespace_handler.dart @@ -20,6 +20,8 @@ const _bulletedListSymbols = ['*', '-']; const _checkboxListSymbols = ['[x]', '-[x]']; const _unCheckboxListSymbols = ['[]', '-[]']; +final _numberRegex = RegExp(r'^(\d+)\.'); + ShortcutEventHandler whiteSpaceHandler = (editorState, event) { if (event.logicalKey != LogicalKeyboardKey.space) { return KeyEventResult.ignored; @@ -42,6 +44,16 @@ ShortcutEventHandler whiteSpaceHandler = (editorState, event) { final textNode = textNodes.first; final text = textNode.toRawString(); + + final numberMatch = _numberRegex.firstMatch(text); + if (numberMatch != null) { + final matchText = numberMatch.group(0); + final numText = numberMatch.group(1); + if (matchText != null && numText != null) { + return _toNumberList(editorState, textNode, matchText, numText); + } + } + if ((_checkboxListSymbols + _unCheckboxListSymbols).any(text.startsWith)) { return _toCheckboxList(editorState, textNode); } else if (_bulletedListSymbols.any(text.startsWith)) { @@ -53,6 +65,31 @@ ShortcutEventHandler whiteSpaceHandler = (editorState, event) { return KeyEventResult.ignored; }; +KeyEventResult _toNumberList(EditorState editorState, TextNode textNode, + String matchText, String numText) { + if (textNode.subtype == StyleKey.bulletedList) { + return KeyEventResult.ignored; + } + + final numValue = int.tryParse(numText); + if (numValue == null) { + return KeyEventResult.ignored; + } + + TransactionBuilder(editorState) + ..deleteText(textNode, 0, matchText.length) + ..updateNode(textNode, + {StyleKey.subtype: StyleKey.numberList, StyleKey.number: numValue}) + ..afterSelection = Selection.collapsed( + Position( + path: textNode.path, + offset: 0, + ), + ) + ..commit(); + return KeyEventResult.handled; +} + KeyEventResult _toBulletedList(EditorState editorState, TextNode textNode) { if (textNode.subtype == StyleKey.bulletedList) { return KeyEventResult.ignored;