From a31f331e092a690d692580af6980705aa7176140 Mon Sep 17 00:00:00 2001 From: dab246 Date: Wed, 15 Mar 2023 10:56:11 +0700 Subject: [PATCH] TF-1371 Update position of Identity in `reply/forward` (cherry picked from commit 53b99854e15b2eea12572d5c18322b43f744609f) --- .../extensions/html_extension.dart | 5 +- .../presentation/composer_controller.dart | 97 ++++++++++++------- .../composer/presentation/composer_view.dart | 2 +- .../presentation/composer_view_web.dart | 74 ++++++-------- pubspec.lock | 16 +-- 5 files changed, 101 insertions(+), 93 deletions(-) diff --git a/core/lib/presentation/extensions/html_extension.dart b/core/lib/presentation/extensions/html_extension.dart index abbc18505..8a1184220 100644 --- a/core/lib/presentation/extensions/html_extension.dart +++ b/core/lib/presentation/extensions/html_extension.dart @@ -24,10 +24,7 @@ extension HtmlExtension on String { 'blockquote', attribute: 'style="margin-left:8px;margin-right:8px;padding-left:12px;padding-right:12px;border-left:5px solid #eee;"'); - String asSignatureHtml() => '--

$this'; - - String toSignatureBlock() => - '
${asSignatureHtml()}

'; + String asSignatureHtml() => '--
$this'; String removeEditorStartTag() { if (trim() == editorStartTags) { diff --git a/lib/features/composer/presentation/composer_controller.dart b/lib/features/composer/presentation/composer_controller.dart index ac24e03a3..d805f5518 100644 --- a/lib/features/composer/presentation/composer_controller.dart +++ b/lib/features/composer/presentation/composer_controller.dart @@ -130,11 +130,22 @@ class ComposerController extends BaseController { List initialAttachments = []; String? _textEditorWeb; + String? _initTextEditor; List? _emailContents; double? maxWithEditor; late Worker uploadInlineImageWorker; - void setTextEditorWeb(String? text) => _textEditorWeb = text; + void onChangeTextEditorWeb(String? text) { + initTextEditor(text); + _textEditorWeb = text; + } + + void initTextEditor(String? text) { + if (_initTextEditor == null) { + _initTextEditor = text; + log('ComposerController::initTextEditor():$_initTextEditor'); + } + } String? get textEditorWeb => _textEditorWeb; @@ -164,9 +175,13 @@ class ComposerController extends BaseController { if (changedEmail) { return newContentHtml; } else if (_isMobileApp && identitySelected.value?.signatureAsString.isNotEmpty == true) { - final contentHtmlWithSignature = - '$newContentHtml${identitySelected.value?.signatureAsString.toSignatureBlock()}'; + await htmlEditorApi?.removeSignature(); + await htmlEditorApi?.insertSignature(identitySelected.value!.signatureAsString.asSignatureHtml()); + + contentHtml = await htmlEditorApi?.getText() ?? ''; + final contentHtmlWithSignature = contentHtml.removeEditorStartTag(); log('ComposerController::_getEmailBodyText():MOBILE:SIGNATURE: $contentHtmlWithSignature'); + return contentHtmlWithSignature; } else { return newContentHtml; @@ -218,6 +233,7 @@ class ComposerController extends BaseController { @override void onClose() { + _initTextEditor = null; if (!BuildUtils.isWeb) { FkUserAgent.release(); } @@ -326,7 +342,8 @@ class ComposerController extends BaseController { }); } - void initRichTextForMobile(BuildContext context, HtmlEditorApi editorApi) { + void initRichTextForMobile(BuildContext context, HtmlEditorApi editorApi, String? content) { + initTextEditor(content); richTextMobileTabletController.htmlEditorApi = editorApi; keyboardRichTextController.onCreateHTMLEditor( editorApi, @@ -390,6 +407,7 @@ class ComposerController extends BaseController { .toList(); if (listIdentities.isNotEmpty) { + _initTextEditor = null; await selectIdentity(listIdentities.first); } } @@ -550,7 +568,7 @@ class ComposerController extends BaseController { final headerEmailQuotedAsHtml = headerEmailQuoted != null ? headerEmailQuoted.addBlockTag('cite') : ''; final trustAsHtml = arguments.emailContents?.asHtmlString ?? ''; - final emailQuotedHtml = '


