TF-3406 Add edit as new email feature

Signed-off-by: dab246 <tdvu@linagora.com>
This commit is contained in:
DatDang
2025-01-20 19:40:43 +07:00
committed by Dat H. Pham
parent 412431ceaa
commit 3ddb81a8c4
15 changed files with 161 additions and 9 deletions
@@ -570,6 +570,19 @@ class ComposerController extends BaseController
);
switch(arguments.emailActionType) {
case EmailActionType.composeFromPresentationEmail:
_initEmailAddress(
presentationEmail: arguments.presentationEmail!,
actionType: EmailActionType.composeFromPresentationEmail
);
_initSubjectEmail(
presentationEmail: arguments.presentationEmail!,
actionType: EmailActionType.composeFromPresentationEmail
);
_getEmailContentOfEmailDrafts(
emailId: arguments.presentationEmail!.id!,
);
break;
case EmailActionType.editDraft:
_initEmailAddress(
presentationEmail: arguments.presentationEmail!,
@@ -32,6 +32,7 @@ extension EmailActionTypeExtension on EmailActionType {
case EmailActionType.editDraft:
case EmailActionType.editSendingEmail:
case EmailActionType.reopenComposerBrowser:
case EmailActionType.composeFromPresentationEmail:
return subject;
default:
return '';
@@ -138,6 +139,8 @@ extension EmailActionTypeExtension on EmailActionType {
return imagePaths.icMailboxArchived;
case EmailActionType.downloadMessageAsEML:
return imagePaths.icDownloadAttachment;
case EmailActionType.composeFromPresentationEmail:
return imagePaths.icEdit;
default:
return '';
}
@@ -159,6 +162,8 @@ extension EmailActionTypeExtension on EmailActionType {
return AppLocalizations.of(context).archiveMessage;
case EmailActionType.downloadMessageAsEML:
return AppLocalizations.of(context).downloadMessageAsEML;
case EmailActionType.composeFromPresentationEmail:
return AppLocalizations.of(context).editAsNewEmail;
default:
return '';
}
@@ -50,6 +50,7 @@ class MobileEditorView extends StatelessWidget with EditorViewMixin {
case EmailActionType.reopenComposerBrowser:
case EmailActionType.composeFromMailtoUri:
case EmailActionType.composeFromUnsubscribeMailtoLink:
case EmailActionType.composeFromPresentationEmail:
if (contentViewState == null) {
return const SizedBox.shrink();
}
@@ -64,9 +65,12 @@ class MobileEditorView extends StatelessWidget with EditorViewMixin {
if (success is GetEmailContentLoading) {
return const CupertinoLoadingWidget(padding: EdgeInsets.all(16.0));
} else {
var newContent = success is GetEmailContentSuccess
? success.htmlEmailContent
: HtmlExtension.editorStartTags;
var newContent = HtmlExtension.editorStartTags;
if (success is GetEmailContentSuccess) {
newContent = success.htmlEmailContent;
} else if (success is GetEmailContentFromCacheSuccess) {
newContent = success.htmlEmailContent;
}
if (newContent.isEmpty) {
newContent = HtmlExtension.editorStartTags;
}
@@ -88,6 +88,7 @@ class WebEditorView extends StatelessWidget with EditorViewMixin {
case EmailActionType.reopenComposerBrowser:
case EmailActionType.composeFromUnsubscribeMailtoLink:
case EmailActionType.composeFromMailtoUri:
case EmailActionType.composeFromPresentationEmail:
if (contentViewState == null) {
return const SizedBox.shrink();
}
@@ -1205,6 +1205,9 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
case EmailActionType.downloadMessageAsEML:
_downloadMessageAsEML(presentationEmail);
break;
case EmailActionType.composeFromPresentationEmail:
_composeFromPresentationEmail(presentationEmail);
break;
default:
break;
}
@@ -1906,6 +1909,14 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
downloadAttachmentForWeb(emlAttachment);
}
void _composeFromPresentationEmail(PresentationEmail presentationEmail) {
if (accountId == null || session == null) return;
mailboxDashBoardController.goToComposer(
ComposerArguments.fromPresentationEmail(presentationEmail),
);
}
void handleDownloadAttachmentAction(BuildContext context, Attachment attachment) {
if (PlatformInfo.isWeb) {
downloadAttachmentForWeb(attachment);
@@ -503,7 +503,8 @@ class EmailView extends GetWidget<SingleEmailController> {
if (mailboxContain?.isArchive == false)
EmailActionType.archiveMessage,
if (PlatformInfo.isWeb && PlatformInfo.isCanvasKit)
EmailActionType.downloadMessageAsEML
EmailActionType.downloadMessageAsEML,
EmailActionType.composeFromPresentationEmail,
];
if (position == null) {
@@ -102,6 +102,12 @@ class ComposerArguments extends RouterArguments {
emailActionType: EmailActionType.editDraft,
presentationEmail: presentationEmail,
);
factory ComposerArguments.fromPresentationEmail(PresentationEmail presentationEmail) =>
ComposerArguments(
emailActionType: EmailActionType.composeFromPresentationEmail,
presentationEmail: presentationEmail,
);
factory ComposerArguments.fromSessionStorageBrowser(ComposerCache composerCache) =>
ComposerArguments(
@@ -83,9 +83,7 @@ extension UpdateCurrentEmailsFlagsExtension on MailboxDashBoardController {
setSelectedEmail(newEmail);
}
if (emailsInCurrentMailbox.isNotEmpty) {
updateEmailFlagByEmailIds([emailId], markAsAnswered: true);
}
updateEmailFlagByEmailIds([emailId], markAsAnswered: true);
}
void updateEmailForwarded(EmailId emailId) {
@@ -39,6 +39,7 @@ import 'package:tmail_ui_user/features/thread/presentation/styles/item_email_til
import 'package:tmail_ui_user/features/thread/presentation/widgets/email_tile_builder.dart'
if (dart.library.html) 'package:tmail_ui_user/features/thread/presentation/widgets/email_tile_web_builder.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
class SearchEmailView extends GetWidget<SearchEmailController>
with AppLoaderMixin {
@@ -745,6 +746,8 @@ class SearchEmailView extends GetWidget<SearchEmailController>
List<Widget> _contextMenuActionTile(BuildContext context, PresentationEmail email) {
return <Widget>[
_markAsEmailSpamOrUnSpamAction(context, email),
if (email.mailboxContain?.isDrafts == false)
_editAsNewEmailContextMenuItemAction(context, email),
];
}
@@ -777,11 +780,44 @@ class SearchEmailView extends GetWidget<SearchEmailController>
.build();
}
Widget _editAsNewEmailContextMenuItemAction(
BuildContext context,
PresentationEmail email,
) {
return (
EmailActionCupertinoActionSheetActionBuilder(
const Key('edit_as_new_email_action'),
SvgPicture.asset(
controller.imagePaths.icEdit,
width: 24,
height: 24,
fit: BoxFit.fill,
colorFilter: AppColor.colorTextButton.asFilter()
),
AppLocalizations.of(context).editAsNewEmail,
email,
iconLeftPadding: controller.responsiveUtils.isMobile(context)
? const EdgeInsetsDirectional.only(start: 12, end: 16)
: const EdgeInsetsDirectional.only(end: 12),
iconRightPadding: controller.responsiveUtils.isMobile(context)
? const EdgeInsetsDirectional.only(start: 12)
: EdgeInsets.zero)
..onActionClick((email) {
popBack();
controller.editAsNewEmail(email);
})
).build();
}
List<PopupMenuEntry> _popupMenuActionTile(BuildContext context, PresentationEmail email) {
return [
PopupMenuItem(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: _markAsEmailSpamOrUnSpamAction(context, email)),
if (email.mailboxContain?.isDrafts == false)
PopupMenuItem(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: _editAsNewEmailContextMenuItemAction(context, email)),
];
}
@@ -43,6 +43,12 @@ mixin EmailActionController {
mailboxDashBoardController.goToComposer(ComposerArguments.editDraftEmail(presentationEmail));
}
void editAsNewEmail(PresentationEmail presentationEmail) {
mailboxDashBoardController.goToComposer(
ComposerArguments.fromPresentationEmail(presentationEmail),
);
}
void previewEmail(PresentationEmail presentationEmail) {
log('EmailActionController::previewEmail():presentationEmailId: ${presentationEmail.id}');
mailboxDashBoardController.openEmailDetailedView(presentationEmail);
@@ -1152,6 +1152,8 @@ class ThreadController extends BaseController with EmailActionController {
case EmailActionType.preview:
if (mailboxContain?.isDrafts == true) {
editDraftEmail(selectedEmail);
} else if (mailboxContain?.isTemplates == true) {
editAsNewEmail(selectedEmail);
} else {
previewEmail(selectedEmail);
}
@@ -697,6 +697,8 @@ class ThreadView extends GetWidget<ThreadController>
_markAsEmailSpamOrUnSpamContextMenuItemAction(context, email, mailboxContain),
if (mailboxContain?.isArchive == false)
_archiveMessageContextMenuItemAction(context, email),
if (mailboxContain?.isDrafts == false)
_editAsNewEmailContextMenuItemAction(context, email),
];
}
@@ -770,7 +772,7 @@ class ThreadView extends GetWidget<ThreadController>
email,
iconLeftPadding: controller.responsiveUtils.isMobile(context)
? const EdgeInsetsDirectional.only(start: 12, end: 16)
: const EdgeInsetsDirectional.only(start: 12),
: const EdgeInsetsDirectional.only(end: 12),
iconRightPadding: controller.responsiveUtils.isMobile(context)
? const EdgeInsetsDirectional.only(start: 12)
: EdgeInsets.zero
@@ -779,6 +781,35 @@ class ThreadView extends GetWidget<ThreadController>
).build();
}
Widget _editAsNewEmailContextMenuItemAction(
BuildContext context,
PresentationEmail email,
) {
return (
EmailActionCupertinoActionSheetActionBuilder(
const Key('edit_as_new_email_action'),
SvgPicture.asset(
controller.imagePaths.icEdit,
width: 24,
height: 24,
fit: BoxFit.fill,
colorFilter: AppColor.colorTextButton.asFilter()
),
AppLocalizations.of(context).editAsNewEmail,
email,
iconLeftPadding: controller.responsiveUtils.isMobile(context)
? const EdgeInsetsDirectional.only(start: 12, end: 16)
: const EdgeInsetsDirectional.only(end: 12),
iconRightPadding: controller.responsiveUtils.isMobile(context)
? const EdgeInsetsDirectional.only(start: 12)
: EdgeInsets.zero)
..onActionClick((email) {
popBack();
controller.editAsNewEmail(email);
})
).build();
}
List<PopupMenuEntry> _popupMenuActionTile(BuildContext context, PresentationEmail email) {
final mailboxContain = email.mailboxContain;
@@ -788,6 +819,8 @@ class ThreadView extends GetWidget<ThreadController>
_buildMarkAsSpamPopupMenuItem(context, email, mailboxContain),
if (mailboxContain?.isArchive == false)
_buildArchiveMessagePopupMenuItem(context, email),
if (mailboxContain?.isDrafts == false)
_buildEditAsNewEmailPopupMenuItem(AppLocalizations.of(context), email),
];
}
@@ -865,6 +898,29 @@ class ThreadView extends GetWidget<ThreadController>
);
}
PopupMenuEntry _buildEditAsNewEmailPopupMenuItem(
AppLocalizations appLocalizations,
PresentationEmail email,
) {
return PopupMenuItem(
padding: EdgeInsets.zero,
child: popupItem(
controller.imagePaths.icEdit,
appLocalizations.editAsNewEmail,
colorIcon: AppColor.colorTextButton,
styleName: const TextStyle(
fontWeight: FontWeight.w500,
fontSize: 16,
color: Colors.black
),
onCallbackAction: () {
popBack();
controller.editAsNewEmail(email);
}
)
);
}
Widget _buildMailboxActionProgressBanner(BuildContext context) {
return Obx(() {
return _MailboxActionProgressBanner(
+7 -1
View File
@@ -1,5 +1,5 @@
{
"@@last_modified": "2025-01-14T12:52:43.828907",
"@@last_modified": "2025-01-20T18:53:16.325121",
"initializing_data": "Initializing data...",
"@initializing_data": {
"type": "text",
@@ -4113,5 +4113,11 @@
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"editAsNewEmail": "Edit as new email",
"@editAsNewEmail": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
}
}
@@ -4321,4 +4321,10 @@ class AppLocalizations {
name: 'downloadAttachmentInEMLPreviewWarningMessage',
);
}
String get editAsNewEmail {
return Intl.message(
'Edit as new email',
name: 'editAsNewEmail',
);
}
}
+1
View File
@@ -16,6 +16,7 @@ enum EmailActionType {
composeFromFileShared,
composeFromEmailAddress,
composeFromMailtoUri,
composeFromPresentationEmail,
reopenComposerBrowser,
moveToTrash,
deletePermanently,