Просмотр исходного кода

[flutter]: fix compile errors after update flutter sdk

appflowy 3 лет назад
Родитель
Сommit
c4e9fd0697

+ 4 - 1
app_flowy/.vscode/settings.json

@@ -2,5 +2,8 @@
     "svgviewer.enableautopreview": true,
     "svgviewer.enableautopreview": true,
     "svgviewer.previewcolumn": "Active",
     "svgviewer.previewcolumn": "Active",
     "svgviewer.showzoominout": true,
     "svgviewer.showzoominout": true,
-    "editor.wordWrapColumn": 120
+    "editor.wordWrapColumn": 120,
+    "editor.minimap.maxColumn": 140,
+    "prettier.printWidth": 140,
+    "editor.wordWrap": "wordWrapColumn"
 }
 }

+ 63 - 79
app_flowy/packages/flowy_editor/lib/src/service/keyboard.dart

@@ -1,32 +1,25 @@
 import 'package:flutter/foundation.dart';
 import 'package:flutter/foundation.dart';
 import 'package:flutter/services.dart';
 import 'package:flutter/services.dart';
+import 'package:flutter/widgets.dart';
 
 
-/* --------------------------------- Typedef -------------------------------- */
+//fixme workaround flutter MacOS issue https://github.com/flutter/flutter/issues/75595
+extension _LogicalKeyboardKeyCaseExt on LogicalKeyboardKey {
+  static const _kUpperToLowerDist = 0x20;
+  static final _kLowerCaseA = LogicalKeyboardKey.keyA.keyId;
+  static final _kLowerCaseZ = LogicalKeyboardKey.keyZ.keyId;
 
 
-enum InputShortcut {
-  CUT,
-  COPY,
-  PASTE,
-  SELECT_ALL,
-  SAVE,
+  LogicalKeyboardKey toUpperCase() {
+    if (keyId < _kLowerCaseA || keyId > _kLowerCaseZ) return this;
+    return LogicalKeyboardKey(keyId - _kUpperToLowerDist);
+  }
 }
 }
 
 
