mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
feat: recognize number
This commit is contained in:
parent
ea271c7342
commit
565617d1f0
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user