Ver código fonte

fix: unable to paste texts contains section or font tag (#3379)

Lucas.Xu 1 ano atrás
pai
commit
5f4e3ecc76

Diferenças do arquivo suprimidas por serem muito extensas
+ 3 - 0
frontend/appflowy_flutter/integration_test/document/document_copy_and_paste_test.dart


+ 1 - 2
frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/actions/option_action.dart

@@ -5,7 +5,6 @@ import 'package:appflowy/workspace/presentation/widgets/pop_up_action.dart';
 import 'package:appflowy_editor/appflowy_editor.dart';
 import 'package:appflowy_popover/appflowy_popover.dart';
 import 'package:easy_localization/easy_localization.dart';
-
 import 'package:flowy_infra/theme_extension.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:flutter/material.dart';
@@ -243,7 +242,7 @@ class ColorOptionAction extends PopoverActionCell {
         }
         final bgColor =
             node.attributes[blockComponentBackgroundColor] as String?;
-        final selectedColor = bgColor?.toColor();
+        final selectedColor = bgColor?.tryToColor();
         // get default background color from themeExtension
         final defaultColor = AFThemeExtension.of(context).calloutBGColor;
         final colors = [

+ 1 - 1
frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/callout/callout_block_component.dart

@@ -139,7 +139,7 @@ class _CalloutBlockComponentWidgetState
   Color get backgroundColor {
     final colorString =
         node.attributes[CalloutBlockKeys.backgroundColor] as String;
-    return colorString.toColor() ?? Colors.transparent;
+    return colorString.tryToColor() ?? Colors.transparent;
   }
 
   // get the emoji of the note block from the node's attributes or default to '📌'

+ 22 - 6
frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/copy_and_paste/custom_paste_command.dart

@@ -43,16 +43,32 @@ CommandShortcutEventHandler _pasteCommandHandler = (editorState) {
     // 3. image
     // 4. plain text
 
+    // try to paste the content in order, if any of them is failed, then try the next one
     if (inAppJson != null && inAppJson.isNotEmpty) {
       await editorState.deleteSelectionIfNeeded();
-      await editorState.pasteInAppJson(inAppJson);
-    } else if (html != null && html.isNotEmpty) {
+      final result = await editorState.pasteInAppJson(inAppJson);
+      if (result) {
+        return;
+      }
+    }
+
+    if (html != null && html.isNotEmpty) {
       await editorState.deleteSelectionIfNeeded();
-      await editorState.pasteHtml(html);
-    } else if (image != null && image.$2?.isNotEmpty == true) {
+      final result = await editorState.pasteHtml(html);
+      if (result) {
+        return;
+      }
+    }
+
+    if (image != null && image.$2?.isNotEmpty == true) {
       await editorState.deleteSelectionIfNeeded();
-      await editorState.pasteImage(image.$1, image.$2!);
-    } else if (plainText != null && plainText.isNotEmpty) {
+      final result = await editorState.pasteImage(image.$1, image.$2!);
+      if (result) {
+        return;
+      }
+    }
+
+    if (plainText != null && plainText.isNotEmpty) {
       await editorState.pastePlainText(plainText);
     }
   }();

+ 4 - 2
frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/copy_and_paste/paste_from_html.dart

@@ -2,7 +2,7 @@ import 'package:appflowy/plugins/document/presentation/editor_plugins/copy_and_p
 import 'package:appflowy_editor/appflowy_editor.dart';
 
 extension PasteFromHtml on EditorState {
-  Future<void> pasteHtml(String html) async {
+  Future<bool> pasteHtml(String html) async {
     final nodes = htmlToDocument(html).root.children.toList();
     // remove the front and back empty line
     while (nodes.isNotEmpty && nodes.first.delta?.isEmpty == true) {
@@ -11,13 +11,15 @@ extension PasteFromHtml on EditorState {
     while (nodes.isNotEmpty && nodes.last.delta?.isEmpty == true) {
       nodes.removeLast();
     }
+    // if there's no nodes being converted successfully, return false
     if (nodes.isEmpty) {
-      return;
+      return false;
     }
     if (nodes.length == 1) {
       await pasteSingleLineNode(nodes.first);
     } else {
       await pasteMultiLineNodes(nodes.toList());
     }
+    return true;
   }
 }

+ 4 - 2
frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/copy_and_paste/paste_from_image.dart

@@ -15,9 +15,9 @@ extension PasteFromImage on EditorState {
     'gif',
   ];
 
-  Future<void> pasteImage(String format, Uint8List imageBytes) async {
+  Future<bool> pasteImage(String format, Uint8List imageBytes) async {
     if (!supportedImageFormats.contains(format)) {
-      return;
+      return false;
     }
 
     final path = await getIt<ApplicationDataStorage>().getPath();
@@ -37,8 +37,10 @@ extension PasteFromImage on EditorState {
       );
       await File(copyToPath).writeAsBytes(imageBytes);
       await insertImageNode(copyToPath);
+      return true;
     } catch (e) {
       Log.error('cannot copy image file', e);
     }
+    return false;
   }
 }

+ 4 - 2
frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/copy_and_paste/paste_from_in_app_json.dart

@@ -5,21 +5,23 @@ import 'package:appflowy_backend/log.dart';
 import 'package:appflowy_editor/appflowy_editor.dart' hide Log;
 
 extension PasteFromInAppJson on EditorState {
-  Future<void> pasteInAppJson(String inAppJson) async {
+  Future<bool> pasteInAppJson(String inAppJson) async {
     try {
       final nodes = Document.fromJson(jsonDecode(inAppJson)).root.children;
       if (nodes.isEmpty) {
-        return;
+        return false;
       }
       if (nodes.length == 1) {
         await pasteSingleLineNode(nodes.first);
       } else {
         await pasteMultiLineNodes(nodes.toList());
       }
+      return true;
     } catch (e) {
       Log.error(
         'Failed to paste in app json: $inAppJson, error: $e',
       );
     }
+    return false;
   }
 }

+ 2 - 3
frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/header/cover_editor.dart

@@ -6,7 +6,6 @@ import 'package:appflowy/generated/locale_keys.g.dart';
 import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart';
 import 'package:appflowy_editor/appflowy_editor.dart';
 import 'package:easy_localization/easy_localization.dart';
-
 import 'package:flowy_infra/size.dart';
 import 'package:flowy_infra/theme_extension.dart';
 import 'package:flowy_infra_ui/style_widget/button.dart';
@@ -536,7 +535,7 @@ class ColorItem extends StatelessWidget {
           dimension: 25,
           child: Container(
             decoration: BoxDecoration(
-              color: option.colorHex.toColor(),
+              color: option.colorHex.tryToColor(),
               shape: BoxShape.circle,
             ),
             child: isChecked
@@ -548,7 +547,7 @@ class ColorItem extends StatelessWidget {
                           color: Theme.of(context).cardColor,
                           width: 3.0,
                         ),
-                        color: option.colorHex.toColor(),
+                        color: option.colorHex.tryToColor(),
                         shape: BoxShape.circle,
                       ),
                     ),

+ 1 - 1
frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/header/document_header_node_widget.dart

@@ -367,7 +367,7 @@ class DocumentCoverState extends State<DocumentCover> {
           fit: BoxFit.cover,
         );
       case CoverType.color:
-        final color = widget.coverDetails?.toColor() ?? Colors.white;
+        final color = widget.coverDetails?.tryToColor() ?? Colors.white;
         return Container(color: color);
       case CoverType.none:
         return const SizedBox.shrink();

+ 1 - 1
frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/outline/outline_block_component.dart

@@ -84,7 +84,7 @@ class _OutlineBlockWidgetState extends State<OutlineBlockWidget>
     if (colorString == null) {
       return Colors.transparent;
     }
-    return colorString.toColor() ?? Colors.transparent;
+    return colorString.tryToColor() ?? Colors.transparent;
   }
 
   late EditorState editorState = context.read<EditorState>();

+ 1 - 1
frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/table/table_option_action.dart

@@ -112,7 +112,7 @@ class TableColorOptionAction extends PopoverActionCell {
             ? TableCellBlockKeys.colBackgroundColor
             : TableCellBlockKeys.rowBackgroundColor;
         final bgColor = cell?.attributes[key] as String?;
-        final selectedColor = bgColor?.toColor();
+        final selectedColor = bgColor?.tryToColor();
         // get default background color from themeExtension
         final defaultColor = AFThemeExtension.of(context).tableCellBGColor;
         final colors = [

+ 2 - 2
frontend/appflowy_flutter/pubspec.lock

@@ -54,8 +54,8 @@ packages:
     dependency: "direct main"
     description:
       path: "."
-      ref: "4a92c88"
-      resolved-ref: "4a92c88b6611af95909e4618be3970cc20f6d930"
+      ref: "6d68f90"
+      resolved-ref: "6d68f9003fa023d215dc5f20e8900f985c2cdaa1"
       url: "https://github.com/AppFlowy-IO/appflowy-editor.git"
     source: git
     version: "1.3.0"

+ 1 - 1
frontend/appflowy_flutter/pubspec.yaml

@@ -48,7 +48,7 @@ dependencies:
   appflowy_editor:
     git:
       url: https://github.com/AppFlowy-IO/appflowy-editor.git
-      ref: 4a92c88
+      ref: 6d68f90
   appflowy_popover:
     path: packages/appflowy_popover
 

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff