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