Przeglądaj źródła

feat: implement auto focus

Lucas.Xu 2 lat temu
rodzic
commit
8afd6a6f1f

+ 1 - 0
frontend/app_flowy/lib/plugins/doc/document_page.dart

@@ -96,6 +96,7 @@ class _DocumentPageState extends State<DocumentPage> {
     final theme = Theme.of(context);
     final editor = AppFlowyEditor(
       editorState: editorState,
+      autoFocus: editorState.document.isEmpty,
       customBuilders: {
         'horizontal_rule': HorizontalRuleWidgetBuilder(),
       },

+ 1 - 0
frontend/app_flowy/packages/appflowy_editor/example/lib/main.dart

@@ -152,6 +152,7 @@ class _MyHomePageState extends State<MyHomePage> {
               editorState: _editorState!,
               themeData: themeData,
               editable: true,
+              autoFocus: _editorState!.document.isEmpty,
               customBuilders: {
                 'text/code_block': CodeBlockNodeWidgetBuilder(),
                 'tex': TeXBlockNodeWidgetBuidler(),

+ 14 - 0
frontend/app_flowy/packages/appflowy_editor/lib/src/core/document/document.dart

@@ -110,6 +110,20 @@ class Document {
     return true;
   }
 
+  bool get isEmpty {
+    if (root.children.isEmpty) {
+      return true;
+    }
+
+    final node = root.children.first;
+    if (node is TextNode &&
+        (node.delta.isEmpty || node.delta.toPlainText().isEmpty)) {
+      return true;
+    }
+
+    return false;
+  }
+
   Map<String, Object> toJson() {
     return {
       'document': root.toJson(),

+ 13 - 0
frontend/app_flowy/packages/appflowy_editor/lib/src/service/editor_service.dart

@@ -31,6 +31,7 @@ class AppFlowyEditor extends StatefulWidget {
     this.shortcutEvents = const [],
     this.selectionMenuItems = const [],
     this.editable = true,
+    this.autoFocus = false,
     ThemeData? themeData,
   }) : super(key: key) {
     this.themeData = themeData ??
@@ -54,6 +55,9 @@ class AppFlowyEditor extends StatefulWidget {
 
   final bool editable;
 
+  /// Set the value to true to focus the editor on the start of the document.
+  final bool autoFocus;
+
   @override
   State<AppFlowyEditor> createState() => _AppFlowyEditorState();
 }
@@ -73,6 +77,15 @@ class _AppFlowyEditorState extends State<AppFlowyEditor> {
     editorState.themeData = widget.themeData;
     editorState.service.renderPluginService = _createRenderPlugin();
     editorState.editable = widget.editable;
+
+    // auto focus
+    WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
+      if (widget.editable && widget.autoFocus) {
+        editorState.service.selectionService.updateSelection(
+          Selection.single(path: [0], startOffset: 0),
+        );
+      }
+    });
   }
 
   @override

+ 61 - 0
frontend/app_flowy/packages/appflowy_editor/test/core/document/document_test.dart

@@ -73,5 +73,66 @@ void main() async {
       final document = Document.fromJson(json);
       expect(document.toJson(), json);
     });
+
+    test('isEmpty', () {
+      expect(
+        true,
+        Document.fromJson({
+          'document': {
+            'type': 'editor',
+            'children': [
+              {
+                'type': 'text',
+                'delta': [],
+              }
+            ],
+          }
+        }).isEmpty,
+      );
+
+      expect(
+        true,
+        Document.fromJson({
+          'document': {
+            'type': 'editor',
+            'children': [],
+          }
+        }).isEmpty,
+      );
+
+      expect(
+        true,
+        Document.fromJson({
+          'document': {
+            'type': 'editor',
+            'children': [
+              {
+                'type': 'text',
+                'delta': [
+                  {'insert': ''}
+                ],
+              }
+            ],
+          }
+        }).isEmpty,
+      );
+
+      expect(
+        false,
+        Document.fromJson({
+          'document': {
+            'type': 'editor',
+            'children': [
+              {
+                'type': 'text',
+                'delta': [
+                  {'insert': 'Welcome to AppFlowy!'}
+                ],
+              }
+            ],
+          }
+        }).isEmpty,
+      );
+    });
   });
 }