diff --git a/lib/features/composer/presentation/composer_controller.dart b/lib/features/composer/presentation/composer_controller.dart index 3c447d824..416e562d0 100644 --- a/lib/features/composer/presentation/composer_controller.dart +++ b/lib/features/composer/presentation/composer_controller.dart @@ -34,6 +34,7 @@ import 'package:rich_text_composer/rich_text_composer.dart'; import 'package:rxdart/rxdart.dart'; import 'package:super_tag_editor/tag_editor.dart'; import 'package:tmail_ui_user/features/base/base_controller.dart'; +import 'package:tmail_ui_user/features/base/state/button_state.dart'; import 'package:tmail_ui_user/features/composer/domain/model/contact_suggestion_source.dart'; import 'package:tmail_ui_user/features/composer/domain/model/email_request.dart'; import 'package:tmail_ui_user/features/composer/domain/state/download_image_as_base64_state.dart'; @@ -167,9 +168,11 @@ class ComposerController extends BaseController { double? maxWithEditor; EmailId? _emailIdEditing; bool isAttachmentCollapsed = false; + ButtonState _closeComposerButtonState = ButtonState.enabled; late Worker uploadInlineImageWorker; late Worker dashboardViewStateWorker; + late bool _isEmailBodyLoaded; ComposerController( this._deviceInfoPlugin, @@ -408,12 +411,14 @@ class ComposerController extends BaseController { } void onLoadCompletedMobileEditorAction(HtmlEditorApi editorApi, WebUri? url) { + _isEmailBodyLoaded = true; if (identitySelected.value == null) { _getAllIdentities(); } } void _initEmail() { + _isEmailBodyLoaded = false; final arguments = PlatformInfo.isWeb ? mailboxDashBoardController.composerArguments : Get.arguments; @@ -785,7 +790,7 @@ class ComposerController extends BaseController { return; } - clearFocusEditor(context); + clearFocus(context); isSendEmailLoading.value = true; @@ -1025,7 +1030,7 @@ class ComposerController extends BaseController { } void openPickAttachmentMenu(BuildContext context, List actionTiles) { - clearFocusEditor(context); + clearFocus(context); (ContextMenuBuilder(context) ..addHeader((ContextMenuHeaderBuilder(const Key('attachment_picker_context_menu_header_builder')) @@ -1083,18 +1088,16 @@ class ComposerController extends BaseController { uploadController.deleteFileUploaded(uploadId); } - Future _isEmailChanged({ + Future _validateEmailChange({ required BuildContext context, required EmailActionType emailActionType, PresentationEmail? presentationEmail, Role? mailboxRole, }) async { final newEmailBody = await _getEmailBodyText(context, asDrafts: true); - log('ComposerController::_isEmailChanged(): newEmailBody: $newEmailBody'); final oldEmailBody = _initTextEditor ?? ''; - log('ComposerController::_isEmailChanged(): oldEmailBody: $oldEmailBody'); final isEmailBodyChanged = !oldEmailBody.trim().isSame(newEmailBody.trim()); - log('ComposerController::_isEmailChanged(): isEmailBodyChanged: $isEmailBodyChanged'); + final newEmailSubject = subjectEmail.value ?? ''; final oldEmailSubject = emailActionType == EmailActionType.editDraft ? presentationEmail?.getEmailTitle().trim() ?? '' @@ -1120,7 +1123,7 @@ class ComposerController extends BaseController { final isBccEmailAddressChanged = !oldBccEmailAddress.isSame(newBccEmailAddress); final isAttachmentsChanged = !initialAttachments.isSame(uploadController.attachmentsUploaded.toList()); - + log('ComposerController::_validateChangeEmail: isEmailBodyChanged = $isEmailBodyChanged | isEmailSubjectChanged = $isEmailSubjectChanged | isToEmailAddressChanged = $isToEmailAddressChanged | isCcEmailAddressChanged = $isCcEmailAddressChanged | isBccEmailAddressChanged = $isBccEmailAddressChanged | isAttachmentsChanged = $isAttachmentsChanged'); if (isEmailBodyChanged || isEmailSubjectChanged || isToEmailAddressChanged || isCcEmailAddressChanged || isBccEmailAddressChanged || isAttachmentsChanged) { @@ -1130,10 +1133,8 @@ class ComposerController extends BaseController { return false; } - void saveToDraftAndClose(BuildContext context) async { - log('ComposerController::saveToDraftAndClose:'); - clearFocusEditor(context); - + Future _handleSaveAsDrafts(BuildContext context) async { + log('ComposerController::_handleSaveAsDrafts:'); final arguments = composerArguments.value; final userProfile = mailboxDashBoardController.userProfile.value; final accountId = mailboxDashBoardController.accountId.value; @@ -1146,9 +1147,7 @@ class ComposerController extends BaseController { session == null || accountId == null ) { - logError('ComposerController::saveToDraftAndClose: Param is NULL'); - _closeComposerAction(); - return; + return null; } if (_emailIdEditing != null && _emailIdEditing != arguments.presentationEmail?.id) { @@ -1160,20 +1159,19 @@ class ComposerController extends BaseController { arguments: arguments, ); - _closeComposerAction(result: SaveToDraftArguments( + return SaveToDraftArguments( session: session, accountId: accountId, newEmail: newEmail, - oldEmailId: _emailIdEditing! - )); + oldEmailId: _emailIdEditing!); } else { - final isChanged = await _isEmailChanged( + final isChanged = await _validateEmailChange( context: context, emailActionType: arguments.emailActionType, presentationEmail: arguments.presentationEmail, mailboxRole: arguments.mailboxRole ); - log('ComposerController::saveToDraftAndClose: isChanged: $isChanged'); + if (isChanged && context.mounted) { final newEmail = await _generateEmail( context, @@ -1183,16 +1181,15 @@ class ComposerController extends BaseController { arguments: arguments, ); - _closeComposerAction(result: SaveToDraftArguments( + return SaveToDraftArguments( session: session, accountId: accountId, newEmail: newEmail, oldEmailId: arguments.emailActionType == EmailActionType.editDraft ? arguments.presentationEmail?.id - : null - )); + : null); } else { - _closeComposerAction(); + return null; } } } @@ -1413,7 +1410,8 @@ class ComposerController extends BaseController { return ''; } - void clearFocusEditor(BuildContext context) { + void clearFocus(BuildContext context) { + log('ComposerController::clearFocus:'); if (PlatformInfo.isMobile) { htmlEditorApi?.unfocus(); KeyboardUtils.hideSystemKeyboardMobile(); @@ -1422,21 +1420,16 @@ class ComposerController extends BaseController { } void _closeComposerAction({dynamic result}) { - uploadController.clearInlineFileUploaded(); + log('ComposerController::_closeComposerAction:'); + isSendEmailLoading.value = false; if (PlatformInfo.isWeb) { - _closeComposerWeb(result: result); + mailboxDashBoardController.closeComposerOverlay(result: result); } else { - isSendEmailLoading.value = false; popBack(result: result); } } - void _closeComposerWeb({dynamic result}) { - isSendEmailLoading.value = false; - mailboxDashBoardController.closeComposerOverlay(result: result); - } - void displayScreenTypeComposerAction(ScreenDisplayMode displayMode) async { createFocusNodeInput(); _updateTextForEditor(); @@ -1722,7 +1715,7 @@ class ComposerController extends BaseController { } void insertImage(BuildContext context, double maxWith) async { - clearFocusEditor(context); + clearFocus(context); if (responsiveUtils.isMobile(context)) { maxWithEditor = maxWith - 40; @@ -1915,6 +1908,8 @@ class ComposerController extends BaseController { subjectEmailInputFocusNode?.hasFocus == true; void handleInitHtmlEditorWeb(String initContent) { + log('ComposerController::handleInitHtmlEditorWeb:'); + _isEmailBodyLoaded = true; richTextWebController.editorController.setFullScreen(); onChangeTextEditorWeb(initContent); richTextWebController.setEnableCodeView(); @@ -2156,4 +2151,25 @@ class ComposerController extends BaseController { ..onTextSearchChangedAction((searchText) => _searchIdentities(searchText)) ).build(); } + + void handleClickCloseComposer(BuildContext context) async { + log('ComposerController::handleClickCloseComposer:'); + if (_closeComposerButtonState == ButtonState.disabled) { + log('ComposerController::handleClickCloseComposer: _closeComposerButtonState = disabled'); + return; + } + + if (!_isEmailBodyLoaded) { + log('ComposerController::handleClickCloseComposer: _isEmailBodyLoaded = false'); + clearFocus(context); + _closeComposerAction(); + return; + } + + _closeComposerButtonState = ButtonState.disabled; + clearFocus(context); + final draftArgs = await _handleSaveAsDrafts(context); + _closeComposerAction(result: draftArgs); + _closeComposerButtonState = ButtonState.enabled; + } } \ 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 0183896af..6d8edc8dc 100644 --- a/lib/features/composer/presentation/composer_view.dart +++ b/lib/features/composer/presentation/composer_view.dart @@ -37,8 +37,8 @@ class ComposerView extends GetWidget { responsiveUtils: controller.responsiveUtils, mobile: MobileContainerView( keyboardRichTextController: controller.keyboardRichTextController, - onCloseViewAction: () => controller.saveToDraftAndClose(context), - onClearFocusAction: () => controller.clearFocusEditor(context), + onCloseViewAction: () => controller.handleClickCloseComposer(context), + onClearFocusAction: () => controller.clearFocus(context), onAttachFileAction: () => controller.isNetworkConnectionAvailable ? controller.openPickAttachmentMenu( context, @@ -59,7 +59,7 @@ class ComposerView extends GetWidget { if (controller.responsiveUtils.isLandscapeMobile(context)) Obx(() => LandscapeAppBarComposerWidget( isSendButtonEnabled: controller.isEnableEmailSendButton.value, - onCloseViewAction: () => controller.saveToDraftAndClose(context), + onCloseViewAction: () => controller.handleClickCloseComposer(context), sendMessageAction: () => controller.validateInformationBeforeSending(context), openContextMenuAction: (position) { controller.openPopupMenuAction( @@ -73,7 +73,7 @@ class ComposerView extends GetWidget { else Obx(() => AppBarComposerWidget( isSendButtonEnabled: controller.isEnableEmailSendButton.value, - onCloseViewAction: () => controller.saveToDraftAndClose(context), + onCloseViewAction: () => controller.handleClickCloseComposer(context), sendMessageAction: () => controller.validateInformationBeforeSending(context), openContextMenuAction: (position) { controller.openPopupMenuAction( @@ -222,8 +222,8 @@ class ComposerView extends GetWidget { ), tablet: TabletContainerView( keyboardRichTextController: controller.keyboardRichTextController, - onCloseViewAction: () => controller.saveToDraftAndClose(context), - onClearFocusAction: () => controller.clearFocusEditor(context), + onCloseViewAction: () => controller.handleClickCloseComposer(context), + onClearFocusAction: () => controller.clearFocus(context), onAttachFileAction: () => controller.isNetworkConnectionAvailable ? controller.openPickAttachmentMenu( context, @@ -239,7 +239,7 @@ class ComposerView extends GetWidget { children: [ Obx(() => DesktopAppBarComposerWidget( emailSubject: controller.subjectEmail.value ?? '', - onCloseViewAction: () => controller.saveToDraftAndClose(context), + onCloseViewAction: () => controller.handleClickCloseComposer(context), constraints: constraints, )), Expanded( diff --git a/lib/features/composer/presentation/composer_view_web.dart b/lib/features/composer/presentation/composer_view_web.dart index c2aae40fe..f01067f6b 100644 --- a/lib/features/composer/presentation/composer_view_web.dart +++ b/lib/features/composer/presentation/composer_view_web.dart @@ -37,7 +37,7 @@ class ComposerView extends GetWidget { mobile: MobileResponsiveContainerView( childBuilder: (context, constraints) { return GestureDetector( - onTap: () => controller.clearFocusEditor(context), + onTap: () => controller.clearFocus(context), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -46,7 +46,7 @@ class ComposerView extends GetWidget { isFormattingOptionsEnabled: controller.richTextWebController.isFormattingOptionsEnabled, openRichToolbarAction: controller.richTextWebController.toggleFormattingOptions, isSendButtonEnabled: controller.isEnableEmailSendButton.value, - onCloseViewAction: () => controller.saveToDraftAndClose(context), + onCloseViewAction: () => controller.handleClickCloseComposer(context), attachFileAction: () => controller.openFilePickerByType(context, FileType.any), insertImageAction: () => controller.insertImage(context, constraints.maxWidth), sendMessageAction: () => controller.validateInformationBeforeSending(context), @@ -231,15 +231,12 @@ class ComposerView extends GetWidget { desktop: Obx(() => DesktopResponsiveContainerView( childBuilder: (context, constraints) { return GestureDetector( - onTap: () => controller.clearFocusEditor(context), + onTap: () => controller.clearFocus(context), child: Column(children: [ Obx(() => DesktopAppBarComposerWidget( emailSubject: controller.subjectEmail.value ?? '', displayMode: controller.screenDisplayMode.value, - onCloseViewAction: () { - controller.clearFocusEditor(context); - controller.saveToDraftAndClose(context); - }, + onCloseViewAction: () => controller.handleClickCloseComposer(context), onChangeDisplayModeAction: controller.displayScreenTypeComposerAction, constraints: constraints, )), @@ -461,17 +458,17 @@ class ComposerView extends GetWidget { }, displayMode: controller.screenDisplayMode.value, emailSubject: controller.subjectEmail.value ?? '', - onCloseViewAction: () => controller.saveToDraftAndClose(context), + onCloseViewAction: () => controller.handleClickCloseComposer(context), onChangeDisplayModeAction: controller.displayScreenTypeComposerAction, )), tablet: TabletResponsiveContainerView( childBuilder: (context, constraints) { return GestureDetector( - onTap: () => controller.clearFocusEditor(context), + onTap: () => controller.clearFocus(context), child: Column(children: [ Obx(() => DesktopAppBarComposerWidget( emailSubject: controller.subjectEmail.value ?? '', - onCloseViewAction: () => controller.saveToDraftAndClose(context), + onCloseViewAction: () => controller.handleClickCloseComposer(context), constraints: constraints, )), ConstrainedBox( diff --git a/lib/features/upload/presentation/controller/upload_controller.dart b/lib/features/upload/presentation/controller/upload_controller.dart index 7d5d23316..0073c4496 100644 --- a/lib/features/upload/presentation/controller/upload_controller.dart +++ b/lib/features/upload/presentation/controller/upload_controller.dart @@ -304,10 +304,6 @@ class UploadController extends BaseController { _uploadingStateInlineFiles.deleteElementByUploadTaskId(uploadId); } - void clearInlineFileUploaded() { - _uploadingStateInlineFiles.clear(); - } - void _handleUploadInlineAttachmentsSuccess(SuccessAttachmentUploadState success) { uploadInlineViewState.value = Right(success); }