-typedef CursorMoveCallback = void Function(
-  LogicalKeyboardKey key,
-  bool wordModifier,
-  bool lineModifier,
-  bool shift,
-);
-
-typedef InputShortcutCallback = void Function(
-  InputShortcut? shortcut,
-);
+enum InputShortcut { CUT, COPY, PASTE, SELECT_ALL, UNDO, REDO }
 
 
-typedef OnDeleteCallback = void Function(
-  bool forward,
-);
-
-/* -------------------------------- Listener -------------------------------- */
+typedef CursorMoveCallback = void Function(
+    LogicalKeyboardKey key, bool wordModifier, bool lineModifier, bool shift);
+typedef InputShortcutCallback = void Function(InputShortcut? shortcut);
+typedef OnDeleteCallback = void Function(bool forward);
 
 
 class FlowyKeyboardListener {
 class FlowyKeyboardListener {
   FlowyKeyboardListener(this.onCursorMove, this.onShortcut, this.onDelete);
   FlowyKeyboardListener(this.onCursorMove, this.onShortcut, this.onDelete);
@@ -35,43 +28,45 @@ class FlowyKeyboardListener {
   final InputShortcutCallback onShortcut;
   final InputShortcutCallback onShortcut;
   final OnDeleteCallback onDelete;
   final OnDeleteCallback onDelete;
 
 
-  static final Set<LogicalKeyboardKey> _moveKeys = {
+  static final Set<LogicalKeyboardKey> _moveKeys = <LogicalKeyboardKey>{
+    LogicalKeyboardKey.arrowRight,
+    LogicalKeyboardKey.arrowLeft,
     LogicalKeyboardKey.arrowUp,
     LogicalKeyboardKey.arrowUp,
     LogicalKeyboardKey.arrowDown,
     LogicalKeyboardKey.arrowDown,
-    LogicalKeyboardKey.arrowLeft,
-    LogicalKeyboardKey.arrowRight,
   };
   };
 
 
-  static final Set<LogicalKeyboardKey> _shortcutKeys = {
+  static final Set<LogicalKeyboardKey> _shortcutKeys = <LogicalKeyboardKey>{
     LogicalKeyboardKey.keyA,
     LogicalKeyboardKey.keyA,
     LogicalKeyboardKey.keyC,
     LogicalKeyboardKey.keyC,
     LogicalKeyboardKey.keyV,
     LogicalKeyboardKey.keyV,
     LogicalKeyboardKey.keyX,
     LogicalKeyboardKey.keyX,
-    LogicalKeyboardKey.keyS,
+    LogicalKeyboardKey.keyZ.toUpperCase(),
+    LogicalKeyboardKey.keyZ,
     LogicalKeyboardKey.delete,
     LogicalKeyboardKey.delete,
     LogicalKeyboardKey.backspace,
     LogicalKeyboardKey.backspace,
   };
   };
 
 
-  static final Set<LogicalKeyboardKey> _nonModifierKeys = {
-    ..._moveKeys,
+  static final Set<LogicalKeyboardKey> _nonModifierKeys = <LogicalKeyboardKey>{
     ..._shortcutKeys,
     ..._shortcutKeys,
+    ..._moveKeys,
   };
   };
 
 
-  static final Set<LogicalKeyboardKey> _winModifierKeys = {
+  static final Set<LogicalKeyboardKey> _modifierKeys = <LogicalKeyboardKey>{
+    LogicalKeyboardKey.shift,
     LogicalKeyboardKey.control,
     LogicalKeyboardKey.control,
     LogicalKeyboardKey.alt,
     LogicalKeyboardKey.alt,
-    LogicalKeyboardKey.shift,
   };
   };
 
 
-  static final Set<LogicalKeyboardKey> _osxModifierKeys = {
+  static final Set<LogicalKeyboardKey> _macOsModifierKeys =
+      <LogicalKeyboardKey>{
+    LogicalKeyboardKey.shift,
     LogicalKeyboardKey.meta,
     LogicalKeyboardKey.meta,
     LogicalKeyboardKey.alt,
     LogicalKeyboardKey.alt,
-    LogicalKeyboardKey.shift,
   };
   };
 
 
-  static final Set<LogicalKeyboardKey> _interestingKeys = {
-    ..._winModifierKeys,
-    ..._osxModifierKeys,
+  static final Set<LogicalKeyboardKey> _interestingKeys = <LogicalKeyboardKey>{
+    ..._modifierKeys,
+    ..._macOsModifierKeys,
     ..._nonModifierKeys,
     ..._nonModifierKeys,
   };
   };
 
 
@@ -80,66 +75,55 @@ class FlowyKeyboardListener {
     LogicalKeyboardKey.keyC: InputShortcut.COPY,
     LogicalKeyboardKey.keyC: InputShortcut.COPY,
     LogicalKeyboardKey.keyV: InputShortcut.PASTE,
     LogicalKeyboardKey.keyV: InputShortcut.PASTE,
     LogicalKeyboardKey.keyA: InputShortcut.SELECT_ALL,
     LogicalKeyboardKey.keyA: InputShortcut.SELECT_ALL,
-    LogicalKeyboardKey.keyS: InputShortcut.SAVE,
   };
   };
 
 
-  bool handleRawKeyEvent(RawKeyEvent event) {
+  KeyEventResult handleRawKeyEvent(RawKeyEvent event) {
     if (kIsWeb) {
     if (kIsWeb) {
-      // On web platform, we should ignore the key because it's processed already.
-      return false;
+      // On web platform, we ignore the key because it's already processed.
+      return KeyEventResult.ignored;
     }
     }
+
     if (event is! RawKeyDownEvent) {
     if (event is! RawKeyDownEvent) {
-      return false;
+      return KeyEventResult.ignored;
     }
     }
 
 
-    final keysPressed = LogicalKeyboardKey.collapseSynonyms(RawKeyboard.instance.keysPressed);
+    final keysPressed =
+        LogicalKeyboardKey.collapseSynonyms(RawKeyboard.instance.keysPressed);
     final key = event.logicalKey;
     final key = event.logicalKey;
     final isMacOS = event.data is RawKeyEventDataMacOs;
     final isMacOS = event.data is RawKeyEventDataMacOs;
-    final modifierKeys = isMacOS ? _osxModifierKeys : _winModifierKeys;
-    // If any one of below cases is hitten:
-    // 1. None of the nonModifierKeys is pressed
-    // 2. Press the key except the keys that trigger shortcut
-    // We will skip this event
     if (!_nonModifierKeys.contains(key) ||
     if (!_nonModifierKeys.contains(key) ||
-        keysPressed.difference(modifierKeys).length > 1 ||
+        keysPressed
+                .difference(isMacOS ? _macOsModifierKeys : _modifierKeys)
+                .length >
+            1 ||
         keysPressed.difference(_interestingKeys).isNotEmpty) {
         keysPressed.difference(_interestingKeys).isNotEmpty) {
-      return false;
+      return KeyEventResult.ignored;
     }
     }
 
 
-    if (_isCursorMoveAction(key)) {
+    final isShortcutModifierPressed =
+        isMacOS ? event.isMetaPressed : event.isControlPressed;
+
+    if (_moveKeys.contains(key)) {
       onCursorMove(
       onCursorMove(
-        key,
-        isMacOS ? event.isAltPressed : event.isControlPressed,
-        isMacOS ? event.isMetaPressed : event.isAltPressed,
-        event.isShiftPressed,
-      );
-      return true;
-    } else if (_isShortcutAction(event, key)) {
-      onShortcut(_keyToShortcut[key]);
-      return true;
-    } else if (LogicalKeyboardKey.delete == key) {
+          key,
+          isMacOS ? event.isAltPressed : event.isControlPressed,
+          isMacOS ? event.isMetaPressed : event.isAltPressed,
+          event.isShiftPressed);
+    } else if (isShortcutModifierPressed && (_shortcutKeys.contains(key))) {
+      if (key == LogicalKeyboardKey.keyZ ||
+          key == LogicalKeyboardKey.keyZ.toUpperCase()) {
+        onShortcut(
+            event.isShiftPressed ? InputShortcut.REDO : InputShortcut.UNDO);
+      } else {
+        onShortcut(_keyToShortcut[key]);
+      }
+    } else if (key == LogicalKeyboardKey.delete) {
       onDelete(true);
       onDelete(true);
-      return true;
-    } else if (LogicalKeyboardKey.backspace == key) {
+    } else if (key == LogicalKeyboardKey.backspace) {
       onDelete(false);
       onDelete(false);
-      return true;
-    }
-    return false;
-  }
-
-  // Helper
-
-  bool _isCursorMoveAction(LogicalKeyboardKey key) => _moveKeys.contains(key);
-
-  bool _isShortcutAction(RawKeyEvent event, LogicalKeyboardKey key) {
-    if (!_shortcutKeys.contains(key)) {
-      return false;
-    }
-
-    if (event.data is RawKeyEventDataMacOs) {
-      return event.isMetaPressed;
     } else {
     } else {
-      return event.isControlPressed;
+      return KeyEventResult.ignored;
     }
     }
+    return KeyEventResult.handled;
   }
   }
 }
 }

+ 6 - 3
app_flowy/packages/flowy_editor/lib/src/widget/proxy.dart

@@ -22,7 +22,8 @@ class BaselineProxy extends SingleChildRenderObjectWidget {
   }
   }
 
 
   @override
   @override
