diff --git a/frontend/appflowy_flutter/integration_test/document/document_copy_and_paste_test.dart b/frontend/appflowy_flutter/integration_test/document/document_copy_and_paste_test.dart
index 6a48f6c5fa..c4c3484192 100644
--- a/frontend/appflowy_flutter/integration_test/document/document_copy_and_paste_test.dart
+++ b/frontend/appflowy_flutter/integration_test/document/document_copy_and_paste_test.dart
@@ -250,6 +250,32 @@ void main() {
);
},
);
+
+ testWidgets('paste the html content contains section', (tester) async {
+ const html =
+ '''''';
+ await tester.pasteContent(
+ html: html,
+ (editorState) {
+ expect(editorState.document.root.children.length, 2);
+ final node1 = editorState.getNodeAtPath([0])!;
+ final node2 = editorState.getNodeAtPath([1])!;
+ expect(node1.type, ParagraphBlockKeys.type);
+ expect(node2.type, ParagraphBlockKeys.type);
+ },
+ );
+ });
+
+ testWidgets('paste the html from google translation', (tester) async {
+ const html =
+ '''Assessment focus: potential motivations, empathy➢Personality characteristics and potential motivations:-Reflection of self-worth-Have a unique definition of success-Be true to your own lifestyle''';
+ await tester.pasteContent(
+ html: html,
+ (editorState) {
+ expect(editorState.document.root.children.length, 8);
+ },
+ );
+ });
}
extension on WidgetTester {
diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/actions/option_action.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/actions/option_action.dart
index 13aa48412e..71a785df12 100644
--- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/actions/option_action.dart
+++ b/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 = [
diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/callout/callout_block_component.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/callout/callout_block_component.dart
index a074681707..0d0f4c0a6f 100644
--- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/callout/callout_block_component.dart
+++ b/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 '📌'
diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/copy_and_paste/custom_paste_command.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/copy_and_paste/custom_paste_command.dart
index 4b6d402dd0..19dc9d4486 100644
--- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/copy_and_paste/custom_paste_command.dart
+++ b/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);
}
}();
diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/copy_and_paste/paste_from_html.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/copy_and_paste/paste_from_html.dart
index cddc26b1c6..e30bcf8a5d 100644
--- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/copy_and_paste/paste_from_html.dart
+++ b/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 pasteHtml(String html) async {
+ Future 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;
}
}
diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/copy_and_paste/paste_from_image.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/copy_and_paste/paste_from_image.dart
index c926591c95..5d0919b18c 100644
--- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/copy_and_paste/paste_from_image.dart
+++ b/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 pasteImage(String format, Uint8List imageBytes) async {
+ Future pasteImage(String format, Uint8List imageBytes) async {
if (!supportedImageFormats.contains(format)) {
- return;
+ return false;
}
final path = await getIt().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;
}
}
diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/copy_and_paste/paste_from_in_app_json.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/copy_and_paste/paste_from_in_app_json.dart
index c36114ee4b..4cc17d599b 100644
--- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/copy_and_paste/paste_from_in_app_json.dart
+++ b/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 pasteInAppJson(String inAppJson) async {
+ Future 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;
}
}
diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/header/cover_editor.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/header/cover_editor.dart
index e00f8c56c7..d3d68fae9a 100644
--- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/header/cover_editor.dart
+++ b/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,
),
),
diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/header/document_header_node_widget.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/header/document_header_node_widget.dart
index 7d420e9b0b..adaca3c844 100644
--- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/header/document_header_node_widget.dart
+++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/header/document_header_node_widget.dart
@@ -367,7 +367,7 @@ class DocumentCoverState extends State {
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();
diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/outline/outline_block_component.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/outline/outline_block_component.dart
index d168e1b4a5..b1ad9e172e 100644
--- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/outline/outline_block_component.dart
+++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/outline/outline_block_component.dart
@@ -84,7 +84,7 @@ class _OutlineBlockWidgetState extends State
if (colorString == null) {
return Colors.transparent;
}
- return colorString.toColor() ?? Colors.transparent;
+ return colorString.tryToColor() ?? Colors.transparent;
}
late EditorState editorState = context.read();
diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/table/table_option_action.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/table/table_option_action.dart
index 3b08a65435..e3f0d4ca4a 100644
--- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/table/table_option_action.dart
+++ b/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 = [
diff --git a/frontend/appflowy_flutter/pubspec.lock b/frontend/appflowy_flutter/pubspec.lock
index cf76ec647f..b35303d219 100644
--- a/frontend/appflowy_flutter/pubspec.lock
+++ b/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"
diff --git a/frontend/appflowy_flutter/pubspec.yaml b/frontend/appflowy_flutter/pubspec.yaml
index c4e08f9df4..ce2e7e1152 100644
--- a/frontend/appflowy_flutter/pubspec.yaml
+++ b/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