Sfoglia il codice sorgente

[editor] Add save keyboard shortcut.

Jaylen Bian 3 anni fa
parent
commit
7b1e5aaba2

+ 0 - 4
app_flowy/lib/workspace/presentation/doc/editor_widget.dart

@@ -58,8 +58,4 @@ class EditorWdiget extends StatelessWidget {
   Future<String> _onImageSelection(File file) {
     throw UnimplementedError();
   }
-
-  void save() {
-    final deltaJson = controller.document.toDelta().toJson();
-  }
 }

+ 1 - 1
app_flowy/macos/Podfile.lock

@@ -49,4 +49,4 @@ SPEC CHECKSUMS:
 
 PODFILE CHECKSUM: 6eac6b3292e5142cfc23bdeb71848a40ec51c14c
 
-COCOAPODS: 1.10.1
+COCOAPODS: 1.9.3

+ 13 - 19
app_flowy/packages/flowy_editor/lib/src/service/controller.dart

@@ -38,8 +38,7 @@ class EditorController extends ChangeNotifier {
       );
 
   Style getSelectionStyle() =>
-      document.collectStyle(selection.start, selection.end - selection.start)
-        ..mergeAll(toggledStyle);
+      document.collectStyle(selection.start, selection.end - selection.start)..mergeAll(toggledStyle);
 
   bool get hasUndo => document.hasUndo;
 
@@ -59,6 +58,12 @@ class EditorController extends ChangeNotifier {
     }
   }
 
