Bladeren bron

fix: could not insert link on the Web

Lucas.Xu 2 jaren geleden
bovenliggende
commit
99cb2430f7

+ 32 - 12
frontend/app_flowy/packages/appflowy_editor/lib/src/commands/format_built_in_text.dart

@@ -3,29 +3,25 @@ import 'package:appflowy_editor/src/document/attributes.dart';
 import 'package:appflowy_editor/src/document/built_in_attribute_keys.dart';
 import 'package:appflowy_editor/src/document/node.dart';
 import 'package:appflowy_editor/src/document/path.dart';
+import 'package:appflowy_editor/src/document/selection.dart';
 import 'package:appflowy_editor/src/editor_state.dart';
 
 Future<void> formatBuiltInTextAttributes(
   EditorState editorState,
   String key,
   Attributes attributes, {
+  Selection? selection,
   Path? path,
   TextNode? textNode,
 }) async {
+  final result = getTextNodeToBeFormatted(
+    editorState,
+    path: path,
+    textNode: textNode,
+  );
   if (BuiltInAttributeKey.globalStyleKeys.contains(key)) {
-    assert(!(path != null && textNode != null));
-    assert(!(path == null && textNode == null));
-
-    TextNode formattedTextNode;
-    if (textNode != null) {
-      formattedTextNode = textNode;
-    } else if (path != null) {
-      formattedTextNode = editorState.document.nodeAtPath(path) as TextNode;
-    } else {
-      throw Exception('path and textNode cannot be null at the same time');
-    }
     // remove all the existing style
-    final newAttributes = formattedTextNode.attributes
+    final newAttributes = result.attributes
       ..removeWhere((key, value) {
         if (BuiltInAttributeKey.globalStyleKeys.contains(key)) {
           return true;
@@ -41,6 +37,13 @@ Future<void> formatBuiltInTextAttributes(
       newAttributes,
       textNode: textNode,
     );
+  } else if (BuiltInAttributeKey.partialStyleKeys.contains(key)) {
+    return updateTextNodeDeltaAttributes(
+      editorState,
+      selection,
+      attributes,
+      textNode: textNode,
+    );
   }
 }
 
@@ -60,3 +63,20 @@ Future<void> formatTextToCheckbox(
     textNode: textNode,
   );
 }
+
+Future<void> formatLinkInText(
+  EditorState editorState,
+  String? link, {
+  Path? path,
+  TextNode? textNode,
+}) async {
+  return formatBuiltInTextAttributes(
+    editorState,
+    BuiltInAttributeKey.href,
+    {
+      BuiltInAttributeKey.href: link,
+    },
+    path: path,
+    textNode: textNode,
+  );
+}

+ 80 - 11
frontend/app_flowy/packages/appflowy_editor/lib/src/commands/format_text.dart

@@ -1,6 +1,9 @@
+import 'dart:async';
+
 import 'package:appflowy_editor/src/document/attributes.dart';
 import 'package:appflowy_editor/src/document/node.dart';
 import 'package:appflowy_editor/src/document/path.dart';
+import 'package:appflowy_editor/src/document/selection.dart';
 import 'package:appflowy_editor/src/editor_state.dart';
 import 'package:appflowy_editor/src/operation/transaction_builder.dart';
 import 'package:flutter/widgets.dart';
@@ -11,24 +14,90 @@ Future<void> updateTextNodeAttributes(
   Path? path,
   TextNode? textNode,
 }) async {
+  final result = getTextNodeToBeFormatted(
+    editorState,
+    path: path,
+    textNode: textNode,
+  );
+
+  final completer = Completer<void>();
+
+  TransactionBuilder(editorState)
+    ..updateNode(result, attributes)
+    ..commit();
+
+  WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
+    completer.complete();
+  });
+
+  return completer.future;
+}
+
+Future<void> updateTextNodeDeltaAttributes(
+  EditorState editorState,
+  Selection? selection,
+  Attributes attributes, {
+  Path? path,
+  TextNode? textNode,
+}) {
+  final result = getTextNodeToBeFormatted(
+    editorState,
+    path: path,
+    textNode: textNode,
+  );
+  final newSelection = _getSelection(editorState, selection: selection);
+
+  final completer = Completer<void>();
+
+  TransactionBuilder(editorState)
+    ..formatText(
+      result,
+      newSelection.startIndex,
+      newSelection.length,
+      attributes,
+    )
+    ..commit();
+
+  WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
+    completer.complete();
+  });
+
+  return completer.future;
+}
+
+// get formatted [TextNode]
+TextNode getTextNodeToBeFormatted(
+  EditorState editorState, {
+  Path? path,
+  TextNode? textNode,
+}) {
   assert(!(path != null && textNode != null));
   assert(!(path == null && textNode == null));
 
-  TextNode formattedTextNode;
+  TextNode result;
   if (textNode != null) {
-    formattedTextNode = textNode;
+    result = textNode;
   } else if (path != null) {
-    formattedTextNode = editorState.document.nodeAtPath(path) as TextNode;
+    result = editorState.document.nodeAtPath(path) as TextNode;
   } else {
     throw Exception('path and textNode cannot be null at the same time');
   }
+  return result;
+}
 
