mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
Merge pull request #824 from AppFlowy-IO/feat/handle-edit-keys
Feat: handle edit keys
This commit is contained in:
commit
c53df59b48
@ -1,5 +1,4 @@
|
||||
import 'package:flowy_editor/flowy_editor.dart';
|
||||
import 'package:flowy_editor/src/service/keyboard_service.dart';
|
||||
import 'package:flowy_editor/src/infra/html_converter.dart';
|
||||
import 'package:flowy_editor/src/document/node_iterator.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
@ -7,6 +7,8 @@ import 'package:flowy_editor/src/service/internal_key_event_handlers/redo_undo_h
|
||||
import 'package:flowy_editor/src/service/internal_key_event_handlers/slash_handler.dart';
|
||||
import 'package:flowy_editor/src/service/internal_key_event_handlers/update_text_style_by_command_x_handler.dart';
|
||||
import 'package:flowy_editor/src/service/internal_key_event_handlers/whitespace_handler.dart';
|
||||
import 'package:flowy_editor/src/service/internal_key_event_handlers/select_all_handler.dart';
|
||||
import 'package:flowy_editor/src/service/internal_key_event_handlers/page_up_down_handler.dart';
|
||||
import 'package:flowy_editor/src/service/keyboard_service.dart';
|
||||
|
||||
List<FlowyKeyEventHandler> defaultKeyEventHandlers = [
|
||||
@ -19,4 +21,6 @@ List<FlowyKeyEventHandler> defaultKeyEventHandlers = [
|
||||
enterWithoutShiftInTextNodesHandler,
|
||||
updateTextStyleByCommandXHandler,
|
||||
whiteSpaceHandler,
|
||||
selectAllHandler,
|
||||
pageUpDownHandler,
|
||||
];
|
||||
|
@ -2,14 +2,8 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import 'package:flowy_editor/flowy_editor.dart';
|
||||
import 'package:flowy_editor/src/service/keyboard_service.dart';
|
||||
|
||||
// Handle delete text.
|
||||
FlowyKeyEventHandler deleteTextHandler = (editorState, event) {
|
||||
if (event.logicalKey != LogicalKeyboardKey.backspace) {
|
||||
return KeyEventResult.ignored;
|
||||
}
|
||||
|
||||
KeyEventResult _handleBackspace(EditorState editorState, RawKeyEvent event) {
|
||||
final selection = editorState.service.selectionService.currentSelection.value;
|
||||
if (selection == null) {
|
||||
return KeyEventResult.ignored;
|
||||
@ -22,7 +16,7 @@ FlowyKeyEventHandler deleteTextHandler = (editorState, event) {
|
||||
return KeyEventResult.ignored;
|
||||
}
|
||||
|
||||
TransactionBuilder transactionBuilder = TransactionBuilder(editorState);
|
||||
final transactionBuilder = TransactionBuilder(editorState);
|
||||
if (textNodes.length == 1) {
|
||||
final textNode = textNodes.first;
|
||||
final index = textNode.delta.prevRunePosition(selection.start.offset);
|
||||
@ -74,23 +68,90 @@ FlowyKeyEventHandler deleteTextHandler = (editorState, event) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
final first = textNodes.first;
|
||||
final last = textNodes.last;
|
||||
var content = textNodes.last.toRawString();
|
||||
content = content.substring(selection.end.offset, content.length);
|
||||
// Merge the fist and the last text node content,
|
||||
// and delete the all nodes expect for the first.
|
||||
transactionBuilder
|
||||
..deleteNodes(textNodes.sublist(1))
|
||||
..mergeText(
|
||||
first,
|
||||
last,
|
||||
firstOffset: selection.start.offset,
|
||||
secondOffset: selection.end.offset,
|
||||
);
|
||||
_deleteNodes(transactionBuilder, textNodes, selection);
|
||||
}
|
||||
|
||||
transactionBuilder.commit();
|
||||
|
||||
return KeyEventResult.handled;
|
||||
}
|
||||
|
||||
KeyEventResult _handleDelete(EditorState editorState, RawKeyEvent event) {
|
||||
final selection = editorState.service.selectionService.currentSelection.value;
|
||||
if (selection == null) {
|
||||
return KeyEventResult.ignored;
|
||||
}
|
||||
final nodes = editorState.service.selectionService.currentSelectedNodes;
|
||||
// make sure all nodes is [TextNode].
|
||||
final textNodes = nodes.whereType<TextNode>().toList();
|
||||
if (textNodes.length != nodes.length) {
|
||||
return KeyEventResult.ignored;
|
||||
}
|
||||
|
||||
final transactionBuilder = TransactionBuilder(editorState);
|
||||
if (textNodes.length == 1) {
|
||||
final textNode = textNodes.first;
|
||||
if (selection.start.offset >= textNode.delta.length) {
|
||||
debugPrint("merge next line");
|
||||
final nextNode = textNode.next;
|
||||
if (nextNode == null) {
|
||||
return KeyEventResult.ignored;
|
||||
}
|
||||
if (nextNode is TextNode) {
|
||||
transactionBuilder.mergeText(textNode, nextNode);
|
||||
}
|
||||
transactionBuilder.deleteNode(nextNode);
|
||||
} else {
|
||||
final index = textNode.delta.nextRunePosition(selection.start.offset);
|
||||
if (selection.isCollapsed) {
|
||||
transactionBuilder.deleteText(
|
||||
textNode,
|
||||
selection.start.offset,
|
||||
index - selection.start.offset,
|
||||
);
|
||||
} else {
|
||||
transactionBuilder.deleteText(
|
||||
textNode,
|
||||
selection.start.offset,
|
||||
selection.end.offset - selection.start.offset,
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_deleteNodes(transactionBuilder, textNodes, selection);
|
||||
}
|
||||
|
||||
transactionBuilder.commit();
|
||||
|
||||
return KeyEventResult.handled;
|
||||
}
|
||||
|
||||
void _deleteNodes(TransactionBuilder transactionBuilder,
|
||||
List<TextNode> textNodes, Selection selection) {
|
||||
final first = textNodes.first;
|
||||
final last = textNodes.last;
|
||||
var content = textNodes.last.toRawString();
|
||||
content = content.substring(selection.end.offset, content.length);
|
||||
// Merge the fist and the last text node content,
|
||||
// and delete the all nodes expect for the first.
|
||||
transactionBuilder
|
||||
..deleteNodes(textNodes.sublist(1))
|
||||
..mergeText(
|
||||
first,
|
||||
last,
|
||||
firstOffset: selection.start.offset,
|
||||
secondOffset: selection.end.offset,
|
||||
);
|
||||
}
|
||||
|
||||
// Handle delete text.
|
||||
FlowyKeyEventHandler deleteTextHandler = (editorState, event) {
|
||||
if (event.logicalKey == LogicalKeyboardKey.backspace) {
|
||||
return _handleBackspace(editorState, event);
|
||||
}
|
||||
if (event.logicalKey == LogicalKeyboardKey.delete) {
|
||||
return _handleDelete(editorState, event);
|
||||
}
|
||||
|
||||
return KeyEventResult.ignored;
|
||||
};
|
||||
|
@ -0,0 +1,31 @@
|
||||
import 'package:flowy_editor/flowy_editor.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
double? getEditorHeight(EditorState editorState) {
|
||||
final renderObj =
|
||||
editorState.service.scrollServiceKey.currentContext?.findRenderObject();
|
||||
if (renderObj is RenderBox) {
|
||||
return renderObj.size.height;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
FlowyKeyEventHandler pageUpDownHandler = (editorState, event) {
|
||||
if (event.logicalKey == LogicalKeyboardKey.pageUp) {
|
||||
final scrollHeight = getEditorHeight(editorState);
|
||||
final scrollService = editorState.service.scrollService;
|
||||
if (scrollHeight != null && scrollService != null) {
|
||||
scrollService.scrollTo(scrollService.dy - scrollHeight);
|
||||
}
|
||||
return KeyEventResult.handled;
|
||||
} else if (event.logicalKey == LogicalKeyboardKey.pageDown) {
|
||||
final scrollHeight = getEditorHeight(editorState);
|
||||
final scrollService = editorState.service.scrollService;
|
||||
if (scrollHeight != null && scrollService != null) {
|
||||
scrollService.scrollTo(scrollService.dy + scrollHeight);
|
||||
}
|
||||
return KeyEventResult.handled;
|
||||
}
|
||||
return KeyEventResult.ignored;
|
||||
};
|
@ -0,0 +1,26 @@
|
||||
import 'package:flowy_editor/flowy_editor.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
KeyEventResult _selectAll(EditorState editorState) {
|
||||
if (editorState.document.root.children.isEmpty) {
|
||||
return KeyEventResult.handled;
|
||||
}
|
||||
final firstNode = editorState.document.root.children.first;
|
||||
final lastNode = editorState.document.root.children.last;
|
||||
var offset = 0;
|
||||
if (lastNode is TextNode) {
|
||||
offset = lastNode.delta.length;
|
||||
}
|
||||
editorState.updateCursorSelection(Selection(
|
||||
start: Position(path: firstNode.path, offset: 0),
|
||||
end: Position(path: lastNode.path, offset: offset)));
|
||||
return KeyEventResult.handled;
|
||||
}
|
||||
|
||||
FlowyKeyEventHandler selectAllHandler = (editorState, event) {
|
||||
if (event.isMetaPressed && event.logicalKey == LogicalKeyboardKey.keyA) {
|
||||
return _selectAll(editorState);
|
||||
}
|
||||
return KeyEventResult.ignored;
|
||||
};
|
Loading…
Reference in New Issue
Block a user