From 291c2a6bd21900d48f9f56c7f48c855809f15185 Mon Sep 17 00:00:00 2001 From: dab246 Date: Wed, 6 Sep 2023 11:50:54 +0700 Subject: [PATCH] TF-2116 Create WebEditorComposer widget and style (cherry picked from commit 6ea82d66c0e319918a1938b39d0961b7d894a02f) --- .../presentation/view/web_editor_view.dart | 194 ++++++++++++++++++ ...tor_widget.dart => web_editor_widget.dart} | 52 +++-- 2 files changed, 227 insertions(+), 19 deletions(-) create mode 100644 lib/features/composer/presentation/view/web_editor_view.dart rename lib/features/composer/presentation/widgets/{email_editor_widget.dart => web_editor_widget.dart} (50%) diff --git a/lib/features/composer/presentation/view/web_editor_view.dart b/lib/features/composer/presentation/view/web_editor_view.dart new file mode 100644 index 000000000..c8a436ae0 --- /dev/null +++ b/lib/features/composer/presentation/view/web_editor_view.dart @@ -0,0 +1,194 @@ + +import 'package:core/presentation/extensions/html_extension.dart'; +import 'package:core/presentation/state/failure.dart'; +import 'package:core/presentation/state/success.dart'; +import 'package:core/utils/app_logger.dart'; +import 'package:dartz/dartz.dart'; +import 'package:flutter/material.dart'; +import 'package:html_editor_enhanced/html_editor.dart'; +import 'package:model/email/email_action_type.dart'; +import 'package:model/email/presentation_email.dart'; +import 'package:tmail_ui_user/features/base/widget/cupertino_loading_widget.dart'; +import 'package:tmail_ui_user/features/composer/presentation/extensions/email_action_type_extension.dart'; +import 'package:tmail_ui_user/features/composer/presentation/widgets/web_editor_widget.dart'; +import 'package:tmail_ui_user/features/email/domain/state/get_email_content_state.dart'; +import 'package:tmail_ui_user/features/email/domain/state/transform_html_email_content_state.dart'; +import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart'; +import 'package:tmail_ui_user/main/utils/app_utils.dart'; + +class WebEditorView extends StatelessWidget { + + final HtmlEditorController editorController; + final ComposerArguments? arguments; + final Either? contentViewState; + final String? currentWebContent; + final OnInitialContentEditorAction? onInitial; + final OnChangeContentEditorAction? onChangeContent; + final VoidCallback? onFocus; + final VoidCallback? onUnFocus; + final OnMouseDownEditorAction? onMouseDown; + final OnEditorSettingsChange? onEditorSettings; + + const WebEditorView({ + super.key, + required this.editorController, + this.arguments, + this.contentViewState, + this.currentWebContent, + this.onInitial, + this.onChangeContent, + this.onFocus, + this.onUnFocus, + this.onMouseDown, + this.onEditorSettings, + }); + + @override + Widget build(BuildContext context) { + if (arguments == null) { + return const SizedBox.shrink(); + } + + switch(arguments!.emailActionType) { + case EmailActionType.compose: + case EmailActionType.composeFromEmailAddress: + case EmailActionType.composeFromFileShared: + return WebEditorWidget( + editorController: editorController, + content: currentWebContent ?? HtmlExtension.editorStartTags, + direction: AppUtils.getCurrentDirection(context), + onInitial: onInitial, + onChangeContent: onChangeContent, + onFocus: onFocus, + onUnFocus: onUnFocus, + onMouseDown: onMouseDown, + onEditorSettings: onEditorSettings, + ); + case EmailActionType.editDraft: + case EmailActionType.editSendingEmail: + case EmailActionType.composeFromContentShared: + case EmailActionType.reopenComposerBrowser: + if (contentViewState == null) { + return const SizedBox.shrink(); + } + return contentViewState!.fold( + (failure) => WebEditorWidget( + editorController: editorController, + content: currentWebContent ?? HtmlExtension.editorStartTags, + direction: AppUtils.getCurrentDirection(context), + onInitial: onInitial, + onChangeContent: onChangeContent, + onFocus: onFocus, + onUnFocus: onUnFocus, + onMouseDown: onMouseDown, + onEditorSettings: onEditorSettings, + ), + (success) { + if (success is GetEmailContentLoading) { + return const CupertinoLoadingWidget(padding: EdgeInsets.all(16.0)); + } else { + var newContent = success is GetEmailContentSuccess + ? success.htmlEmailContent + : HtmlExtension.editorStartTags; + if (newContent.isEmpty) { + newContent = HtmlExtension.editorStartTags; + } + return WebEditorWidget( + editorController: editorController, + content: currentWebContent ?? newContent, + direction: AppUtils.getCurrentDirection(context), + onInitial: onInitial, + onChangeContent: onChangeContent, + onFocus: onFocus, + onUnFocus: onUnFocus, + onMouseDown: onMouseDown, + onEditorSettings: onEditorSettings, + ); + } + } + ); + case EmailActionType.reply: + case EmailActionType.replyAll: + case EmailActionType.forward: + if (contentViewState == null) { + return const SizedBox.shrink(); + } + return contentViewState!.fold( + (failure) { + final emailContentQuoted = _getEmailContentQuotedAsHtml( + context: context, + emailContent: '', + emailActionType: arguments!.emailActionType, + presentationEmail: arguments!.presentationEmail! + ); + return WebEditorWidget( + editorController: editorController, + content: currentWebContent ?? emailContentQuoted, + direction: AppUtils.getCurrentDirection(context), + onInitial: onInitial, + onChangeContent: onChangeContent, + onFocus: onFocus, + onUnFocus: onUnFocus, + onMouseDown: onMouseDown, + onEditorSettings: onEditorSettings, + ); + }, + (success) { + if (success is TransformHtmlEmailContentLoading) { + return const CupertinoLoadingWidget(padding: EdgeInsets.all(16.0)); + } else { + final emailContentQuoted = _getEmailContentQuotedAsHtml( + context: context, + emailContent: success is TransformHtmlEmailContentSuccess + ? success.htmlContent + : '', + emailActionType: arguments!.emailActionType, + presentationEmail: arguments!.presentationEmail! + ); + return WebEditorWidget( + editorController: editorController, + content: currentWebContent ?? emailContentQuoted, + direction: AppUtils.getCurrentDirection(context), + onInitial: onInitial, + onChangeContent: onChangeContent, + onFocus: onFocus, + onUnFocus: onUnFocus, + onMouseDown: onMouseDown, + onEditorSettings: onEditorSettings, + ); + } + } + ); + default: + return WebEditorWidget( + editorController: editorController, + content: currentWebContent ?? HtmlExtension.editorStartTags, + direction: AppUtils.getCurrentDirection(context), + onInitial: onInitial, + onChangeContent: onChangeContent, + onFocus: onFocus, + onUnFocus: onUnFocus, + onMouseDown: onMouseDown, + onEditorSettings: onEditorSettings, + ); + } + } + + String _getEmailContentQuotedAsHtml({ + required BuildContext context, + required String emailContent, + required EmailActionType emailActionType, + required PresentationEmail presentationEmail, + }) { + final headerEmailQuoted = emailActionType.getHeaderEmailQuoted( + context: context, + presentationEmail: presentationEmail + ); + log('WebEditorView::getEmailContentQuotedAsHtml:headerEmailQuoted: $headerEmailQuoted'); + final headerEmailQuotedAsHtml = headerEmailQuoted != null + ? headerEmailQuoted.addCiteTag() + : ''; + final emailQuotedHtml = '${HtmlExtension.editorStartTags}$headerEmailQuotedAsHtml${emailContent.addBlockQuoteTag()}'; + return emailQuotedHtml; + } +} diff --git a/lib/features/composer/presentation/widgets/email_editor_widget.dart b/lib/features/composer/presentation/widgets/web_editor_widget.dart similarity index 50% rename from lib/features/composer/presentation/widgets/email_editor_widget.dart rename to lib/features/composer/presentation/widgets/web_editor_widget.dart index ee4eb1666..03754c6e0 100644 --- a/lib/features/composer/presentation/widgets/email_editor_widget.dart +++ b/lib/features/composer/presentation/widgets/web_editor_widget.dart @@ -3,39 +3,53 @@ import 'package:core/presentation/utils/html_transformer/html_utils.dart'; import 'package:core/utils/app_logger.dart'; import 'package:flutter/material.dart'; import 'package:html_editor_enhanced/html_editor.dart'; -import 'package:tmail_ui_user/features/composer/presentation/composer_controller.dart'; -class EmailEditorWidget extends StatefulWidget { +typedef OnChangeContentEditorAction = Function(String? text); +typedef OnInitialContentEditorAction = Function(String text); +typedef OnMouseDownEditorAction = Function(BuildContext context); +typedef OnEditorSettingsChange = Function(EditorSettings settings); + +class WebEditorWidget extends StatefulWidget { - final ComposerController controller; final String content; final TextDirection direction; + final HtmlEditorController editorController; + final OnInitialContentEditorAction? onInitial; + final OnChangeContentEditorAction? onChangeContent; + final VoidCallback? onFocus; + final VoidCallback? onUnFocus; + final OnMouseDownEditorAction? onMouseDown; + final OnEditorSettingsChange? onEditorSettings; - const EmailEditorWidget({ + const WebEditorWidget({ super.key, - required this.controller, required this.content, required this.direction, + required this.editorController, + this.onInitial, + this.onChangeContent, + this.onFocus, + this.onUnFocus, + this.onMouseDown, + this.onEditorSettings, }); @override - State createState() => _EmailEditorState(); + State createState() => _WebEditorState(); } -class _EmailEditorState extends State { +class _WebEditorState extends State { - late ComposerController _controller; late HtmlEditorController _editorController; @override void initState() { - _controller = widget.controller; - _editorController = _controller.richTextWebController.editorController; + _editorController = widget.editorController; super.initState(); } @override - void didUpdateWidget(covariant EmailEditorWidget oldWidget) { + void didUpdateWidget(covariant WebEditorWidget oldWidget) { log('_EmailEditorState::didUpdateWidget():Old: ${oldWidget.direction} | current: ${widget.direction}'); if (oldWidget.direction != widget.direction) { _editorController.updateBodyDirection(widget.direction.name); @@ -61,14 +75,14 @@ class _EmailEditorState extends State { ), otherOptions: const OtherOptions(height: 550), callbacks: Callbacks( - onBeforeCommand: _controller.onChangeTextEditorWeb, - onChangeContent: _controller.onChangeTextEditorWeb, - onInit: () => _controller.handleInitHtmlEditorWeb(widget.content), - onFocus: _controller.handleOnFocusHtmlEditorWeb, - onBlur: _controller.handleOnUnFocusHtmlEditorWeb, - onMouseDown: () => _controller.handleOnMouseDownHtmlEditorWeb(context), - onChangeSelection: _controller.richTextWebController.onEditorSettingsChange, - onChangeCodeview: _controller.onChangeTextEditorWeb + onBeforeCommand: widget.onChangeContent, + onChangeContent: widget.onChangeContent, + onInit: () => widget.onInitial?.call(widget.content), + onFocus: widget.onFocus, + onBlur: widget.onUnFocus, + onMouseDown: () => widget.onMouseDown?.call(context), + onChangeSelection: widget.onEditorSettings, + onChangeCodeview: widget.onChangeContent ), ); }