From 255f30590f7367b4c6097771cc959310d740a2e5 Mon Sep 17 00:00:00 2001 From: "Lucas.Xu" Date: Thu, 24 Aug 2023 19:25:05 +0800 Subject: [PATCH] feat: add custom context menu items for copy, cut, and paste commands --- .../document_copy_and_paste_test.dart | 24 +++++++++++++++++++ .../document/presentation/editor_page.dart | 1 + .../context_menu/custom_context_menu.dart | 21 ++++++++++++++++ .../editor_state_paste_node_extension.dart | 10 +------- .../presentation/editor_plugins/plugins.dart | 1 + frontend/appflowy_flutter/pubspec.lock | 4 ++-- frontend/appflowy_flutter/pubspec.yaml | 2 +- frontend/resources/translations/en.json | 5 ++++ 8 files changed, 56 insertions(+), 12 deletions(-) create mode 100644 frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/context_menu/custom_context_menu.dart 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 = + '''image'''; + 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": {