-  TransactionBuilder(editorState)
-    ..updateNode(formattedTextNode, attributes)
-    ..commit();
-
-  WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
-    print('AAAAAAAAAAAAAA');
-    return;
-  });
+Selection _getSelection(
+  EditorState editorState, {
+  Selection? selection,
+}) {
+  final currentSelection =
+      editorState.service.selectionService.currentSelection.value;
+  Selection result;
+  if (selection != null) {
+    result = selection;
+  } else if (currentSelection != null) {
+    result = currentSelection;
+  } else {
+    throw Exception('path and textNode cannot be null at the same time');
+  }
+  return result;
 }

+ 4 - 0
frontend/app_flowy/packages/appflowy_editor/lib/src/document/selection.dart

@@ -53,6 +53,10 @@ class Selection {
 
   Selection get reversed => copyWith(start: end, end: start);
 
+  int get startIndex => normalize.start.offset;
+  int get endIndex => normalize.end.offset;
+  int get length => endIndex - startIndex;
+
   Selection collapse({bool atStart = false}) {
     if (atStart) {
       return Selection(start: start, end: start);

+ 2 - 2
frontend/app_flowy/packages/appflowy_editor/lib/src/render/rich_text/checkbox_text.dart

@@ -74,8 +74,8 @@ class _CheckboxNodeWidgetState extends State<CheckboxNodeWidget>
               padding: iconPadding,
               name: check ? 'check' : 'uncheck',
             ),
-            onTap: () {
-              formatTextToCheckbox(
+            onTap: () async {
+              await formatTextToCheckbox(
                 widget.editorState,
                 !check,
                 textNode: widget.textNode,

+ 4 - 5
frontend/app_flowy/packages/appflowy_editor/lib/src/render/toolbar/toolbar_item.dart

@@ -1,4 +1,5 @@
 import 'package:appflowy_editor/appflowy_editor.dart';
+import 'package:appflowy_editor/src/commands/format_built_in_text.dart';
 import 'package:appflowy_editor/src/extensions/url_launcher_extension.dart';
 import 'package:appflowy_editor/src/infra/flowy_svg.dart';
 import 'package:appflowy_editor/src/render/link_menu/link_menu.dart';
@@ -345,11 +346,8 @@ void showLinkMenu(
           onOpenLink: () async {
             await safeLaunchUrl(linkText);
           },
-          onSubmitted: (text) {
-            TransactionBuilder(editorState)
-              ..formatText(
-                  textNode, index, length, {BuiltInAttributeKey.href: text})
-              ..commit();
+          onSubmitted: (text) async {
+            await formatLinkInText(editorState, text, textNode: textNode);
             _dismissLinkMenu();
           },
           onCopyLink: () {
@@ -377,6 +375,7 @@ void showLinkMenu(
   Overlay.of(context)?.insert(_linkMenuOverlay!);
 
   editorState.service.scrollService?.disable();
+  editorState.service.keyboardService?.disable();
   editorState.service.selectionService.currentSelection
       .addListener(_dismissLinkMenu);
 }