-  void updateRenderObject(BuildContext context, covariant RenderBaselineProxy renderObject) {
+  void updateRenderObject(
+      BuildContext context, covariant RenderBaselineProxy renderObject) {
     renderObject
     renderObject
       ..textStyle = textStyle!
       ..textStyle = textStyle!
       ..padding = padding!;
       ..padding = padding!;
@@ -37,7 +38,8 @@ class EmbedProxy extends SingleChildRenderObjectWidget {
   const EmbedProxy(Widget child) : super(child: child);
   const EmbedProxy(Widget child) : super(child: child);
 
 
   @override
   @override
-  RenderEmbedProxy createRenderObject(BuildContext context) => RenderEmbedProxy(null);
+  RenderEmbedProxy createRenderObject(BuildContext context) =>
+      RenderEmbedProxy(null);
 }
 }
 
 
 /* ---------------------------------- Text ---------------------------------- */
 /* ---------------------------------- Text ---------------------------------- */
@@ -80,7 +82,8 @@ class RichTextProxy extends SingleChildRenderObjectWidget {
   }
   }
 
 
   @override
   @override
-  void updateRenderObject(BuildContext context, covariant RenderParagraphProxy renderObject) {
+  void updateRenderObject(
+      BuildContext context, covariant RenderParagraphProxy renderObject) {
     renderObject
     renderObject
       ..textStyle = textStyle
       ..textStyle = textStyle
       ..textAlign = textAlign
       ..textAlign = textAlign

+ 168 - 77
app_flowy/packages/flowy_editor/lib/src/widget/raw_editor.dart

@@ -60,7 +60,8 @@ class RawEditor extends StatefulWidget {
     this.embedBuilder,
     this.embedBuilder,
   )   : assert(maxHeight == null || maxHeight > 0, 'maxHeight cannot be null'),
   )   : assert(maxHeight == null || maxHeight > 0, 'maxHeight cannot be null'),
         assert(minHeight == null || minHeight >= 0, 'minHeight cannot be null'),
         assert(minHeight == null || minHeight >= 0, 'minHeight cannot be null'),
-        assert(maxHeight == null || minHeight == null || maxHeight >= minHeight),
+        assert(
+            maxHeight == null || minHeight == null || maxHeight >= minHeight),
         showCursor = showCursor ?? true,
         showCursor = showCursor ?? true,
         super(key: key);
         super(key: key);
 
 
@@ -111,7 +112,10 @@ abstract class EditorState extends State<RawEditor> {
 }
 }
 
 
 class _RawEditorState extends EditorState
 class _RawEditorState extends EditorState
-    with AutomaticKeepAliveClientMixin<RawEditor>, WidgetsBindingObserver, TickerProviderStateMixin<RawEditor>
+    with
+        AutomaticKeepAliveClientMixin<RawEditor>,
+        WidgetsBindingObserver,
+        TickerProviderStateMixin<RawEditor>
     implements TextSelectionDelegate, TextInputClient {
     implements TextSelectionDelegate, TextInputClient {
   final GlobalKey _editorKey = GlobalKey();
   final GlobalKey _editorKey = GlobalKey();
   final List<TextEditingValue> _sentRemoteValues = [];
   final List<TextEditingValue> _sentRemoteValues = [];
@@ -129,7 +133,8 @@ class _RawEditorState extends EditorState
   bool _didAutoFocus = false;
   bool _didAutoFocus = false;
   bool _keyboardVisible = false;
   bool _keyboardVisible = false;
   DefaultStyles? _styles;
   DefaultStyles? _styles;
-  final ClipboardStatusNotifier? _clipboardStatus = kIsWeb ? null : ClipboardStatusNotifier();
+  final ClipboardStatusNotifier? _clipboardStatus =
+      kIsWeb ? null : ClipboardStatusNotifier();
   final LayerLink _toolbarLayerLink = LayerLink();
   final LayerLink _toolbarLayerLink = LayerLink();
   final LayerLink _startHandleLayerLink = LayerLink();
   final LayerLink _startHandleLayerLink = LayerLink();
   final LayerLink _endHandleLayerLink = LayerLink();
   final LayerLink _endHandleLayerLink = LayerLink();
@@ -177,57 +182,78 @@ class _RawEditorState extends EditorState
         downKey = key == LogicalKeyboardKey.arrowDown;
         downKey = key == LogicalKeyboardKey.arrowDown;
 
 
     if ((rightKey || leftKey) && !(rightKey && leftKey)) {
     if ((rightKey || leftKey) && !(rightKey && leftKey)) {
-      newSelection =
-          _jumpToBeginOrEndOfWord(newSelection, wordModifier, leftKey, rightKey, plainText, lineModifier, shift);
+      newSelection = _jumpToBeginOrEndOfWord(newSelection, wordModifier,
+          leftKey, rightKey, plainText, lineModifier, shift);
     }
     }
 
 
     if (downKey || upKey) {
     if (downKey || upKey) {
-      newSelection = _handleMovingCursorVertically(upKey, downKey, shift, selection, newSelection, plainText);
+      newSelection = _handleMovingCursorVertically(
+          upKey, downKey, shift, selection, newSelection, plainText);
     }
     }
 
 
     if (!shift) {
     if (!shift) {
-      newSelection = _placeCollapsedSelection(selection, newSelection, leftKey, rightKey);
+      newSelection =
+          _placeCollapsedSelection(selection, newSelection, leftKey, rightKey);
     }
     }
 
 
     widget.controller.updateSelection(newSelection, ChangeSource.LOCAL);
     widget.controller.updateSelection(newSelection, ChangeSource.LOCAL);
   }
   }
 
 
