mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-11-10 10:18:57 +03:00
feat: Implement arrow up/down/left/right event handler. #708
This commit is contained in:
parent
e1d990e4ae
commit
2f86cac8af
@ -61,6 +61,16 @@ class __ImageNodeWidgetState extends State<_ImageNodeWidget> with Selectable {
|
||||
return Offset.zero;
|
||||
}
|
||||
|
||||
@override
|
||||
Offset getLeftOfOffset() {
|
||||
return Offset.zero;
|
||||
}
|
||||
|
||||
@override
|
||||
Offset getRightOfOffset() {
|
||||
return Offset.zero;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return _build(context);
|
||||
|
@ -1,3 +1,5 @@
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:example/plugin/debuggable_rich_text.dart';
|
||||
import 'package:flowy_editor/flowy_editor.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
@ -108,6 +110,30 @@ class _SelectedTextNodeWidgetState extends State<_SelectedTextNodeWidget>
|
||||
return _renderParagraph.localToGlobal(offset);
|
||||
}
|
||||
|
||||
@override
|
||||
Offset getLeftOfOffset() {
|
||||
final textSelection = _textSelection;
|
||||
if (textSelection != null) {
|
||||
final leftTextSelection = TextSelection.collapsed(
|
||||
offset: max(0, textSelection.baseOffset - 1),
|
||||
);
|
||||
return getOffsetByTextSelection(leftTextSelection);
|
||||
}
|
||||
return Offset.zero;
|
||||
}
|
||||
|
||||
@override
|
||||
Offset getRightOfOffset() {
|
||||
final textSelection = _textSelection;
|
||||
if (textSelection != null) {
|
||||
final leftTextSelection = TextSelection.collapsed(
|
||||
offset: min(node.toRawString().length, textSelection.extentOffset + 1),
|
||||
);
|
||||
return getOffsetByTextSelection(leftTextSelection);
|
||||
}
|
||||
return Offset.zero;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Widget richText;
|
||||
@ -117,6 +143,10 @@ class _SelectedTextNodeWidgetState extends State<_SelectedTextNodeWidget>
|
||||
richText = RichText(key: _textKey, text: node.toTextSpan());
|
||||
}
|
||||
|
||||
if (node.children.isEmpty) {
|
||||
return richText;
|
||||
}
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
|
@ -1,4 +1,5 @@
|
||||
import 'dart:async';
|
||||
import 'package:flowy_editor/service/service.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flowy_editor/document/node.dart';
|
||||
@ -19,13 +20,14 @@ class ApplyOptions {
|
||||
});
|
||||
}
|
||||
|
||||
// TODO
|
||||
final selectionServiceKey = GlobalKey();
|
||||
|
||||
class EditorState {
|
||||
final StateTree document;
|
||||
final RenderPlugins renderPlugins;
|
||||
List<Node> selectedNodes = [];
|
||||
|
||||
// Service reference.
|
||||
final service = FlowyService();
|
||||
|
||||
final UndoManager undoManager = UndoManager();
|
||||
Selection? cursorSelection;
|
||||
|
||||
|
@ -11,6 +11,12 @@ mixin Selectable<T extends StatefulWidget> on State<T> {
|
||||
/// The return result must be an local offset.
|
||||
Rect getCursorRect(Offset start);
|
||||
|
||||
/// Returns one unit offset to the left of the offset
|
||||
Offset getLeftOfOffset(/* Cause */);
|
||||
|
||||
/// Returns one unit offset to the right of the offset
|
||||
Offset getRightOfOffset(/* Cause */);
|
||||
|
||||
/// For [TextNode] only.
|
||||
TextSelection? getTextSelection();
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
import 'package:flowy_editor/service/flowy_key_event_handlers/arrow_keys_handler.dart';
|
||||
import 'package:flowy_editor/service/flowy_key_event_handlers/delete_nodes_handler.dart';
|
||||
import 'package:flowy_editor/service/flowy_key_event_handlers/delete_single_text_node_handler.dart';
|
||||
import 'package:flowy_editor/service/keyboard_service.dart';
|
||||
@ -26,12 +27,14 @@ class _FlowyEditorState extends State<FlowyEditor> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return FlowySelection(
|
||||
key: selectionServiceKey,
|
||||
key: editorState.service.selectionServiceKey,
|
||||
editorState: editorState,
|
||||
child: FlowyKeyboard(
|
||||
key: editorState.service.keyboardServiceKey,
|
||||
handlers: [
|
||||
flowyDeleteNodesHandler,
|
||||
deleteSingleTextNodeHandler,
|
||||
arrowKeysHandler,
|
||||
...widget.keyEventHandler,
|
||||
],
|
||||
editorState: editorState,
|
||||
|
@ -0,0 +1,37 @@
|
||||
import 'package:flowy_editor/extensions/object_extensions.dart';
|
||||
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';
|
||||
|
||||
FlowyKeyEventHandler arrowKeysHandler = (editorState, event) {
|
||||
if (event.logicalKey != LogicalKeyboardKey.arrowUp &&
|
||||
event.logicalKey != LogicalKeyboardKey.arrowDown &&
|
||||
event.logicalKey != LogicalKeyboardKey.arrowLeft &&
|
||||
event.logicalKey != LogicalKeyboardKey.arrowRight) {
|
||||
return KeyEventResult.ignored;
|
||||
}
|
||||
|
||||
// TODO: Up and Down
|
||||
|
||||
// Left and Right
|
||||
final selectedNodes = editorState.selectedNodes;
|
||||
if (selectedNodes.length != 1) {
|
||||
return KeyEventResult.ignored;
|
||||
}
|
||||
|
||||
final node = selectedNodes.first.unwrapOrNull<TextNode>();
|
||||
final selectable = node?.key?.currentState?.unwrapOrNull<Selectable>();
|
||||
Offset? offset;
|
||||
if (event.logicalKey == LogicalKeyboardKey.arrowLeft) {
|
||||
offset = selectable?.getLeftOfOffset();
|
||||
} else if (event.logicalKey == LogicalKeyboardKey.arrowRight) {
|
||||
offset = selectable?.getRightOfOffset();
|
||||
}
|
||||
final selectionService = editorState.service.selectionService;
|
||||
if (offset != null) {
|
||||
selectionService.updateCursor(offset);
|
||||
return KeyEventResult.handled;
|
||||
}
|
||||
return KeyEventResult.ignored;
|
||||
};
|
@ -33,8 +33,7 @@ FlowyKeyEventHandler deleteSingleTextNodeHandler = (editorState, event) {
|
||||
final previous = node!.previous! as TextNode;
|
||||
final newTextSelection = TextSelection.collapsed(
|
||||
offset: previous.toRawString().length);
|
||||
final selectionService =
|
||||
selectionServiceKey.currentState as FlowySelectionService;
|
||||
final selectionService = editorState.service.selectionService;
|
||||
final previousSelectable =
|
||||
previous.key?.currentState?.unwrapOrNull<Selectable>();
|
||||
final newOfset = previousSelectable
|
||||
@ -58,8 +57,7 @@ FlowyKeyEventHandler deleteSingleTextNodeHandler = (editorState, event) {
|
||||
..commit();
|
||||
final newTextSelection =
|
||||
TextSelection.collapsed(offset: textSelection.baseOffset - 1);
|
||||
final selectionService =
|
||||
selectionServiceKey.currentState as FlowySelectionService;
|
||||
final selectionService = editorState.service.selectionService;
|
||||
final newOfset =
|
||||
selectable.getOffsetByTextSelection(newTextSelection);
|
||||
selectionService.updateCursor(newOfset);
|
||||
|
@ -46,7 +46,7 @@ class _FlowyKeyboardState extends State<FlowyKeyboard> {
|
||||
}
|
||||
|
||||
for (final handler in widget.handlers) {
|
||||
debugPrint('handle keyboard event $event by $handler');
|
||||
// debugPrint('handle keyboard event $event by $handler');
|
||||
|
||||
KeyEventResult result = handler(widget.editorState, event);
|
||||
|
||||
|
@ -0,0 +1,15 @@
|
||||
import 'package:flowy_editor/service/selection_service.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class FlowyService {
|
||||
// selection service
|
||||
final selectionServiceKey = GlobalKey(debugLabel: 'flowy_selection_service');
|
||||
FlowySelectionService get selectionService {
|
||||
assert(selectionServiceKey.currentState != null &&
|
||||
selectionServiceKey.currentState is FlowySelectionService);
|
||||
return selectionServiceKey.currentState! as FlowySelectionService;
|
||||
}
|
||||
|
||||
// keyboard service
|
||||
final keyboardServiceKey = GlobalKey(debugLabel: 'flowy_keyboard_service');
|
||||
}
|
Loading…
Reference in New Issue
Block a user