From 7473fdffdf8ec2d218a20287f1ef9bfe32a7d94b Mon Sep 17 00:00:00 2001 From: dab246 Date: Mon, 11 Jul 2022 12:33:29 +0700 Subject: [PATCH] TF-332 Fix when nothing is change tmail still making jmap request --- .../presentation/composer_controller.dart | 112 +++++--- .../composer/presentation/composer_view.dart | 68 +++-- .../presentation/composer_view_web.dart | 264 ++++++++++-------- lib/l10n/intl_messages.arb | 8 +- lib/main/localizations/app_localizations.dart | 6 + 5 files changed, 283 insertions(+), 175 deletions(-) diff --git a/lib/features/composer/presentation/composer_controller.dart b/lib/features/composer/presentation/composer_controller.dart index 5e97f3a57..2d344698d 100644 --- a/lib/features/composer/presentation/composer_controller.dart +++ b/lib/features/composer/presentation/composer_controller.dart @@ -12,7 +12,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:get/get.dart'; -import 'package:html_editor_enhanced/html_editor.dart' as html_editor_browser; +import 'package:html_editor_enhanced/html_editor.dart' as editor_web; import 'package:http_parser/http_parser.dart'; import 'package:jmap_dart_client/jmap/core/id.dart'; import 'package:jmap_dart_client/jmap/identities/identity.dart'; @@ -62,7 +62,6 @@ class ComposerController extends BaseController { final composerArguments = Rxn(); final isEnableEmailSendButton = false.obs; final isInitialRecipient = false.obs; - final emailContents = Rxn>(); final listEmailAddressType = [].obs; final subjectEmail = Rxn(); final screenDisplayMode = ScreenDisplayMode.normal.obs; @@ -71,6 +70,7 @@ class ComposerController extends BaseController { final bccAddressExpandMode = ExpandMode.EXPAND.obs; final identitySelected = Rxn(); final listIdentities = [].obs; + final emailContentsViewState = Rx>(Right(UIState.idle)); final SendEmailInteractor _sendEmailInteractor; final GetAutoCompleteInteractor _getAutoCompleteInteractor; @@ -88,8 +88,7 @@ class ComposerController extends BaseController { List listBccEmailAddress = []; ContactSuggestionSource _contactSuggestionSource = ContactSuggestionSource.tMailContact; HtmlEditorApi? htmlEditorApi; - final html_editor_browser.HtmlEditorController htmlControllerBrowser = - html_editor_browser.HtmlEditorController(processNewLineAsBr: true); + final htmlControllerBrowser = editor_web.HtmlEditorController(processNewLineAsBr: true); final subjectEmailInputController = TextEditingController(); final toEmailAddressController = TextEditingController(); @@ -98,6 +97,7 @@ class ComposerController extends BaseController { List initialAttachments = []; String? _textEditorWeb; + List? _emailContents; void setTextEditorWeb(String? text) => _textEditorWeb = text; @@ -105,21 +105,34 @@ class ComposerController extends BaseController { void setSubjectEmail(String subject) => subjectEmail.value = subject; - Future _getEmailBodyText({bool changedEmail = false}) async { - if (kIsWeb) { - return await htmlControllerBrowser.getText(); - } else { - if (changedEmail) { - return await htmlEditorApi?.getText() ?? ''; + Future _getEmailBodyText(BuildContext context, { + bool changedEmail = false + }) async { + if (BuildUtils.isWeb) { + var contentHtml = ''; + if (_responsiveUtils.isWebDesktop(context) && + screenDisplayMode.value == ScreenDisplayMode.minimize) { + contentHtml = textEditorWeb ?? ''; } else { - final content = await htmlEditorApi?.getText() ?? ''; - if (_isMobileApp && identitySelected.value?.textSignature?.value.isNotEmpty == true) { - final newContent = '$content${identitySelected.value?.textSignature?.value.toSignatureBlock()}'; - log('ComposerController::_generateEmail()_MOBILE: $newContent'); - return newContent; - } else { - return content; - } + contentHtml = await htmlControllerBrowser.getText(); + } + log('ComposerController::_getEmailBodyText():WEB: contentHtml: $contentHtml'); + final newContentHtml = contentHtml.removeEditorStartTag(); + log('ComposerController::_getEmailBodyText():WEB: newContentHtml: $newContentHtml'); + return newContentHtml; + } else { + final contentHtml = await htmlEditorApi?.getText() ?? ''; + log('ComposerController::_getEmailBodyText():MOBILE: $contentHtml'); + final newContentHtml = contentHtml.removeEditorStartTag(); + if (changedEmail) { + return newContentHtml; + } else if (_isMobileApp && identitySelected.value?.textSignature?.value.isNotEmpty == true) { + final contentHtmlWithSignature = + '$newContentHtml${identitySelected.value?.textSignature?.value.toSignatureBlock()}'; + log('ComposerController::_getEmailBodyText():MOBILE:SIGNATURE: $contentHtmlWithSignature'); + return contentHtmlWithSignature; + } else { + return newContentHtml; } } } @@ -175,12 +188,24 @@ class ComposerController extends BaseController { super.dispose(); } + @override + void onData(Either newState) { + super.onData(newState); + newState.map((success) async { + if (success is GetEmailContentLoading) { + emailContentsViewState.value = Right(success); + } + }); + } + @override void onDone() { viewState.value.fold( (failure) { if (failure is LocalFilePickerFailure || failure is LocalFilePickerCancel) { _pickFileFailure(failure); + } else if (failure is GetEmailContentFailure) { + emailContentsViewState.value = Left(failure); } }, (success) { @@ -218,7 +243,7 @@ class ComposerController extends BaseController { if (arguments.emailActionType == EmailActionType.edit) { _getEmailContentAction(arguments); } - _initToEmailAddress(arguments); + _initEmailAddress(arguments); _initSubjectEmail(arguments); _initAttachments(arguments); } @@ -338,7 +363,7 @@ class ComposerController extends BaseController { return null; } - void _initToEmailAddress(ComposerArguments arguments) { + void _initEmailAddress(ComposerArguments arguments) { final userProfile = mailboxDashBoardController.userProfile.value; if (arguments.presentationEmail != null && userProfile != null) { final userEmailAddress = EmailAddress(null, userProfile.email); @@ -419,8 +444,12 @@ class ComposerController extends BaseController { return emailQuotedHtml; } - Future _generateEmail(Map mapDefaultMailboxId, - UserProfile userProfile, {bool asDrafts = false}) async { + Future _generateEmail( + BuildContext context, + Map mapDefaultMailboxId, + UserProfile userProfile, + {bool asDrafts = false} + ) async { final generateEmailId = EmailId(Id(_uuid.v1())); final outboxMailboxId = mapDefaultMailboxId[PresentationMailbox.roleOutbox]; final draftMailboxId = mapDefaultMailboxId[PresentationMailbox.roleDrafts]; @@ -437,7 +466,7 @@ class ComposerController extends BaseController { final generatePartId = PartId(_uuid.v1()); final generateBlobId = Id(_uuid.v1()); - var emailBodyText = await _getEmailBodyText(); + var emailBodyText = await _getEmailBodyText(context); log('ComposerController::_generateEmail(): $emailBodyText'); final userAgent = await userAgentPlatform; log('ComposerController::_generateEmail(): userAgent: $userAgent'); @@ -561,7 +590,7 @@ class ComposerController extends BaseController { if (arguments != null && session != null && mapDefaultMailboxId.isNotEmpty && userProfile != null) { - final email = await _generateEmail(mapDefaultMailboxId, userProfile); + final email = await _generateEmail(context, mapDefaultMailboxId, userProfile); final accountId = session.accounts.keys.first; final sentMailboxId = mapDefaultMailboxId[PresentationMailbox.roleSent]; final submissionCreateId = Id(const Uuid().v1()); @@ -666,14 +695,17 @@ class ComposerController extends BaseController { uploadController.deleteFileUploaded(uploadId); } - Future _isEmailChanged(BuildContext context, ComposerArguments arguments) async { - final currentTextInComposer = await _getEmailBodyText(changedEmail: true); - final newEmailBody = currentTextInComposer.removeEditorDefaultSpace(); + Future _isEmailChanged( + BuildContext context, + ComposerArguments arguments, + ) async { + final newEmailBody = await _getEmailBodyText(context, changedEmail: true); log('ComposerController::_isEmailChanged(): newEmailBody: $newEmailBody'); - var oldEmailBody = ''; - final contentEmail = getContentEmail(context); - if (arguments.emailActionType != EmailActionType.compose && contentEmail != null && contentEmail.isNotEmpty) { - oldEmailBody = kIsWeb ? contentEmail : '\n$contentEmail\n'; + var oldEmailBody = getContentEmail(context) ?? ''; + log('ComposerController::_isEmailChanged(): getContentEmail: $oldEmailBody'); + if (arguments.emailActionType != EmailActionType.compose && + oldEmailBody.isNotEmpty) { + oldEmailBody = BuildUtils.isWeb ? oldEmailBody : '\n$oldEmailBody\n'; } if (BuildUtils.isWeb) { if (identitySelected.value?.htmlSignature?.value.isNotEmpty == true) { @@ -733,7 +765,11 @@ class ComposerController extends BaseController { final isChanged = await _isEmailChanged(context, arguments); log('ComposerController::saveEmailAsDrafts(): saveEmailAsDrafts isChanged: $isChanged'); if (isChanged) { - final newEmail = await _generateEmail(mapDefaultMailboxId, userProfile, asDrafts: true); + final newEmail = await _generateEmail( + context, + mapDefaultMailboxId, + userProfile, + asDrafts: true); final accountId = session.accounts.keys.first; final oldEmail = arguments.presentationEmail; @@ -764,21 +800,15 @@ class ComposerController extends BaseController { } void _getEmailContentSuccess(GetEmailContentSuccess success) { - emailContents.value = success.emailContents; if (success.attachments.isNotEmpty) { initialAttachments = success.attachments; uploadController.initializeUploadAttachments(success.attachments); } + emailContentsViewState.value = Right(success); + _emailContents = success.emailContents; } - String? getEmailContentDraftsAsHtml() { - final listContents = emailContents.value; - if (listContents != null) { - return listContents.asHtmlString; - } else { - return null; - } - } + String? getEmailContentDraftsAsHtml() => _emailContents?.asHtmlString; String getEmailAddressSender() { final arguments = composerArguments.value; diff --git a/lib/features/composer/presentation/composer_view.dart b/lib/features/composer/presentation/composer_view.dart index e0ef85483..281ee6967 100644 --- a/lib/features/composer/presentation/composer_view.dart +++ b/lib/features/composer/presentation/composer_view.dart @@ -10,15 +10,17 @@ import 'package:flutter_svg/flutter_svg.dart'; import 'package:get/get.dart'; import 'package:jmap_dart_client/jmap/identities/identity.dart'; import 'package:model/model.dart'; +import 'package:tmail_ui_user/features/base/mixin/app_loader_mixin.dart'; import 'package:tmail_ui_user/features/composer/domain/state/upload_attachment_state.dart'; import 'package:tmail_ui_user/features/composer/presentation/composer_controller.dart'; import 'package:tmail_ui_user/features/composer/presentation/widgets/attachment_file_composer_builder.dart'; import 'package:tmail_ui_user/features/composer/presentation/widgets/email_address_input_builder.dart'; import 'package:tmail_ui_user/features/upload/presentation/extensions/list_upload_file_state_extension.dart'; import 'package:tmail_ui_user/features/upload/presentation/model/upload_file_state.dart'; +import 'package:tmail_ui_user/features/email/domain/state/get_email_content_state.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; -class ComposerView extends GetWidget { +class ComposerView extends GetWidget with AppLoaderMixin { final responsiveUtils = Get.find(); final imagePaths = Get.find(); @@ -490,25 +492,59 @@ class ComposerView extends GetWidget { Widget _buildComposerEditor(BuildContext context) { return Obx(() { - if (controller.composerArguments.value?.emailActionType == EmailActionType.compose) { - return HtmlEditor( - key: const Key('composer_editor'), - minHeight: 550, - initialContent: ''.addEditorDefaultSpace(), - onCreated: (editorApi) => controller.htmlEditorApi = editorApi); - } else { - final message = controller.getContentEmail(context); - return message != null && message.isNotEmpty - ? HtmlEditor( - key: const Key('composer_editor'), - minHeight: 550, - onCreated: (editorApi) => controller.htmlEditorApi = editorApi, - initialContent: message) - : const SizedBox.shrink(); + final argsComposer = controller.composerArguments.value; + + if (argsComposer == null) { + return const SizedBox.shrink(); + } + + switch(argsComposer.emailActionType) { + case EmailActionType.compose: + case EmailActionType.composeFromEmailAddress: + return _buildHtmlEditor(HtmlExtension.editorStartTags); + case EmailActionType.edit: + return controller.emailContentsViewState.value.fold( + (failure) => _buildHtmlEditor(HtmlExtension.editorStartTags), + (success) { + if (success is GetEmailContentLoading) { + return Padding( + padding: const EdgeInsets.all(16.0), + child: loadingWidget, + ); + } else if (success is GetEmailContentSuccess) { + var contentHtml = success.emailContents.asHtmlString; + if (contentHtml.isEmpty == true) { + contentHtml = HtmlExtension.editorStartTags; + } + return _buildHtmlEditor(contentHtml); + } else { + return _buildHtmlEditor(HtmlExtension.editorStartTags); + } + }); + case EmailActionType.reply: + case EmailActionType.replyAll: + case EmailActionType.forward: + var contentHtml = controller.getEmailContentQuotedAsHtml( + context, + argsComposer); + if (contentHtml.isEmpty == true) { + contentHtml = HtmlExtension.editorStartTags; + } + return _buildHtmlEditor(contentHtml); + default: + return _buildHtmlEditor(HtmlExtension.editorStartTags); } }); } + Widget _buildHtmlEditor(String initialContent) { + return HtmlEditor( + key: const Key('composer_editor'), + minHeight: 550, + initialContent: initialContent, + onCreated: (editorApi) => controller.htmlEditorApi = editorApi); + } + Widget _buildAttachmentsLoadingView({EdgeInsets? padding, double? size}) { return Obx(() => controller.viewState.value.fold( (failure) => const SizedBox.shrink(), diff --git a/lib/features/composer/presentation/composer_view_web.dart b/lib/features/composer/presentation/composer_view_web.dart index eea368fc6..e20a84ce8 100644 --- a/lib/features/composer/presentation/composer_view_web.dart +++ b/lib/features/composer/presentation/composer_view_web.dart @@ -6,10 +6,11 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:get/get.dart'; -import 'package:html_editor_enhanced/html_editor.dart' as html_editor_browser; +import 'package:html_editor_enhanced/html_editor.dart' as editor_web; import 'package:jmap_dart_client/jmap/identities/identity.dart'; import 'package:model/model.dart'; import 'package:pointer_interceptor/pointer_interceptor.dart'; +import 'package:tmail_ui_user/features/base/mixin/app_loader_mixin.dart'; import 'package:tmail_ui_user/features/composer/domain/state/upload_attachment_state.dart'; import 'package:tmail_ui_user/features/composer/presentation/composer_controller.dart'; import 'package:tmail_ui_user/features/composer/presentation/model/screen_display_mode.dart'; @@ -17,9 +18,10 @@ import 'package:tmail_ui_user/features/composer/presentation/widgets/attachment_ import 'package:tmail_ui_user/features/composer/presentation/widgets/email_address_input_builder.dart'; import 'package:tmail_ui_user/features/upload/presentation/extensions/list_upload_file_state_extension.dart'; import 'package:tmail_ui_user/features/upload/presentation/model/upload_file_state.dart'; +import 'package:tmail_ui_user/features/email/domain/state/get_email_content_state.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; -class ComposerView extends GetWidget { +class ComposerView extends GetWidget with AppLoaderMixin { final responsiveUtils = Get.find(); final imagePaths = Get.find(); @@ -53,7 +55,12 @@ class ComposerView extends GetWidget { const Divider(color: AppColor.colorDividerComposer, height: 1), Padding(padding: const EdgeInsets.symmetric(horizontal: 16), child: _buildListButton(context)), const Divider(color: AppColor.colorDividerComposer, height: 1), - Expanded(child: _buildEditorAndAttachments(context)), + Expanded(child: Column( + children: [ + _buildAttachmentsWidget(context), + _buildEditorForm(context) + ] + )), ] ))) ) @@ -92,7 +99,7 @@ class ComposerView extends GetWidget { padding: const EdgeInsets.only(left: 10), child: buildIconWeb( icon: SvgPicture.asset(imagePaths.icCloseMailbox, fit: BoxFit.fill), - tooltip: AppLocalizations.of(context).close, + tooltip: AppLocalizations.of(context).saveAndClose, onTap: () => controller.saveEmailAsDrafts(context) )), buildIconWeb( @@ -147,23 +154,7 @@ class ComposerView extends GetWidget { ) ) )) - ), - tabletLarge: Scaffold( - backgroundColor: Colors.black38, - body: Align(alignment: Alignment.center, child: Card( - color: Colors.transparent, - shadowColor: Colors.transparent, - child: Container( - decoration: const BoxDecoration(color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(24))), - margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 20), - child: ClipRRect( - borderRadius: const BorderRadius.all(Radius.circular(24)), - child: LayoutBuilder(builder: (context, constraints) => - PointerInterceptor(child: _buildBodyForDesktop(context, constraints))) - ) - ) - )) - ), + ) ); } @@ -172,7 +163,7 @@ class ComposerView extends GetWidget { children: [ buildIconWeb( icon: SvgPicture.asset(imagePaths.icCloseMailbox, fit: BoxFit.fill), - tooltip: AppLocalizations.of(context).close, + tooltip: AppLocalizations.of(context).saveAndClose, onTap: () => controller.saveEmailAsDrafts(context)), if (responsiveUtils.isDesktop(context)) Obx(() => buildIconWeb( @@ -204,7 +195,7 @@ class ComposerView extends GetWidget { children: [ buildIconWeb( icon: SvgPicture.asset(imagePaths.icClose, width: 30, height: 30, fit: BoxFit.fill), - tooltip: AppLocalizations.of(context).close, + tooltip: AppLocalizations.of(context).saveAndClose, iconPadding: EdgeInsets.zero, onTap: () => controller.saveEmailAsDrafts(context)), Expanded(child: _buildTitleComposer(context)), @@ -287,8 +278,15 @@ class ComposerView extends GetWidget { ])), const Divider(color: AppColor.colorDividerComposer, height: 1), Expanded(child: Padding( - padding: EdgeInsets.only(left: responsiveUtils.isMobile(context) ? 16 : 60, right: responsiveUtils.isMobile(context) ? 16 : 25), - child: _buildEditorAndAttachments(context))), + padding: EdgeInsets.only( + left: responsiveUtils.isMobile(context) ? 16 : 60, + right: responsiveUtils.isMobile(context) ? 16 : 25), + child: Column( + children: [ + _buildAttachmentsWidget(context), + _buildEditorForm(context) + ] + ))), const Divider(color: AppColor.colorDividerComposer, height: 1), Obx(() => _buildBottomBar(context, controller.isEnableEmailSendButton.value)), ]); @@ -489,105 +487,137 @@ class ComposerView extends GetWidget { ); } - Widget _buildEditorAndAttachments(BuildContext context) { + Widget _buildEditorForm(BuildContext context) { return Obx(() { - final uploadAttachments = controller.uploadController.listUploadAttachments; + final argsComposer = controller.composerArguments.value; - return Column( - children: [ - if (uploadAttachments.isNotEmpty) - ...[ - Padding( - padding: EdgeInsets.only( - top: 4, - bottom: 4, - left: responsiveUtils.isMobile(context) ? 16 : 20, - right: responsiveUtils.isMobile(context) ? 16: 0), - child: _buildAttachmentsTitle(context, - uploadAttachments, - controller.expandModeAttachments.value)), - _buildAttachmentsLoadingView(), - Padding( - padding: EdgeInsets.only( - bottom: 8, - left: responsiveUtils.isMobile(context) ? 16 : 10, - right: responsiveUtils.isMobile(context) ? 16 : 10), - child: _buildAttachmentsList(context, - uploadAttachments, - controller.expandModeAttachments.value)) - ], - if (controller.composerArguments.value != null) - _buildComposeEditor(context) - ] - ); + if (argsComposer == null) { + return const SizedBox.shrink(); + } + + final currentTextEditor = controller.textEditorWeb; + + switch(argsComposer.emailActionType) { + case EmailActionType.compose: + case EmailActionType.composeFromEmailAddress: + return _buildHtmlEditor( + context, + currentTextEditor ?? HtmlExtension.editorStartTags); + case EmailActionType.edit: + return controller.emailContentsViewState.value.fold( + (failure) => _buildHtmlEditor( + context, + currentTextEditor ?? HtmlExtension.editorStartTags), + (success) { + if (success is GetEmailContentLoading) { + return Padding( + padding: const EdgeInsets.all(16.0), + child: loadingWidget, + ); + } else if (success is GetEmailContentSuccess) { + var contentHtml = success.emailContents.asHtmlString; + if (contentHtml.isEmpty == true) { + contentHtml = HtmlExtension.editorStartTags; + } + return _buildHtmlEditor(context, currentTextEditor ?? contentHtml); + } else { + return _buildHtmlEditor( + context, + currentTextEditor ?? HtmlExtension.editorStartTags); + } + }); + case EmailActionType.reply: + case EmailActionType.replyAll: + case EmailActionType.forward: + var contentHtml = controller.getEmailContentQuotedAsHtml( + context, + argsComposer); + if (contentHtml.isEmpty == true) { + contentHtml = HtmlExtension.editorStartTags; + } + return _buildHtmlEditor(context, currentTextEditor ?? contentHtml); + default: + return _buildHtmlEditor( + context, + currentTextEditor ?? HtmlExtension.editorStartTags); + } }); } - Widget _buildComposeEditor(BuildContext context) { - if (controller.composerArguments.value?.emailActionType == EmailActionType.compose) { - final initContent = controller.textEditorWeb ?? ''.addEditorDefaultSpace(); - return Expanded(child: Padding( - padding: EdgeInsets.symmetric(horizontal: responsiveUtils.isMobile(context) ? 8 : 10), - child: _buildEditor(context, initContent))); - } else if (controller.composerArguments.value?.emailActionType == EmailActionType.edit) { - final initContent = controller.textEditorWeb ?? controller.getEmailContentDraftsAsHtml(); - if (initContent != null) { - return Expanded(child: Padding( - padding: EdgeInsets.symmetric(horizontal: responsiveUtils.isMobile(context) ? 8 : 10), - child: _buildEditor(context, initContent))); - } else { - return const Padding( - padding: EdgeInsets.all(16), - child: SizedBox( - width: 30, - height: 30, - child: CupertinoActivityIndicator(color: AppColor.colorLoading))); - } - } else { - final initContent = controller.textEditorWeb ?? controller.getEmailContentQuotedAsHtml(context, controller.composerArguments.value!); - return Expanded(child: Padding( - padding: EdgeInsets.symmetric(horizontal: responsiveUtils.isMobile(context) ? 8 : 10), - child: _buildEditor(context, initContent))); - } + Widget _buildHtmlEditor(BuildContext context, String initContent) { + log('ComposerView::_buildHtmlEditor(): initContent: $initContent'); + + return Expanded( + child: Padding( + padding: EdgeInsets.symmetric( + horizontal: responsiveUtils.isMobile(context) ? 8 : 10), + child: editor_web.HtmlEditor( + key: const Key('composer_editor_web'), + controller: controller.htmlControllerBrowser, + htmlEditorOptions: const editor_web.HtmlEditorOptions( + hint: '', + darkMode: false, + ), + blockQuotedContent: initContent, + htmlToolbarOptions: const editor_web.HtmlToolbarOptions( + toolbarPosition: editor_web.ToolbarPosition.custom), + otherOptions: const editor_web.OtherOptions(height: 550), + callbacks: editor_web.Callbacks( + onBeforeCommand: (String? currentHtml) { + log('ComposerView::_buildComposerEditor(): onBeforeCommand : $currentHtml'); + controller.setTextEditorWeb(currentHtml); + }, onChangeContent: (String? changed) { + log('ComposerView::_buildComposerEditor(): onChangeContent : $changed'); + controller.setTextEditorWeb(changed); + }, onInit: () { + log('ComposerView::_buildComposerEditor(): onInit'); + controller.setTextEditorWeb(initContent); + controller.setFullScreenEditor(); + }, onFocus: () { + FocusManager.instance.primaryFocus?.unfocus(); + Future.delayed(const Duration(milliseconds: 500), () { + controller.htmlControllerBrowser.setFocus(); + }); + }, onBlur: () { + controller.onEditorFocusChange(false); + }, onMouseDown: () { + controller.onEditorFocusChange(true); + }), + ) + ) + ); } - Widget _buildEditor(BuildContext context, String initContent) { - log('ComposerView::_buildEditor(): initContent: $initContent'); - - return html_editor_browser.HtmlEditor( - key: const Key('composer_editor_web'), - controller: controller.htmlControllerBrowser, - htmlEditorOptions: const html_editor_browser.HtmlEditorOptions( - hint: '', - darkMode: false, - ), - blockQuotedContent: initContent, - htmlToolbarOptions: const html_editor_browser.HtmlToolbarOptions( - toolbarPosition: html_editor_browser.ToolbarPosition.custom - ), - otherOptions: const html_editor_browser.OtherOptions(height: 550), - callbacks: html_editor_browser.Callbacks( - onBeforeCommand: (String? currentHtml) { - log('ComposerView::_buildComposerEditor(): onBeforeCommand : $currentHtml'); - controller.setTextEditorWeb(currentHtml); - }, onChangeContent: (String? changed) { - log('ComposerView::_buildComposerEditor(): onChangeContent : $changed'); - controller.setTextEditorWeb(changed); - }, onInit: () { - log('ComposerView::_buildComposerEditor(): onInit'); - controller.setFullScreenEditor(); - }, onFocus: () { - FocusManager.instance.primaryFocus?.unfocus(); - Future.delayed(const Duration(milliseconds: 500), () { - controller.htmlControllerBrowser.setFocus(); - }); - }, onBlur: () { - controller.onEditorFocusChange(false); - }, onMouseDown: () { - controller.onEditorFocusChange(true); - } - ), - ); + Widget _buildAttachmentsWidget(BuildContext context) { + return Obx(() { + final attachments = controller.uploadController.listUploadAttachments; + if (attachments.isNotEmpty) { + return Column(children: [ + Padding( + padding: EdgeInsets.only( + top: 4, + bottom: 4, + left: responsiveUtils.isMobile(context) ? 16 : 20, + right: responsiveUtils.isMobile(context) ? 16: 0), + child: _buildAttachmentsTitle( + context, + attachments, + controller.expandModeAttachments.value)), + _buildAttachmentsLoadingView(), + Padding( + padding: EdgeInsets.only( + bottom: 8, + left: responsiveUtils.isMobile(context) ? 16 : 10, + right: responsiveUtils.isMobile(context) ? 16 : 10), + child: _buildAttachmentsList( + context, + attachments, + controller.expandModeAttachments.value)) + ]); + } else { + return const SizedBox.shrink(); + } + }); } Widget _buildAttachmentsLoadingView({EdgeInsets? padding, double? size}) { diff --git a/lib/l10n/intl_messages.arb b/lib/l10n/intl_messages.arb index ae42e8e5a..b7ee47594 100644 --- a/lib/l10n/intl_messages.arb +++ b/lib/l10n/intl_messages.arb @@ -1,5 +1,5 @@ { - "@@last_modified": "2022-07-05T19:24:56.876056", + "@@last_modified": "2022-07-11T12:17:57.489417", "initializing_data": "Initializing data...", "@initializing_data": { "type": "text", @@ -1567,5 +1567,11 @@ "type": "text", "placeholders_order": [], "placeholders": {} + }, + "saveAndClose": "Save & close", + "@saveAndClose": { + "type": "text", + "placeholders_order": [], + "placeholders": {} } } \ No newline at end of file diff --git a/lib/main/localizations/app_localizations.dart b/lib/main/localizations/app_localizations.dart index 1cf90574e..df9d5d5e3 100644 --- a/lib/main/localizations/app_localizations.dart +++ b/lib/main/localizations/app_localizations.dart @@ -1608,4 +1608,10 @@ class AppLocalizations { name: 'messageDialogSendEmailUploadingAttachment' ); } + + String get saveAndClose { + return Intl.message( + 'Save & close', + name: 'saveAndClose'); + } } \ No newline at end of file