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 6d4945f715..6a48f6c5fa 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
@@ -226,6 +226,30 @@ void main() {
);
},
);
+
+ // https://github.com/AppFlowy-IO/AppFlowy/issues/3263
+ testWidgets(
+ 'paste the image from clipboard when html and image are both available',
+ (tester) async {
+ const html =
+ '''
''';
+ final image = await rootBundle.load('assets/test/images/sample.png');
+ final bytes = image.buffer.asUint8List();
+ await tester.pasteContent(
+ html: html,
+ image: ('png', bytes),
+ (editorState) {
+ expect(editorState.document.root.children.length, 2);
+ final node = editorState.getNodeAtPath([0])!;
+ expect(node.type, ImageBlockKeys.type);
+ expect(
+ node.attributes[ImageBlockKeys.url],
+ 'https://user-images.githubusercontent.com/9403740/262918875-603f4adb-58dd-49b5-8201-341d354935fd.png',
+ );
+ },
+ );
+ },
+ );
}
extension on WidgetTester {
diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_page.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_page.dart
index 562784c0ea..a0eb718458 100644
--- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_page.dart
+++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_page.dart
@@ -159,6 +159,7 @@ class _AppFlowyEditorPageState extends State {
// customize the shortcuts
characterShortcutEvents: characterShortcutEvents,
commandShortcutEvents: commandShortcutEvents,
+ contextMenuItems: customContextMenuItems,
header: widget.header,
footer: const VSpace(200),
);
diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/context_menu/custom_context_menu.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/context_menu/custom_context_menu.dart
new file mode 100644
index 0000000000..70aea8bbb5
--- /dev/null
+++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/context_menu/custom_context_menu.dart
@@ -0,0 +1,21 @@
+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';
+
+final List> customContextMenuItems = [
+ [
+ ContextMenuItem(
+ name: LocaleKeys.document_plugins_contextMenu_copy.tr(),
+ onPressed: (editorState) => customCopyCommand.execute(editorState),
+ ),
+ ContextMenuItem(
+ name: LocaleKeys.document_plugins_contextMenu_paste.tr(),
+ onPressed: (editorState) => customPasteCommand.execute(editorState),
+ ),
+ ContextMenuItem(
+ name: LocaleKeys.document_plugins_contextMenu_cut.tr(),
+ onPressed: (editorState) => customCutCommand.execute(editorState),
+ ),
+ ],
+];
diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/copy_and_paste/editor_state_paste_node_extension.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/copy_and_paste/editor_state_paste_node_extension.dart
index 1d72a72e04..369256eb84 100644
--- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/copy_and_paste/editor_state_paste_node_extension.dart
+++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/copy_and_paste/editor_state_paste_node_extension.dart
@@ -17,15 +17,7 @@ extension PasteNodes on EditorState {
if (delta.isEmpty) {
transaction.insertNode(
selection.end.path.next,
- insertedDelta == null
- ? node.copyWith(
- type: node.type,
- attributes: {
- ...node.attributes,
- ...insertedNode.attributes,
- },
- )
- : insertedNode,
+ insertedNode,
);
transaction.deleteNode(node);
final path = calculatePath(selection.end.path, [insertedNode]);
diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/plugins.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/plugins.dart
index cfa32a363a..f1218e3f95 100644
--- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/plugins.dart
+++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/plugins.dart
@@ -3,6 +3,7 @@ export 'actions/option_action.dart';
export 'callout/callout_block_component.dart';
export 'code_block/code_block_component.dart';
export 'code_block/code_block_shortcut_event.dart';
+export 'context_menu/custom_context_menu.dart';
export 'copy_and_paste/custom_copy_command.dart';
export 'copy_and_paste/custom_cut_command.dart';
export 'copy_and_paste/custom_paste_command.dart';
diff --git a/frontend/appflowy_flutter/pubspec.lock b/frontend/appflowy_flutter/pubspec.lock
index 00c4a1f6b8..7cdbf463ed 100644
--- a/frontend/appflowy_flutter/pubspec.lock
+++ b/frontend/appflowy_flutter/pubspec.lock
@@ -54,8 +54,8 @@ packages:
dependency: "direct main"
description:
path: "."
- ref: f4db21c
- resolved-ref: f4db21c3678290d133ae6cffa015d3d79920bf84
+ ref: "28c5adf"
+ resolved-ref: "28c5adf0f94c22e74a260c8a0bf5b20cb6e5a12d"
url: "https://github.com/AppFlowy-IO/appflowy-editor.git"
source: git
version: "1.2.3"
diff --git a/frontend/appflowy_flutter/pubspec.yaml b/frontend/appflowy_flutter/pubspec.yaml
index c7453ab9b1..515090bc81 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: f4db21c
+ ref: 28c5adf
appflowy_popover:
path: packages/appflowy_popover
diff --git a/frontend/resources/translations/en.json b/frontend/resources/translations/en.json
index d6f31cc476..3e02821916 100644
--- a/frontend/resources/translations/en.json
+++ b/frontend/resources/translations/en.json
@@ -548,6 +548,11 @@
},
"outline": {
"addHeadingToCreateOutline": "Add headings to create a table of contents."
+ },
+ "contextMenu": {
+ "copy": "Copy",
+ "cut": "Cut",
+ "paste": "Paste"
}
},
"textBlock": {