From b245841ec3ac4ee89300a34b74033a12b93b1c13 Mon Sep 17 00:00:00 2001 From: "Lucas.Xu" Date: Sat, 30 Jul 2022 00:00:10 +0800 Subject: [PATCH] feat: implement text delete --- .../flowy_editor/example/assets/example.json | 6 +- .../lib/service/editor_service.dart | 2 + .../delele_text_handler.dart | 83 +++++++++++++++++++ 3 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 frontend/app_flowy/packages/flowy_editor/lib/service/internal_key_event_handlers/delele_text_handler.dart diff --git a/frontend/app_flowy/packages/flowy_editor/example/assets/example.json b/frontend/app_flowy/packages/flowy_editor/example/assets/example.json index 6a0fba3021..9f1d278e16 100644 --- a/frontend/app_flowy/packages/flowy_editor/example/assets/example.json +++ b/frontend/app_flowy/packages/flowy_editor/example/assets/example.json @@ -162,7 +162,11 @@ "type": "text", "delta": [ { - "insert": "Hello world" + "insert": "Hello " + }, + { + "insert": "world", + "attributes": { "bold": true } } ], "attributes": { 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 1d961737ff..b7a64ffcc7 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,3 +1,4 @@ +import 'package:flowy_editor/service/internal_key_event_handlers/delele_text_handler.dart'; import 'package:flutter/material.dart'; import 'package:flowy_editor/editor_state.dart'; @@ -30,6 +31,7 @@ NodeWidgetBuilders defaultBuilders = { }; List defaultKeyEventHandler = [ + deleteTextHandler, slashShortcutHandler, flowyDeleteNodesHandler, arrowKeysHandler, diff --git a/frontend/app_flowy/packages/flowy_editor/lib/service/internal_key_event_handlers/delele_text_handler.dart b/frontend/app_flowy/packages/flowy_editor/lib/service/internal_key_event_handlers/delele_text_handler.dart new file mode 100644 index 0000000000..b50d947d5c --- /dev/null +++ b/frontend/app_flowy/packages/flowy_editor/lib/service/internal_key_event_handlers/delele_text_handler.dart @@ -0,0 +1,83 @@ +import 'package:flowy_editor/flowy_editor.dart'; +import 'package:flowy_editor/service/keyboard_service.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +// Handle delete text. +FlowyKeyEventHandler deleteTextHandler = (editorState, event) { + if (event.logicalKey != LogicalKeyboardKey.backspace) { + return KeyEventResult.ignored; + } + + final selection = editorState.service.selectionService.currentSelection; + if (selection == null) { + return KeyEventResult.ignored; + } + + final nodes = editorState.service.selectionService.currentSelectedNodes.value; + // make sure all nodes is [TextNode]. + final textNodes = nodes.whereType().toList(); + if (textNodes.length != nodes.length) { + return KeyEventResult.ignored; + } + + TransactionBuilder transactionBuilder = TransactionBuilder(editorState); + if (textNodes.length == 1) { + final textNode = textNodes.first; + final index = selection.start.offset - 1; + if (index < 0) { + // 1. style + if (textNode.subtype != null) { + transactionBuilder.updateNode(textNode, { + 'subtype': null, + }); + } else { + // 2. non-style + // find previous text node. + while (textNode.previous != null) { + if (textNode.previous is TextNode) { + final previous = textNode.previous as TextNode; + transactionBuilder + ..deleteNode(textNode) + ..insertText( + previous, + previous.toRawString().length, + textNode.toRawString(), + ); + // FIXME: keep the attributes. + break; + } + } + } + } else { + transactionBuilder.deleteText( + textNode, + selection.start.offset - 1, + 1, + ); + } + } else { + for (var i = 0; i < textNodes.length; i++) { + final textNode = textNodes[i]; + if (i == 0) { + transactionBuilder.deleteText( + textNode, + selection.start.offset, + textNode.toRawString().length - selection.start.offset, + ); + } else if (i == textNodes.length - 1) { + transactionBuilder.deleteText( + textNode, + 0, + selection.end.offset, + ); + } else { + transactionBuilder.deleteNode(textNode); + } + } + } + + transactionBuilder.commit(); + + return KeyEventResult.handled; +};