From 81f492a1025c712f16cef28cf375072800e44f44 Mon Sep 17 00:00:00 2001 From: dab246 Date: Fri, 12 Jul 2024 17:46:58 +0700 Subject: [PATCH 1/2] TF-2989 Fix drag and drop text within composer is broken --- .../presentation/composer_controller.dart | 34 ++- .../presentation/composer_view_web.dart | 250 +++++++++--------- .../view/web/web_editor_view.dart | 4 +- .../widgets/web/web_editor_widget.dart | 7 +- 4 files changed, 162 insertions(+), 133 deletions(-) diff --git a/lib/features/composer/presentation/composer_controller.dart b/lib/features/composer/presentation/composer_controller.dart index 29db9ba951..5f702e4a97 100644 --- a/lib/features/composer/presentation/composer_controller.dart +++ b/lib/features/composer/presentation/composer_controller.dart @@ -385,22 +385,42 @@ class ComposerController extends BaseController with DragDropFileMixin implement }); _subscriptionOnDragEnter = html.window.onDragEnter.listen((event) { - mailboxDashBoardController.localFileDraggableAppState.value = DraggableAppState.active; + event.preventDefault(); + + if (_validateFilesTransfer(event.dataTransfer.types)) { + mailboxDashBoardController.localFileDraggableAppState.value = DraggableAppState.active; + } }); _subscriptionOnDragOver = html.window.onDragOver.listen((event) { - mailboxDashBoardController.localFileDraggableAppState.value = DraggableAppState.active; + event.preventDefault(); + + if (_validateFilesTransfer(event.dataTransfer.types)) { + mailboxDashBoardController.localFileDraggableAppState.value = DraggableAppState.active; + } }); _subscriptionOnDragLeave = html.window.onDragLeave.listen((event) { - mailboxDashBoardController.localFileDraggableAppState.value = DraggableAppState.inActive; + event.preventDefault(); + + if (_validateFilesTransfer(event.dataTransfer.types)) { + mailboxDashBoardController.localFileDraggableAppState.value = DraggableAppState.inActive; + } }); _subscriptionOnDrop = html.window.onDrop.listen((event) { - mailboxDashBoardController.localFileDraggableAppState.value = DraggableAppState.inActive; + event.preventDefault(); + + if (_validateFilesTransfer(event.dataTransfer.types)) { + mailboxDashBoardController.localFileDraggableAppState.value = DraggableAppState.inActive; + } }); } + bool _validateFilesTransfer(List? types) { + return types?.any((type) => type == 'Files') ?? false; + } + Future _saveComposerCacheOnWebAction() async { _autoCreateEmailTag(); @@ -2091,8 +2111,10 @@ class ComposerController extends BaseController with DragDropFileMixin implement } } - void handleOnDragEnterHtmlEditorWeb() { - mailboxDashBoardController.localFileDraggableAppState.value = DraggableAppState.active; + void handleOnDragEnterHtmlEditorWeb(List? types) { + if (_validateFilesTransfer(types)) { + mailboxDashBoardController.localFileDraggableAppState.value = DraggableAppState.active; + } } void onLocalFileDropZoneListener({ diff --git a/lib/features/composer/presentation/composer_view_web.dart b/lib/features/composer/presentation/composer_view_web.dart index e6984d39b6..943356f8cb 100644 --- a/lib/features/composer/presentation/composer_view_web.dart +++ b/lib/features/composer/presentation/composer_view_web.dart @@ -653,133 +653,139 @@ class ComposerView extends GetWidget { ), Expanded( child: LayoutBuilder( - builder: (context, constraintsEditor) { - return Container( - decoration: const BoxDecoration( - border: Border( - bottom: BorderSide( - color: ComposerStyle.borderColor, - width: 1 - ) - ), - color: ComposerStyle.backgroundEditorColor - ), - child: Stack( - children: [ - Column( - children: [ - Expanded( - child: Padding( - padding: ComposerStyle.tabletEditorPadding, - child: Obx(() => WebEditorView( - editorController: controller.richTextWebController!.editorController, - arguments: controller.composerArguments.value, - contentViewState: controller.emailContentsViewState.value, - currentWebContent: controller.textEditorWeb, - onInitial: controller.handleInitHtmlEditorWeb, - onChangeContent: controller.onChangeTextEditorWeb, - onFocus: controller.handleOnFocusHtmlEditorWeb, - onMouseDown: controller.handleOnMouseDownHtmlEditorWeb, - onEditorSettings: controller.richTextWebController!.onEditorSettingsChange, - onEditorTextSizeChanged: controller.richTextWebController!.onEditorTextSizeChanged, - width: constraints.maxWidth, - height: constraints.maxHeight, - onDragEnter: controller.handleOnDragEnterHtmlEditorWeb, - )), - ), - ), - Obx(() { - if (controller.uploadController.listUploadAttachments.isNotEmpty) { - return AttachmentComposerWidget( - listFileUploaded: controller.uploadController.listUploadAttachments, - isCollapsed: controller.isAttachmentCollapsed, - onDeleteAttachmentAction: controller.deleteAttachmentUploaded, - onToggleExpandAttachmentAction: (isCollapsed) => controller.isAttachmentCollapsed = isCollapsed, - ); - } else { - return const SizedBox.shrink(); - } - }), - Obx(() { - if (controller.richTextWebController!.isFormattingOptionsEnabled) { - return ToolbarRichTextWebBuilder( - richTextWebController: controller.richTextWebController!, - padding: ComposerStyle.richToolbarPadding, - decoration: const BoxDecoration( - color: ComposerStyle.richToolbarColor, - boxShadow: ComposerStyle.richToolbarShadow - ), - ); - } else { - return const SizedBox.shrink(); - } - }) - ], - ), - Align( - alignment: AlignmentDirectional.topCenter, - child: Obx(() => InsertImageLoadingBarWidget( - uploadInlineViewState: controller.uploadController.uploadInlineViewState.value, - viewState: controller.viewState.value, - padding: ComposerStyle.insertImageLoadingBarPadding, - )), - ), - Obx(() { - if (controller.mailboxDashBoardController.isAttachmentDraggableAppActive) { - return Positioned.fill( - child: PointerInterceptor( - child: AttachmentDropZoneWidget( - imagePaths: controller.imagePaths, - width: constraintsEditor.maxWidth, - height: constraintsEditor.maxHeight, - onAttachmentDropZoneListener: controller.onAttachmentDropZoneListener, - ) + builder: (context, constraintsBody) { + return Stack( + children: [ + Column( + children: [ + Expanded( + child: Container( + decoration: const BoxDecoration( + border: Border( + bottom: BorderSide( + color: ComposerStyle.borderColor, + width: 1 + ) + ), + color: ComposerStyle.backgroundEditorColor ), - ); - } else { - return const SizedBox.shrink(); - } - }), - Obx(() { - if (controller.mailboxDashBoardController.isLocalFileDraggableAppActive) { - return Positioned.fill( - child: PointerInterceptor( - child: LocalFileDropZoneWidget( - imagePaths: controller.imagePaths, - width: constraintsEditor.maxWidth, - height: constraintsEditor.maxHeight, - onLocalFileDropZoneListener: (details) => - controller.onLocalFileDropZoneListener( - context: context, - details: details, - maxWidth: constraintsEditor.maxWidth, + child: Column( + children: [ + Expanded( + child: Padding( + padding: ComposerStyle.tabletEditorPadding, + child: Obx(() => WebEditorView( + editorController: controller.richTextWebController!.editorController, + arguments: controller.composerArguments.value, + contentViewState: controller.emailContentsViewState.value, + currentWebContent: controller.textEditorWeb, + onInitial: controller.handleInitHtmlEditorWeb, + onChangeContent: controller.onChangeTextEditorWeb, + onFocus: controller.handleOnFocusHtmlEditorWeb, + onMouseDown: controller.handleOnMouseDownHtmlEditorWeb, + onEditorSettings: controller.richTextWebController!.onEditorSettingsChange, + onEditorTextSizeChanged: controller.richTextWebController!.onEditorTextSizeChanged, + width: constraints.maxWidth, + height: constraints.maxHeight, + onDragEnter: controller.handleOnDragEnterHtmlEditorWeb, + )), ), - ) + ), + Obx(() { + if (controller.uploadController.listUploadAttachments.isNotEmpty) { + return AttachmentComposerWidget( + listFileUploaded: controller.uploadController.listUploadAttachments, + isCollapsed: controller.isAttachmentCollapsed, + onDeleteAttachmentAction: controller.deleteAttachmentUploaded, + onToggleExpandAttachmentAction: (isCollapsed) => controller.isAttachmentCollapsed = isCollapsed, + ); + } else { + return const SizedBox.shrink(); + } + }), + Obx(() { + if (controller.richTextWebController!.isFormattingOptionsEnabled) { + return ToolbarRichTextWebBuilder( + richTextWebController: controller.richTextWebController!, + padding: ComposerStyle.richToolbarPadding, + decoration: const BoxDecoration( + color: ComposerStyle.richToolbarColor, + boxShadow: ComposerStyle.richToolbarShadow + ), + ); + } else { + return const SizedBox.shrink(); + } + }) + ], ), - ); - } else { - return const SizedBox.shrink(); - } - }), - ], - ), + ), + ), + Obx(() => BottomBarComposerWidget( + isCodeViewEnabled: controller.richTextWebController!.codeViewEnabled, + isFormattingOptionsEnabled: controller.richTextWebController!.isFormattingOptionsEnabled, + hasReadReceipt: controller.hasRequestReadReceipt.value, + openRichToolbarAction: controller.richTextWebController!.toggleFormattingOptions, + attachFileAction: () => controller.openFilePickerByType(context, FileType.any), + insertImageAction: () => controller.insertImage(context, constraints.maxWidth), + showCodeViewAction: controller.richTextWebController!.toggleCodeView, + deleteComposerAction: () => controller.handleClickDeleteComposer(context), + saveToDraftAction: () => controller.handleClickSaveAsDraftsButton(context), + sendMessageAction: () => controller.handleClickSendButton(context), + requestReadReceiptAction: () => controller.toggleRequestReadReceipt(context), + )), + ], + ), + Align( + alignment: AlignmentDirectional.topCenter, + child: Obx(() => InsertImageLoadingBarWidget( + uploadInlineViewState: controller.uploadController.uploadInlineViewState.value, + viewState: controller.viewState.value, + padding: ComposerStyle.insertImageLoadingBarPadding, + )), + ), + Obx(() { + if (controller.mailboxDashBoardController.isAttachmentDraggableAppActive) { + return Positioned.fill( + child: PointerInterceptor( + child: AttachmentDropZoneWidget( + imagePaths: controller.imagePaths, + width: constraintsBody.maxWidth, + height: constraintsBody.maxHeight, + onAttachmentDropZoneListener: controller.onAttachmentDropZoneListener, + ) + ), + ); + } else { + return const SizedBox.shrink(); + } + }), + Obx(() { + if (controller.mailboxDashBoardController.isLocalFileDraggableAppActive) { + return Positioned.fill( + child: PointerInterceptor( + child: LocalFileDropZoneWidget( + imagePaths: controller.imagePaths, + width: constraintsBody.maxWidth, + height: constraintsBody.maxHeight, + onLocalFileDropZoneListener: (details) => + controller.onLocalFileDropZoneListener( + context: context, + details: details, + maxWidth: constraintsBody.maxWidth, + ), + ) + ), + ); + } else { + return const SizedBox.shrink(); + } + }), + ], ); - } + }, ), - ), - Obx(() => BottomBarComposerWidget( - isCodeViewEnabled: controller.richTextWebController!.codeViewEnabled, - isFormattingOptionsEnabled: controller.richTextWebController!.isFormattingOptionsEnabled, - hasReadReceipt: controller.hasRequestReadReceipt.value, - openRichToolbarAction: controller.richTextWebController!.toggleFormattingOptions, - attachFileAction: () => controller.openFilePickerByType(context, FileType.any), - insertImageAction: () => controller.insertImage(context, constraints.maxWidth), - showCodeViewAction: controller.richTextWebController!.toggleCodeView, - deleteComposerAction: () => controller.handleClickDeleteComposer(context), - saveToDraftAction: () => controller.handleClickSaveAsDraftsButton(context), - sendMessageAction: () => controller.handleClickSendButton(context), - requestReadReceiptAction: () => controller.toggleRequestReadReceipt(context), - )), + ) ]), ); }, diff --git a/lib/features/composer/presentation/view/web/web_editor_view.dart b/lib/features/composer/presentation/view/web/web_editor_view.dart index 5da136ef90..90e757b48b 100644 --- a/lib/features/composer/presentation/view/web/web_editor_view.dart +++ b/lib/features/composer/presentation/view/web/web_editor_view.dart @@ -14,6 +14,8 @@ import 'package:tmail_ui_user/features/email/domain/state/transform_html_email_c import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart'; import 'package:tmail_ui_user/main/utils/app_utils.dart'; +typedef OnDragEnterListener = Function(List? types); + class WebEditorView extends StatelessWidget with EditorViewMixin { final HtmlEditorController editorController; @@ -29,7 +31,7 @@ class WebEditorView extends StatelessWidget with EditorViewMixin { final OnEditorTextSizeChanged? onEditorTextSizeChanged; final double? width; final double? height; - final VoidCallback? onDragEnter; + final OnDragEnterListener? onDragEnter; const WebEditorView({ super.key, diff --git a/lib/features/composer/presentation/widgets/web/web_editor_widget.dart b/lib/features/composer/presentation/widgets/web/web_editor_widget.dart index a2ac28b523..c95ffd8bc3 100644 --- a/lib/features/composer/presentation/widgets/web/web_editor_widget.dart +++ b/lib/features/composer/presentation/widgets/web/web_editor_widget.dart @@ -5,6 +5,7 @@ import 'package:core/utils/app_logger.dart'; import 'package:core/utils/html/html_utils.dart'; import 'package:flutter/material.dart'; import 'package:html_editor_enhanced/html_editor.dart'; +import 'package:tmail_ui_user/features/composer/presentation/view/web/web_editor_view.dart'; import 'package:universal_html/html.dart' hide VoidCallback; typedef OnChangeContentEditorAction = Function(String? text); @@ -27,7 +28,7 @@ class WebEditorWidget extends StatefulWidget { final OnEditorTextSizeChanged? onEditorTextSizeChanged; final double? width; final double? height; - final VoidCallback? onDragEnter; + final OnDragEnterListener? onDragEnter; const WebEditorWidget({ super.key, @@ -63,8 +64,6 @@ class _WebEditorState extends State { bool _dropListenerRegistered = false; Function(Event)? _dropListener; - - @override void initState() { super.initState(); @@ -175,7 +174,7 @@ class _WebEditorState extends State { HtmlUtils.lineHeight100Percent.name ), onDragEnter: widget.onDragEnter, - onDragLeave: () {}, + onDragLeave: (_) {}, ), ); } From 401ec487cf8d5876788a48048bd1fbc0a6a3e0ea Mon Sep 17 00:00:00 2001 From: dab246 Date: Mon, 15 Jul 2024 16:40:07 +0700 Subject: [PATCH 2/2] TF-2989 Update `html_editor_enhanced` dependency --- pubspec.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.lock b/pubspec.lock index eebc18bf90..f38644f000 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1107,7 +1107,7 @@ packages: description: path: "." ref: sprint_25_flutter_3_22_2 - resolved-ref: "76079012ae7c4b1193e6646aef8de5aa88f246b9" + resolved-ref: "0020802d02f69fc02bc56cf18d6962d10babe097" url: "https://github.com/linagora/html-editor-enhanced.git" source: git version: "2.5.1"