+  Future<bool> save() async {
+    document.toDelta().toJson();
+    // TODO: vedon - Save document to database
+    return true;
+  }
+
   @override
   void dispose() {
     document.close();
@@ -75,9 +80,7 @@ class EditorController extends ChangeNotifier {
   }
 
   void formatText(int index, int length, Attribute? attribute) {
-    if (length == 0 &&
-        attribute!.isInline &&
-        attribute.key != Attribute.link.key) {
+    if (length == 0 && attribute!.isInline && attribute.key != Attribute.link.key) {
       toggledStyle = toggledStyle.put(attribute);
     }
 
@@ -92,24 +95,16 @@ class EditorController extends ChangeNotifier {
     notifyListeners();
   }
 
-  void replaceText(
-      int index, int length, Object? data, TextSelection? textSelection) {
+  void replaceText(int index, int length, Object? data, TextSelection? textSelection) {
     assert(data is String || data is Embeddable);
 
     Delta? delta;
     if (length > 0 || data is! String || data.isNotEmpty) {
       delta = document.replace(index, length, data);
-      var shouldRetainDelta = toggledStyle.isNotEmpty &&
-          delta.isNotEmpty &&
-          delta.length <= 2 &&
-          delta.last.isInsert;
-      if (shouldRetainDelta &&
-          toggledStyle.isNotEmpty &&
-          delta.length == 2 &&
-          delta.last.data == '\n') {
+      var shouldRetainDelta = toggledStyle.isNotEmpty && delta.isNotEmpty && delta.length <= 2 && delta.last.isInsert;
+      if (shouldRetainDelta && toggledStyle.isNotEmpty && delta.length == 2 && delta.last.data == '\n') {
         // if all attributes are inline, shouldRetainDelta should be false
-        final anyAttributeNotInline =
-            toggledStyle.values.any((attr) => !attr.isInline);
+        final anyAttributeNotInline = toggledStyle.values.any((attr) => !attr.isInline);
         shouldRetainDelta &= anyAttributeNotInline;
       }
       if (shouldRetainDelta) {
@@ -151,8 +146,7 @@ class EditorController extends ChangeNotifier {
 
     textSelection = selection.copyWith(
       baseOffset: delta.transformPosition(selection.baseOffset, force: false),
-      extentOffset:
-          delta.transformPosition(selection.extentOffset, force: false),
+      extentOffset: delta.transformPosition(selection.extentOffset, force: false),
     );
     if (selection != textSelection) {
       _updateSelection(textSelection, source);

+ 4 - 2
app_flowy/packages/flowy_editor/lib/src/service/keyboard.dart

@@ -8,6 +8,7 @@ enum InputShortcut {
   COPY,
   PASTE,
   SELECT_ALL,
+  SAVE,
 }
 
 typedef CursorMoveCallback = void Function(
@@ -46,6 +47,7 @@ class KeyboardListener {
     LogicalKeyboardKey.keyC,
     LogicalKeyboardKey.keyV,
     LogicalKeyboardKey.keyX,
+    LogicalKeyboardKey.keyS,
     LogicalKeyboardKey.delete,
     LogicalKeyboardKey.backspace,
   };
@@ -78,6 +80,7 @@ class KeyboardListener {
     LogicalKeyboardKey.keyC: InputShortcut.COPY,
     LogicalKeyboardKey.keyV: InputShortcut.PASTE,
     LogicalKeyboardKey.keyA: InputShortcut.SELECT_ALL,
+    LogicalKeyboardKey.keyS: InputShortcut.SAVE,
   };
 
   bool handleRawKeyEvent(RawKeyEvent event) {
@@ -89,8 +92,7 @@ class KeyboardListener {
       return false;
     }
 
-    final keysPressed =
-        LogicalKeyboardKey.collapseSynonyms(RawKeyboard.instance.keysPressed);
+    final keysPressed = LogicalKeyboardKey.collapseSynonyms(RawKeyboard.instance.keysPressed);
     final key = event.logicalKey;
     final isMacOS = event.data is RawKeyEventDataMacOs;
     final modifierKeys = isMacOS ? _osxModifierKeys : _winModifierKeys;

+ 68 - 135
app_flowy/packages/flowy_editor/lib/src/widget/raw_editor.dart

@@ -1,6 +1,7 @@
 import 'dart:async';
 import 'dart:convert';
 import 'dart:math' as math;
+import 'dart:developer';
 
 import 'package:flutter/cupertino.dart';
 import 'package:flutter/foundation.dart';
@@ -59,8 +60,7 @@ class RawEditor extends StatefulWidget {
     this.embedBuilder,
   )   : assert(maxHeight == null || maxHeight > 0, 'maxHeight 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,
         super(key: key);
 
@@ -111,10 +111,7 @@ abstract class EditorState extends State<RawEditor> {
 }
 
 class _RawEditorState extends EditorState
-    with
-        AutomaticKeepAliveClientMixin<RawEditor>,
-        WidgetsBindingObserver,
-        TickerProviderStateMixin<RawEditor>
+    with AutomaticKeepAliveClientMixin<RawEditor>, WidgetsBindingObserver, TickerProviderStateMixin<RawEditor>
     implements TextSelectionDelegate, TextInputClient {
   final GlobalKey _editorKey = GlobalKey();
   final List<TextEditingValue> _sentRemoteValues = [];
@@ -132,8 +129,7 @@ class _RawEditorState extends EditorState
   bool _didAutoFocus = false;
   bool _keyboardVisible = false;
   DefaultStyles? _styles;
-  final ClipboardStatusNotifier? _clipboardStatus =
-      kIsWeb ? null : ClipboardStatusNotifier();
+  final ClipboardStatusNotifier? _clipboardStatus = kIsWeb ? null : ClipboardStatusNotifier();
   final LayerLink _toolbarLayerLink = LayerLink();
   final LayerLink _startHandleLayerLink = LayerLink();
   final LayerLink _endHandleLayerLink = LayerLink();
@@ -181,78 +177,57 @@ class _RawEditorState extends EditorState
         downKey = key == LogicalKeyboardKey.arrowDown;
 
     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) {
-      newSelection = _handleMovingCursorVertically(
-          upKey, downKey, shift, selection, newSelection, plainText);
+      newSelection = _handleMovingCursorVertically(upKey, downKey, shift, selection, newSelection, plainText);
     }
 
     if (!shift) {
-      newSelection =
-          _placeCollapsedSelection(selection, newSelection, leftKey, rightKey);
+      newSelection = _placeCollapsedSelection(selection, newSelection, leftKey, rightKey);
     }
 
     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;
     if (!selection.isCollapsed) {
       if (leftKey) {
-        newOffset = newSelection.baseOffset < newSelection.extentOffset
-            ? newSelection.baseOffset
-            : newSelection.extentOffset;
+        newOffset =
+            newSelection.baseOffset < newSelection.extentOffset ? newSelection.baseOffset : newSelection.extentOffset;
       } 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));
   }
 
   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 localPosition = TextPosition(
-        offset: originPosition.offset - child.container.documentOffset);
+    final localPosition = TextPosition(offset: originPosition.offset - child.container.documentOffset);
 
-    var position = upKey
-        ? child.getPositionAbove(localPosition)
-        : child.getPositionBelow(localPosition);
+    var position = upKey ? child.getPositionAbove(localPosition) : child.getPositionBelow(localPosition);
 
     if (position == null) {
-      final sibling = upKey
-          ? getRenderEditor()!.childBefore(child)
-          : getRenderEditor()!.childAfter(child);
+      final sibling = upKey ? getRenderEditor()!.childBefore(child) : getRenderEditor()!.childAfter(child);
       if (sibling == null) {
         position = TextPosition(offset: upKey ? 0 : plainText.length - 1);
       } 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);
-        position = TextPosition(
-            offset: sibling.container.documentOffset + siblingPosition.offset);
+        position = TextPosition(offset: sibling.container.documentOffset + siblingPosition.offset);
       }
     } else {
-      position = TextPosition(
-          offset: child.container.documentOffset + position.offset);
+      position = TextPosition(offset: child.container.documentOffset + position.offset);
     }
 
     if (position.offset == newSelection.extentOffset) {
@@ -275,47 +250,33 @@ class _RawEditorState extends EditorState
     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 (leftKey) {
         final textSelection = getRenderEditor()!.selectWordAtPosition(
-            TextPosition(
-                offset: _previousCharacter(
-                    newSelection.extentOffset, plainText, false)));
+            TextPosition(offset: _previousCharacter(newSelection.extentOffset, plainText, false)));
         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);
     } else if (lineModifier) {
       if (leftKey) {
         final textSelection = getRenderEditor()!.selectLineAtPosition(
-            TextPosition(
-                offset: _previousCharacter(
-                    newSelection.extentOffset, plainText, false)));
+            TextPosition(offset: _previousCharacter(newSelection.extentOffset, plainText, false)));
         return newSelection.copyWith(extentOffset: textSelection.baseOffset);
       }
       final startPoint = newSelection.extentOffset;
       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;
     }
 
     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;
       newSelection = newSelection.copyWith(extentOffset: nextExtent);
       if (shift) {
@@ -325,8 +286,7 @@ class _RawEditorState extends EditorState
     }
 
     if (leftKey && newSelection.extentOffset > 0) {
-      final previousExtent =
-          _previousCharacter(newSelection.extentOffset, plainText, true);
+      final previousExtent = _previousCharacter(newSelection.extentOffset, plainText, true);
       final distance = newSelection.extentOffset - previousExtent;
       newSelection = newSelection.copyWith(extentOffset: previousExtent);
       if (shift) {
@@ -366,9 +326,7 @@ class _RawEditorState extends EditorState
     var count = 0;
     int? lastNonWhitespace;
     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;
       }
       if (count + currentString.length >= index) {
@@ -379,8 +337,7 @@ class _RawEditorState extends EditorState
     return 0;
   }
 
-  bool get hasConnection =>
-      _textInputConnection != null && _textInputConnection!.attached;
+  bool get hasConnection => _textInputConnection != null && _textInputConnection!.attached;
 
   void openConnectionIfNeeded() {
     if (!shouldCreateInputConnection) {
@@ -431,8 +388,7 @@ class _RawEditorState extends EditorState
       return;
     }
 
-    final shouldRemember =
-        textEditingValue.text != _lastKnownRemoteTextEditingValue!.text;
+    final shouldRemember = textEditingValue.text != _lastKnownRemoteTextEditingValue!.text;
     _lastKnownRemoteTextEditingValue = actualValue;
     _textInputConnection!.setEditingState(actualValue);
     if (shouldRemember) {
@@ -441,8 +397,7 @@ class _RawEditorState extends EditorState
   }
 
   @override
-  TextEditingValue? get currentTextEditingValue =>
-      _lastKnownRemoteTextEditingValue;
+  TextEditingValue? get currentTextEditingValue => _lastKnownRemoteTextEditingValue;
 
   @override
   AutofillScope? get currentAutofillScope => null;
@@ -474,8 +429,7 @@ class _RawEditorState extends EditorState
     final text = value.text;
     final cursorPosition = value.selection.extentOffset;
     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
@@ -525,11 +479,8 @@ class _RawEditorState extends EditorState
     super.build(context);
 
     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(
@@ -552,8 +503,7 @@ class _RawEditorState extends EditorState
     );
 
     if (widget.scrollable) {
-      final baselinePadding =
-          EdgeInsets.only(top: _styles!.paragraph!.verticalSpacing.item1);
+      final baselinePadding = EdgeInsets.only(top: _styles!.paragraph!.verticalSpacing.item1);
       child = BaselineProxy(
         textStyle: _styles!.paragraph!.style,
         padding: baselinePadding,
@@ -584,8 +534,7 @@ class _RawEditorState extends EditorState
     );
   }
 
-  void _handleSelectionChanged(
-      TextSelection selection, SelectionChangedCause cause) {
+  void _handleSelectionChanged(TextSelection selection, SelectionChangedCause cause) {
     widget.controller.updateSelection(selection, ChangeSource.LOCAL);
 
     _selectionOverlay?.handlesVisible = _shouldShowSelectionHandles();
@@ -614,9 +563,7 @@ class _RawEditorState extends EditorState
             _styles,
             widget.enableInteractiveSelection,
             _hasFocus,
-            attrs.containsKey(Attribute.codeBlock.key)
-                ? const EdgeInsets.all(16)
-                : null,
+            attrs.containsKey(Attribute.codeBlock.key) ? const EdgeInsets.all(16) : null,
             widget.embedBuilder,
             _cursorController,
             indentLevelCounts);
@@ -628,8 +575,7 @@ class _RawEditorState extends EditorState
     return result;
   }
 
-  EditableTextLine _getEditableTextLineFromNode(
-      Line node, BuildContext context) {
+  EditableTextLine _getEditableTextLineFromNode(Line node, BuildContext context) {
     final textLine = TextLine(
       line: node,
       textDirection: _textDirection,
@@ -652,8 +598,7 @@ class _RawEditorState extends EditorState
     return editableTextLine;
   }
 
-  Tuple2<double, double> _getVerticalSpacingForLine(
-      Line line, DefaultStyles? defaultStyles) {
+  Tuple2<double, double> _getVerticalSpacingForLine(Line line, DefaultStyles? defaultStyles) {
     final attrs = line.style.attributes;
     if (attrs.containsKey(Attribute.header.key)) {
       final int? level = attrs[Attribute.header.key]!.value;
@@ -678,8 +623,7 @@ class _RawEditorState extends EditorState
     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;
     if (attrs.containsKey(Attribute.quoteBlock.key)) {
       return defaultStyles!.quote!.verticalSpacing;
@@ -722,8 +666,7 @@ class _RawEditorState extends EditorState
     } else {
       _keyboardVisibilityController = KeyboardVisibilityController();
       _keyboardVisible = _keyboardVisibilityController!.isVisible;
-      _keyboardVisibilitySubscription =
-          _keyboardVisibilityController?.onChange.listen((visible) {
+      _keyboardVisibilitySubscription = _keyboardVisibilityController?.onChange.listen((visible) {
         _keyboardVisible = visible;
         if (visible) {
           _onChangeTextEditingValue();
@@ -746,9 +689,7 @@ class _RawEditorState extends EditorState
     super.didChangeDependencies();
     final parentStyles = EditorStyles.getStyles(context, true);
     final defaultStyles = DefaultStyles.getInstance(context);
-    _styles = (parentStyles != null)
-        ? defaultStyles.merge(parentStyles)
-        : defaultStyles;
+    _styles = (parentStyles != null) ? defaultStyles.merge(parentStyles) : defaultStyles;
 
     if (widget.customStyles != null) {
       _styles = _styles!.merge(widget.customStyles!);
@@ -808,8 +749,7 @@ class _RawEditorState extends EditorState
   }
 
   bool _shouldShowSelectionHandles() {
-    return widget.showSelectionHandles &&
-        !widget.controller.selection.isCollapsed;
+    return widget.showSelectionHandles && !widget.controller.selection.isCollapsed;
   }
 
   void handleDelete(bool forward) {
@@ -820,8 +760,7 @@ class _RawEditorState extends EditorState
     var textAfter = selection.textAfter(plainText);
     if (selection.isCollapsed) {
       if (!forward && textBefore.isNotEmpty) {
-        final characterBoundary =
-            _previousCharacter(textBefore.length, textBefore, true);
+        final characterBoundary = _previousCharacter(textBefore.length, textBefore, true);
         textBefore = textBefore.substring(0, characterBoundary);
         cursorPosition = characterBoundary;
       }
@@ -844,10 +783,16 @@ class _RawEditorState extends EditorState
   Future<void> handleShortcut(InputShortcut? shortcut) async {
     final selection = widget.controller.selection;
     final plainText = textEditingValue.text;
+    if (shortcut == InputShortcut.SAVE) {
+      bool saved = await widget.controller.save();
+      if (!saved) {
+        log('Unabled to save document.');
+      }
+      return;
+    }
     if (shortcut == InputShortcut.COPY) {
       if (!selection.isCollapsed) {
-        await Clipboard.setData(
-            ClipboardData(text: selection.textInside(plainText)));
+        await Clipboard.setData(ClipboardData(text: selection.textInside(plainText)));
       }
       return;
     }
@@ -864,8 +809,7 @@ class _RawEditorState extends EditorState
         );
 
         textEditingValue = TextEditingValue(
-          text:
-              selection.textBefore(plainText) + selection.textAfter(plainText),
+          text: selection.textBefore(plainText) + selection.textAfter(plainText),
           selection: TextSelection.collapsed(offset: selection.start),
         );
       }
@@ -883,8 +827,7 @@ class _RawEditorState extends EditorState
       }
       return;
     }
-    if (shortcut == InputShortcut.SELECT_ALL &&
-        widget.enableInteractiveSelection) {
+    if (shortcut == InputShortcut.SELECT_ALL && widget.enableInteractiveSelection) {
       widget.controller.updateSelection(
           selection.copyWith(
             baseOffset: 0,
@@ -938,16 +881,14 @@ class _RawEditorState extends EditorState
   void _onChangeTextEditingValue() {
     _showCaretOnScreen();
     updateRemoteValueIfNeeded();
-    _cursorController.startOrStopCursorTimerIfNeeded(
-        _hasFocus, widget.controller.selection);
+    _cursorController.startOrStopCursorTimerIfNeeded(_hasFocus, widget.controller.selection);
     if (hasConnection) {
       _cursorController
         ..stopCursorTimer(resetCharTicks: false)
         ..startCursorTimer();
     }
 
-    SchedulerBinding.instance!.addPostFrameCallback(
-        (_) => _updateOrDisposeSelectionOverlayIfNeeded());
+    SchedulerBinding.instance!.addPostFrameCallback((_) => _updateOrDisposeSelectionOverlayIfNeeded());
     if (mounted) {
       setState(() {
         // Use widget.controller.value in build()
@@ -990,8 +931,7 @@ class _RawEditorState extends EditorState
 
   void _handleFocusChanged() {
     openOrCloseConnection();
-    _cursorController.startOrStopCursorTimerIfNeeded(
-        _hasFocus, widget.controller.selection);
+    _cursorController.startOrStopCursorTimerIfNeeded(_hasFocus, widget.controller.selection);
     _updateOrDisposeSelectionOverlayIfNeeded();
     if (_hasFocus) {
       WidgetsBinding.instance!.addObserver(this);
@@ -1022,8 +962,7 @@ class _RawEditorState extends EditorState
       _showCaretOnScreenScheduled = false;
 
       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 offset = getRenderEditor()!.getOffsetToRevealCursor(
@@ -1106,8 +1045,7 @@ class _RawEditorState extends EditorState
       final value = textEditingValue;
       final data = await Clipboard.getData(Clipboard.kTextPlain);
       if (data != null) {
-        final length =
-            textEditingValue.selection.end - textEditingValue.selection.start;
+        final length = textEditingValue.selection.end - textEditingValue.selection.start;
         widget.controller.replaceText(
           value.selection.start,
           length,
@@ -1116,9 +1054,7 @@ class _RawEditorState extends EditorState
         );
         // move cursor to the end of pasted text selection
         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);
       }
     }
   }
@@ -1128,8 +1064,7 @@ class _RawEditorState extends EditorState
     if (data == null) {
       return false;
     }
-    return textEditingValue.text.length - value.text.length ==
-        data.text!.length;
+    return textEditingValue.text.length - value.text.length == data.text!.length;
   }
 
   @override
@@ -1162,8 +1097,7 @@ class _RawEditorState extends EditorState
   }
 
   @override
-  void userUpdateTextEditingValue(
-      TextEditingValue value, SelectionChangedCause cause) {
+  void userUpdateTextEditingValue(TextEditingValue value, SelectionChangedCause cause) {
     // TODO: implement userUpdateTextEditingValue
   }
 }
@@ -1213,8 +1147,7 @@ class _Editor extends MultiChildRenderObjectWidget {
   }
 
   @override
-  void updateRenderObject(
-      BuildContext context, covariant RenderEditor renderObject) {
+  void updateRenderObject(BuildContext context, covariant RenderEditor renderObject) {
     renderObject
       ..document = document
       ..container = document.root

+ 5 - 5
app_flowy/pubspec.lock

@@ -14,7 +14,7 @@ packages:
       name: analyzer
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.7.2"
+    version: "1.7.1"
   animations:
     dependency: transitive
     description:
@@ -35,7 +35,7 @@ packages:
       name: async
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "2.7.0"
+    version: "2.6.1"
   bloc:
     dependency: transitive
     description:
@@ -119,7 +119,7 @@ packages:
       name: charcode
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.3.1"
+    version: "1.2.0"
   checked_yaml:
     dependency: transitive
     description:
@@ -456,7 +456,7 @@ packages:
       name: meta
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.7.0"
+    version: "1.3.0"
   mime:
     dependency: transitive
     description:
@@ -701,7 +701,7 @@ packages:
       name: test_api
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "0.4.1"
+    version: "0.3.0"
   textstyle_extensions:
     dependency: transitive
     description: