Преглед на файлове

fix: node change notifier doesn't work

Lucas.Xu преди 2 години
родител
ревизия
55d46edeaf

+ 2 - 0
frontend/app_flowy/packages/flowy_editor/example/lib/main.dart

@@ -55,6 +55,7 @@ class MyHomePage extends StatefulWidget {
 
 class _MyHomePageState extends State<MyHomePage> {
   late EditorState _editorState;
+  final editorKey = GlobalKey();
   int page = 0;
 
   @override
@@ -116,6 +117,7 @@ class _MyHomePageState extends State<MyHomePage> {
             document: document,
           );
           return FlowyEditor(
+            key: editorKey,
             editorState: _editorState,
             keyEventHandlers: const [],
             customBuilders: {

+ 0 - 2
frontend/app_flowy/packages/flowy_editor/lib/service/editor_service.dart

@@ -12,7 +12,6 @@ import 'package:flowy_editor/render/selection/floating_shortcut_widget.dart';
 import 'package:flowy_editor/service/input_service.dart';
 import 'package:flowy_editor/service/internal_key_event_handlers/arrow_keys_handler.dart';
 import 'package:flowy_editor/service/internal_key_event_handlers/delete_nodes_handler.dart';
-import 'package:flowy_editor/service/internal_key_event_handlers/delete_single_text_node_handler.dart';
 import 'package:flowy_editor/service/internal_key_event_handlers/enter_in_edge_of_text_node_handler.dart';
 import 'package:flowy_editor/service/internal_key_event_handlers/shortcut_handler.dart';
 import 'package:flowy_editor/service/keyboard_service.dart';
@@ -33,7 +32,6 @@ NodeWidgetBuilders defaultBuilders = {
 List<FlowyKeyEventHandler> defaultKeyEventHandler = [
   slashShortcutHandler,
   flowyDeleteNodesHandler,
-  deleteSingleTextNodeHandler,
   arrowKeysHandler,
   enterInEdgeOfTextNodeHandler,
 ];

+ 22 - 0
frontend/app_flowy/packages/flowy_editor/lib/service/input_service.dart

@@ -94,6 +94,7 @@ class _FlowyInputState extends State<FlowyInput>
     // TODO: implement the detail
     for (final delta in deltas) {
       if (delta is TextEditingDeltaInsertion) {
+        _applyInsert(delta);
       } else if (delta is TextEditingDeltaDeletion) {
       } else if (delta is TextEditingDeltaReplacement) {
       } else if (delta is TextEditingDeltaNonTextUpdate) {
@@ -103,6 +104,27 @@ class _FlowyInputState extends State<FlowyInput>
     }
   }
 
+  void _applyInsert(TextEditingDeltaInsertion delta) {
+    final selectionService = _editorState.service.selectionService;
+    final currentSelection = selectionService.currentSelection;
+    if (currentSelection == null) {
+      return;
+    }
+    if (currentSelection.isSingle) {
+      final textNode =
+          selectionService.currentSelectedNodes.value.first as TextNode;
+      TransactionBuilder(_editorState)
+        ..insertText(
+          textNode,
+          delta.insertionOffset,
+          delta.textInserted,
+        )
+        ..commit();
+    } else {
+      // TODO: implement
+    }
+  }
+
   @override
   void close() {
     _textInputConnection?.close();

+ 0 - 69
frontend/app_flowy/packages/flowy_editor/lib/service/internal_key_event_handlers/delete_single_text_node_handler.dart

@@ -1,69 +0,0 @@
-import 'package:flowy_editor/document/node.dart';
-import 'package:flowy_editor/operation/transaction_builder.dart';
-import 'package:flowy_editor/render/selection/selectable.dart';
-import 'package:flowy_editor/service/keyboard_service.dart';
-import 'package:flowy_editor/extensions/object_extensions.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter/services.dart';
-
-// TODO: need to be refactored, just a example code.
-FlowyKeyEventHandler deleteSingleTextNodeHandler = (editorState, event) {
-  if (event.logicalKey != LogicalKeyboardKey.backspace) {
-    return KeyEventResult.ignored;
-  }
-
-  // final selectionNodes = editorState.selectedNodes;
-  // if (selectionNodes.length == 1 && selectionNodes.first is TextNode) {
-  //   final node = selectionNodes.first.unwrapOrNull<TextNode>();
-  //   final selectable = node?.key?.currentState?.unwrapOrNull<Selectable>();
-  //   if (selectable != null) {
-  //     final textSelection = selectable.getCurrentTextSelection();
-  //     if (textSelection != null) {
-  //       if (textSelection.isCollapsed) {
-  //         /// Three cases:
-  //         /// Delete the zero character,
-  //         ///   1. if there is still text node in front of it, then merge them.
-  //         ///   2. if not, just ignore
-  //         /// Delete the non-zero character,
-  //         ///   3. delete the single character.
-  //         if (textSelection.baseOffset == 0) {
-  //           if (node?.previous != null && node?.previous is TextNode) {
-  //             final previous = node!.previous! as TextNode;
-  //             final newTextSelection = TextSelection.collapsed(
-  //                 offset: previous.toRawString().length);
-  //             final selectionService = editorState.service.selectionService;
-  //             final previousSelectable =
-  //                 previous.key?.currentState?.unwrapOrNull<Selectable>();
-  //             final newOfset = previousSelectable
-  //                 ?.getOffsetByTextSelection(newTextSelection);
-  //             if (newOfset != null) {
-  //               // selectionService.updateCursor(newOfset);
-  //             }
-  //             // merge
-  //             TransactionBuilder(editorState)
-  //               ..deleteNode(node)
-  //               ..insertText(
-  //                   previous, previous.toRawString().length, node.toRawString())
-  //               ..commit();
-  //             return KeyEventResult.handled;
-  //           } else {
-  //             return KeyEventResult.ignored;
-  //           }
-  //         } else {
-  //           TransactionBuilder(editorState)
-  //             ..deleteText(node!, textSelection.baseOffset - 1, 1)
-  //             ..commit();
-  //           final newTextSelection =
-  //               TextSelection.collapsed(offset: textSelection.baseOffset - 1);
-  //           final selectionService = editorState.service.selectionService;
-  //           final newOfset =
-  //               selectable.getOffsetByTextSelection(newTextSelection);
-  //           // selectionService.updateCursor(newOfset);
-  //           return KeyEventResult.handled;
-  //         }
-  //       }
-  //     }
-  //   }
-  // }
-  return KeyEventResult.ignored;
-};

+ 30 - 16
frontend/app_flowy/packages/flowy_editor/lib/service/render_plugin_service.dart

@@ -75,10 +75,7 @@ class FlowyRenderPlugin extends FlowyRenderPluginService {
     if (builder != null && builder.nodeValidator(node)) {
       final key = GlobalKey(debugLabel: name);
       node.key = key;
-      return _wrap(
-        builder.build(context),
-        context,
-      );
+      return _autoUpdateNodeWidget(builder, context);
     } else {
       assert(false, 'Could not query the builder with this $name');
       // TODO: return a placeholder widget with tips.
@@ -87,14 +84,14 @@ class FlowyRenderPlugin extends FlowyRenderPluginService {
   }
 
   @override
-  void register(String name, NodeWidgetBuilder<Node> builder) {
+  void register(String name, NodeWidgetBuilder builder) {
     debugPrint('[Plugins] registering $name...');
     _validatePlugin(name);
     _builders[name] = builder;
   }
 
   @override
-  void registerAll(Map<String, NodeWidgetBuilder<Node>> builders) {
+  void registerAll(Map<String, NodeWidgetBuilder> builders) {
     builders.forEach(register);
   }
 
@@ -104,18 +101,35 @@ class FlowyRenderPlugin extends FlowyRenderPluginService {
     _builders.remove(name);
   }
 
-  Widget _wrap(Widget widget, NodeWidgetContext context) {
+  Widget _autoUpdateNodeWidget(
+      NodeWidgetBuilder builder, NodeWidgetContext context) {
+    Widget notifier;
+    if (context.node is TextNode) {
+      notifier = ChangeNotifierProvider.value(
+          value: context.node as TextNode,
+          builder: (_, child) {
+            return Consumer<TextNode>(
+              builder: ((_, value, child) {
+                debugPrint('Text Node is rebuilding...');
+                return builder.build(context);
+              }),
+            );
+          });
+    } else {
+      notifier = ChangeNotifierProvider.value(
+          value: context.node,
+          builder: (_, child) {
+            return Consumer<Node>(
+              builder: ((_, value, child) {
+                debugPrint('Node is rebuilding...');
+                return builder.build(context);
+              }),
+            );
+          });
+    }
     return CompositedTransformTarget(
       link: context.node.layerLink,
-      child: ChangeNotifierProvider<Node>.value(
-        value: context.node,
-        builder: (context, child) => Consumer(
-          builder: ((context, value, child) {
-            debugPrint('Node is rebuilding...');
-            return widget;
-          }),
-        ),
-      ),
+      child: notifier,
     );
   }