From 8833df1740f0b161a9714ba586a0ac5db2036830 Mon Sep 17 00:00:00 2001 From: "Lucas.Xu" Date: Thu, 11 Jul 2024 21:42:02 +0800 Subject: [PATCH] fix: ai chat result contains html escape text (#5721) * fix: ai chat result contains html escape text * feat: support copy the code block from ai chat page * feat: support copy code block from ai chat page * fix: add hover effect to color picker button * chore: increase minimum window size --- .../presentation/ai_message_bubble.dart | 4 ++-- .../message/ai_markdown_text.dart | 8 ++----- .../code_block/code_block_copy_button.dart | 21 +++++++++++++---- .../copy_and_paste/custom_paste_command.dart | 4 ++-- .../parsers/markdown_code_parser.dart | 4 +--- .../lib/shared/markdown_to_document.dart | 11 +++++++++ .../tasks/app_window_size_manager.dart | 4 ++-- .../menu/sidebar/import/import_panel.dart | 10 ++------ .../shared/document_color_setting_button.dart | 23 +++++++++++++------ frontend/appflowy_flutter/pubspec.lock | 4 ++-- frontend/appflowy_flutter/pubspec.yaml | 2 +- 11 files changed, 57 insertions(+), 38 deletions(-) create mode 100644 frontend/appflowy_flutter/lib/shared/markdown_to_document.dart diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/ai_message_bubble.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/ai_message_bubble.dart index 61788a650f..afea319d10 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/ai_message_bubble.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/ai_message_bubble.dart @@ -7,10 +7,10 @@ import 'package:appflowy/plugins/ai_chat/presentation/chat_avatar.dart'; import 'package:appflowy/plugins/ai_chat/presentation/chat_input.dart'; import 'package:appflowy/plugins/ai_chat/presentation/chat_popmenu.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/copy_and_paste/clipboard_service.dart'; +import 'package:appflowy/shared/markdown_to_document.dart'; import 'package:appflowy/startup/startup.dart'; import 'package:appflowy/workspace/presentation/home/toast.dart'; import 'package:appflowy/workspace/presentation/widgets/dialogs.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'; @@ -183,7 +183,7 @@ class CopyButton extends StatelessWidget { color: Theme.of(context).colorScheme.primary, ), onPressed: () async { - final document = markdownToDocument(textMessage.text); + final document = customMarkdownToDocument(textMessage.text); await getIt().setData( ClipboardServiceData( plainText: textMessage.text, diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/message/ai_markdown_text.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/message/ai_markdown_text.dart index 59f89ad3a3..2d816bb5db 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/message/ai_markdown_text.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/message/ai_markdown_text.dart @@ -1,6 +1,7 @@ import 'package:appflowy/plugins/document/presentation/editor_configuration.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart'; import 'package:appflowy/plugins/document/presentation/editor_style.dart'; +import 'package:appflowy/shared/markdown_to_document.dart'; import 'package:appflowy/util/theme_extension.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:flowy_infra/theme_extension.dart'; @@ -120,12 +121,7 @@ class _AppFlowyEditorMarkdownState extends State<_AppFlowyEditorMarkdown> { } EditorState _parseMarkdown(String markdown) { - final document = markdownToDocument( - markdown, - markdownParsers: [ - const MarkdownCodeBlockParser(), - ], - ); + final document = customMarkdownToDocument(markdown); final editorState = EditorState(document: document); return editorState; } diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/code_block/code_block_copy_button.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/code_block/code_block_copy_button.dart index 9c6ff01bf9..d2b1c48fa2 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/code_block/code_block_copy_button.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/code_block/code_block_copy_button.dart @@ -1,16 +1,17 @@ -import 'package:flutter/material.dart'; +import 'dart:convert'; import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/copy_and_paste/clipboard_service.dart'; import 'package:appflowy/startup/startup.dart'; -import 'package:appflowy/workspace/presentation/home/toast.dart'; +import 'package:appflowy/workspace/presentation/widgets/dialogs.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:appflowy_editor_plugins/appflowy_editor_plugins.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/theme_extension.dart'; import 'package:flowy_infra_ui/style_widget/icon_button.dart'; import 'package:flowy_infra_ui/widget/flowy_tooltip.dart'; +import 'package:flutter/material.dart'; CodeBlockCopyBuilder codeBlockCopyBuilder = (_, node) => _CopyButton(node: node); @@ -28,16 +29,26 @@ class _CopyButton extends StatelessWidget { message: LocaleKeys.document_codeBlock_copyTooltip.tr(), child: FlowyIconButton( onPressed: () async { + final delta = node.delta; + if (delta == null) { + return; + } + + final document = Document.blank() + ..insert([0], [node.copyWith()]) + ..toJson(); + await getIt().setData( ClipboardServiceData( - plainText: node.delta?.toPlainText(), + plainText: delta.toPlainText(), + inAppJson: jsonEncode(document.toJson()), ), ); if (context.mounted) { - showSnackBarMessage( + showToastNotification( context, - LocaleKeys.document_codeBlock_codeCopiedSnackbar.tr(), + message: LocaleKeys.document_codeBlock_codeCopiedSnackbar.tr(), ); } }, 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 53812fbfe4..ff0957a318 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 @@ -1,5 +1,3 @@ -import 'package:flutter/material.dart'; - import 'package:appflowy/plugins/document/application/document_bloc.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/copy_and_paste/clipboard_service.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/copy_and_paste/editor_state_paste_node_extension.dart'; @@ -10,6 +8,7 @@ import 'package:appflowy/plugins/document/presentation/editor_plugins/copy_and_p import 'package:appflowy/startup/startup.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:appflowy_editor_plugins/appflowy_editor_plugins.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:string_validator/string_validator.dart'; @@ -54,6 +53,7 @@ CommandShortcutEventHandler _pasteCommandHandler = (editorState) { // try to paste the content in order, if any of them is failed, then try the next one if (inAppJson != null && inAppJson.isNotEmpty) { + debugPrint('paste in app json: $inAppJson'); await editorState.deleteSelectionIfNeeded(); if (await editorState.pasteInAppJson(inAppJson)) { return; diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/parsers/markdown_code_parser.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/parsers/markdown_code_parser.dart index 4033db3142..d756c25d6b 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/parsers/markdown_code_parser.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/parsers/markdown_code_parser.dart @@ -40,12 +40,10 @@ class MarkdownCodeBlockParser extends CustomMarkdownParser { language = languageClass.substring('language-'.length); } - final deltaDecoder = DeltaMarkdownDecoder(); - return [ codeBlockNode( language: language, - delta: deltaDecoder.convertNodes(code.children), + delta: Delta()..insert(code.textContent.trimRight()), ), ]; } diff --git a/frontend/appflowy_flutter/lib/shared/markdown_to_document.dart b/frontend/appflowy_flutter/lib/shared/markdown_to_document.dart new file mode 100644 index 0000000000..9a000e9e3c --- /dev/null +++ b/frontend/appflowy_flutter/lib/shared/markdown_to_document.dart @@ -0,0 +1,11 @@ +import 'package:appflowy/plugins/document/presentation/editor_plugins/parsers/markdown_code_parser.dart'; +import 'package:appflowy_editor/appflowy_editor.dart'; + +Document customMarkdownToDocument(String markdown) { + return markdownToDocument( + markdown, + markdownParsers: [ + const MarkdownCodeBlockParser(), + ], + ); +} diff --git a/frontend/appflowy_flutter/lib/startup/tasks/app_window_size_manager.dart b/frontend/appflowy_flutter/lib/startup/tasks/app_window_size_manager.dart index a783e835a2..c0a683df0d 100644 --- a/frontend/appflowy_flutter/lib/startup/tasks/app_window_size_manager.dart +++ b/frontend/appflowy_flutter/lib/startup/tasks/app_window_size_manager.dart @@ -6,8 +6,8 @@ import 'package:appflowy/core/config/kv_keys.dart'; import 'package:appflowy/startup/startup.dart'; class WindowSizeManager { - static const double minWindowHeight = 600.0; - static const double minWindowWidth = 800.0; + static const double minWindowHeight = 640.0; + static const double minWindowWidth = 960.0; // Preventing failed assertion due to Texture Descriptor Validation static const double maxWindowHeight = 8192.0; static const double maxWindowWidth = 8192.0; diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/import/import_panel.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/import/import_panel.dart index 5ab9d56cdc..9bda8ff288 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/import/import_panel.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/import/import_panel.dart @@ -4,12 +4,11 @@ import 'dart:io'; import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/plugins/document/application/document_data_pb_extension.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/migration/editor_migration.dart'; -import 'package:appflowy/plugins/document/presentation/editor_plugins/parsers/markdown_code_parser.dart'; +import 'package:appflowy/shared/markdown_to_document.dart'; import 'package:appflowy/startup/startup.dart'; import 'package:appflowy/workspace/application/settings/share/import_service.dart'; import 'package:appflowy/workspace/presentation/home/menu/sidebar/import/import_type.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/protobuf.dart'; -import 'package:appflowy_editor/appflowy_editor.dart' hide Log; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/file_picker/file_picker_service.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; @@ -221,12 +220,7 @@ class _ImportPanelState extends State { Uint8List? _documentDataFrom(ImportType importType, String data) { switch (importType) { case ImportType.markdownOrText: - final document = markdownToDocument( - data, - markdownParsers: [ - const MarkdownCodeBlockParser(), - ], - ); + final document = customMarkdownToDocument(data); return DocumentDataPBFromTo.fromDocument(document)?.writeToBuffer(); case ImportType.historyDocument: final document = EditorMigration.migrateDocument(data); diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/settings/shared/document_color_setting_button.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/shared/document_color_setting_button.dart index 04e959470a..6e052b84a8 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/settings/shared/document_color_setting_button.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/settings/shared/document_color_setting_button.dart @@ -1,3 +1,4 @@ +import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/util/color_to_hex_string.dart'; import 'package:appflowy/workspace/presentation/settings/shared/settings_alert_dialog.dart'; @@ -137,13 +138,19 @@ class DocumentColorSettingDialogState onChanged: (_) => _updateSelectedColor(), onFieldSubmitted: (_) => _updateSelectedColor(), validator: (v) => validateHexValue(v, opacityController.text), - suffixIcon: GestureDetector( - onTap: () => _showColorPickerDialog( - context: context, - currentColor: widget.currentColor, - updateColor: _updateColor, + suffixIcon: Padding( + padding: const EdgeInsets.all(6.0), + child: FlowyIconButton( + onPressed: () => _showColorPickerDialog( + context: context, + currentColor: widget.currentColor, + updateColor: _updateColor, + ), + icon: const FlowySvg( + FlowySvgs.m_aa_color_s, + size: Size.square(20), + ), ), - child: const Icon(Icons.color_lens_rounded), ), ), const VSpace(8), @@ -378,7 +385,9 @@ void _showColorPickerDialog({ barrierColor: const Color.fromARGB(128, 0, 0, 0), builder: (context) { return AlertDialog( - icon: const Icon(Icons.palette), + icon: const FlowySvg( + FlowySvgs.m_aa_color_s, + ), title: Text( title ?? LocaleKeys.settings_appearance_documentSettings_pickColor.tr(), diff --git a/frontend/appflowy_flutter/pubspec.lock b/frontend/appflowy_flutter/pubspec.lock index bd056d1491..26ea4eca22 100644 --- a/frontend/appflowy_flutter/pubspec.lock +++ b/frontend/appflowy_flutter/pubspec.lock @@ -53,8 +53,8 @@ packages: dependency: "direct main" description: path: "." - ref: d2d9873 - resolved-ref: d2d987312d3a667336c7e12c36da7dbbb62d66db + ref: e0d673a + resolved-ref: e0d673afbbbcaf9df0276f7e0b6405d8f6e98112 url: "https://github.com/AppFlowy-IO/appflowy-editor.git" source: git version: "3.1.0" diff --git a/frontend/appflowy_flutter/pubspec.yaml b/frontend/appflowy_flutter/pubspec.yaml index 9ce3e32526..ea740c283c 100644 --- a/frontend/appflowy_flutter/pubspec.yaml +++ b/frontend/appflowy_flutter/pubspec.yaml @@ -189,7 +189,7 @@ dependency_overrides: appflowy_editor: git: url: https://github.com/AppFlowy-IO/appflowy-editor.git - ref: "d2d9873" + ref: "e0d673a" appflowy_editor_plugins: git: