Browse Source

Flowy editor keyboard fix (#1044)

* 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 <[email protected]>
Co-authored-by: Lucas.Xu <[email protected]>
Sean Riley Hawkins 2 years ago
parent
commit
8856b9abb7

+ 32 - 1
frontend/app_flowy/packages/appflowy_editor/lib/src/service/shortcut_event/built_in_shortcut_events.dart

@@ -58,116 +58,146 @@ List<ShortcutEvent> 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<ShortcutEvent> builtInShortcutEvents = [
     key: 'select all',
     command: 'meta+a',
     windowsCommand: 'ctrl+a',
+    linuxCommand: 'ctrl+a',
     handler: selectAllHandler,
   ),
   ShortcutEvent(

+ 6 - 6
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<void> _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<void> _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<void> _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<void> _testPressArrowKeyWithMetaInSelection(
     Selection.single(path: [0], startOffset: 0),
   );
 
-  if (Platform.isWindows) {
+  if (Platform.isWindows || Platform.isLinux) {
     await editor.pressLogicKey(
       LogicalKeyboardKey.arrowDown,
       isControlPressed: true,

+ 2 - 2
frontend/app_flowy/packages/appflowy_editor/test/service/internal_key_event_handlers/redo_undo_handler_test.dart

@@ -43,7 +43,7 @@ Future<void> _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<void> _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,

+ 1 - 1
frontend/app_flowy/packages/appflowy_editor/test/service/internal_key_event_handlers/select_all_handler_test.dart

@@ -28,7 +28,7 @@ Future<void> _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);

+ 8 - 8
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<void> _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<void> _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<void> _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<void> _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<void> _testUpdateTextStyleByCommandX(
 
   await editor.updateSelection(selection);
 
-  if (Platform.isWindows) {
+  if (Platform.isWindows || Platform.isLinux) {
     await editor.pressLogicKey(
       key,
       isShiftPressed: isShiftPressed,
@@ -239,7 +239,7 @@ Future<void> _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<void> _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<void> _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);

+ 137 - 2
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),
+      );
+    });
   });
 }