$headerEmailQuotedAsHtml${trustAsHtml.addBlockQuoteTag()}


'; + final emailQuotedHtml = '${HtmlExtension.editorStartTags}$headerEmailQuotedAsHtml${trustAsHtml.addBlockQuoteTag()}'; return emailQuotedHtml; } @@ -905,44 +923,30 @@ class ComposerController extends BaseController { ) async { final newEmailBody = await _getEmailBodyText(context, changedEmail: true); log('ComposerController::_isEmailChanged(): newEmailBody: $newEmailBody'); - var oldEmailBody = ''; - if (context.mounted) { - 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?.signatureAsString.isNotEmpty == true) { - oldEmailBody = '$oldEmailBody${identitySelected.value?.signatureAsString.toSignatureBlock()}'; - } - } - + var oldEmailBody = _initTextEditor ?? ''; log('ComposerController::_isEmailChanged(): oldEmailBody: $oldEmailBody'); final isEmailBodyChanged = !oldEmailBody.trim().isSame(newEmailBody.trim()); log('ComposerController::_isEmailChanged(): isEmailBodyChanged: $isEmailBodyChanged'); - final newEmailSubject = subjectEmail.value; + final newEmailSubject = subjectEmail.value ?? ''; final titleEmail = arguments.presentationEmail?.getEmailTitle().trim() ?? ''; - final oldEmailSubject = arguments.emailActionType.getSubjectComposer(currentContext!, titleEmail); - final isEmailSubjectChanged = !oldEmailSubject.isSame(newEmailSubject); + final oldEmailSubject = arguments.emailActionType == EmailActionType.edit ? titleEmail : ''; + final isEmailSubjectChanged = !oldEmailSubject.trim().isSame(newEmailSubject.trim()); final recipients = arguments.presentationEmail ?.generateRecipientsEmailAddressForComposer(arguments.emailActionType, arguments.mailboxRole) ?? const Tuple3([], [], []); final newToEmailAddress = listToEmailAddress; - final oldToEmailAddress = recipients.value1; + final oldToEmailAddress = arguments.emailActionType == EmailActionType.edit ? recipients.value1 : []; final isToEmailAddressChanged = !oldToEmailAddress.isSame(newToEmailAddress); - final newCcEmailAddress = listToEmailAddress; - final oldCcEmailAddress = recipients.value1; + final newCcEmailAddress = listCcEmailAddress; + final oldCcEmailAddress = arguments.emailActionType == EmailActionType.edit ? recipients.value2 : []; final isCcEmailAddressChanged = !oldCcEmailAddress.isSame(newCcEmailAddress); - final newBccEmailAddress = listToEmailAddress; - final oldBccEmailAddress = recipients.value1; + final newBccEmailAddress = listBccEmailAddress; + final oldBccEmailAddress = arguments.emailActionType == EmailActionType.edit ? recipients.value3 : []; final isBccEmailAddressChanged = !oldBccEmailAddress.isSame(newBccEmailAddress); final isAttachmentsChanged = !initialAttachments.isSame(uploadController.attachmentsUploaded.toList()); @@ -1129,6 +1133,7 @@ class ComposerController extends BaseController { _updateTextForEditor(); screenDisplayMode.value = displayMode; _autoFocusFieldWhenLauncher(); + selectIdentity(identitySelected.value); } void _updateTextForEditor() async { @@ -1335,7 +1340,7 @@ class ComposerController extends BaseController { _removeBccEmailAddressFromFormerIdentity(formerIdentity.bcc!); } - if (!_isMobileApp) { + if (!_isMobileApp && newIdentity != formerIdentity) { _removeSignature(); } } @@ -1345,8 +1350,10 @@ class ComposerController extends BaseController { await _applyBccEmailAddressFromIdentity(newIdentity.bcc!); } - if (!_isMobileApp && newIdentity.signatureAsString.isNotEmpty == true) { - _applySignature(newIdentity.signatureAsString); + if (!_isMobileApp + && newIdentity != formerIdentity + && newIdentity.signatureAsString.isNotEmpty == true) { + _applySignature(newIdentity.signatureAsString.asSignatureHtml()); } return Future.value(null); @@ -1379,12 +1386,10 @@ class ComposerController extends BaseController { } void _applySignature(String signature) { - final signatureAsHtml = '--

