feat: handle arrow keys

This commit is contained in:
Vincent Chan 2022-07-27 15:46:43 +08:00
parent 982cd62fcc
commit e74f5e84dc
4 changed files with 88 additions and 13 deletions

View File

@ -126,7 +126,7 @@ class __TextNodeWidgetState extends State<_TextNodeWidget>
textCapitalization: TextCapitalization.sentences,
),
);
editorState.cursorSelection = _localSelectionToGlobal(node, selection);
editorState.updateCursorSelection(_localSelectionToGlobal(node, selection));
_textInputConnection
?..show()
..setEditingState(

View File

@ -31,7 +31,22 @@ class EditorState {
final service = FlowyService();
final UndoManager undoManager = UndoManager();
Selection? cursorSelection;
Selection? _cursorSelection;
Selection? get cursorSelection {
return _cursorSelection;
}
/// add the set reason in the future, don't use setter
updateCursorSelection(Selection? cursorSelection) {
// broadcast to other users here
if (cursorSelection == null) {
service.selectionService.clearSelection();
} else {
service.selectionService.updateSelection(cursorSelection);
}
_cursorSelection = cursorSelection;
}
Timer? _debouncedSealHistoryItemTimer;
@ -58,7 +73,7 @@ class EditorState {
for (final op in transaction.operations) {
_applyOperation(op);
}
cursorSelection = transaction.afterSelection;
updateCursorSelection(transaction.afterSelection);
if (options.recordUndo) {
final undoItem = undoManager.getUndoHistoryItem();

View File

@ -1,7 +1,17 @@
import 'package:flowy_editor/document/node.dart';
import 'package:flowy_editor/document/position.dart';
import 'package:flowy_editor/service/keyboard_service.dart';
import 'package:flowy_editor/document/selection.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
int _endOffsetOfNode(Node node) {
if (node is TextNode) {
return node.delta.length;
}
return 0;
}
FlowyKeyEventHandler arrowKeysHandler = (editorState, event) {
if (event.logicalKey != LogicalKeyboardKey.arrowUp &&
event.logicalKey != LogicalKeyboardKey.arrowDown &&
@ -10,5 +20,54 @@ FlowyKeyEventHandler arrowKeysHandler = (editorState, event) {
return KeyEventResult.ignored;
}
final currentSelection = editorState.cursorSelection;
if (currentSelection == null) {
return KeyEventResult.ignored;
}
if (event.logicalKey == LogicalKeyboardKey.arrowLeft) {
// turn left
if (currentSelection.isCollapsed) {
final end = currentSelection.end;
final offset = end.offset;
if (offset == 0) {
final node = editorState.document.nodeAtPath(end.path)!;
final prevNode = node.previous;
if (prevNode != null) {
editorState.updateCursorSelection(Selection.collapsed(Position(
path: prevNode.path, offset: _endOffsetOfNode(prevNode))));
}
return KeyEventResult.handled;
}
editorState.updateCursorSelection(
Selection.collapsed(Position(path: end.path, offset: offset - 1)));
} else {
editorState
.updateCursorSelection(currentSelection.collapse(atStart: true));
}
return KeyEventResult.handled;
} else if (event.logicalKey == LogicalKeyboardKey.arrowRight) {
if (currentSelection.isCollapsed) {
final end = currentSelection.end;
final offset = end.offset;
final node = editorState.document.nodeAtPath(end.path)!;
final lengthOfNode = _endOffsetOfNode(node);
if (offset >= lengthOfNode) {
final nextNode = node.next;
if (nextNode != null) {
editorState.updateCursorSelection(
Selection.collapsed(Position(path: nextNode.path, offset: 0)));
}
return KeyEventResult.handled;
}
editorState.updateCursorSelection(
Selection.collapsed(Position(path: end.path, offset: offset + 1)));
} else {
editorState.updateCursorSelection(currentSelection.collapse());
}
return KeyEventResult.handled;
}
return KeyEventResult.ignored;
};

View File

@ -1,4 +1,3 @@
import 'package:flowy_editor/document/path.dart';
import 'package:flowy_editor/document/node.dart';
import 'package:flowy_editor/document/position.dart';
import 'package:flowy_editor/document/selection.dart';
@ -49,7 +48,7 @@ mixin FlowySelectionService<T extends StatefulWidget> on State<T> {
/// [start] is the offset under the global coordinate system.
Node? computeNodeInOffset(Node node, Offset offset);
/// Return the [Node]s in multiple selection. Emtpy list would be returned
/// Return the [Node]s in multiple selection. Empty list would be returned
/// if no nodes are in range.
///
/// [start] is the offset under the global coordinate system.
@ -136,8 +135,8 @@ class _FlowySelectionState extends State<FlowySelection>
TapGestureRecognizer:
GestureRecognizerFactoryWithHandlers<TapGestureRecognizer>(
() => TapGestureRecognizer(),
(recongizer) {
recongizer.onTapDown = _onTapDown;
(recognizer) {
recognizer.onTapDown = _onTapDown;
},
)
},
@ -167,9 +166,9 @@ class _FlowySelectionState extends State<FlowySelection>
if (end != null) {
return computeNodesInRange(editorState.document.root, start, end);
} else {
final reuslt = computeNodeInOffset(editorState.document.root, start);
if (reuslt != null) {
return [reuslt];
final result = computeNodeInOffset(editorState.document.root, start);
if (result != null) {
return [result];
}
}
return [];
@ -253,8 +252,10 @@ class _FlowySelectionState extends State<FlowySelection>
if (selectable != null) {
final position = selectable.getPositionInOffset(tapOffset!);
final selection = Selection.collapsed(position);
updateSelection(selection);
editorState.updateCursorSelection(selection);
}
} else {
editorState.updateCursorSelection(null);
}
}
@ -283,7 +284,7 @@ class _FlowySelectionState extends State<FlowySelection>
final selection = Selection(
start: isDownward ? start : end, end: isDownward ? end : start);
debugPrint('[_onPanUpdate] $selection');
updateSelection(selection);
editorState.updateCursorSelection(selection);
}
}
@ -302,7 +303,7 @@ class _FlowySelectionState extends State<FlowySelection>
_cursorOverlays
..forEach((overlay) => overlay.remove())
..clear();
// clear floating shortcusts
// clear floating shortcuts
editorState.service.floatingShortcutServiceKey.currentState
?.unwrapOrNull<FlowyFloatingShortcutService>()
?.hide();