diff --git a/frontend/app_flowy/packages/flowy_editor/lib/document/node.dart b/frontend/app_flowy/packages/flowy_editor/lib/document/node.dart index 8b80fd0b51..9760268e80 100644 --- a/frontend/app_flowy/packages/flowy_editor/lib/document/node.dart +++ b/frontend/app_flowy/packages/flowy_editor/lib/document/node.dart @@ -1,6 +1,7 @@ import 'dart:collection'; import 'package:flowy_editor/document/path.dart'; import 'package:flowy_editor/document/text_delta.dart'; +import 'package:flowy_editor/operation/operation.dart'; import 'package:flutter/material.dart'; import './attributes.dart'; @@ -172,6 +173,14 @@ class TextNode extends Node { required Delta delta, }) : _delta = delta; + TextNode.empty() + : _delta = Delta([TextInsert('')]), + super( + type: 'text', + children: LinkedList(), + attributes: {}, + ); + Delta get delta { return _delta; } diff --git a/frontend/app_flowy/packages/flowy_editor/lib/extensions/node_extensions.dart b/frontend/app_flowy/packages/flowy_editor/lib/extensions/node_extensions.dart index 49cc38f749..52b7596240 100644 --- a/frontend/app_flowy/packages/flowy_editor/lib/extensions/node_extensions.dart +++ b/frontend/app_flowy/packages/flowy_editor/lib/extensions/node_extensions.dart @@ -1,5 +1,3 @@ -import 'dart:math'; - import 'package:flowy_editor/document/node.dart'; import 'package:flowy_editor/document/selection.dart'; import 'package:flowy_editor/extensions/object_extensions.dart'; diff --git a/frontend/app_flowy/packages/flowy_editor/lib/extensions/path_extensions.dart b/frontend/app_flowy/packages/flowy_editor/lib/extensions/path_extensions.dart index b37d846482..793dc552dd 100644 --- a/frontend/app_flowy/packages/flowy_editor/lib/extensions/path_extensions.dart +++ b/frontend/app_flowy/packages/flowy_editor/lib/extensions/path_extensions.dart @@ -22,4 +22,15 @@ extension PathExtensions on Path { } return true; } + + Path get next { + Path nextPath = Path.from(this, growable: true); + if (isEmpty) { + return nextPath; + } + final last = nextPath.last; + return nextPath + ..removeLast() + ..add(last + 1); + } } diff --git a/frontend/app_flowy/packages/flowy_editor/lib/render/node_widget_builder.dart b/frontend/app_flowy/packages/flowy_editor/lib/render/node_widget_builder.dart index 06f364d67b..659c380720 100644 --- a/frontend/app_flowy/packages/flowy_editor/lib/render/node_widget_builder.dart +++ b/frontend/app_flowy/packages/flowy_editor/lib/render/node_widget_builder.dart @@ -31,7 +31,7 @@ class NodeWidgetBuilder { throw UnimplementedError(); /// TODO: refactore this part. - /// return widget embeded with ChangeNotifier and widget itself. + /// return widget embedded with ChangeNotifier and widget itself. Widget call( BuildContext buildContext, ) { diff --git a/frontend/app_flowy/packages/flowy_editor/lib/service/editor_service.dart b/frontend/app_flowy/packages/flowy_editor/lib/service/editor_service.dart index 307b586f31..d5223ec36a 100644 --- a/frontend/app_flowy/packages/flowy_editor/lib/service/editor_service.dart +++ b/frontend/app_flowy/packages/flowy_editor/lib/service/editor_service.dart @@ -1,5 +1,6 @@ import 'package:flowy_editor/render/selection/floating_shortcut_widget.dart'; import 'package:flowy_editor/service/input_service.dart'; +import 'package:flowy_editor/service/internal_key_event_handlers/enter_in_edge_of_text_node_handler.dart'; import 'package:flowy_editor/service/shortcut_service.dart'; import 'package:flowy_editor/service/internal_key_event_handlers/arrow_keys_handler.dart'; import 'package:flowy_editor/service/internal_key_event_handlers/delete_nodes_handler.dart'; @@ -47,6 +48,7 @@ class _FlowyEditorState extends State { flowyDeleteNodesHandler, deleteSingleTextNodeHandler, arrowKeysHandler, + enterInEdgeOfTextNodeHandler, ...widget.keyEventHandlers, ], editorState: editorState, diff --git a/frontend/app_flowy/packages/flowy_editor/lib/service/input_service.dart b/frontend/app_flowy/packages/flowy_editor/lib/service/input_service.dart index c02e9828e4..bdbcd24467 100644 --- a/frontend/app_flowy/packages/flowy_editor/lib/service/input_service.dart +++ b/frontend/app_flowy/packages/flowy_editor/lib/service/input_service.dart @@ -1,5 +1,8 @@ +import 'package:flowy_editor/document/position.dart'; +import 'package:flowy_editor/document/selection.dart'; import 'package:flowy_editor/editor_state.dart'; import 'package:flowy_editor/document/node.dart'; +import 'package:flowy_editor/operation/transaction_builder.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -86,7 +89,18 @@ class _FlowyInputState extends State } @override - void apply(List deltas) {} + void apply(List deltas) { +// TODO: implement the detail + for (final delta in deltas) { + if (delta is TextEditingDeltaInsertion) { + } else if (delta is TextEditingDeltaDeletion) { + } else if (delta is TextEditingDeltaReplacement) { + } else if (delta is TextEditingDeltaNonTextUpdate) { + // We don't need to care the [TextEditingDeltaNonTextUpdate]. + // Do nothing. + } + } + } @override void close() { diff --git a/frontend/app_flowy/packages/flowy_editor/lib/service/internal_key_event_handlers/enter_in_edge_of_text_node_handler.dart b/frontend/app_flowy/packages/flowy_editor/lib/service/internal_key_event_handlers/enter_in_edge_of_text_node_handler.dart new file mode 100644 index 0000000000..d1e89d393e --- /dev/null +++ b/frontend/app_flowy/packages/flowy_editor/lib/service/internal_key_event_handlers/enter_in_edge_of_text_node_handler.dart @@ -0,0 +1,46 @@ +import 'package:flowy_editor/document/node.dart'; +import 'package:flowy_editor/document/position.dart'; +import 'package:flowy_editor/document/selection.dart'; +import 'package:flowy_editor/operation/transaction_builder.dart'; +import 'package:flowy_editor/service/keyboard_service.dart'; +import 'package:flowy_editor/extensions/path_extensions.dart'; +import 'package:flowy_editor/extensions/node_extensions.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +FlowyKeyEventHandler enterInEdgeOfTextNodeHandler = (editorState, event) { + if (event.logicalKey != LogicalKeyboardKey.enter) { + return KeyEventResult.ignored; + } + + final nodes = editorState.service.selectionService.currentSelectedNodes.value; + final selection = editorState.service.selectionService.currentSelection; + if (selection == null || + nodes.length != 1 || + nodes.first is! TextNode || + !selection.isCollapsed) { + return KeyEventResult.ignored; + } + + final textNode = nodes.first as TextNode; + + if (textNode.selectable!.end() == selection.end) { + TransactionBuilder(editorState) + ..insertNode( + textNode.path.next, + TextNode.empty(), + ) + ..commit(); + return KeyEventResult.handled; + } else if (textNode.selectable!.start() == selection.start) { + TransactionBuilder(editorState) + ..insertNode( + textNode.path, + TextNode.empty(), + ) + ..commit(); + return KeyEventResult.handled; + } + + return KeyEventResult.ignored; +};