$signature'; - log('ComposerController::_applySignature(): $signatureAsHtml'); if (BuildUtils.isWeb) { - richTextWebController.editorController.insertSignature(signatureAsHtml); + richTextWebController.editorController.insertSignature(signature); } else { - htmlEditorApi?.insertSignature(signatureAsHtml); + htmlEditorApi?.insertSignature(signature); } } @@ -1528,4 +1533,26 @@ class ComposerController extends BaseController { ); } } + + void handleInitHtmlEditorWeb(String initContent) { + onChangeTextEditorWeb(initContent); + richTextWebController.setEnableCodeView(); + } + + void handleOnFocusHtmlEditorWeb() { + FocusManager.instance.primaryFocus?.unfocus(); + Future.delayed(const Duration(milliseconds: 500), () { + richTextWebController.editorController.setFocus(); + }); + richTextWebController.closeAllMenuPopup(); + } + + void handleOnUnFocusHtmlEditorWeb() { + onEditorFocusChange(false); + } + + void handleOnMouseDownHtmlEditorWeb(BuildContext context) { + Navigator.maybePop(context); + onEditorFocusChange(true); + } } \ No newline at end of file diff --git a/lib/features/composer/presentation/composer_view.dart b/lib/features/composer/presentation/composer_view.dart index 59d17b5d5..97adea488 100644 --- a/lib/features/composer/presentation/composer_view.dart +++ b/lib/features/composer/presentation/composer_view.dart @@ -622,7 +622,7 @@ class ComposerView extends GetWidget minHeight: 550, addDefaultSelectionMenuItems: false, initialContent: initialContent ?? '', - onCreated: (editorApi) => controller.initRichTextForMobile(context, editorApi) + onCreated: (editorApi) => controller.initRichTextForMobile(context, editorApi, initialContent) ), ); } diff --git a/lib/features/composer/presentation/composer_view_web.dart b/lib/features/composer/presentation/composer_view_web.dart index 6fd32dc54..610c928de 100644 --- a/lib/features/composer/presentation/composer_view_web.dart +++ b/lib/features/composer/presentation/composer_view_web.dart @@ -774,52 +774,36 @@ class ComposerView extends GetWidget 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: HtmlEditor( - key: const Key('composer_editor_web'), - controller: controller.richTextWebController.editorController, - htmlEditorOptions: const HtmlEditorOptions( - shouldEnsureVisible: true, - hint: '', - darkMode: false, - customBodyCssStyle: bodyCssStyleForEditor), - blockQuotedContent: initContent, - htmlToolbarOptions: const HtmlToolbarOptions( - toolbarType: ToolbarType.hide, - defaultToolbarButtons: []), - otherOptions: const OtherOptions(height: 550), - callbacks: Callbacks(onBeforeCommand: (currentHtml) { - log('ComposerView::_buildHtmlEditor(): onBeforeCommand : $currentHtml'); - controller.setTextEditorWeb(currentHtml); - }, onChangeContent: (changed) { - log('ComposerView::_buildHtmlEditor(): onChangeContent : $changed'); - controller.setTextEditorWeb(changed); - }, onInit: () { - log('ComposerView::_buildHtmlEditor(): onInit'); - controller.setTextEditorWeb(initContent); - controller.richTextWebController.setEnableCodeView(); - }, onFocus: () { - log('ComposerView::_buildHtmlEditor(): onFocus'); - FocusManager.instance.primaryFocus?.unfocus(); - Future.delayed(const Duration(milliseconds: 500), () { - controller.richTextWebController.editorController.setFocus(); - }); - controller.richTextWebController.closeAllMenuPopup(); - }, onBlur: () { - controller.onEditorFocusChange(false); - }, onMouseDown: () { - Navigator.maybePop(context); - controller.onEditorFocusChange(true); - }, onChangeSelection: (settings) { - controller.richTextWebController.onEditorSettingsChange(settings); - }, onChangeCodeview: (contentChanged) { - log('ComposerView::_buildHtmlEditor(): onChangeCodeView : $contentChanged'); - controller.setTextEditorWeb(contentChanged); - }), - ) + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 10), + child: HtmlEditor( + key: const Key('composer_editor_web'), + controller: controller.richTextWebController.editorController, + htmlEditorOptions: const HtmlEditorOptions( + shouldEnsureVisible: true, + hint: '', + darkMode: false, + customBodyCssStyle: bodyCssStyleForEditor + ), + blockQuotedContent: initContent, + htmlToolbarOptions: const HtmlToolbarOptions( + toolbarType: ToolbarType.hide, + toolbarPosition: ToolbarPosition.custom, + defaultToolbarButtons: [] + ), + otherOptions: const OtherOptions(height: 550), + callbacks: Callbacks( + onBeforeCommand: controller.onChangeTextEditorWeb, + onChangeContent: controller.onChangeTextEditorWeb, + onInit: () => controller.handleInitHtmlEditorWeb(initContent), + onFocus: controller.handleOnFocusHtmlEditorWeb, + onBlur: controller.handleOnUnFocusHtmlEditorWeb, + onMouseDown: () => controller.handleOnMouseDownHtmlEditorWeb(context), + onChangeSelection: controller.richTextWebController.onEditorSettingsChange, + onChangeCodeview: controller.onChangeTextEditorWeb + ), ) + ) ); } diff --git a/pubspec.lock b/pubspec.lock index 98044cc66..e762c6dc9 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -365,7 +365,7 @@ packages: description: path: "." ref: email_supported - resolved-ref: cd9b1ed2667348f7663c8947bb41f0a9321e09d7 + resolved-ref: "8eeda3863740f7e1961a7157dff474d20f3c5209" url: "https://github.com/linagora/enough_html_editor.git" source: git version: "0.0.5" @@ -867,7 +867,7 @@ packages: description: path: "." ref: email_supported - resolved-ref: "750fc01e09b5a98b06463e336a4b30851d90fa70" + resolved-ref: e9f24750953af0a3ec030affe2542c8261ce5f47 url: "https://github.com/linagora/html-editor-enhanced.git" source: git version: "2.5.1" @@ -1657,26 +1657,26 @@ packages: dependency: transitive description: name: vector_graphics - sha256: "2f317d969a9f1eb59d1890643107da749698b7c08c4b0532fc95c8a7130d2803" + sha256: "4cf8e60dbe4d3a693d37dff11255a172594c0793da542183cbfe7fe978ae4aaa" url: "https://pub.dev" source: hosted - version: "1.1.3" + version: "1.1.4" vector_graphics_codec: dependency: transitive description: name: vector_graphics_codec - sha256: "13cccfda2dd61232a19dfb769b7a907e2ab23aabfebb9053c81e29c6c11b1766" + sha256: "278ad5f816f58b1967396d1f78ced470e3e58c9fe4b27010102c0a595c764468" url: "https://pub.dev" source: hosted - version: "1.1.3" + version: "1.1.4" vector_graphics_compiler: dependency: transitive description: name: vector_graphics_compiler - sha256: "524c9889a1327401124fe068840a8867f0d57987c1219a2a696ade629ec2bec3" + sha256: "0bf61ad56e6fd6688a2865d3ceaea396bc6a0a90ea0d7ad5049b1b76c09d6163" url: "https://pub.dev" source: hosted - version: "1.1.3" + version: "1.1.4" vector_math: dependency: transitive description: