TF-82 Edit a email draft
This commit is contained in:
@@ -9,8 +9,9 @@ class EmailRequest with EquatableMixin {
|
||||
final Email email;
|
||||
final Id submissionCreateId;
|
||||
final MailboxId? mailboxIdSaved;
|
||||
final EmailId? emailIdDestroyed;
|
||||
|
||||
EmailRequest(this.email, this.submissionCreateId, {this.mailboxIdSaved});
|
||||
EmailRequest(this.email, this.submissionCreateId, {this.mailboxIdSaved, this.emailIdDestroyed});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [email, submissionCreateId, mailboxIdSaved];
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
import 'package:core/core.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||
|
||||
class UpdateEmailDraftsSuccess extends UIState {
|
||||
|
||||
final Email emailAsDrafts;
|
||||
|
||||
UpdateEmailDraftsSuccess(this.emailAsDrafts);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [];
|
||||
}
|
||||
|
||||
class UpdateEmailDraftsFailure extends FeatureFailure {
|
||||
final exception;
|
||||
|
||||
UpdateEmailDraftsFailure(this.exception);
|
||||
|
||||
@override
|
||||
List<Object> get props => [exception];
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import 'package:core/core.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:jmap_dart_client/jmap/account_id.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/state/update_email_drafts_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/repository/email_repository.dart';
|
||||
|
||||
class UpdateEmailDraftsInteractor {
|
||||
final EmailRepository emailRepository;
|
||||
|
||||
UpdateEmailDraftsInteractor(this.emailRepository);
|
||||
|
||||
Stream<Either<Failure, Success>> execute(AccountId accountId, Email newEmail, EmailId oldEmailId) async* {
|
||||
try {
|
||||
final newEmailDrafts = await emailRepository.updateEmailDrafts(accountId, newEmail, oldEmailId);
|
||||
if (newEmailDrafts != null) {
|
||||
yield Right<Failure, Success>(UpdateEmailDraftsSuccess(newEmailDrafts));
|
||||
} else {
|
||||
yield Left<Failure, Success>(UpdateEmailDraftsFailure(null));
|
||||
}
|
||||
} catch (e) {
|
||||
yield Left<Failure, Success>(UpdateEmailDraftsFailure(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,7 @@ import 'package:tmail_ui_user/features/composer/domain/repository/contact_reposi
|
||||
import 'package:tmail_ui_user/features/composer/domain/usecases/get_autocomplete_with_device_contact_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/usecases/get_device_contact_suggestions_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/usecases/save_email_as_drafts_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/usecases/update_email_drafts_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/usecases/upload_attachment_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/usecases/save_email_addresses_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/usecases/get_autocomplete_interactor.dart';
|
||||
@@ -36,6 +37,7 @@ import 'package:tmail_ui_user/features/email/data/local/html_analyzer.dart';
|
||||
import 'package:tmail_ui_user/features/email/data/network/email_api.dart';
|
||||
import 'package:tmail_ui_user/features/email/data/repository/email_repository_impl.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/repository/email_repository.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/get_email_content_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/upload/domain/usecases/local_file_picker_interactor.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
|
||||
@@ -113,6 +115,8 @@ class ComposerBindings extends BaseBindings {
|
||||
Get.lazyPut(() => UploadMultipleAttachmentInteractor(Get.find<UploadAttachmentInteractor>()));
|
||||
Get.lazyPut(() => SendEmailInteractor(Get.find<EmailRepository>()));
|
||||
Get.lazyPut(() => SaveEmailAsDraftsInteractor(Get.find<EmailRepository>()));
|
||||
Get.lazyPut(() => GetEmailContentInteractor(Get.find<EmailRepository>()));
|
||||
Get.lazyPut(() => UpdateEmailDraftsInteractor(Get.find<EmailRepository>()));
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -130,7 +134,9 @@ class ComposerBindings extends BaseBindings {
|
||||
Get.find<TextEditingController>(),
|
||||
Get.find<LocalFilePickerInteractor>(),
|
||||
Get.find<UploadMultipleAttachmentInteractor>(),
|
||||
Get.find<SaveEmailAsDraftsInteractor>()
|
||||
Get.find<SaveEmailAsDraftsInteractor>(),
|
||||
Get.find<GetEmailContentInteractor>(),
|
||||
Get.find<UpdateEmailDraftsInteractor>(),
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -33,8 +33,11 @@ import 'package:tmail_ui_user/features/composer/domain/state/upload_attachment_s
|
||||
import 'package:tmail_ui_user/features/composer/domain/usecases/save_email_addresses_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/usecases/save_email_as_drafts_interactor.dart';
|
||||
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/domain/usecases/upload_mutiple_attachment_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/extensions/email_action_type_extension.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/get_email_content_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/get_email_content_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mailbox_dashboard_controller.dart';
|
||||
import 'package:tmail_ui_user/features/upload/domain/state/local_file_picker_state.dart';
|
||||
@@ -52,6 +55,7 @@ class ComposerController extends BaseController {
|
||||
final composerArguments = Rxn<ComposerArguments>();
|
||||
final isEnableEmailSendButton = false.obs;
|
||||
final attachments = <Attachment>[].obs;
|
||||
final emailContents = <EmailContent>[].obs;
|
||||
|
||||
final SendEmailInteractor _sendEmailInteractor;
|
||||
final SaveEmailAddressesInteractor _saveEmailAddressInteractor;
|
||||
@@ -65,6 +69,8 @@ class ComposerController extends BaseController {
|
||||
final UploadMultipleAttachmentInteractor _uploadMultipleAttachmentInteractor;
|
||||
final DeviceInfoPlugin _deviceInfoPlugin;
|
||||
final SaveEmailAsDraftsInteractor _saveEmailAsDraftsInteractor;
|
||||
final GetEmailContentInteractor _getEmailContentInteractor;
|
||||
final UpdateEmailDraftsInteractor _updateEmailDraftsInteractor;
|
||||
|
||||
List<EmailAddress> listToEmailAddress = [];
|
||||
List<EmailAddress> listCcEmailAddress = [];
|
||||
@@ -100,6 +106,8 @@ class ComposerController extends BaseController {
|
||||
this._localFilePickerInteractor,
|
||||
this._uploadMultipleAttachmentInteractor,
|
||||
this._saveEmailAsDraftsInteractor,
|
||||
this._getEmailContentInteractor,
|
||||
this._updateEmailDraftsInteractor,
|
||||
);
|
||||
|
||||
@override
|
||||
@@ -113,7 +121,7 @@ class ComposerController extends BaseController {
|
||||
@override
|
||||
void onReady() async {
|
||||
super.onReady();
|
||||
_getSelectedEmail();
|
||||
_initEmail();
|
||||
|
||||
Future.delayed(Duration(milliseconds: 500), () => _checkContactPermission());
|
||||
}
|
||||
@@ -136,6 +144,8 @@ class ComposerController extends BaseController {
|
||||
|| success is UploadMultipleAttachmentAllSuccess
|
||||
|| success is UploadMultipleAttachmentHasSomeFailure) {
|
||||
_uploadAttachmentsSuccess(success);
|
||||
} else if (success is GetEmailContentSuccess) {
|
||||
_getEmailContentSuccess(success);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -152,19 +162,22 @@ class ComposerController extends BaseController {
|
||||
popBack();
|
||||
}
|
||||
|
||||
void _getSelectedEmail() {
|
||||
void _initEmail() {
|
||||
final arguments = Get.arguments;
|
||||
if (arguments is ComposerArguments) {
|
||||
composerArguments.value = arguments;
|
||||
_initToEmailAddress();
|
||||
_initSubjectEmail();
|
||||
if (arguments.emailActionType == EmailActionType.edit) {
|
||||
_getEmailContentAction(arguments);
|
||||
}
|
||||
_initToEmailAddress(arguments);
|
||||
_initSubjectEmail(arguments);
|
||||
}
|
||||
}
|
||||
|
||||
void _initSubjectEmail() {
|
||||
void _initSubjectEmail(ComposerArguments arguments) {
|
||||
if (Get.context != null) {
|
||||
final subjectEmail = composerArguments.value?.presentationEmail?.getEmailTitle().trim() ?? '';
|
||||
final newSubject = composerArguments.value?.emailActionType.getSubjectComposer(Get.context!, subjectEmail) ?? '';
|
||||
final subjectEmail = arguments.presentationEmail?.getEmailTitle().trim() ?? '';
|
||||
final newSubject = arguments.emailActionType.getSubjectComposer(Get.context!, subjectEmail);
|
||||
setSubjectEmail(newSubject);
|
||||
subjectEmailInputController.text = newSubject;
|
||||
}
|
||||
@@ -174,16 +187,19 @@ class ComposerController extends BaseController {
|
||||
if (composerArguments.value != null
|
||||
&& composerArguments.value!.emailActionType != EmailActionType.compose
|
||||
&& Get.context != null) {
|
||||
final contentEmailQuoted = _getBodyEmailQuotedAsHtml(Get.context!);
|
||||
return contentEmailQuoted;
|
||||
if (composerArguments.value?.emailActionType == EmailActionType.edit) {
|
||||
return _getOldEmailContentAsHtml(Get.context!);
|
||||
} else {
|
||||
return _getBodyEmailQuotedAsHtml(Get.context!, composerArguments.value!);
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
Tuple2<String, String>? getHeaderEmailQuoted(String locale) {
|
||||
if (composerArguments.value != null && composerArguments.value?.presentationEmail != null) {
|
||||
final sentDate = composerArguments.value!.presentationEmail?.sentAt;
|
||||
final emailAddress = composerArguments.value!.presentationEmail?.from.listEmailAddressToString(isFullEmailAddress: true) ?? '';
|
||||
Tuple2<String, String>? _getHeaderEmailQuoted(String locale, ComposerArguments arguments) {
|
||||
if (arguments.presentationEmail != null) {
|
||||
final sentDate = arguments.presentationEmail?.sentAt;
|
||||
final emailAddress = arguments.presentationEmail?.from.listEmailAddressToString(isFullEmailAddress: true) ?? '';
|
||||
return Tuple2(sentDate.formatDate(pattern: 'MMM d, y h:mm a', locale: locale), emailAddress);
|
||||
}
|
||||
return null;
|
||||
@@ -194,15 +210,13 @@ class ComposerController extends BaseController {
|
||||
expandMode.value = newExpandMode;
|
||||
}
|
||||
|
||||
void _initToEmailAddress() {
|
||||
if (composerArguments.value != null && composerArguments.value?.presentationEmail != null) {
|
||||
final userEmailAddress = EmailAddress(null, composerArguments.value!.userProfile.email);
|
||||
void _initToEmailAddress(ComposerArguments arguments) {
|
||||
if (arguments.presentationEmail != null) {
|
||||
final userEmailAddress = EmailAddress(null, arguments.userProfile.email);
|
||||
|
||||
final recipients = composerArguments.value!.presentationEmail!.generateRecipientsEmailAddressForComposer(
|
||||
composerArguments.value?.emailActionType,
|
||||
composerArguments.value?.mailboxRole);
|
||||
final recipients = arguments.presentationEmail!.generateRecipientsEmailAddressForComposer(arguments.emailActionType, arguments.mailboxRole);
|
||||
|
||||
if (composerArguments.value?.mailboxRole == PresentationMailbox.roleSent) {
|
||||
if (arguments.mailboxRole == PresentationMailbox.roleSent || arguments.emailActionType == EmailActionType.edit) {
|
||||
listToEmailAddress = recipients.value1;
|
||||
listCcEmailAddress = recipients.value2;
|
||||
listBccEmailAddress = recipients.value3;
|
||||
@@ -258,15 +272,15 @@ class ComposerController extends BaseController {
|
||||
}
|
||||
}
|
||||
|
||||
String _getBodyEmailQuotedAsHtml(BuildContext context) {
|
||||
final headerEmailQuoted = getHeaderEmailQuoted(Localizations.localeOf(context).toLanguageTag());
|
||||
String _getBodyEmailQuotedAsHtml(BuildContext context, ComposerArguments arguments) {
|
||||
final headerEmailQuoted = _getHeaderEmailQuoted(Localizations.localeOf(context).toLanguageTag(), arguments);
|
||||
|
||||
final headerEmailQuotedAsHtml = headerEmailQuoted != null
|
||||
? AppLocalizations.of(context).header_email_quoted(headerEmailQuoted.value1, headerEmailQuoted.value2)
|
||||
.addBlockTag('p', attribute: 'style=\"font-size:14px;font-style:italic;color:#182952;\"')
|
||||
: '';
|
||||
|
||||
final trustAsHtml = composerArguments.value?.emailContents
|
||||
final trustAsHtml = arguments.emailContents
|
||||
?.map((emailContent) => emailContent.content)
|
||||
.toList()
|
||||
.join('</br>') ?? '';
|
||||
@@ -276,12 +290,12 @@ class ComposerController extends BaseController {
|
||||
return emailQuotedHtml;
|
||||
}
|
||||
|
||||
Future<Email> generateEmail({bool asDrafts = false}) async {
|
||||
Future<Email> _generateEmail(ComposerArguments arguments, {bool asDrafts = false}) async {
|
||||
final generateEmailId = EmailId(Id(_uuid.v1()));
|
||||
final outboxMailboxId = composerArguments.value!.mapMailboxId[PresentationMailbox.roleOutbox];
|
||||
final draftMailboxId = composerArguments.value!.mapMailboxId[PresentationMailbox.roleDrafts];
|
||||
final outboxMailboxId = arguments.mapMailboxId[PresentationMailbox.roleOutbox];
|
||||
final draftMailboxId = arguments.mapMailboxId[PresentationMailbox.roleDrafts];
|
||||
final listFromEmailAddress = {
|
||||
EmailAddress(null, composerArguments.value!.userProfile.email)
|
||||
EmailAddress(null, arguments.userProfile.email)
|
||||
};
|
||||
final generatePartId = PartId(_uuid.v1());
|
||||
final generateBlobId = Id(_uuid.v1());
|
||||
@@ -335,16 +349,23 @@ class ComposerController extends BaseController {
|
||||
|
||||
void sendEmailAction(BuildContext context) async {
|
||||
if (isEnableEmailSendButton.value) {
|
||||
_saveEmailAddress();
|
||||
final arguments = composerArguments.value;
|
||||
if (arguments != null) {
|
||||
_saveEmailAddress();
|
||||
|
||||
final email = await generateEmail();
|
||||
final accountId = composerArguments.value!.session.accounts.keys.first;
|
||||
final sentMailboxId = composerArguments.value!.mapMailboxId[PresentationMailbox.roleSent];
|
||||
final submissionCreateId = Id(_uuid.v1());
|
||||
final email = await _generateEmail(arguments);
|
||||
final accountId = arguments.session.accounts.keys.first;
|
||||
final sentMailboxId = arguments.mapMailboxId[PresentationMailbox.roleSent];
|
||||
final submissionCreateId = Id(_uuid.v1());
|
||||
|
||||
mailboxDashBoardController.consumeState(_sendEmailInteractor.execute(
|
||||
accountId,
|
||||
EmailRequest(email, submissionCreateId, mailboxIdSaved: sentMailboxId)));
|
||||
mailboxDashBoardController.consumeState(_sendEmailInteractor.execute(
|
||||
accountId,
|
||||
EmailRequest(
|
||||
email,
|
||||
submissionCreateId,
|
||||
mailboxIdSaved: sentMailboxId,
|
||||
emailIdDestroyed: arguments.emailActionType == EmailActionType.edit ? arguments.presentationEmail?.id : null)));
|
||||
}
|
||||
|
||||
popBack();
|
||||
} else {
|
||||
@@ -457,12 +478,57 @@ class ComposerController extends BaseController {
|
||||
}
|
||||
|
||||
void saveEmailAsDrafts() async {
|
||||
_saveEmailAddress();
|
||||
final arguments = composerArguments.value;
|
||||
if (arguments != null) {
|
||||
_saveEmailAddress();
|
||||
|
||||
final newEmail = await generateEmail(asDrafts: true);
|
||||
final accountId = composerArguments.value!.session.accounts.keys.first;
|
||||
final newEmail = await _generateEmail(arguments, asDrafts: true);
|
||||
final accountId = arguments.session.accounts.keys.first;
|
||||
final oldEmail = arguments.presentationEmail;
|
||||
|
||||
mailboxDashBoardController.consumeState(_saveEmailAsDraftsInteractor.execute(accountId, newEmail));
|
||||
if (arguments.emailActionType == EmailActionType.edit && oldEmail != null) {
|
||||
mailboxDashBoardController.consumeState(_updateEmailDraftsInteractor.execute(accountId, newEmail, oldEmail.id));
|
||||
} else {
|
||||
mailboxDashBoardController.consumeState(_saveEmailAsDraftsInteractor.execute(accountId, newEmail));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _getEmailContentAction(ComposerArguments arguments) async {
|
||||
final baseDownloadUrl = arguments.session.getDownloadUrl();
|
||||
final accountId = arguments.session.accounts.keys.first;
|
||||
final emailId = arguments.presentationEmail?.id;
|
||||
if (emailId != null) {
|
||||
consumeState(_getEmailContentInteractor.execute(accountId, emailId, baseDownloadUrl));
|
||||
}
|
||||
}
|
||||
|
||||
void _getEmailContentSuccess(GetEmailContentSuccess success) {
|
||||
emailContents.value = success.emailContents;
|
||||
attachments.value = success.attachments;
|
||||
}
|
||||
|
||||
String _getOldEmailContentAsHtml(BuildContext context) {
|
||||
if (emailContents.isNotEmpty) {
|
||||
final trustAsHtml = emailContents
|
||||
.map((emailContent) => emailContent.content)
|
||||
.toList()
|
||||
.join('</br>');
|
||||
return trustAsHtml;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
String getEmailAddressSender() {
|
||||
final arguments = composerArguments.value;
|
||||
if (arguments != null) {
|
||||
if (arguments.emailActionType == EmailActionType.edit) {
|
||||
return arguments.presentationEmail?.from?.first.emailAddress ?? '';
|
||||
} else {
|
||||
return arguments.userProfile.email;
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
void backToEmailViewAction() {
|
||||
|
||||
@@ -59,9 +59,16 @@ class ComposerView extends GetWidget<ComposerController> {
|
||||
return Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 8),
|
||||
child: Obx(() => (TopBarComposerWidgetBuilder(imagePaths, controller.isEnableEmailSendButton.value)
|
||||
..addSendEmailActionClick(() => controller.sendEmailAction(context))
|
||||
..addAttachFileActionClick(() => controller.openPickAttachmentMenu(context, _pickAttachmentsActionTiles(context)))
|
||||
..addSendEmailActionClick(() {
|
||||
controller.htmlEditorApi?.unfocus(context);
|
||||
controller.sendEmailAction(context);
|
||||
})
|
||||
..addAttachFileActionClick(() {
|
||||
controller.htmlEditorApi?.unfocus(context);
|
||||
controller.openPickAttachmentMenu(context, _pickAttachmentsActionTiles(context));
|
||||
})
|
||||
..addBackActionClick(() {
|
||||
controller.htmlEditorApi?.unfocus(context);
|
||||
controller.saveEmailAsDrafts();
|
||||
controller.backToEmailViewAction();
|
||||
}))
|
||||
@@ -137,8 +144,8 @@ class ComposerView extends GetWidget<ComposerController> {
|
||||
children: [
|
||||
Obx(() => controller.composerArguments.value != null
|
||||
? Text(
|
||||
'<${controller.composerArguments.value?.userProfile.email ?? ''}>',
|
||||
style: TextStyle(fontSize: 14, color: AppColor.nameUserColor))
|
||||
'<${controller.getEmailAddressSender()}>',
|
||||
style: TextStyle(fontSize: 14, color: AppColor.nameUserColor))
|
||||
: SizedBox.shrink()
|
||||
)
|
||||
],
|
||||
|
||||
@@ -19,6 +19,8 @@ extension EmailActionTypeExtension on EmailActionType {
|
||||
} else {
|
||||
return '${AppLocalizations.of(context).prefix_forward_email} $subject';
|
||||
}
|
||||
case EmailActionType.edit:
|
||||
return subject;
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
|
||||
@@ -38,4 +38,6 @@ abstract class EmailDataSource {
|
||||
Future<Email?> saveEmailAsDrafts(AccountId accountId, Email email);
|
||||
|
||||
Future<bool> removeEmailDrafts(AccountId accountId, EmailId emailId);
|
||||
|
||||
Future<Email?> updateEmailDrafts(AccountId accountId, Email newEmail, EmailId oldEmailId);
|
||||
}
|
||||
@@ -104,4 +104,13 @@ class EmailDataSourceImpl extends EmailDataSource {
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Email?> updateEmailDrafts(AccountId accountId, Email newEmail, EmailId oldEmailId) {
|
||||
return Future.sync(() async {
|
||||
return await emailAPI.updateEmailDrafts(accountId, newEmail, oldEmailId);
|
||||
}).catchError((error) {
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -68,6 +68,11 @@ class EmailAPI {
|
||||
final setEmailMethod = SetEmailMethod(accountId)
|
||||
..addCreate(emailRequest.email.id.id, emailRequest.email);
|
||||
|
||||
if (emailRequest.emailIdDestroyed != null) {
|
||||
setEmailMethod
|
||||
..addDestroy({emailRequest.emailIdDestroyed!.id});
|
||||
}
|
||||
|
||||
final setEmailSubmissionMethod = SetEmailSubmissionMethod(accountId)
|
||||
..addCreate(
|
||||
emailRequest.submissionCreateId,
|
||||
@@ -107,8 +112,11 @@ class EmailAPI {
|
||||
methodName: setEmailInvocation.methodName);
|
||||
|
||||
return Future.sync(() async {
|
||||
final emailCreated = setEmailResponse!.created![emailRequest.email.id.id];
|
||||
return setEmailSubmissionResponse!.updated![emailCreated!.id.id] == null;
|
||||
final emailCreated = setEmailResponse?.created?[emailRequest.email.id.id];
|
||||
if (emailCreated != null) {
|
||||
return setEmailSubmissionResponse?.updated?[emailCreated.id.id] == null;
|
||||
}
|
||||
return false;
|
||||
}).catchError((error) {
|
||||
throw error;
|
||||
});
|
||||
@@ -301,4 +309,34 @@ class EmailAPI {
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
|
||||
Future<Email?> updateEmailDrafts(AccountId accountId, Email newEmail, EmailId oldEmailId) async {
|
||||
final setEmailMethod = SetEmailMethod(accountId)
|
||||
..addCreate(newEmail.id.id, newEmail)
|
||||
..addDestroy({oldEmailId.id});
|
||||
|
||||
final requestBuilder = JmapRequestBuilder(_httpClient, ProcessingInvocation());
|
||||
|
||||
final setEmailInvocation = requestBuilder.invocation(setEmailMethod);
|
||||
|
||||
final response = await (requestBuilder
|
||||
..usings(setEmailMethod.requiredCapabilities))
|
||||
.build()
|
||||
.execute();
|
||||
|
||||
final setEmailResponse = response.parse<SetEmailResponse>(
|
||||
setEmailInvocation.methodCallId,
|
||||
SetEmailResponse.deserialize);
|
||||
|
||||
return Future.sync(() async {
|
||||
final emailUpdated = setEmailResponse?.created?[newEmail.id.id];
|
||||
final emailDestroyed = setEmailResponse?.destroyed?.contains(oldEmailId.id);
|
||||
if (emailUpdated != null && emailDestroyed == true) {
|
||||
return emailUpdated;
|
||||
}
|
||||
return null;
|
||||
}).catchError((error) {
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -98,4 +98,9 @@ class EmailRepositoryImpl extends EmailRepository {
|
||||
Future<bool> removeEmailDrafts(AccountId accountId, EmailId emailId) {
|
||||
return emailDataSource.removeEmailDrafts(accountId, emailId);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Email?> updateEmailDrafts(AccountId accountId, Email newEmail, EmailId oldEmailId) {
|
||||
return emailDataSource.updateEmailDrafts(accountId, newEmail, oldEmailId);
|
||||
}
|
||||
}
|
||||
@@ -45,4 +45,6 @@ abstract class EmailRepository {
|
||||
Future<Email?> saveEmailAsDrafts(AccountId accountId, Email email);
|
||||
|
||||
Future<bool> removeEmailDrafts(AccountId accountId, EmailId emailId);
|
||||
|
||||
Future<Email?> updateEmailDrafts(AccountId accountId, Email newEmail, EmailId oldEmailId);
|
||||
}
|
||||
@@ -342,7 +342,7 @@ class EmailController extends BaseController {
|
||||
|
||||
bool canComposeEmail() => mailboxDashBoardController.sessionCurrent != null
|
||||
&& mailboxDashBoardController.userProfile.value != null
|
||||
&& mailboxDashBoardController.mapDefaultMailboxId.containsKey(PresentationMailbox.roleOutbox)
|
||||
&& mailboxDashBoardController.mapDefaultMailboxId.isNotEmpty
|
||||
&& mailboxDashBoardController.selectedEmail.value != null;
|
||||
|
||||
void backToThreadView() {
|
||||
|
||||
@@ -10,6 +10,8 @@ import 'package:model/model.dart';
|
||||
import 'package:tmail_ui_user/features/base/base_controller.dart';
|
||||
import 'package:tmail_ui_user/features/caching/caching_manager.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/state/save_email_as_drafts_state.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/state/send_email_state.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/state/update_email_drafts_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/mark_as_email_read_state.dart';
|
||||
import 'package:tmail_ui_user/features/login/domain/usecases/delete_credential_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_mailbox_request.dart';
|
||||
@@ -86,9 +88,10 @@ class MailboxController extends BaseController {
|
||||
|| success is MoveMultipleEmailToMailboxHasSomeEmailFailure) {
|
||||
mailboxDashBoardController.clearState();
|
||||
refreshMailboxChanges();
|
||||
} else if (success is SaveEmailAsDraftsSuccess) {
|
||||
refreshMailboxChanges();
|
||||
} else if (success is RemoveEmailDraftsSuccess) {
|
||||
} else if (success is SaveEmailAsDraftsSuccess
|
||||
|| success is RemoveEmailDraftsSuccess
|
||||
|| success is SendEmailSuccess
|
||||
|| success is UpdateEmailDraftsSuccess) {
|
||||
refreshMailboxChanges();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -10,6 +10,7 @@ import 'package:model/model.dart';
|
||||
import 'package:tmail_ui_user/features/base/base_controller.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/state/save_email_as_drafts_state.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/state/send_email_state.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/state/update_email_drafts_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/email_controller.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/get_user_profile_state.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/remove_email_drafts_state.dart';
|
||||
@@ -85,6 +86,10 @@ class MailboxDashBoardController extends BaseController {
|
||||
icon: _imagePaths.icSendToast);
|
||||
}
|
||||
clearState();
|
||||
} else if (failure is SaveEmailAsDraftsFailure
|
||||
|| failure is RemoveEmailDraftsFailure
|
||||
|| failure is UpdateEmailDraftsFailure) {
|
||||
clearState();
|
||||
}
|
||||
},
|
||||
(success) {
|
||||
@@ -102,7 +107,8 @@ class MailboxDashBoardController extends BaseController {
|
||||
} else if (success is SaveEmailAsDraftsSuccess) {
|
||||
_saveEmailAsDraftsSuccess(success);
|
||||
clearState();
|
||||
} else if (success is RemoveEmailDraftsSuccess) {
|
||||
} else if (success is RemoveEmailDraftsSuccess
|
||||
|| success is UpdateEmailDraftsSuccess) {
|
||||
clearState();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@ import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
|
||||
import 'package:model/model.dart';
|
||||
import 'package:tmail_ui_user/features/base/base_controller.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/state/save_email_as_drafts_state.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/state/send_email_state.dart';
|
||||
import 'package:tmail_ui_user/features/composer/domain/state/update_email_drafts_state.dart';
|
||||
import 'package:tmail_ui_user/features/destination_picker/presentation/model/destination_picker_arguments.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/model/move_request.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/mark_as_email_star_state.dart';
|
||||
@@ -135,7 +137,9 @@ class ThreadController extends BaseController {
|
||||
} else if (success is SearchEmailNewQuery){
|
||||
_searchEmail();
|
||||
} else if (success is SaveEmailAsDraftsSuccess
|
||||
|| success is RemoveEmailDraftsSuccess) {
|
||||
|| success is RemoveEmailDraftsSuccess
|
||||
|| success is SendEmailSuccess
|
||||
|| success is UpdateEmailDraftsSuccess) {
|
||||
cancelSelectEmail();
|
||||
_refreshEmailChanges();
|
||||
}
|
||||
@@ -673,7 +677,7 @@ class ThreadController extends BaseController {
|
||||
|
||||
bool canComposeEmail() => mailboxDashBoardController.sessionCurrent != null
|
||||
&& mailboxDashBoardController.userProfile.value != null
|
||||
&& mailboxDashBoardController.mapDefaultMailboxId.containsKey(PresentationMailbox.roleOutbox);
|
||||
&& mailboxDashBoardController.mapDefaultMailboxId.isNotEmpty;
|
||||
|
||||
bool isSelectionEnabled() => currentSelectMode.value == SelectMode.ACTIVE;
|
||||
|
||||
@@ -704,6 +708,20 @@ class ThreadController extends BaseController {
|
||||
push(AppRoutes.EMAIL);
|
||||
}
|
||||
|
||||
void editEmail(PresentationEmail presentationEmail) {
|
||||
if (canComposeEmail()) {
|
||||
push(
|
||||
AppRoutes.COMPOSER,
|
||||
arguments: ComposerArguments(
|
||||
emailActionType: EmailActionType.edit,
|
||||
presentationEmail: presentationEmail,
|
||||
mailboxRole: mailboxDashBoardController.selectedMailbox.value?.role,
|
||||
session: mailboxDashBoardController.sessionCurrent!,
|
||||
userProfile: mailboxDashBoardController.userProfile.value!,
|
||||
mapMailboxId: mailboxDashBoardController.mapDefaultMailboxId));
|
||||
}
|
||||
}
|
||||
|
||||
void composeEmailAction() {
|
||||
if (canComposeEmail()) {
|
||||
push(
|
||||
|
||||
@@ -375,7 +375,13 @@ class ThreadView extends GetWidget<ThreadController> {
|
||||
controller.currentSelectMode.value,
|
||||
controller.mailboxDashBoardController.searchState.value.searchStatus,
|
||||
controller.searchQuery)
|
||||
..onOpenEmailAction((selectedEmail) => controller.previewEmail(context, selectedEmail))
|
||||
..onOpenEmailAction((selectedEmail) {
|
||||
if (controller.mailboxDashBoardController.selectedMailbox.value?.role == PresentationMailbox.roleDrafts) {
|
||||
controller.editEmail(selectedEmail);
|
||||
} else {
|
||||
controller.previewEmail(context, selectedEmail);
|
||||
}
|
||||
})
|
||||
..onSelectEmailAction((selectedEmail) => controller.selectEmail(context, selectedEmail)))
|
||||
.build()),
|
||||
)
|
||||
|
||||
@@ -10,4 +10,5 @@ enum EmailActionType {
|
||||
move,
|
||||
markAsSpam,
|
||||
delete,
|
||||
edit,
|
||||
}
|
||||
@@ -106,6 +106,8 @@ extension PresentationEmailExtension on PresentationEmail {
|
||||
} else {
|
||||
return Tuple3(to.asList() + from.asList(), cc.asList(), bcc.asList());
|
||||
}
|
||||
case EmailActionType.edit:
|
||||
return Tuple3(to.asList(), cc.asList(), bcc.asList());
|
||||
default:
|
||||
return Tuple3([], [], []);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user