-  TextSelection _placeCollapsedSelection(
-      TextSelection selection, TextSelection newSelection, bool leftKey, bool rightKey) {
+  TextSelection _placeCollapsedSelection(TextSelection selection,
+      TextSelection newSelection, bool leftKey, bool rightKey) {
     var newOffset = newSelection.extentOffset;
     var newOffset = newSelection.extentOffset;
     if (!selection.isCollapsed) {
     if (!selection.isCollapsed) {
       if (leftKey) {
       if (leftKey) {
-        newOffset =
-            newSelection.baseOffset < newSelection.extentOffset ? newSelection.baseOffset : newSelection.extentOffset;
+        newOffset = newSelection.baseOffset < newSelection.extentOffset
+            ? newSelection.baseOffset
+            : newSelection.extentOffset;
       } else if (rightKey) {
       } else if (rightKey) {
-        newOffset =
-            newSelection.baseOffset > newSelection.extentOffset ? newSelection.baseOffset : newSelection.extentOffset;
+        newOffset = newSelection.baseOffset > newSelection.extentOffset
+            ? newSelection.baseOffset
+            : newSelection.extentOffset;
       }
       }
     }
     }
     return TextSelection.fromPosition(TextPosition(offset: newOffset));
     return TextSelection.fromPosition(TextPosition(offset: newOffset));
   }
   }
 
 
   TextSelection _handleMovingCursorVertically(
   TextSelection _handleMovingCursorVertically(
-      bool upKey, bool downKey, bool shift, TextSelection selection, TextSelection newSelection, String plainText) {
-    final originPosition = TextPosition(offset: upKey ? selection.baseOffset : selection.extentOffset);
+      bool upKey,
+      bool downKey,
+      bool shift,
+      TextSelection selection,
+      TextSelection newSelection,
+      String plainText) {
+    final originPosition = TextPosition(
+        offset: upKey ? selection.baseOffset : selection.extentOffset);
 
 
     final child = getRenderEditor()!.childAtPosition(originPosition);
     final child = getRenderEditor()!.childAtPosition(originPosition);
-    final localPosition = TextPosition(offset: originPosition.offset - child.container.documentOffset);
-
-    var position = upKey ? child.getPositionAbove(localPosition) : child.getPositionBelow(localPosition);
+    final localPosition = TextPosition(
+        offset: originPosition.offset - child.container.documentOffset);
+    var position = upKey
+        ? child.getPositionAbove(localPosition)
+        : child.getPositionBelow(localPosition);
 
 
     if (position == null) {
     if (position == null) {
-      final sibling = upKey ? getRenderEditor()!.childBefore(child) : getRenderEditor()!.childAfter(child);
+      final sibling = upKey
+          ? getRenderEditor()!.childBefore(child)
+          : getRenderEditor()!.childAfter(child);
+
       if (sibling == null) {
       if (sibling == null) {
         position = TextPosition(offset: upKey ? 0 : plainText.length - 1);
         position = TextPosition(offset: upKey ? 0 : plainText.length - 1);
       } else {
       } else {
-        final finalOffset = Offset(child.getOffsetForCaret(localPosition).dx,
-            sibling.getOffsetForCaret(TextPosition(offset: upKey ? sibling.container.length - 1 : 0)).dy);
+        final finalOffset = Offset(
+            child.getOffsetForCaret(localPosition).dx,
+            sibling
+                .getOffsetForCaret(TextPosition(
+                    offset: upKey ? sibling.container.length - 1 : 0))
+                .dy);
         final siblingPosition = sibling.getPositionForOffset(finalOffset);
         final siblingPosition = sibling.getPositionForOffset(finalOffset);
-        position = TextPosition(offset: sibling.container.documentOffset + siblingPosition.offset);
+        position = TextPosition(
+            offset: sibling.container.documentOffset + siblingPosition.offset);
       }
       }
     } else {
     } else {
-      position = TextPosition(offset: child.container.documentOffset + position.offset);
+      position = TextPosition(
+          offset: child.container.documentOffset + position.offset);
     }
     }
 
 
     if (position.offset == newSelection.extentOffset) {
     if (position.offset == newSelection.extentOffset) {
@@ -250,33 +276,49 @@ class _RawEditorState extends EditorState
     return newSelection;
     return newSelection;
   }
   }
 
 
-  TextSelection _jumpToBeginOrEndOfWord(TextSelection newSelection, bool wordModifier, bool leftKey, bool rightKey,
-      String plainText, bool lineModifier, bool shift) {
+  TextSelection _jumpToBeginOrEndOfWord(
+      TextSelection newSelection,
+      bool wordModifier,
+      bool leftKey,
+      bool rightKey,
+      String plainText,
+      bool lineModifier,
+      bool shift) {
     if (wordModifier) {
     if (wordModifier) {
       if (leftKey) {
       if (leftKey) {
         final textSelection = getRenderEditor()!.selectWordAtPosition(
         final textSelection = getRenderEditor()!.selectWordAtPosition(
-            TextPosition(offset: _previousCharacter(newSelection.extentOffset, plainText, false)));
+            TextPosition(
+                offset: _previousCharacter(
+                    newSelection.extentOffset, plainText, false)));
+
         return newSelection.copyWith(extentOffset: textSelection.baseOffset);
         return newSelection.copyWith(extentOffset: textSelection.baseOffset);
       }
       }
-      final textSelection = getRenderEditor()!
-          .selectWordAtPosition(TextPosition(offset: _nextCharacter(newSelection.extentOffset, plainText, false)));
+      final textSelection = getRenderEditor()!.selectWordAtPosition(
+          TextPosition(
+              offset:
+                  _nextCharacter(newSelection.extentOffset, plainText, false)));
       return newSelection.copyWith(extentOffset: textSelection.extentOffset);
       return newSelection.copyWith(extentOffset: textSelection.extentOffset);
     } else if (lineModifier) {
     } else if (lineModifier) {
       if (leftKey) {
       if (leftKey) {
         final textSelection = getRenderEditor()!.selectLineAtPosition(
         final textSelection = getRenderEditor()!.selectLineAtPosition(
-            TextPosition(offset: _previousCharacter(newSelection.extentOffset, plainText, false)));
+            TextPosition(
+                offset: _previousCharacter(
+                    newSelection.extentOffset, plainText, false)));
         return newSelection.copyWith(extentOffset: textSelection.baseOffset);
         return newSelection.copyWith(extentOffset: textSelection.baseOffset);
       }
       }
       final startPoint = newSelection.extentOffset;
       final startPoint = newSelection.extentOffset;
       if (startPoint < plainText.length) {
       if (startPoint < plainText.length) {
-        final textSelection = getRenderEditor()!.selectLineAtPosition(TextPosition(offset: startPoint));
+        final textSelection = getRenderEditor()!
+            .selectLineAtPosition(TextPosition(offset: startPoint));
         return newSelection.copyWith(extentOffset: textSelection.extentOffset);
         return newSelection.copyWith(extentOffset: textSelection.extentOffset);
       }
       }
       return newSelection;
       return newSelection;
     }
     }
 
 
     if (rightKey && newSelection.extentOffset < plainText.length) {
     if (rightKey && newSelection.extentOffset < plainText.length) {
-      final nextExtent = _nextCharacter(newSelection.extentOffset, plainText, true);
+      final nextExtent =
+          _nextCharacter(newSelection.extentOffset, plainText, true);
+
       final distance = nextExtent - newSelection.extentOffset;
       final distance = nextExtent - newSelection.extentOffset;
       newSelection = newSelection.copyWith(extentOffset: nextExtent);
       newSelection = newSelection.copyWith(extentOffset: nextExtent);
       if (shift) {
       if (shift) {
@@ -286,7 +328,8 @@ class _RawEditorState extends EditorState
     }
     }
 
 
     if (leftKey && newSelection.extentOffset > 0) {
     if (leftKey && newSelection.extentOffset > 0) {
-      final previousExtent = _previousCharacter(newSelection.extentOffset, plainText, true);
+      final previousExtent =
+          _previousCharacter(newSelection.extentOffset, plainText, true);
       final distance = newSelection.extentOffset - previousExtent;
       final distance = newSelection.extentOffset - previousExtent;
       newSelection = newSelection.copyWith(extentOffset: previousExtent);
       newSelection = newSelection.copyWith(extentOffset: previousExtent);
       if (shift) {
       if (shift) {
@@ -326,7 +369,9 @@ class _RawEditorState extends EditorState
     var count = 0;
     var count = 0;
     int? lastNonWhitespace;
     int? lastNonWhitespace;
     for (final currentString in string.characters) {
     for (final currentString in string.characters) {
-      if (!includeWhitespace && !WHITE_SPACE.contains(currentString.characters.first.toString().codeUnitAt(0))) {
+      if (!includeWhitespace &&
+          !WHITE_SPACE.contains(
+              currentString.characters.first.toString().codeUnitAt(0))) {
         lastNonWhitespace = count;
         lastNonWhitespace = count;
       }
       }
       if (count + currentString.length >= index) {
       if (count + currentString.length >= index) {
@@ -337,7 +382,8 @@ class _RawEditorState extends EditorState
     return 0;
     return 0;
   }
   }
 
 
-  bool get hasConnection => _textInputConnection != null && _textInputConnection!.attached;
+  bool get hasConnection =>
+      _textInputConnection != null && _textInputConnection!.attached;
 
 
   void openConnectionIfNeeded() {
   void openConnectionIfNeeded() {
     if (!shouldCreateInputConnection) {
     if (!shouldCreateInputConnection) {
@@ -388,7 +434,8 @@ class _RawEditorState extends EditorState
       return;
       return;
     }
     }
 
 
-    final shouldRemember = textEditingValue.text != _lastKnownRemoteTextEditingValue!.text;
+    final shouldRemember =
+        textEditingValue.text != _lastKnownRemoteTextEditingValue!.text;
     _lastKnownRemoteTextEditingValue = actualValue;
     _lastKnownRemoteTextEditingValue = actualValue;
     _textInputConnection!.setEditingState(actualValue);
     _textInputConnection!.setEditingState(actualValue);
     if (shouldRemember) {
     if (shouldRemember) {
@@ -397,7 +444,8 @@ class _RawEditorState extends EditorState
   }
   }
 
 
   @override
   @override
-  TextEditingValue? get currentTextEditingValue => _lastKnownRemoteTextEditingValue;
+  TextEditingValue? get currentTextEditingValue =>
+      _lastKnownRemoteTextEditingValue;
 
 
   @override
   @override
   AutofillScope? get currentAutofillScope => null;
   AutofillScope? get currentAutofillScope => null;
@@ -429,7 +477,8 @@ class _RawEditorState extends EditorState
     final text = value.text;
     final text = value.text;
     final cursorPosition = value.selection.extentOffset;
     final cursorPosition = value.selection.extentOffset;
     final diff = getDiff(oldText, text, cursorPosition);
     final diff = getDiff(oldText, text, cursorPosition);
-    widget.controller.replaceText(diff.start, diff.deleted.length, diff.inserted, value.selection);
+    widget.controller.replaceText(
+        diff.start, diff.deleted.length, diff.inserted, value.selection);
   }
   }
 
 
   @override
   @override
@@ -472,6 +521,20 @@ class _RawEditorState extends EditorState
     _sentRemoteValues.clear();
     _sentRemoteValues.clear();
   }
   }
 
 
+  @override
+  void copySelection(SelectionChangedCause cause) {}
+
+  @override
+  void cutSelection(SelectionChangedCause cause) {}
+
+  @override
+  Future<void> pasteText(SelectionChangedCause cause) {
+    return Future(() => {});
+  }
+
+  @override
+  void selectAll(SelectionChangedCause cause) {}
+
   @override
   @override
   Widget build(BuildContext context) {
   Widget build(BuildContext context) {
     assert(debugCheckHasMediaQuery(context));
     assert(debugCheckHasMediaQuery(context));
@@ -479,8 +542,11 @@ class _RawEditorState extends EditorState
     super.build(context);
     super.build(context);
 
 
     var _doc = widget.controller.document;
     var _doc = widget.controller.document;
-    if (_doc.isEmpty() && !widget.focusNode.hasFocus && widget.placeholder != null) {
-      _doc = Document.fromJson(jsonDecode('[{"attributes":{"placeholder":true},"insert":"${widget.placeholder}\\n"}]'));
+    if (_doc.isEmpty() &&
+        !widget.focusNode.hasFocus &&
+        widget.placeholder != null) {
+      _doc = Document.fromJson(jsonDecode(
+          '[{"attributes":{"placeholder":true},"insert":"${widget.placeholder}\\n"}]'));
     }
     }
 
 
     Widget child = CompositedTransformTarget(
     Widget child = CompositedTransformTarget(
@@ -503,7 +569,8 @@ class _RawEditorState extends EditorState
     );
     );
 
 
     if (widget.scrollable) {
     if (widget.scrollable) {
-      final baselinePadding = EdgeInsets.only(top: _styles!.paragraph!.verticalSpacing.item1);
+      final baselinePadding =
+          EdgeInsets.only(top: _styles!.paragraph!.verticalSpacing.item1);
       child = BaselineProxy(
       child = BaselineProxy(
         textStyle: _styles!.paragraph!.style,
         textStyle: _styles!.paragraph!.style,
         padding: baselinePadding,
         padding: baselinePadding,
@@ -534,7 +601,8 @@ class _RawEditorState extends EditorState
     );
     );
   }
   }
 
 
-  void _handleSelectionChanged(TextSelection selection, SelectionChangedCause cause) {
+  void _handleSelectionChanged(
+      TextSelection selection, SelectionChangedCause cause) {
     widget.controller.updateSelection(selection, ChangeSource.LOCAL);
     widget.controller.updateSelection(selection, ChangeSource.LOCAL);
 
 
     _selectionOverlay?.handlesVisible = _shouldShowSelectionHandles();
     _selectionOverlay?.handlesVisible = _shouldShowSelectionHandles();
@@ -563,7 +631,9 @@ class _RawEditorState extends EditorState
             _styles,
             _styles,
             widget.enableInteractiveSelection,
             widget.enableInteractiveSelection,
             _hasFocus,
             _hasFocus,
-            attrs.containsKey(Attribute.codeBlock.key) ? const EdgeInsets.all(16) : null,
+            attrs.containsKey(Attribute.codeBlock.key)
+                ? const EdgeInsets.all(16)
+                : null,
             widget.embedBuilder,
             widget.embedBuilder,
             _cursorController,
             _cursorController,
             indentLevelCounts);
             indentLevelCounts);
@@ -575,7 +645,8 @@ class _RawEditorState extends EditorState
     return result;
     return result;
   }
   }
 
 
-  EditableTextLine _getEditableTextLineFromNode(Line node, BuildContext context) {
+  EditableTextLine _getEditableTextLineFromNode(
+      Line node, BuildContext context) {
     final textLine = TextLine(
     final textLine = TextLine(
       line: node,
       line: node,
       textDirection: _textDirection,
       textDirection: _textDirection,
@@ -598,7 +669,8 @@ class _RawEditorState extends EditorState
     return editableTextLine;
     return editableTextLine;
   }
   }
 
 
-  Tuple2<double, double> _getVerticalSpacingForLine(Line line, DefaultStyles? defaultStyles) {
+  Tuple2<double, double> _getVerticalSpacingForLine(
+      Line line, DefaultStyles? defaultStyles) {
     final attrs = line.style.attributes;
     final attrs = line.style.attributes;
     if (attrs.containsKey(Attribute.header.key)) {
     if (attrs.containsKey(Attribute.header.key)) {
       final int? level = attrs[Attribute.header.key]!.value;
       final int? level = attrs[Attribute.header.key]!.value;
@@ -623,7 +695,8 @@ class _RawEditorState extends EditorState
     return defaultStyles!.paragraph!.verticalSpacing;
     return defaultStyles!.paragraph!.verticalSpacing;
   }
   }
 
 
-  Tuple2<double, double> _getVerticalSpacingForBlock(Block node, DefaultStyles? defaultStyles) {
+  Tuple2<double, double> _getVerticalSpacingForBlock(
+      Block node, DefaultStyles? defaultStyles) {
     final attrs = node.style.attributes;
     final attrs = node.style.attributes;
     if (attrs.containsKey(Attribute.quoteBlock.key)) {
     if (attrs.containsKey(Attribute.quoteBlock.key)) {
       return defaultStyles!.quote!.verticalSpacing;
       return defaultStyles!.quote!.verticalSpacing;
@@ -666,7 +739,8 @@ class _RawEditorState extends EditorState
     } else {
     } else {
       _keyboardVisibilityController = KeyboardVisibilityController();
       _keyboardVisibilityController = KeyboardVisibilityController();
       _keyboardVisible = _keyboardVisibilityController!.isVisible;
       _keyboardVisible = _keyboardVisibilityController!.isVisible;
-      _keyboardVisibilitySubscription = _keyboardVisibilityController?.onChange.listen((visible) {
+      _keyboardVisibilitySubscription =
+          _keyboardVisibilityController?.onChange.listen((visible) {
         _keyboardVisible = visible;
         _keyboardVisible = visible;
         if (visible) {
         if (visible) {
           _onChangeTextEditingValue();
           _onChangeTextEditingValue();
@@ -674,13 +748,8 @@ class _RawEditorState extends EditorState
       });
       });
     }
     }
 
 
-    _focusAttachment = widget.focusNode.attach(context, onKey: (node, event) {
-      if (_keyboardListener.handleRawKeyEvent(event)) {
-        return KeyEventResult.handled;
-      } else {
-        return KeyEventResult.ignored;
-      }
-    });
+    _focusAttachment = widget.focusNode.attach(context,
+        onKey: (node, event) => _keyboardListener.handleRawKeyEvent(event));
     widget.focusNode.addListener(_handleFocusChanged);
     widget.focusNode.addListener(_handleFocusChanged);
   }
   }
 
 
@@ -689,7 +758,9 @@ class _RawEditorState extends EditorState
     super.didChangeDependencies();
     super.didChangeDependencies();
     final parentStyles = EditorStyles.getStyles(context, true);
     final parentStyles = EditorStyles.getStyles(context, true);
     final defaultStyles = DefaultStyles.getInstance(context);
     final defaultStyles = DefaultStyles.getInstance(context);
-    _styles = (parentStyles != null) ? defaultStyles.merge(parentStyles) : defaultStyles;
+    _styles = (parentStyles != null)
+        ? defaultStyles.merge(parentStyles)
+        : defaultStyles;
 
 
     if (widget.customStyles != null) {
     if (widget.customStyles != null) {
       _styles = _styles!.merge(widget.customStyles!);
       _styles = _styles!.merge(widget.customStyles!);
@@ -723,13 +794,8 @@ class _RawEditorState extends EditorState
     if (widget.focusNode != oldWidget.focusNode) {
     if (widget.focusNode != oldWidget.focusNode) {
       oldWidget.focusNode.removeListener(_handleFocusChanged);
       oldWidget.focusNode.removeListener(_handleFocusChanged);
       _focusAttachment?.detach();
       _focusAttachment?.detach();
-      _focusAttachment = widget.focusNode.attach(context, onKey: (node, event) {
-        if (_keyboardListener.handleRawKeyEvent(event)) {
-          return KeyEventResult.handled;
-        } else {
-          return KeyEventResult.ignored;
-        }
-      });
+      _focusAttachment = widget.focusNode.attach(context,
+          onKey: (node, event) => _keyboardListener.handleRawKeyEvent(event));
       widget.focusNode.addListener(_handleFocusChanged);
       widget.focusNode.addListener(_handleFocusChanged);
       updateKeepAlive();
       updateKeepAlive();
     }
     }
@@ -749,7 +815,8 @@ class _RawEditorState extends EditorState
   }
   }
 
 
   bool _shouldShowSelectionHandles() {
   bool _shouldShowSelectionHandles() {
-    return widget.showSelectionHandles && !widget.controller.selection.isCollapsed;
+    return widget.showSelectionHandles &&
+        !widget.controller.selection.isCollapsed;
   }
   }
 
 
   void handleDelete(bool forward) {
   void handleDelete(bool forward) {
@@ -760,7 +827,8 @@ class _RawEditorState extends EditorState
     var textAfter = selection.textAfter(plainText);
     var textAfter = selection.textAfter(plainText);
     if (selection.isCollapsed) {
     if (selection.isCollapsed) {
       if (!forward && textBefore.isNotEmpty) {
       if (!forward && textBefore.isNotEmpty) {
-        final characterBoundary = _previousCharacter(textBefore.length, textBefore, true);
+        final characterBoundary =
+            _previousCharacter(textBefore.length, textBefore, true);
         textBefore = textBefore.substring(0, characterBoundary);
         textBefore = textBefore.substring(0, characterBoundary);
         cursorPosition = characterBoundary;
         cursorPosition = characterBoundary;
       }
       }
@@ -783,13 +851,24 @@ class _RawEditorState extends EditorState
   Future<void> handleShortcut(InputShortcut? shortcut) async {
   Future<void> handleShortcut(InputShortcut? shortcut) async {
     final selection = widget.controller.selection;
     final selection = widget.controller.selection;
     final plainText = textEditingValue.text;
     final plainText = textEditingValue.text;
-    if (shortcut == InputShortcut.SAVE) {
-      widget.controller.save();
+
+    if (shortcut == InputShortcut.UNDO) {
+      if (widget.controller.hasUndo) {
+        widget.controller.undo();
+      }
+      return;
+    }
+    if (shortcut == InputShortcut.REDO) {
+      if (widget.controller.hasRedo) {
+        widget.controller.redo();
+      }
       return;
       return;
     }
     }
+
     if (shortcut == InputShortcut.COPY) {
     if (shortcut == InputShortcut.COPY) {
       if (!selection.isCollapsed) {
       if (!selection.isCollapsed) {
-        await Clipboard.setData(ClipboardData(text: selection.textInside(plainText)));
+        await Clipboard.setData(
+            ClipboardData(text: selection.textInside(plainText)));
       }
       }
       return;
       return;
     }
     }
@@ -806,7 +885,8 @@ class _RawEditorState extends EditorState
         );
         );
 
 
         textEditingValue = TextEditingValue(
         textEditingValue = TextEditingValue(
-          text: selection.textBefore(plainText) + selection.textAfter(plainText),
+          text:
+              selection.textBefore(plainText) + selection.textAfter(plainText),
           selection: TextSelection.collapsed(offset: selection.start),
           selection: TextSelection.collapsed(offset: selection.start),
         );
         );
       }
       }
@@ -824,7 +904,8 @@ class _RawEditorState extends EditorState
       }
       }
       return;
       return;
     }
     }
-    if (shortcut == InputShortcut.SELECT_ALL && widget.enableInteractiveSelection) {
+    if (shortcut == InputShortcut.SELECT_ALL &&
+        widget.enableInteractiveSelection) {
       widget.controller.updateSelection(
       widget.controller.updateSelection(
           selection.copyWith(
           selection.copyWith(
             baseOffset: 0,
             baseOffset: 0,
@@ -878,14 +959,16 @@ class _RawEditorState extends EditorState
   void _onChangeTextEditingValue() {
   void _onChangeTextEditingValue() {
     _showCaretOnScreen();
     _showCaretOnScreen();
     updateRemoteValueIfNeeded();
     updateRemoteValueIfNeeded();
-    _cursorController.startOrStopCursorTimerIfNeeded(_hasFocus, widget.controller.selection);
+    _cursorController.startOrStopCursorTimerIfNeeded(
+        _hasFocus, widget.controller.selection);
     if (hasConnection) {
     if (hasConnection) {
       _cursorController
       _cursorController
         ..stopCursorTimer(resetCharTicks: false)
         ..stopCursorTimer(resetCharTicks: false)
         ..startCursorTimer();
         ..startCursorTimer();
     }
     }
 
 
-    SchedulerBinding.instance!.addPostFrameCallback((_) => _updateOrDisposeSelectionOverlayIfNeeded());
+    SchedulerBinding.instance!.addPostFrameCallback(
+        (_) => _updateOrDisposeSelectionOverlayIfNeeded());
     if (mounted) {
     if (mounted) {
       setState(() {
       setState(() {
         // Use widget.controller.value in build()
         // Use widget.controller.value in build()
@@ -928,7 +1011,8 @@ class _RawEditorState extends EditorState
 
 
   void _handleFocusChanged() {
   void _handleFocusChanged() {
     openOrCloseConnection();
     openOrCloseConnection();
-    _cursorController.startOrStopCursorTimerIfNeeded(_hasFocus, widget.controller.selection);
+    _cursorController.startOrStopCursorTimerIfNeeded(
+        _hasFocus, widget.controller.selection);
     _updateOrDisposeSelectionOverlayIfNeeded();
     _updateOrDisposeSelectionOverlayIfNeeded();
     if (_hasFocus) {
     if (_hasFocus) {
       WidgetsBinding.instance!.addObserver(this);
       WidgetsBinding.instance!.addObserver(this);
@@ -959,7 +1043,8 @@ class _RawEditorState extends EditorState
       _showCaretOnScreenScheduled = false;
       _showCaretOnScreenScheduled = false;
 
 
       final viewport = RenderAbstractViewport.of(getRenderEditor())!;
       final viewport = RenderAbstractViewport.of(getRenderEditor())!;
-      final editorOffset = getRenderEditor()!.localToGlobal(const Offset(0, 0), ancestor: viewport);
+      final editorOffset = getRenderEditor()!
+          .localToGlobal(const Offset(0, 0), ancestor: viewport);
       final offsetInViewport = _scrollController!.offset + editorOffset.dy;
       final offsetInViewport = _scrollController!.offset + editorOffset.dy;
 
 
       final offset = getRenderEditor()!.getOffsetToRevealCursor(
       final offset = getRenderEditor()!.getOffsetToRevealCursor(
@@ -1042,7 +1127,8 @@ class _RawEditorState extends EditorState
       final value = textEditingValue;
       final value = textEditingValue;
       final data = await Clipboard.getData(Clipboard.kTextPlain);
       final data = await Clipboard.getData(Clipboard.kTextPlain);
       if (data != null) {
       if (data != null) {
-        final length = textEditingValue.selection.end - textEditingValue.selection.start;
+        final length =
+            textEditingValue.selection.end - textEditingValue.selection.start;
         widget.controller.replaceText(
         widget.controller.replaceText(
           value.selection.start,
           value.selection.start,
           length,
           length,
@@ -1051,7 +1137,9 @@ class _RawEditorState extends EditorState
         );
         );
         // move cursor to the end of pasted text selection
         // move cursor to the end of pasted text selection
         widget.controller.updateSelection(
         widget.controller.updateSelection(
-            TextSelection.collapsed(offset: value.selection.start + data.text!.length), ChangeSource.LOCAL);
+            TextSelection.collapsed(
+                offset: value.selection.start + data.text!.length),
+            ChangeSource.LOCAL);
       }
       }
     }
     }
   }
   }
@@ -1061,7 +1149,8 @@ class _RawEditorState extends EditorState
     if (data == null) {
     if (data == null) {
       return false;
       return false;
     }
     }
-    return textEditingValue.text.length - value.text.length == data.text!.length;
+    return textEditingValue.text.length - value.text.length ==
+        data.text!.length;
   }
   }
 
 
   @override
   @override
@@ -1094,7 +1183,8 @@ class _RawEditorState extends EditorState
   }
   }
 
 
   @override
   @override
-  void userUpdateTextEditingValue(TextEditingValue value, SelectionChangedCause cause) {
+  void userUpdateTextEditingValue(
+      TextEditingValue value, SelectionChangedCause cause) {
     // TODO: implement userUpdateTextEditingValue
     // TODO: implement userUpdateTextEditingValue
   }
   }
 }
 }
@@ -1144,7 +1234,8 @@ class _Editor extends MultiChildRenderObjectWidget {
   }
   }
 
 
   @override
   @override
-  void updateRenderObject(BuildContext context, covariant RenderEditor renderObject) {
+  void updateRenderObject(
+      BuildContext context, covariant RenderEditor renderObject) {
     renderObject
     renderObject
       ..document = document
       ..document = document
       ..container = document.root
       ..container = document.root

+ 1 - 1
app_flowy/packages/flowy_editor/lib/src/widget/text_block.dart

@@ -474,7 +474,7 @@ class __CheckboxState extends State<_Checkbox> {
     return Container(
     return Container(
       alignment: AlignmentDirectional.topEnd,
       alignment: AlignmentDirectional.topEnd,
       width: widget.width,
       width: widget.width,
-      padding: const EdgeInsetsDirectional.only(end: 13),
+      padding: const EdgeInsetsDirectional.only(end: 2),
       child: Checkbox(
       child: Checkbox(
         value: widget.isChecked,
         value: widget.isChecked,
         onChanged: _onCheckboxChanged,
         onChanged: _onCheckboxChanged,

+ 4 - 4
app_flowy/pubspec.lock

@@ -35,7 +35,7 @@ packages:
       name: async
       name: async
       url: "https://pub.dartlang.org"
       url: "https://pub.dartlang.org"
     source: hosted
     source: hosted
-    version: "2.7.0"
+    version: "2.8.2"
   bloc:
   bloc:
     dependency: transitive
     dependency: transitive
     description:
     description:
@@ -112,7 +112,7 @@ packages:
       name: characters
       name: characters
       url: "https://pub.dartlang.org"
       url: "https://pub.dartlang.org"
     source: hosted
     source: hosted
-    version: "1.1.0"
+    version: "1.2.0"
   charcode:
   charcode:
     dependency: transitive
     dependency: transitive
     description:
     description:
@@ -470,7 +470,7 @@ packages:
       name: matcher
       name: matcher
       url: "https://pub.dartlang.org"
       url: "https://pub.dartlang.org"
     source: hosted
     source: hosted
-    version: "0.12.10"
+    version: "0.12.11"
   meta:
   meta:
     dependency: transitive
     dependency: transitive
     description:
     description:
@@ -743,7 +743,7 @@ packages:
       name: test_api
       name: test_api
       url: "https://pub.dartlang.org"
       url: "https://pub.dartlang.org"
     source: hosted
     source: hosted
-    version: "0.4.1"
+    version: "0.4.3"
   textstyle_extensions:
   textstyle_extensions:
     dependency: transitive
     dependency: transitive
     description:
     description: