TF-2189 Edit sending email in Sending Queue on iOS

Signed-off-by: dab246 <tdvu@linagora.com>
(cherry picked from commit 79e1e2de5555973a5ba4a0c2b8fc3c091bcd63a3)
This commit is contained in:
dab246
2023-10-19 13:51:54 +07:00
committed by Dat H. Pham
parent a956685829
commit 3481e659df
11 changed files with 226 additions and 176 deletions
@@ -12,10 +12,19 @@ class SendEmailLoading extends UIState {}
class SendEmailSuccess extends UIActionState {
final String? storedSendingId;
SendEmailSuccess({
jmap.State? currentEmailState,
jmap.State? currentMailboxState,
this.storedSendingId,
}) : super(currentEmailState, currentMailboxState);
@override
List<Object?> get props => [
...super.props,
storedSendingId,
];
}
class SendEmailFailure extends FeatureFailure {
@@ -34,4 +43,14 @@ class SendEmailFailure extends FeatureFailure {
this.mailboxRequest,
this.sendingEmailActionType
}) : super(exception: exception);
@override
List<Object?> get props => [
...super.props,
session,
accountId,
emailRequest,
mailboxRequest,
sendingEmailActionType,
];
}
@@ -51,7 +51,8 @@ class SendEmailInteractor {
yield Right<Failure, Success>(
SendEmailSuccess(
currentEmailState: currentEmailState,
currentMailboxState: currentMailboxState
currentMailboxState: currentMailboxState,
storedSendingId: emailRequest.storedSendingId
)
);
} else {
@@ -54,6 +54,7 @@ import 'package:tmail_ui_user/features/composer/presentation/model/draggable_ema
import 'package:tmail_ui_user/features/composer/presentation/model/image_source.dart';
import 'package:tmail_ui_user/features/composer/presentation/model/inline_image.dart';
import 'package:tmail_ui_user/features/composer/presentation/model/prefix_recipient_state.dart';
import 'package:tmail_ui_user/features/composer/presentation/model/save_to_draft_arguments.dart';
import 'package:tmail_ui_user/features/composer/presentation/model/save_to_draft_view_event.dart';
import 'package:tmail_ui_user/features/composer/presentation/model/screen_display_mode.dart';
import 'package:tmail_ui_user/features/composer/presentation/styles/composer_style.dart';
@@ -856,108 +857,98 @@ class ComposerController extends BaseController {
_handleSendMessages(context);
}
bool get _isParamUserNull {
if (composerArguments.value == null ||
mailboxDashBoardController.userProfile.value == null ||
mailboxDashBoardController.sessionCurrent == null ||
mailboxDashBoardController.accountId.value == null
) {
logError('ComposerController::isParamUserNotNull: Param is NULL');
return true;
}
return false;
}
void _handleSendMessages(BuildContext context) async {
final session = mailboxDashBoardController.sessionCurrent;
final arguments = composerArguments.value;
final accountId = mailboxDashBoardController.accountId.value;
final sentMailboxId = mailboxDashBoardController.mapDefaultMailboxIdByRole[PresentationMailbox.roleSent];
final outboxMailboxId = mailboxDashBoardController.outboxMailbox?.id;
final userProfile = mailboxDashBoardController.userProfile.value;
if (_isParamUserNull) {
logError('ComposerController::_handleSendMessages: Param is NULL');
_closeComposerAction();
return;
}
if (arguments != null && accountId != null && userProfile != null && session != null) {
final createdEmail = await _generateEmail(
context,
userProfile,
outboxMailboxId: outboxMailboxId,
arguments: arguments
);
final emailRequest = arguments.emailActionType == EmailActionType.editSendingEmail
? arguments.sendingEmail!.toEmailRequest(newEmail: createdEmail)
: EmailRequest(
email: createdEmail,
sentMailboxId: sentMailboxId,
identityId: identitySelected?.id,
emailIdDestroyed: arguments.emailActionType == EmailActionType.editDraft
? arguments.presentationEmail?.id
: null,
emailIdAnsweredOrForwarded: arguments.presentationEmail?.id,
emailActionType: arguments.emailActionType
);
final mailboxRequest = outboxMailboxId == null
? CreateNewMailboxRequest(Id(_uuid.v1()), PresentationMailbox.outboxMailboxName)
: null;
if (!networkConnectionController.isNetworkConnectionAvailable()) {
switch(arguments.sendingEmailActionType) {
case SendingEmailActionType.create:
_showConfirmDialogStoreSendingEmail(
SendingEmailArguments(
session,
accountId,
emailRequest,
mailboxRequest,
actionMode: ComposeActionMode.pushQueue
)
);
break;
case SendingEmailActionType.edit:
uploadController.clearInlineFileUploaded();
_closeComposerAction(
result: SendingEmailArguments(
session,
accountId,
emailRequest,
mailboxRequest,
actionMode: ComposeActionMode.editQueue
)
);
break;
default:
uploadController.clearInlineFileUploaded();
_closeComposerAction(
result: SendingEmailArguments(
session,
accountId,
emailRequest,
mailboxRequest,
)
);
}
if (networkConnectionController.isNetworkConnectionAvailable()) {
final sendingArgs = await _createSendingEmailArguments(context);
_closeComposerAction(result: sendingArgs);
} else {
if (composerArguments.value!.sendingEmailActionType == SendingEmailActionType.create) {
_showConfirmDialogStoreSendingEmail(context);
} else {
uploadController.clearInlineFileUploaded();
final sendingArgs = await _createSendingEmailArguments(context);
_closeComposerAction(
result: SendingEmailArguments(
session,
accountId,
emailRequest,
mailboxRequest,
)
result: composerArguments.value!.sendingEmailActionType == SendingEmailActionType.edit
? sendingArgs.copyWith(actionMode: ComposeActionMode.editQueue)
: sendingArgs
);
}
} else {
logError('ComposerController::_handleSendMessages: arguments/accountId/userProfile/session is NULL');
uploadController.clearInlineFileUploaded();
_closeComposerAction();
}
}
void _showConfirmDialogStoreSendingEmail(SendingEmailArguments sendingEmailArguments) {
Future<SendingEmailArguments> _createSendingEmailArguments(BuildContext context) async {
final session = mailboxDashBoardController.sessionCurrent!;
final arguments = composerArguments.value!;
final accountId = mailboxDashBoardController.accountId.value!;
final userProfile = mailboxDashBoardController.userProfile.value!;
final createdEmail = await _generateEmail(
context,
userProfile,
outboxMailboxId: mailboxDashBoardController.outboxMailbox?.id,
arguments: arguments
);
final emailRequest = arguments.emailActionType == EmailActionType.editSendingEmail
? arguments.sendingEmail!.toEmailRequest(newEmail: createdEmail)
: EmailRequest(
email: createdEmail,
sentMailboxId: mailboxDashBoardController.mapDefaultMailboxIdByRole[PresentationMailbox.roleSent],
identityId: identitySelected?.id,
emailIdDestroyed: arguments.emailActionType == EmailActionType.editDraft
? arguments.presentationEmail?.id
: null,
emailIdAnsweredOrForwarded: arguments.presentationEmail?.id,
emailActionType: arguments.emailActionType
);
final mailboxRequest = mailboxDashBoardController.outboxMailbox?.id == null
? CreateNewMailboxRequest(
Id(_uuid.v1()),
PresentationMailbox.outboxMailboxName
)
: null;
return SendingEmailArguments(
session,
accountId,
emailRequest,
mailboxRequest,
);
}
void _showConfirmDialogStoreSendingEmail(BuildContext context) {
showConfirmDialogAction(
currentContext!,
context,
PlatformInfo.isIOS
? AppLocalizations.of(currentContext!).messageDialogOfflineModeOnIOS
? AppLocalizations.of(context).messageDialogOfflineModeOnIOS
: '',
AppLocalizations.of(currentContext!).proceed,
onConfirmAction: () {
uploadController.clearInlineFileUploaded();
_closeComposerAction(result: sendingEmailArguments);
AppLocalizations.of(context).proceed,
onConfirmAction: () async {
final sendingArgs = await _createSendingEmailArguments(context);
_closeComposerAction(
result: sendingArgs.copyWith(actionMode: ComposeActionMode.pushQueue)
);
},
onCancelAction: () {
uploadController.clearInlineFileUploaded();
_closeComposerAction();
},
title: AppLocalizations.of(currentContext!).youAreInOfflineMode,
onCancelAction: _closeComposerAction,
title: AppLocalizations.of(context).youAreInOfflineMode,
icon: SvgPicture.asset(_imagePaths.icDialogOfflineMode),
alignCenter: true,
messageStyle: const TextStyle(
@@ -968,25 +959,25 @@ class ComposerController extends BaseController {
listTextSpan: PlatformInfo.isIOS
? null
: [
TextSpan(text: AppLocalizations.of(currentContext!).messageDialogWhenStoreSendingEmailFirst),
TextSpan(text: AppLocalizations.of(context).messageDialogWhenStoreSendingEmailFirst),
TextSpan(
text: AppLocalizations.of(currentContext!).messageDialogWhenStoreSendingEmailSecond,
text: AppLocalizations.of(context).messageDialogWhenStoreSendingEmailSecond,
style: const TextStyle(
color: AppColor.colorTitleSendingItem,
fontSize: 15,
fontWeight: FontWeight.w600
),
),
TextSpan(text: AppLocalizations.of(currentContext!).messageDialogWhenStoreSendingEmailThird),
TextSpan(text: AppLocalizations.of(context).messageDialogWhenStoreSendingEmailThird),
TextSpan(
text: AppLocalizations.of(currentContext!).sendingQueue,
text: AppLocalizations.of(context).sendingQueue,
style: const TextStyle(
color: AppColor.colorTitleSendingItem,
fontSize: 15,
fontWeight: FontWeight.w600
),
),
TextSpan(text: AppLocalizations.of(currentContext!).messageDialogWhenStoreSendingEmailTail)
TextSpan(text: AppLocalizations.of(context).messageDialogWhenStoreSendingEmailTail)
]
);
}
@@ -1195,12 +1186,7 @@ class ComposerController extends BaseController {
accountId == null
) {
logError('ComposerController::saveToDraftAndClose: Param is NULL');
uploadController.clearInlineFileUploaded();
if (PlatformInfo.isWeb) {
mailboxDashBoardController.closeComposerOverlay();
} else {
if (canPop) popBack();
}
_closeComposerAction();
return;
}
@@ -1213,12 +1199,12 @@ class ComposerController extends BaseController {
arguments: arguments,
);
mailboxDashBoardController.updateEmailToDraft(
_closeComposerAction(result: SaveToDraftArguments(
session: session,
accountId: accountId,
newEmail: newEmail,
oldEmailId: _emailIdEditing!
);
));
} else {
final isChanged = await _isEmailChanged(
context: context,
@@ -1236,29 +1222,18 @@ class ComposerController extends BaseController {
arguments: arguments,
);
if (arguments.emailActionType == EmailActionType.editDraft &&
arguments.presentationEmail?.id != null) {
mailboxDashBoardController.updateEmailToDraft(
session: session,
accountId: accountId,
newEmail: newEmail,
oldEmailId: arguments.presentationEmail!.id!
);
} else {
mailboxDashBoardController.saveEmailToDraft(
session: session,
accountId: accountId,
email: newEmail
);
}
_closeComposerAction(result: SaveToDraftArguments(
session: session,
accountId: accountId,
newEmail: newEmail,
oldEmailId: arguments.emailActionType == EmailActionType.editDraft
? arguments.presentationEmail?.id
: null
));
} else {
_closeComposerAction();
}
}
uploadController.clearInlineFileUploaded();
if (PlatformInfo.isWeb) {
mailboxDashBoardController.closeComposerOverlay();
} else {
if (canPop) popBack();
}
}
void saveToDraftAction(BuildContext context) {
@@ -1294,21 +1269,14 @@ class ComposerController extends BaseController {
draftMailboxId: event.draftMailboxId,
arguments: event.arguments
);
if (event.emailIdEditing == null) {
mailboxDashBoardController.saveEmailToDraft(
session: event.session,
accountId: event.accountId,
email: newEmail
);
} else {
mailboxDashBoardController.updateEmailToDraft(
mailboxDashBoardController.saveEmailToDraft(
arguments: SaveToDraftArguments(
session: event.session,
accountId: event.accountId,
newEmail: newEmail,
oldEmailId: event.emailIdEditing!
);
}
oldEmailId: event.emailIdEditing
)
);
}
File _covertSharedMediaFileToFile(SharedMediaFile sharedMediaFile) {
@@ -1473,6 +1441,8 @@ class ComposerController extends BaseController {
}
void _closeComposerAction({dynamic result}) {
uploadController.clearInlineFileUploaded();
if (PlatformInfo.isWeb) {
_closeComposerWeb(result: result);
} else {
@@ -1481,7 +1451,6 @@ class ComposerController extends BaseController {
}
void _closeComposerWeb({dynamic result}) {
FocusManager.instance.primaryFocus?.unfocus();
mailboxDashBoardController.closeComposerOverlay(result: result);
}
@@ -0,0 +1,26 @@
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/core/session/session.dart';
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
import 'package:tmail_ui_user/main/routes/router_arguments.dart';
class SaveToDraftArguments extends RouterArguments {
final Session session;
final AccountId accountId;
final Email newEmail;
final EmailId? oldEmailId;
SaveToDraftArguments({
required this.session,
required this.accountId,
required this.newEmail,
required this.oldEmailId
});
@override
List<Object?> get props => [
session,
accountId,
newEmail,
oldEmailId,
];
}
@@ -362,7 +362,8 @@ class MailboxController extends BaseMailboxController with MailboxActionHandlerM
void _selectSelectedMailboxDefault() {
final isSearchEmailRunning = mailboxDashBoardController.searchController.isSearchEmailRunning;
if (isSearchEmailRunning) {
final dashboardRoute = mailboxDashBoardController.dashboardRoute.value;
if (isSearchEmailRunning || dashboardRoute == DashboardRoutes.sendingQueue) {
log('MailboxController::_selectMailboxDefault(): isSearchEmailRunning is $isSearchEmailRunning');
return;
}
@@ -86,6 +86,7 @@ import 'package:tmail_ui_user/features/offline_mode/manager/sending_email_cache_
import 'package:tmail_ui_user/features/quotas/presentation/quotas_bindings.dart';
import 'package:tmail_ui_user/features/search/email/domain/usecases/refresh_changes_search_email_interactor.dart';
import 'package:tmail_ui_user/features/search/email/presentation/search_email_bindings.dart';
import 'package:tmail_ui_user/features/sending_queue/domain/usecases/delete_sending_email_interactor.dart';
import 'package:tmail_ui_user/features/sending_queue/domain/usecases/get_all_sending_email_interactor.dart';
import 'package:tmail_ui_user/features/sending_queue/domain/usecases/store_sending_email_interactor.dart';
import 'package:tmail_ui_user/features/sending_queue/domain/usecases/update_sending_email_interactor.dart';
@@ -168,6 +169,7 @@ class MailboxDashBoardBindings extends BaseBindings {
Get.find<EmptySpamFolderInteractor>(),
Get.find<SaveEmailAsDraftsInteractor>(),
Get.find<UpdateEmailDraftsInteractor>(),
Get.find<DeleteSendingEmailInteractor>(),
));
Get.put(AdvancedFilterController());
}
@@ -32,7 +32,9 @@ import 'package:tmail_ui_user/features/composer/domain/usecases/save_email_as_dr
import 'package:tmail_ui_user/features/composer/domain/usecases/send_email_interactor.dart';
import 'package:tmail_ui_user/features/composer/domain/usecases/update_email_drafts_interactor.dart';
import 'package:tmail_ui_user/features/composer/presentation/model/compose_action_mode.dart';
import 'package:tmail_ui_user/features/composer/presentation/model/save_to_draft_arguments.dart';
import 'package:tmail_ui_user/features/email/domain/model/mark_read_action.dart';
import 'package:tmail_ui_user/features/email/domain/state/delete_sending_email_state.dart';
import 'package:tmail_ui_user/features/email/domain/state/mark_as_email_read_state.dart';
import 'package:tmail_ui_user/features/email/domain/state/store_sending_email_state.dart';
import 'package:tmail_ui_user/features/composer/presentation/composer_bindings.dart';
@@ -105,6 +107,7 @@ import 'package:tmail_ui_user/features/push_notification/presentation/services/f
import 'package:tmail_ui_user/features/sending_queue/domain/model/sending_email.dart';
import 'package:tmail_ui_user/features/sending_queue/domain/state/get_all_sending_email_state.dart';
import 'package:tmail_ui_user/features/sending_queue/domain/state/update_sending_email_state.dart';
import 'package:tmail_ui_user/features/sending_queue/domain/usecases/delete_sending_email_interactor.dart';
import 'package:tmail_ui_user/features/sending_queue/domain/usecases/get_all_sending_email_interactor.dart';
import 'package:tmail_ui_user/features/sending_queue/domain/usecases/store_sending_email_interactor.dart';
import 'package:tmail_ui_user/features/sending_queue/domain/usecases/update_sending_email_interactor.dart';
@@ -172,6 +175,7 @@ class MailboxDashBoardController extends ReloadableController {
final EmptySpamFolderInteractor _emptySpamFolderInteractor;
final SaveEmailAsDraftsInteractor _saveEmailAsDraftsInteractor;
final UpdateEmailDraftsInteractor _updateEmailDraftsInteractor;
final DeleteSendingEmailInteractor _deleteSendingEmailInteractor;
GetAllVacationInteractor? _getAllVacationInteractor;
UpdateVacationInteractor? _updateVacationInteractor;
@@ -249,6 +253,7 @@ class MailboxDashBoardController extends ReloadableController {
this._emptySpamFolderInteractor,
this._saveEmailAsDraftsInteractor,
this._updateEmailDraftsInteractor,
this._deleteSendingEmailInteractor,
) : super(
getAuthenticatedAccountInteractor,
updateAuthenticationAccountInteractor
@@ -298,12 +303,7 @@ class MailboxDashBoardController extends ReloadableController {
dispatchMailboxUIAction(RefreshChangeMailboxAction(success.storedState));
_deleteMailboxStateToRefreshAction();
} else if (success is SendEmailSuccess) {
if (currentOverlayContext != null && currentContext != null) {
_appToast.showToastSuccessMessage(
currentOverlayContext!,
AppLocalizations.of(currentContext!).message_has_been_sent_successfully,
leadingSVGIcon: _imagePaths.icSendSuccessToast);
}
_handleSendEmailSuccess(success);
} else if (success is SaveEmailAsDraftsSuccess) {
_saveEmailAsDraftsSuccess(success);
} else if (success is MoveToMailboxSuccess) {
@@ -347,6 +347,8 @@ class MailboxDashBoardController extends ReloadableController {
_emptySpamFolderSuccess(success);
} else if (success is MarkAsEmailReadSuccess) {
_markAsReadEmailSuccess(success);
} else if (success is DeleteSendingEmailSuccess) {
getAllSendingEmails();
}
}
@@ -1261,6 +1263,8 @@ class MailboxDashBoardController extends ReloadableController {
if (result is SendingEmailArguments) {
handleSendEmailAction(result);
} else if (result is SaveToDraftArguments) {
saveEmailToDraft(arguments: result);
}
}
@@ -1373,6 +1377,8 @@ class MailboxDashBoardController extends ReloadableController {
final result = await push(AppRoutes.composer, arguments: arguments);
if (result is SendingEmailArguments) {
handleSendEmailAction(result);
} else if (result is SaveToDraftArguments) {
saveEmailToDraft(arguments: result);
}
}
}
@@ -2081,34 +2087,46 @@ class MailboxDashBoardController extends ReloadableController {
draggableAppState.value = DraggableAppState.inActive;
}
void saveEmailToDraft({
required Session session,
required AccountId accountId,
required Email email
}) {
consumeState(
_saveEmailAsDraftsInteractor.execute(
session,
accountId,
email
)
);
void saveEmailToDraft({required SaveToDraftArguments arguments}) {
if (arguments.oldEmailId != null) {
consumeState(
_updateEmailDraftsInteractor.execute(
arguments.session,
arguments.accountId,
arguments.newEmail,
arguments.oldEmailId!
)
);
} else {
consumeState(
_saveEmailAsDraftsInteractor.execute(
arguments.session,
arguments.accountId,
arguments.newEmail,
)
);
}
}
void updateEmailToDraft({
required Session session,
required AccountId accountId,
required Email newEmail,
required EmailId oldEmailId
}) {
consumeState(
_updateEmailDraftsInteractor.execute(
session,
accountId,
newEmail,
oldEmailId
)
);
void _handleSendEmailSuccess(SendEmailSuccess success) {
if (PlatformInfo.isIOS &&
success.storedSendingId != null &&
accountId.value != null &&
sessionCurrent != null
) {
consumeState(_deleteSendingEmailInteractor.execute(
accountId.value!,
sessionCurrent!.username,
success.storedSendingId!
));
}
if (currentOverlayContext != null && currentContext != null) {
_appToast.showToastSuccessMessage(
currentOverlayContext!,
AppLocalizations.of(currentContext!).message_has_been_sent_successfully,
leadingSVGIcon: _imagePaths.icSendSuccessToast
);
}
}
@override
@@ -22,6 +22,20 @@ class SendingEmailArguments extends RouterArguments {
}
);
SendingEmailArguments copyWith({
Session? session,
AccountId? accountId,
EmailRequest? emailRequest,
CreateNewMailboxRequest? mailboxRequest,
ComposeActionMode? actionMode,
}) => SendingEmailArguments(
session ?? this.session,
accountId ?? this.accountId,
emailRequest ?? this.emailRequest,
mailboxRequest ?? this.mailboxRequest,
actionMode: actionMode ?? this.actionMode
);
@override
List<Object?> get props => [
session,
@@ -192,9 +192,7 @@ class SendingQueueController extends BaseController with MessageDialogActionMixi
_deleteListSendingEmailAction(context, listSendingEmails);
break;
case SendingEmailActionType.edit:
if (!isConnectedNetwork) {
_editSendingEmailAction(listSendingEmails.first);
}
_editSendingEmailAction(listSendingEmails.first);
break;
case SendingEmailActionType.create:
break;
@@ -94,7 +94,11 @@ class SendingQueueView extends GetWidget<SendingQueueController> with AppLoaderM
onLongPressAction: controller.handleOnLongPressAction,
onSelectLeadingAction: controller.toggleSelectionSendingEmail,
onTapAction: (actionType, sendingEmail) {
if (!controller.isConnectedNetwork && sendingEmail.isEditableSupported) {
if (PlatformInfo.isAndroid &&
!controller.isConnectedNetwork &&
sendingEmail.isEditableSupported) {
controller.handleSendingEmailActionType(context, actionType, [sendingEmail]);
} else if (PlatformInfo.isIOS && sendingEmail.isEditableSupported) {
controller.handleSendingEmailActionType(context, actionType, [sendingEmail]);
}
});
@@ -4,8 +4,6 @@ import 'package:flutter/cupertino.dart';
class SendingQueueUtils {
static EdgeInsets getMarginBannerMessageByResponsiveSize(double width) {
if (ResponsiveUtils.isMatchedMobileWidth(width)) {
return const EdgeInsets.only(top: 16, left: 16, right: 16);