From 8856b9abb7531408eae6a163e04ef43b4694c842 Mon Sep 17 00:00:00 2001 From: Sean Riley Hawkins <42723553+rileyhawk1417@users.noreply.github.com> Date: Thu, 15 Sep 2022 15:44:24 +0200 Subject: [PATCH] Flowy editor keyboard fix (#1044) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: fix linux build * Merge pull request #599 from AppFlowy-IO/refactor/grid_decode_cell_data Refactor/grid decode cell data * fix: ๐Ÿ”ง fixed keyboard shortcut bugs * test: ๐Ÿงช updated keyboard layout tests * fix: included macOS for tests * fix: macOS test * fix: add linux in test * fix: redefine move cursor end command error on macOS Co-authored-by: Nathan.fooo <86001920+appflowy@users.noreply.github.com> Co-authored-by: Lucas.Xu --- .../built_in_shortcut_events.dart | 33 ++++- .../arrow_keys_handler_test.dart | 12 +- .../redo_undo_handler_test.dart | 4 +- .../select_all_handler_test.dart | 2 +- ..._text_style_by_command_x_handler_test.dart | 16 +- .../shortcut_event/shortcut_event_test.dart | 139 +++++++++++++++++- 6 files changed, 186 insertions(+), 20 deletions(-) diff --git a/frontend/app_flowy/packages/appflowy_editor/lib/src/service/shortcut_event/built_in_shortcut_events.dart b/frontend/app_flowy/packages/appflowy_editor/lib/src/service/shortcut_event/built_in_shortcut_events.dart index 20b9d9722a..6923e9b531 100644 --- a/frontend/app_flowy/packages/appflowy_editor/lib/src/service/shortcut_event/built_in_shortcut_events.dart +++ b/frontend/app_flowy/packages/appflowy_editor/lib/src/service/shortcut_event/built_in_shortcut_events.dart @@ -58,116 +58,146 @@ List builtInShortcutEvents = [ key: 'Move cursor top', command: 'meta+arrow up', windowsCommand: 'ctrl+arrow up', + linuxCommand: 'ctrl+arrow up', handler: cursorTop, ), ShortcutEvent( key: 'Move cursor bottom', command: 'meta+arrow down', windowsCommand: 'ctrl+arrow down', + linuxCommand: 'ctrl+arrow down', handler: cursorBottom, ), ShortcutEvent( key: 'Move cursor begin', command: 'meta+arrow left', windowsCommand: 'ctrl+arrow left', + linuxCommand: 'ctrl+arrow left', handler: cursorBegin, ), ShortcutEvent( key: 'Move cursor end', command: 'meta+arrow right', windowsCommand: 'ctrl+arrow right', + linuxCommand: 'ctrl+arrow right', handler: cursorEnd, ), ShortcutEvent( key: 'Cursor top select', command: 'meta+shift+arrow up', windowsCommand: 'ctrl+shift+arrow up', + linuxCommand: 'ctrl+shift+arrow up', handler: cursorTopSelect, ), ShortcutEvent( key: 'Cursor bottom select', command: 'meta+shift+arrow down', windowsCommand: 'ctrl+shift+arrow down', + linuxCommand: 'ctrl+shift+arrow down', handler: cursorBottomSelect, ), ShortcutEvent( key: 'Cursor begin select', command: 'meta+shift+arrow left', windowsCommand: 'ctrl+shift+arrow left', + linuxCommand: 'ctrl+shift+arrow left', handler: cursorBeginSelect, ), ShortcutEvent( key: 'Cursor end select', command: 'meta+shift+arrow right', windowsCommand: 'ctrl+shift+arrow right', + linuxCommand: 'ctrl+shift+arrow right', handler: cursorEndSelect, ), ShortcutEvent( key: 'Redo', command: 'meta+shift+z', windowsCommand: 'ctrl+shift+z', + linuxCommand: 'ctrl+shift+z', handler: redoEventHandler, ), ShortcutEvent( key: 'Undo', command: 'meta+z', windowsCommand: 'ctrl+z', + linuxCommand: 'ctrl+z', handler: undoEventHandler, ), ShortcutEvent( key: 'Format bold', command: 'meta+b', windowsCommand: 'ctrl+b', + linuxCommand: 'ctrl+b', handler: formatBoldEventHandler, ), ShortcutEvent( key: 'Format italic', command: 'meta+i', windowsCommand: 'ctrl+i', + linuxCommand: 'ctrl+i', handler: formatItalicEventHandler, ), ShortcutEvent( key: 'Format underline', command: 'meta+u', windowsCommand: 'ctrl+u', + linuxCommand: 'ctrl+u', handler: formatUnderlineEventHandler, ), ShortcutEvent( key: 'Format strikethrough', command: 'meta+shift+s', windowsCommand: 'ctrl+shift+s', + linuxCommand: 'ctrl+shift+s', handler: formatStrikethroughEventHandler, ), ShortcutEvent( key: 'Format highlight', command: 'meta+shift+h', windowsCommand: 'ctrl+shift+h', + linuxCommand: 'ctrl+shift+h', handler: formatHighlightEventHandler, ), ShortcutEvent( key: 'Format link', command: 'meta+k', windowsCommand: 'ctrl+k', + linuxCommand: 'ctrl+k', handler: formatLinkEventHandler, ), ShortcutEvent( key: 'Copy', command: 'meta+c', windowsCommand: 'ctrl+c', + linuxCommand: 'ctrl+c', handler: copyEventHandler, ), ShortcutEvent( key: 'Paste', command: 'meta+v', windowsCommand: 'ctrl+v', + linuxCommand: 'ctrl+v', handler: pasteEventHandler, ), ShortcutEvent( - key: 'Paste', + key: 'Cut', command: 'meta+x', windowsCommand: 'ctrl+x', + linuxCommand: 'ctrl+x', handler: cutEventHandler, ), + ShortcutEvent( + key: 'Home', + command: 'home', + handler: cursorBegin, + ), + ShortcutEvent( + key: 'End', + command: 'end', + handler: cursorEnd, + ), + // TODO: split the keys. ShortcutEvent( key: 'Delete Text', @@ -193,6 +223,7 @@ List builtInShortcutEvents = [ key: 'select all', command: 'meta+a', windowsCommand: 'ctrl+a', + linuxCommand: 'ctrl+a', handler: selectAllHandler, ), ShortcutEvent( diff --git a/frontend/app_flowy/packages/appflowy_editor/test/service/internal_key_event_handlers/arrow_keys_handler_test.dart b/frontend/app_flowy/packages/appflowy_editor/test/service/internal_key_event_handlers/arrow_keys_handler_test.dart index 5000c3ec93..b9b163f489 100644 --- a/frontend/app_flowy/packages/appflowy_editor/test/service/internal_key_event_handlers/arrow_keys_handler_test.dart +++ b/frontend/app_flowy/packages/appflowy_editor/test/service/internal_key_event_handlers/arrow_keys_handler_test.dart @@ -287,7 +287,7 @@ void main() async { LogicalKeyboardKey.arrowDown, isShiftPressed: true, ); - if (Platform.isWindows) { + if (Platform.isWindows || Platform.isLinux) { await editor.pressLogicKey( LogicalKeyboardKey.arrowRight, isShiftPressed: true, @@ -321,7 +321,7 @@ void main() async { LogicalKeyboardKey.arrowUp, isShiftPressed: true, ); - if (Platform.isWindows) { + if (Platform.isWindows || Platform.isLinux) { await editor.pressLogicKey( LogicalKeyboardKey.arrowLeft, isShiftPressed: true, @@ -398,7 +398,7 @@ Future _testPressArrowKeyWithMetaInSelection( } } await editor.updateSelection(selection); - if (Platform.isWindows) { + if (Platform.isWindows || Platform.isLinux) { await editor.pressLogicKey( LogicalKeyboardKey.arrowLeft, isControlPressed: true, @@ -415,7 +415,7 @@ Future _testPressArrowKeyWithMetaInSelection( Selection.single(path: [0], startOffset: 0), ); - if (Platform.isWindows) { + if (Platform.isWindows || Platform.isLinux) { await editor.pressLogicKey( LogicalKeyboardKey.arrowRight, isControlPressed: true, @@ -432,7 +432,7 @@ Future _testPressArrowKeyWithMetaInSelection( Selection.single(path: [0], startOffset: text.length), ); - if (Platform.isWindows) { + if (Platform.isWindows || Platform.isLinux) { await editor.pressLogicKey( LogicalKeyboardKey.arrowUp, isControlPressed: true, @@ -449,7 +449,7 @@ Future _testPressArrowKeyWithMetaInSelection( Selection.single(path: [0], startOffset: 0), ); - if (Platform.isWindows) { + if (Platform.isWindows || Platform.isLinux) { await editor.pressLogicKey( LogicalKeyboardKey.arrowDown, isControlPressed: true, diff --git a/frontend/app_flowy/packages/appflowy_editor/test/service/internal_key_event_handlers/redo_undo_handler_test.dart b/frontend/app_flowy/packages/appflowy_editor/test/service/internal_key_event_handlers/redo_undo_handler_test.dart index 6fa98e9997..b165f279e7 100644 --- a/frontend/app_flowy/packages/appflowy_editor/test/service/internal_key_event_handlers/redo_undo_handler_test.dart +++ b/frontend/app_flowy/packages/appflowy_editor/test/service/internal_key_event_handlers/redo_undo_handler_test.dart @@ -43,7 +43,7 @@ Future _testBackspaceUndoRedo( await editor.pressLogicKey(LogicalKeyboardKey.backspace); expect(editor.documentLength, 2); - if (Platform.isWindows) { + if (Platform.isWindows || Platform.isLinux) { await editor.pressLogicKey( LogicalKeyboardKey.keyZ, isControlPressed: true, @@ -59,7 +59,7 @@ Future _testBackspaceUndoRedo( expect((editor.nodeAtPath([1]) as TextNode).toRawString(), text); expect(editor.documentSelection, selection); - if (Platform.isWindows) { + if (Platform.isWindows || Platform.isLinux) { await editor.pressLogicKey( LogicalKeyboardKey.keyZ, isControlPressed: true, diff --git a/frontend/app_flowy/packages/appflowy_editor/test/service/internal_key_event_handlers/select_all_handler_test.dart b/frontend/app_flowy/packages/appflowy_editor/test/service/internal_key_event_handlers/select_all_handler_test.dart index 6efd2064e9..937988da58 100644 --- a/frontend/app_flowy/packages/appflowy_editor/test/service/internal_key_event_handlers/select_all_handler_test.dart +++ b/frontend/app_flowy/packages/appflowy_editor/test/service/internal_key_event_handlers/select_all_handler_test.dart @@ -28,7 +28,7 @@ Future _testSelectAllHandler(WidgetTester tester, int lines) async { editor.insertTextNode(text); } await editor.startTesting(); - if (Platform.isWindows) { + if (Platform.isWindows || Platform.isLinux) { await editor.pressLogicKey(LogicalKeyboardKey.keyA, isControlPressed: true); } else { await editor.pressLogicKey(LogicalKeyboardKey.keyA, isMetaPressed: true); diff --git a/frontend/app_flowy/packages/appflowy_editor/test/service/internal_key_event_handlers/update_text_style_by_command_x_handler_test.dart b/frontend/app_flowy/packages/appflowy_editor/test/service/internal_key_event_handlers/update_text_style_by_command_x_handler_test.dart index bf595b1deb..99c05b4bce 100644 --- a/frontend/app_flowy/packages/appflowy_editor/test/service/internal_key_event_handlers/update_text_style_by_command_x_handler_test.dart +++ b/frontend/app_flowy/packages/appflowy_editor/test/service/internal_key_event_handlers/update_text_style_by_command_x_handler_test.dart @@ -84,7 +84,7 @@ Future _testUpdateTextStyleByCommandX( var selection = Selection.single(path: [1], startOffset: 2, endOffset: text.length - 2); await editor.updateSelection(selection); - if (Platform.isWindows) { + if (Platform.isWindows || Platform.isLinux) { await editor.pressLogicKey( key, isShiftPressed: isShiftPressed, @@ -111,7 +111,7 @@ Future _testUpdateTextStyleByCommandX( selection = Selection.single(path: [1], startOffset: 0, endOffset: text.length); await editor.updateSelection(selection); - if (Platform.isWindows) { + if (Platform.isWindows || Platform.isLinux) { await editor.pressLogicKey( key, isShiftPressed: isShiftPressed, @@ -136,7 +136,7 @@ Future _testUpdateTextStyleByCommandX( true); await editor.updateSelection(selection); - if (Platform.isWindows) { + if (Platform.isWindows || Platform.isLinux) { await editor.pressLogicKey( key, isShiftPressed: isShiftPressed, @@ -158,7 +158,7 @@ Future _testUpdateTextStyleByCommandX( end: Position(path: [2], offset: text.length), ); await editor.updateSelection(selection); - if (Platform.isWindows) { + if (Platform.isWindows || Platform.isLinux) { await editor.pressLogicKey( key, isShiftPressed: isShiftPressed, @@ -193,7 +193,7 @@ Future _testUpdateTextStyleByCommandX( await editor.updateSelection(selection); - if (Platform.isWindows) { + if (Platform.isWindows || Platform.isLinux) { await editor.pressLogicKey( key, isShiftPressed: isShiftPressed, @@ -239,7 +239,7 @@ Future _testLinkMenuInSingleTextSelection(WidgetTester tester) async { expect(find.byType(ToolbarWidget), findsOneWidget); // trigger the link menu - if (Platform.isWindows) { + if (Platform.isWindows || Platform.isLinux) { await editor.pressLogicKey(LogicalKeyboardKey.keyK, isControlPressed: true); } else { await editor.pressLogicKey(LogicalKeyboardKey.keyK, isMetaPressed: true); @@ -262,7 +262,7 @@ Future _testLinkMenuInSingleTextSelection(WidgetTester tester) async { true); await editor.updateSelection(selection); - if (Platform.isWindows) { + if (Platform.isWindows || Platform.isLinux) { await editor.pressLogicKey(LogicalKeyboardKey.keyK, isControlPressed: true); } else { await editor.pressLogicKey(LogicalKeyboardKey.keyK, isMetaPressed: true); @@ -279,7 +279,7 @@ Future _testLinkMenuInSingleTextSelection(WidgetTester tester) async { expect(find.byType(LinkMenu), findsNothing); // Remove link - if (Platform.isWindows) { + if (Platform.isWindows || Platform.isLinux) { await editor.pressLogicKey(LogicalKeyboardKey.keyK, isControlPressed: true); } else { await editor.pressLogicKey(LogicalKeyboardKey.keyK, isMetaPressed: true); diff --git a/frontend/app_flowy/packages/appflowy_editor/test/service/shortcut_event/shortcut_event_test.dart b/frontend/app_flowy/packages/appflowy_editor/test/service/shortcut_event/shortcut_event_test.dart index 93a0a7bb84..0c85691504 100644 --- a/frontend/app_flowy/packages/appflowy_editor/test/service/shortcut_event/shortcut_event_test.dart +++ b/frontend/app_flowy/packages/appflowy_editor/test/service/shortcut_event/shortcut_event_test.dart @@ -39,7 +39,7 @@ void main() async { await editor.updateSelection( Selection.single(path: [1], startOffset: text.length), ); - if (Platform.isWindows) { + if (Platform.isWindows || Platform.isLinux) { await editor.pressLogicKey( LogicalKeyboardKey.arrowLeft, isControlPressed: true, @@ -62,11 +62,12 @@ void main() async { if (event.key == 'Move cursor begin') { event.updateCommand( windowsCommand: 'alt+arrow left', + linuxCommand: 'alt+arrow left', macOSCommand: 'alt+arrow left', ); } } - if (Platform.isWindows || Platform.isMacOS) { + if (Platform.isWindows || Platform.isMacOS || Platform.isLinux) { await editor.pressLogicKey( LogicalKeyboardKey.arrowLeft, isAltPressed: true, @@ -82,5 +83,139 @@ void main() async { Selection.single(path: [1], startOffset: 0), ); }); + + testWidgets('redefine move cursor end command', (tester) async { + const text = 'Welcome to Appflowy ๐Ÿ˜'; + final editor = tester.editor + ..insertTextNode(text) + ..insertTextNode(text); + await editor.startTesting(); + await editor.updateSelection( + Selection.single(path: [1], startOffset: 0), + ); + if (Platform.isWindows || Platform.isLinux) { + await editor.pressLogicKey( + LogicalKeyboardKey.arrowRight, + isControlPressed: true, + ); + } else { + await editor.pressLogicKey( + LogicalKeyboardKey.arrowRight, + isMetaPressed: true, + ); + } + expect( + editor.documentSelection, + Selection.single(path: [1], startOffset: text.length), + ); + await editor.updateSelection( + Selection.single(path: [1], startOffset: 0), + ); + + for (final event in builtInShortcutEvents) { + if (event.key == 'Move cursor end') { + event.updateCommand( + windowsCommand: 'alt+arrow right', + linuxCommand: 'alt+arrow right', + macOSCommand: 'alt+arrow right', + ); + } + } + await editor.pressLogicKey( + LogicalKeyboardKey.arrowRight, + isAltPressed: true, + ); + expect( + editor.documentSelection, + Selection.single(path: [1], startOffset: text.length), + ); + }); + + testWidgets('Test Home Key to move to start of current text', + (tester) async { + const text = 'Welcome to Appflowy ๐Ÿ˜'; + final editor = tester.editor + ..insertTextNode(text) + ..insertTextNode(text); + await editor.startTesting(); + await editor.updateSelection( + Selection.single(path: [1], startOffset: text.length), + ); + if (Platform.isWindows || Platform.isLinux || Platform.isMacOS) { + await editor.pressLogicKey( + LogicalKeyboardKey.home, + ); + } + + expect( + editor.documentSelection, + Selection.single(path: [1], startOffset: 0), + ); + await editor.updateSelection( + Selection.single(path: [1], startOffset: text.length), + ); + + for (final event in builtInShortcutEvents) { + if (event.key == 'Move cursor begin') { + event.updateCommand( + windowsCommand: 'home', + linuxCommand: 'home', + macOSCommand: 'home', + ); + } + } + if (Platform.isWindows || Platform.isMacOS || Platform.isLinux) { + await editor.pressLogicKey( + LogicalKeyboardKey.home, + ); + } + expect( + editor.documentSelection, + Selection.single(path: [1], startOffset: 0), + ); + }); + + testWidgets('Test End Key to move to end of current text', (tester) async { + const text = 'Welcome to Appflowy ๐Ÿ˜'; + final editor = tester.editor + ..insertTextNode(text) + ..insertTextNode(text); + await editor.startTesting(); + await editor.updateSelection( + Selection.single(path: [1], startOffset: text.length), + ); + if (Platform.isWindows || Platform.isLinux || Platform.isMacOS) { + await editor.pressLogicKey( + LogicalKeyboardKey.end, + ); + } + + expect( + editor.documentSelection, + Selection.single(path: [1], startOffset: text.length), + ); + await editor.updateSelection( + Selection.single(path: [1], startOffset: 0), + ); + + for (final event in builtInShortcutEvents) { + if (event.key == 'Move cursor end') { + event.updateCommand( + windowsCommand: 'end', + linuxCommand: 'end', + macOSCommand: 'end', + ); + } + } + if (Platform.isWindows || Platform.isMacOS || Platform.isLinux) { + await editor.pressLogicKey( + LogicalKeyboardKey.end, + ); + } + expect( + editor.documentSelection, + Selection.single(path: [1], startOffset: text.length), + ); + }); }); }