diff --git a/assets/images/ic_selected.svg b/assets/images/ic_selected.svg
new file mode 100644
index 000000000..8cee3bcb1
--- /dev/null
+++ b/assets/images/ic_selected.svg
@@ -0,0 +1,4 @@
+
diff --git a/core/lib/core.dart b/core/lib/core.dart
index d45341d83..4734f686a 100644
--- a/core/lib/core.dart
+++ b/core/lib/core.dart
@@ -26,6 +26,9 @@ export 'presentation/views/button/button_builder.dart';
export 'presentation/views/image/avatar_builder.dart';
export 'presentation/views/list/sliver_grid_delegate_fixed_height.dart';
export 'presentation/views/text/text_form_field_builder.dart';
+export 'presentation/views/image/icon_builder.dart';
+export 'presentation/views/context_menu/context_menu_action_builder.dart';
+export 'presentation/views/context_menu/context_menu_builder.dart';
// Resources
export 'presentation/resources/assets_paths.dart';
diff --git a/core/lib/presentation/resources/image_paths.dart b/core/lib/presentation/resources/image_paths.dart
index 427ea123b..7eccb38db 100644
--- a/core/lib/presentation/resources/image_paths.dart
+++ b/core/lib/presentation/resources/image_paths.dart
@@ -36,6 +36,7 @@ class ImagePaths {
String get icComposerMenu => _getImagePath('ic_composer_menu.svg');
String get icComposerFileShare => _getImagePath('ic_composer_file_share.svg');
String get icExpandAddress => _getImagePath('ic_expand_address.svg');
+ String get icSelected => _getImagePath('ic_selected.svg');
String _getImagePath(String imageName) {
return AssetsPaths.images + imageName;
diff --git a/core/lib/presentation/views/context_menu/context_menu_action_builder.dart b/core/lib/presentation/views/context_menu/context_menu_action_builder.dart
new file mode 100644
index 000000000..7b0402cb3
--- /dev/null
+++ b/core/lib/presentation/views/context_menu/context_menu_action_builder.dart
@@ -0,0 +1,31 @@
+import 'package:core/presentation/extensions/color_extension.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/widgets.dart';
+import 'package:flutter_svg/flutter_svg.dart';
+import 'package:meta/meta.dart';
+
+typedef OnContextMenuActionClick = void Function(T data);
+
+abstract class ContextMenuActionBuilder {
+ @protected final Key key;
+ @protected final SvgPicture actionIcon;
+ @protected final String actionName;
+ @protected OnContextMenuActionClick? onContextMenuActionClick;
+
+ ContextMenuActionBuilder(
+ this.key,
+ this.actionIcon,
+ this.actionName);
+
+ void onActionClick(OnContextMenuActionClick onContextMenuActionClick) {
+ this.onContextMenuActionClick = onContextMenuActionClick;
+ }
+
+ TextStyle actionTextStyle() {
+ return TextStyle(
+ fontSize: 15,
+ color: AppColor.nameUserColor);
+ }
+
+ Widget build();
+}
\ No newline at end of file
diff --git a/core/lib/presentation/views/context_menu/context_menu_builder.dart b/core/lib/presentation/views/context_menu/context_menu_builder.dart
new file mode 100644
index 000000000..f6847af96
--- /dev/null
+++ b/core/lib/presentation/views/context_menu/context_menu_builder.dart
@@ -0,0 +1,100 @@
+
+import 'package:flutter/material.dart';
+import 'package:flutter/widgets.dart';
+import 'package:get/get.dart';
+
+typedef OnCloseContextMenuAction = void Function();
+
+class ContextMenuBuilder {
+
+ final BuildContext _context;
+ final List _actionTiles = [];
+ final bool areTilesHorizontal;
+
+ Widget? _header;
+ Widget? _footer;
+ OnCloseContextMenuAction? _onCloseContextMenuAction;
+
+ ContextMenuBuilder(
+ this._context,
+ {
+ this.areTilesHorizontal = false
+ }
+ );
+
+ void addTiles(List tiles) {
+ _actionTiles.addAll(tiles);
+ }
+
+ void addHeader(Widget header) {
+ _header = header;
+ }
+
+ void addFooter(Widget footer) {
+ _footer = footer;
+ }
+
+ void addOnCloseContextMenuAction(OnCloseContextMenuAction onCloseContextMenuAction) {
+ _onCloseContextMenuAction = onCloseContextMenuAction;
+ }
+
+ RoundedRectangleBorder _shape() {
+ return RoundedRectangleBorder(
+ borderRadius: BorderRadius.only(
+ topLeft: Radius.circular(20.0),
+ topRight: Radius.circular(20.0)));
+ }
+
+ BoxDecoration _decoration(BuildContext context) {
+ return BoxDecoration(
+ color: Colors.white,
+ borderRadius: BorderRadius.only(
+ topLeft: const Radius.circular(20.0),
+ topRight: const Radius.circular(20.0)));
+ }
+
+ void build() {
+ Get.bottomSheet(
+ GestureDetector(
+ onTap: () {
+ if (_onCloseContextMenuAction != null) {
+ _onCloseContextMenuAction!();
+ }},
+ child: SingleChildScrollView(
+ child: Container(
+ margin: EdgeInsets.zero,
+ decoration: _decoration(_context),
+ child: GestureDetector(
+ onTap: () => {},
+ child: Wrap(
+ children: [
+ _header ?? SizedBox.shrink(),
+ Divider(),
+ areTilesHorizontal
+ ? Row(children: [
+ ..._actionTiles,
+ _actionTiles.isNotEmpty && _footer != null ? Divider() : SizedBox.shrink()
+ ])
+ : Column(children: [
+ ..._actionTiles,
+ _actionTiles.isNotEmpty && _footer != null ? Divider() : SizedBox.shrink()
+ ]),
+ _footer != null
+ ? Padding(
+ padding: EdgeInsets.only(bottom: 10.0),
+ child: Wrap(children: [_footer ?? SizedBox.shrink()]))
+ : SizedBox.shrink(),
+ ],
+ ),
+ ),
+ ),
+ ),
+ ),
+ useRootNavigator: true,
+ shape: _shape(),
+ isScrollControlled: true,
+ enableDrag: false,
+ backgroundColor: Colors.transparent
+ );
+ }
+}
\ No newline at end of file
diff --git a/core/lib/presentation/views/image/avatar_builder.dart b/core/lib/presentation/views/image/avatar_builder.dart
index e853eda60..e086b6b63 100644
--- a/core/lib/presentation/views/image/avatar_builder.dart
+++ b/core/lib/presentation/views/image/avatar_builder.dart
@@ -2,12 +2,15 @@ import 'package:core/presentation/extensions/color_extension.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
+typedef OnTapAvatarActionClick = void Function();
+
class AvatarBuilder {
Key? _key;
String? _text;
double? _size;
String? _iconStatus;
Color? _bgColor;
+ OnTapAvatarActionClick? _onTapAvatarActionClick;
AvatarBuilder key(Key key) {
_key = key;
@@ -34,31 +37,41 @@ class AvatarBuilder {
return this;
}
+ AvatarBuilder addOnTapActionClick(OnTapAvatarActionClick onTapAvatarActionClick) {
+ _onTapAvatarActionClick = onTapAvatarActionClick;
+ return this;
+ }
+
Widget build() {
- return Container(
- key: _key,
- width: _size ?? 40,
- height: _size ?? 40,
- alignment: Alignment.center,
- child: Stack(
- children: [
- Container(
- width: _size ?? 40,
- height: _size ?? 40,
- alignment: Alignment.center,
- decoration: BoxDecoration(
- borderRadius: BorderRadius.circular((_size ?? 40) / 2),
- border: Border.all(color: Colors.white),
- color: _bgColor ?? AppColor.avatarColor),
- child: Text(
- '${_text ?? ''}',
- style: TextStyle(fontSize: 20, color: AppColor.avatarTextColor, fontWeight: FontWeight.w500))),
- if (_iconStatus != null && _iconStatus!.isNotEmpty)
- Align(
- child: SvgPicture.asset(_iconStatus!, width: 12, height: 12, fit: BoxFit.fill),
- alignment: Alignment.bottomRight)
- ],
- )
+ return GestureDetector(
+ onTap: () {
+ if (_onTapAvatarActionClick != null) {
+ _onTapAvatarActionClick!();
+ }},
+ child: Container(
+ key: _key,
+ width: _size ?? 40,
+ height: _size ?? 40,
+ alignment: Alignment.center,
+ child: Stack(
+ children: [
+ Container(
+ width: _size ?? 40,
+ height: _size ?? 40,
+ alignment: Alignment.center,
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.circular((_size ?? 40) / 2),
+ border: Border.all(color: Colors.white),
+ color: _bgColor ?? AppColor.avatarColor),
+ child: Text(
+ '${_text ?? ''}',
+ style: TextStyle(fontSize: 20, color: AppColor.avatarTextColor, fontWeight: FontWeight.w500))),
+ if (_iconStatus != null && _iconStatus!.isNotEmpty)
+ Align(
+ child: SvgPicture.asset(_iconStatus!, width: 12, height: 12, fit: BoxFit.fill),
+ alignment: Alignment.bottomRight)
+ ],
+ )),
);
}
}
\ No newline at end of file
diff --git a/core/lib/presentation/views/image/icon_builder.dart b/core/lib/presentation/views/image/icon_builder.dart
new file mode 100644
index 000000000..ee6fae814
--- /dev/null
+++ b/core/lib/presentation/views/image/icon_builder.dart
@@ -0,0 +1,44 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_svg/flutter_svg.dart';
+
+typedef OnPressIconActionClick = void Function();
+
+class IconBuilder {
+ Key? _key;
+ double? _size;
+ String? _icon;
+ OnPressIconActionClick? _onPressIconActionClick;
+
+ IconBuilder(this._icon);
+
+ void key(Key key) {
+ _key = key;
+ }
+
+ void size(double size) {
+ _size = size;
+ }
+
+ void addOnTapActionClick(OnPressIconActionClick onPressIconActionClick) {
+ _onPressIconActionClick = onPressIconActionClick;
+ }
+
+ Widget build() {
+ return Container(
+ key: _key,
+ width: _size ?? 40,
+ height: _size ?? 40,
+ alignment: Alignment.center,
+ padding: EdgeInsets.all(3),
+ child: IconButton(
+ padding: EdgeInsets.zero,
+ iconSize: _size ?? 40,
+ icon: SvgPicture.asset(_icon!, width: _size ?? 40, height: _size ?? 40, fit: BoxFit.fill),
+ onPressed: () => {
+ if (_onPressIconActionClick != null) {
+ _onPressIconActionClick!()
+ }
+ })
+ );
+ }
+}
\ No newline at end of file
diff --git a/core/pubspec.yaml b/core/pubspec.yaml
index a37ae8ed6..8c41bfecf 100644
--- a/core/pubspec.yaml
+++ b/core/pubspec.yaml
@@ -50,6 +50,9 @@ dependencies:
# sqflite
sqflite: 2.0.0+4
+ # GetX
+ get: 4.1.4
+
dev_dependencies:
flutter_test:
sdk: flutter
diff --git a/lib/features/thread/presentation/thread_bindings.dart b/lib/features/thread/presentation/thread_bindings.dart
index bd8bd68a6..82adc1713 100644
--- a/lib/features/thread/presentation/thread_bindings.dart
+++ b/lib/features/thread/presentation/thread_bindings.dart
@@ -1,4 +1,5 @@
import 'package:core/presentation/utils/responsive_utils.dart';
+import 'package:flutter/cupertino.dart';
import 'package:get/get.dart';
import 'package:tmail_ui_user/features/thread/data/datasource/thread_datasource.dart';
import 'package:tmail_ui_user/features/thread/data/datasource_impl/thread_datasource_impl.dart';
@@ -16,9 +17,11 @@ class ThreadBindings extends Bindings {
Get.lazyPut(() => ThreadRepositoryImpl(Get.find()));
Get.lazyPut(() => Get.find());
Get.lazyPut(() => GetEmailsInMailboxInteractor(Get.find()));
+ Get.lazyPut(() => ScrollController());
Get.put(ThreadController(
Get.find(),
Get.find(),
+ Get.find(),
));
}
}
\ No newline at end of file
diff --git a/lib/features/thread/presentation/thread_controller.dart b/lib/features/thread/presentation/thread_controller.dart
index 38554daa8..f17f80f09 100644
--- a/lib/features/thread/presentation/thread_controller.dart
+++ b/lib/features/thread/presentation/thread_controller.dart
@@ -2,6 +2,7 @@ import 'package:core/core.dart';
import 'package:core/presentation/utils/responsive_utils.dart';
import 'package:dartz/dartz.dart';
import 'package:flutter/material.dart';
+import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart';
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/core/filter/filter.dart';
@@ -21,7 +22,9 @@ import 'package:tmail_ui_user/features/thread/domain/constants/thread_constants.
import 'package:tmail_ui_user/features/thread/domain/state/get_all_email_state.dart';
import 'package:tmail_ui_user/features/thread/domain/usecases/get_emails_in_mailbox_interactor.dart';
import 'package:tmail_ui_user/features/thread/presentation/model/load_more_state.dart';
+import 'package:tmail_ui_user/features/thread/presentation/widgets/email_context_menu_action_builder.dart';
import 'package:tmail_ui_user/main/actions/email_action.dart';
+import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
import 'package:tmail_ui_user/main/routes/app_routes.dart';
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
@@ -30,6 +33,7 @@ class ThreadController extends BaseController {
final mailboxDashBoardController = Get.find();
final GetEmailsInMailboxInteractor _getEmailsInMailboxInteractor;
final ResponsiveUtils responsiveUtils;
+ final ScrollController listEmailController;
final _properties = Properties({
'id', 'subject', 'from', 'to', 'cc', 'bcc', 'keywords', 'receivedAt',
@@ -38,6 +42,7 @@ class ThreadController extends BaseController {
final emailList = [].obs;
final loadMoreState = LoadMoreState.IDLE.obs;
+ final currentSelectMode = SelectMode.INACTIVE.obs;
int positionCurrent = 0;
int lastGetTotal = 0;
@@ -45,7 +50,8 @@ class ThreadController extends BaseController {
ThreadController(
this.responsiveUtils,
- this._getEmailsInMailboxInteractor
+ this._getEmailsInMailboxInteractor,
+ this.listEmailController,
);
@override
@@ -66,8 +72,9 @@ class ThreadController extends BaseController {
@override
void dispose() {
- super.dispose();
mailboxDashBoardController.selectedMailbox.close();
+ listEmailController.dispose();
+ super.dispose();
}
@override
@@ -175,13 +182,35 @@ class ThreadController extends BaseController {
: SelectMode.INACTIVE;
}
- void selectEmail(BuildContext context, PresentationEmail presentationEmailSelected) {
+ void previewEmail(BuildContext context, PresentationEmail presentationEmailSelected) {
mailboxDashBoardController.setSelectedEmail(presentationEmailSelected);
if (!responsiveUtils.isDesktop(context)) {
goToEmail(context);
}
}
+ void selectEmail(BuildContext context, PresentationEmail presentationEmailSelected) {
+ emailList.value = emailList.map((email) => email.id == presentationEmailSelected.id ? email.toggleSelect() : email).toList();
+ if (_isUnSelectedAll()) {
+ currentSelectMode.value = SelectMode.INACTIVE;
+ } else {
+ if (currentSelectMode.value == SelectMode.INACTIVE) {
+ currentSelectMode.value = SelectMode.ACTIVE;
+ }
+ }
+ }
+
+ List getListEmailSelected() => emailList.where((email) => email.selectMode == SelectMode.ACTIVE).toList();
+
+ bool _isUnSelectedAll() => emailList.every((email) => email.selectMode == SelectMode.INACTIVE);
+
+ bool _isEmailAllRead(List listEmail) => listEmail.every((email) => !email.isUnReadEmail());
+
+ void cancelSelectEmail() {
+ emailList.value = emailList.map((email) => email.toSelectedEmail(selectMode: SelectMode.INACTIVE)).toList();
+ currentSelectMode.value = SelectMode.INACTIVE;
+ }
+
void _updateStateUnReadEmail(EmailId emailId, {required bool unRead}) {
final newEmailList = emailList
.map((email) => email.id == emailId ? email.markAsReadPresentationEmail(unRead: unRead) : email)
@@ -189,6 +218,73 @@ class ThreadController extends BaseController {
emailList.value = newEmailList;
}
+ void unreadSelectedEmail(List listEmail) {
+ popBack();
+ }
+
+ void openContextMenuSelectedEmail(BuildContext context, ImagePaths imagePaths, List listEmail) {
+ (ContextMenuBuilder(context)
+ ..addTiles(_contextMenuActionList(context, imagePaths, listEmail)))
+ .build();
+ }
+
+ List _contextMenuActionList(BuildContext context, ImagePaths imagePaths, List listEmail) {
+ return [
+ _moveToTrashAction(context, imagePaths, listEmail),
+ _moveToMailboxAction(context, imagePaths, listEmail),
+ _markAsSeenAction(context, imagePaths, listEmail),
+ _markAsFlagAction(context, imagePaths, listEmail),
+ _moveToSpamAction(context, imagePaths, listEmail),
+ SizedBox(height: 40),
+ ];
+ }
+
+ Widget _markAsSeenAction(BuildContext context, ImagePaths imagePaths, List listEmail) {
+ return (EmailContextMenuActionBuilder(
+ Key('mark_as_seen_context_menu_action'),
+ SvgPicture.asset(imagePaths.icEyeDisable, width: 24, height: 24, fit: BoxFit.fill),
+ _isEmailAllRead(listEmail) ? AppLocalizations.of(context).mark_as_unread : AppLocalizations.of(context).mark_as_read,
+ listEmail)
+ ..onActionClick((data) => unreadSelectedEmail(data)))
+ .build();
+ }
+
+ Widget _moveToTrashAction(BuildContext context, ImagePaths imagePaths, List listEmail) {
+ return (EmailContextMenuActionBuilder(
+ Key('move_to_trash_context_menu_action'),
+ SvgPicture.asset(imagePaths.icTrash, width: 24, height: 24, fit: BoxFit.fill),
+ AppLocalizations.of(context).move_to_trash, listEmail)
+ ..onActionClick((data) => {}))
+ .build();
+ }
+
+ Widget _moveToMailboxAction(BuildContext context, ImagePaths imagePaths, List listEmail) {
+ return (EmailContextMenuActionBuilder(
+ Key('move_to_mailbox_context_menu_action'),
+ SvgPicture.asset(imagePaths.icFolder, width: 24, height: 24, fit: BoxFit.fill),
+ AppLocalizations.of(context).move_to_mailbox, listEmail)
+ ..onActionClick((data) => {}))
+ .build();
+ }
+
+ Widget _markAsFlagAction(BuildContext context, ImagePaths imagePaths, List listEmail) {
+ return (EmailContextMenuActionBuilder(
+ Key('mark_as_flag_context_menu_action'),
+ SvgPicture.asset(imagePaths.icFlag, width: 24, height: 24, fit: BoxFit.fill),
+ AppLocalizations.of(context).mark_as_flag, listEmail)
+ ..onActionClick((data) => {}))
+ .build();
+ }
+
+ Widget _moveToSpamAction(BuildContext context, ImagePaths imagePaths, List listEmail) {
+ return (EmailContextMenuActionBuilder(
+ Key('move_to_spam_context_menu_action'),
+ SvgPicture.asset(imagePaths.icMailboxSpam, width: 24, height: 24, fit: BoxFit.fill),
+ AppLocalizations.of(context).move_to_spam, listEmail)
+ ..onActionClick((data) => {}))
+ .build();
+ }
+
bool canComposeEmail() => mailboxDashBoardController.sessionCurrent != null
&& mailboxDashBoardController.userProfile.value != null
&& mailboxDashBoardController.mapMailboxId.containsKey(PresentationMailbox.roleOutbox);
diff --git a/lib/features/thread/presentation/thread_view.dart b/lib/features/thread/presentation/thread_view.dart
index f1aa148d3..d9e5556bf 100644
--- a/lib/features/thread/presentation/thread_view.dart
+++ b/lib/features/thread/presentation/thread_view.dart
@@ -6,6 +6,7 @@ import 'package:model/email/presentation_email.dart';
import 'package:model/model.dart';
import 'package:tmail_ui_user/features/thread/presentation/model/load_more_state.dart';
import 'package:tmail_ui_user/features/thread/presentation/thread_controller.dart';
+import 'package:tmail_ui_user/features/thread/presentation/widgets/app_bar_thread_select_mode_active_builder.dart';
import 'package:tmail_ui_user/features/thread/presentation/widgets/app_bar_thread_widget_builder.dart';
import 'package:tmail_ui_user/features/thread/presentation/widgets/email_tile_builder.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
@@ -30,7 +31,7 @@ class ThreadView extends GetWidget {
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- _buildAppBarMailboxListMail(context),
+ _buildAppBarThread(context),
_buildLoadingView(),
Expanded(child: _buildListEmail(context)),
_buildLoadingViewLoadMore()
@@ -47,17 +48,37 @@ class ThreadView extends GetWidget {
);
}
- Widget _buildAppBarMailboxListMail(BuildContext context) {
+ Widget _buildAppBarThread(BuildContext context) {
+ return Obx(() => controller.currentSelectMode.value == SelectMode.ACTIVE
+ ? _buildAppBarSelectModeActive(context)
+ : _buildAppBarNormal(context));
+ }
+
+ Widget _buildAppBarNormal(BuildContext context) {
return Obx(() => Padding(
- padding: EdgeInsets.only(left: 15, right: 12),
- child: AppBarThreadWidgetBuilder(
+ padding: EdgeInsets.only(left: 15, right: 12),
+ child: AppBarThreadWidgetBuilder(
context,
imagePaths,
responsiveUtils,
controller.mailboxDashBoardController.selectedMailbox.value,
controller.mailboxDashBoardController.userProfile.value)
- .onOpenListMailboxActionClick(() => controller.openMailboxLeftMenu())
- .build()));
+ .onOpenListMailboxActionClick(() => controller.openMailboxLeftMenu())
+ .build()));
+ }
+
+ Widget _buildAppBarSelectModeActive(BuildContext context) {
+ return Obx(() => Padding(
+ padding: EdgeInsets.only(left: 15, right: 12),
+ child: (AppBarThreadSelectModeActiveBuilder(
+ context,
+ imagePaths,
+ controller.getListEmailSelected())
+ ..addCloseActionClick(() => controller.cancelSelectEmail())
+ ..addRemoveEmailActionClick((listEmail) => {})
+ ..addUnreadEmailActionClick((listEmail) => controller.unreadSelectedEmail(listEmail))
+ ..addOpenContextMenuActionClick((listEmail) => controller.openContextMenuSelectedEmail(context, imagePaths, listEmail)))
+ .build()));
}
Widget _buildLoadingView() {
@@ -92,12 +113,16 @@ class ThreadView extends GetWidget {
alignment: Alignment.center,
padding: EdgeInsets.zero,
color: responsiveUtils.isMobile(context) ? AppColor.bgMailboxListMail : Colors.white,
- child: RefreshIndicator(
- color: AppColor.primaryColor,
- onRefresh: () async => controller.refreshGetAllEmailAction(),
- child: Obx(() => controller.emailList.isNotEmpty
- ? _buildListEmailBody(context, controller.emailList)
- : _buildEmptyEmail(context))));
+ child: Obx(() => controller.currentSelectMode.value == SelectMode.INACTIVE
+ ? RefreshIndicator(
+ color: AppColor.primaryColor,
+ onRefresh: () async => controller.refreshGetAllEmailAction(),
+ child: controller.emailList.isNotEmpty
+ ? _buildListEmailBody(context, controller.emailList)
+ : _buildEmptyEmail(context))
+ : controller.emailList.isNotEmpty
+ ? _buildListEmailBody(context, controller.emailList)
+ : _buildEmptyEmail(context)));
}
Widget _buildListEmailBody(BuildContext context, List listPresentationEmail) {
@@ -114,18 +139,21 @@ class ThreadView extends GetWidget {
return false;
},
child: ListView.builder(
+ controller: controller.listEmailController,
padding: EdgeInsets.only(top: 16),
key: Key('presentation_email_list'),
itemCount: listPresentationEmail.length,
itemBuilder: (context, index) =>
- Obx(() => EmailTileBuilder(
- context,
- imagePaths,
- controller.getSelectMode(listPresentationEmail[index], controller.mailboxDashBoardController.selectedEmail.value),
- listPresentationEmail[index],
- responsiveUtils)
- .onOpenMailAction(() => controller.selectEmail(context, listPresentationEmail[index]))
- .build())
+ Obx(() => (EmailTileBuilder(
+ context,
+ imagePaths,
+ controller.getSelectMode(listPresentationEmail[index], controller.mailboxDashBoardController.selectedEmail.value),
+ listPresentationEmail[index],
+ responsiveUtils,
+ controller.currentSelectMode.value)
+ ..onOpenEmailAction((selectedEmail) => controller.previewEmail(context, selectedEmail))
+ ..onSelectEmailAction((selectedEmail) => controller.selectEmail(context, selectedEmail)))
+ .build()),
));
}
}
diff --git a/lib/features/thread/presentation/widgets/app_bar_thread_select_mode_active_builder.dart b/lib/features/thread/presentation/widgets/app_bar_thread_select_mode_active_builder.dart
new file mode 100644
index 000000000..c4b08ab51
--- /dev/null
+++ b/lib/features/thread/presentation/widgets/app_bar_thread_select_mode_active_builder.dart
@@ -0,0 +1,111 @@
+
+import 'package:core/core.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/widgets.dart';
+import 'package:model/email/presentation_email.dart';
+import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
+
+typedef OnCloseActionClick = void Function();
+typedef OnUnreadEmailActionClick = void Function(List listEmail);
+typedef OnRemoveEmailActionClick = void Function(List listEmail);
+typedef OnOpenContextMenuActionClick = void Function(List listEmail);
+
+class AppBarThreadSelectModeActiveBuilder {
+ OnCloseActionClick? _onCloseActionClick;
+ OnUnreadEmailActionClick? _onUnreadEmailActionClick;
+ OnRemoveEmailActionClick? _onRemoveEmailActionClick;
+ OnOpenContextMenuActionClick? _onOpenContextMenuActionClick;
+
+ final BuildContext _context;
+ final ImagePaths _imagePaths;
+ final List _listEmail;
+
+ AppBarThreadSelectModeActiveBuilder(this._context, this._imagePaths, this._listEmail);
+
+ void addCloseActionClick(OnCloseActionClick onCloseActionClick) {
+ _onCloseActionClick = onCloseActionClick;
+ }
+
+ void addUnreadEmailActionClick(OnUnreadEmailActionClick onUnreadEmailActionClick) {
+ _onUnreadEmailActionClick = onUnreadEmailActionClick;
+ }
+
+ void addRemoveEmailActionClick(OnRemoveEmailActionClick onRemoveEmailActionClick) {
+ _onRemoveEmailActionClick = onRemoveEmailActionClick;
+ }
+
+ void addOpenContextMenuActionClick(OnOpenContextMenuActionClick onOpenContextMenuActionClick) {
+ _onOpenContextMenuActionClick = onOpenContextMenuActionClick;
+ }
+
+ Widget build() {
+ return Container(
+ key: Key('app_bar_thread_select_mode_active'),
+ alignment: Alignment.center,
+ padding: EdgeInsets.symmetric(vertical: 8),
+ color: Colors.white,
+ child: MediaQuery(
+ data: MediaQueryData(padding: EdgeInsets.zero),
+ child: Row(
+ crossAxisAlignment: CrossAxisAlignment.center,
+ mainAxisAlignment: MainAxisAlignment.end,
+ children: [
+ _buildBackButton(),
+ Expanded(child: _buildCountItemSelected()),
+ _buildListOptionButton(),
+ ]
+ )
+ )
+ );
+ }
+
+ Widget _buildCountItemSelected() {
+ return Padding(
+ padding: EdgeInsets.only(left: 12),
+ child: Text(
+ AppLocalizations.of(_context).count_email_selected(_listEmail.length),
+ maxLines: 1,
+ overflow: TextOverflow.ellipsis,
+ style: TextStyle(fontSize: 18, color: AppColor.nameUserColor, fontWeight: FontWeight.w500)));
+ }
+
+ Widget _buildBackButton() {
+ return ButtonBuilder(_imagePaths.icComposerClose)
+ .padding(5)
+ .size(30)
+ .onPressActionClick(() {
+ if (_onCloseActionClick != null) {
+ _onCloseActionClick!();
+ }})
+ .build();
+ }
+
+ Widget _buildListOptionButton() {
+ return Row(
+ mainAxisAlignment: MainAxisAlignment.start,
+ crossAxisAlignment: CrossAxisAlignment.center,
+ children: [
+ ButtonBuilder(_imagePaths.icTrash).key(Key('button_remove_email_selected'))
+ .onPressActionClick(() {
+ if (_onRemoveEmailActionClick != null) {
+ _onRemoveEmailActionClick!(_listEmail);
+ }})
+ .build(),
+ SizedBox(width: 10),
+ ButtonBuilder(_imagePaths.icEyeDisable).key(Key('button_unread_email_selected'))
+ .onPressActionClick(() {
+ if (_onUnreadEmailActionClick != null) {
+ _onUnreadEmailActionClick!(_listEmail);
+ }})
+ .build(),
+ SizedBox(width: 10),
+ ButtonBuilder(_imagePaths.icComposerMenu).key(Key('button_menu_select_email'))
+ .onPressActionClick(() {
+ if (_onOpenContextMenuActionClick != null) {
+ _onOpenContextMenuActionClick!(_listEmail);
+ }})
+ .build(),
+ ]
+ );
+ }
+}
\ No newline at end of file
diff --git a/lib/features/thread/presentation/widgets/email_context_menu_action_builder.dart b/lib/features/thread/presentation/widgets/email_context_menu_action_builder.dart
new file mode 100644
index 000000000..a1c55cd88
--- /dev/null
+++ b/lib/features/thread/presentation/widgets/email_context_menu_action_builder.dart
@@ -0,0 +1,33 @@
+
+import 'package:core/core.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/widgets.dart';
+import 'package:flutter_svg/svg.dart';
+import 'package:model/model.dart';
+
+class EmailContextMenuActionBuilder extends ContextMenuActionBuilder> {
+ final List _listEmail;
+
+ EmailContextMenuActionBuilder(
+ Key key,
+ SvgPicture actionIcon,
+ String actionName,
+ this._listEmail
+ ) : super(key, actionIcon, actionName);
+
+ @override
+ ListTile build() {
+ return ListTile(
+ key: key,
+ leading: Padding(
+ padding: EdgeInsets.only(left: 12),
+ child: actionIcon),
+ title: Text(actionName, style: actionTextStyle()),
+ onTap: () {
+ if (onContextMenuActionClick != null) {
+ onContextMenuActionClick!(_listEmail);
+ }
+ }
+ );
+ }
+}
\ No newline at end of file
diff --git a/lib/features/thread/presentation/widgets/email_tile_builder.dart b/lib/features/thread/presentation/widgets/email_tile_builder.dart
index 0ef744701..5d982639b 100644
--- a/lib/features/thread/presentation/widgets/email_tile_builder.dart
+++ b/lib/features/thread/presentation/widgets/email_tile_builder.dart
@@ -1,3 +1,4 @@
+import 'dart:math';
import 'dart:ui';
import 'package:core/core.dart';
@@ -5,7 +6,8 @@ import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:model/model.dart';
-typedef OnOpenMailActionClick = void Function();
+typedef OnOpenEmailActionClick = void Function(PresentationEmail selectedEmail);
+typedef OnSelectEmailActionClick = void Function(PresentationEmail selectedEmail);
class EmailTileBuilder {
@@ -14,8 +16,10 @@ class EmailTileBuilder {
final PresentationEmail _presentationEmail;
final BuildContext _context;
final ResponsiveUtils _responsiveUtils;
+ final SelectMode _selectModeAll;
- OnOpenMailActionClick? _onOpenMailActionClick;
+ OnOpenEmailActionClick? _onOpenEmailActionClick;
+ OnSelectEmailActionClick? _onSelectEmailActionClick;
EmailTileBuilder(
this._context,
@@ -23,11 +27,15 @@ class EmailTileBuilder {
this._selectMode,
this._presentationEmail,
this._responsiveUtils,
+ this._selectModeAll,
);
- EmailTileBuilder onOpenMailAction(OnOpenMailActionClick onOpenMailActionClick) {
- _onOpenMailActionClick = onOpenMailActionClick;
- return this;
+ void onOpenEmailAction(OnOpenEmailActionClick onOpenEmailActionClick) {
+ _onOpenEmailActionClick = onOpenEmailActionClick;
+ }
+
+ void onSelectEmailAction(OnSelectEmailActionClick onSelectEmailActionClick) {
+ _onSelectEmailActionClick = onSelectEmailActionClick;
}
Widget build() {
@@ -41,28 +49,25 @@ class EmailTileBuilder {
padding: EdgeInsets.only(top: 10, bottom: 10, left: 25, right: 6),
alignment: Alignment.center,
decoration: BoxDecoration(
- borderRadius: BorderRadius.circular(16),
- color: _selectMode== SelectMode.ACTIVE
- ? _responsiveUtils.isDesktop(_context)
- ? AppColor.mailboxSelectedBackgroundColor
- : _responsiveUtils.isMobile(_context) ? AppColor.bgMailboxListMail : Colors.white
- : _responsiveUtils.isMobile(_context) ? AppColor.bgMailboxListMail : Colors.white),
+ borderRadius: BorderRadius.circular(_selectModeAll == SelectMode.ACTIVE ? 0 : 16),
+ color: _getBackgroundColorItem()),
child: MediaQuery(
data: MediaQueryData(padding: EdgeInsets.zero),
child: ListTile(
contentPadding: EdgeInsets.zero,
onTap: () => {
- if (_onOpenMailActionClick != null) {
- _onOpenMailActionClick!()
+ if (_onOpenEmailActionClick != null) {
+ _onOpenEmailActionClick!(_presentationEmail)
+ }
+ },
+ onLongPress: () => {
+ if (_onSelectEmailActionClick != null) {
+ _onSelectEmailActionClick!(_presentationEmail)
}
},
leading: Transform(
transform: Matrix4.translationValues(-10.0, -10.0, 0.0),
- child: AvatarBuilder()
- .text('${_presentationEmail.getAvatarText()}')
- .size(40)
- .iconStatus(_imagePaths.icOffline)
- .build()),
+ child: _buildAvatarIcon()),
title: Transform(
transform: Matrix4.translationValues(-10.0, 0.0, 0.0),
child: Row(
@@ -131,4 +136,70 @@ class EmailTileBuilder {
)
);
}
+
+ Widget _buildAvatarIcon () {
+ if (_selectModeAll == SelectMode.ACTIVE) {
+ return AnimatedSwitcher(
+ duration: Duration(milliseconds: 600),
+ transitionBuilder: __transitionBuilder,
+ child: _presentationEmail.selectMode == SelectMode.ACTIVE
+ ? (IconBuilder(_imagePaths.icSelected)
+ ..addOnTapActionClick(() {
+ if (_selectModeAll == SelectMode.ACTIVE && _onSelectEmailActionClick != null) {
+ _onSelectEmailActionClick!(_presentationEmail);
+ }}))
+ .build()
+ : AvatarBuilder()
+ .text('${_presentationEmail.getAvatarText()}')
+ .size(40)
+ .iconStatus(_imagePaths.icOffline)
+ .addOnTapActionClick(() {
+ if (_selectModeAll == SelectMode.ACTIVE && _onSelectEmailActionClick != null) {
+ _onSelectEmailActionClick!(_presentationEmail);
+ }})
+ .build()
+ );
+ } else {
+ return AvatarBuilder()
+ .text('${_presentationEmail.getAvatarText()}')
+ .size(40)
+ .iconStatus(_imagePaths.icOffline)
+ .build();
+ }
+ }
+
+ Widget __transitionBuilder(Widget widget, Animation animation) {
+ final rotateAnim = Tween(begin: pi, end: 0.0).animate(animation);
+ return AnimatedBuilder(
+ animation: rotateAnim,
+ child: widget,
+ builder: (context, widget) {
+ final isUnder = _presentationEmail.selectMode == SelectMode.ACTIVE;
+ final value = isUnder ? min(rotateAnim.value, pi / 2) : rotateAnim.value;
+ return Transform(
+ transform: Matrix4.rotationY(value),
+ child: widget,
+ alignment: Alignment.center,
+ );
+ },
+ );
+ }
+
+ Color _getBackgroundColorItem() {
+ if (_selectModeAll == SelectMode.ACTIVE) {
+ if (_presentationEmail.selectMode == SelectMode.ACTIVE) {
+ return AppColor.mailboxSelectedBackgroundColor;
+ } else {
+ return _responsiveUtils.isMobile(_context) ? AppColor.bgMailboxListMail : Colors.white;
+ }
+ } else {
+ if (_responsiveUtils.isMobile(_context)) {
+ return AppColor.bgMailboxListMail;
+ } else if (_responsiveUtils.isDesktop(_context)) {
+ return _selectMode == SelectMode.ACTIVE ? AppColor.mailboxSelectedBackgroundColor : Colors.white;
+ } else {
+ return Colors.white;
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb
index b7c2f879a..3519fd2b1 100644
--- a/lib/l10n/intl_en.arb
+++ b/lib/l10n/intl_en.arb
@@ -142,5 +142,62 @@
"@prefix_forward_email": {
"type": "text",
"placeholders": {}
+ },
+ "your_email_being_sent": "Your email being sent...",
+ "@your_email_being_sent": {
+ "type": "text",
+ "placeholders": {}
+ },
+ "your_email_should_have_at_least_one_recipient": "Your email should have at least one recipient",
+ "@your_email_should_have_at_least_one_recipient": {
+ "type": "text",
+ "placeholders": {}
+ },
+ "message_sent": "Message sent",
+ "@message_sent": {
+ "type": "text",
+ "placeholders": {}
+ },
+ "error_message_sent": "Error message sent",
+ "@error_message_sent": {
+ "type": "text",
+ "placeholders": {}
+ },
+ "count_email_selected": "{count} selected",
+ "@count_email_selected": {
+ "type": "text",
+ "placeholders": {
+ "count": {}
+ }
+ },
+ "mark_as_unread": "Mark as unread",
+ "@mark_as_unread": {
+ "type": "text",
+ "placeholders": {}
+ },
+ "mark_as_read": "Mark as read",
+ "@mark_as_read": {
+ "type": "text",
+ "placeholders": {}
+ },
+ "move_to_trash": "Move to trash",
+ "@move_to_trash": {
+ "type": "text",
+ "placeholders": {}
+ },
+ "move_to_mailbox": "Move to mailbox",
+ "@move_to_mailbox": {
+ "type": "text",
+ "placeholders": {}
+ },
+ "mark_as_flag": "Star",
+ "@mark_as_flag": {
+ "type": "text",
+ "placeholders": {}
+ },
+ "move_to_spam": "Move to spam",
+ "@move_to_spam": {
+ "type": "text",
+ "placeholders": {}
}
}
\ No newline at end of file
diff --git a/lib/l10n/intl_fr.arb b/lib/l10n/intl_fr.arb
index b7c2f879a..3519fd2b1 100644
--- a/lib/l10n/intl_fr.arb
+++ b/lib/l10n/intl_fr.arb
@@ -142,5 +142,62 @@
"@prefix_forward_email": {
"type": "text",
"placeholders": {}
+ },
+ "your_email_being_sent": "Your email being sent...",
+ "@your_email_being_sent": {
+ "type": "text",
+ "placeholders": {}
+ },
+ "your_email_should_have_at_least_one_recipient": "Your email should have at least one recipient",
+ "@your_email_should_have_at_least_one_recipient": {
+ "type": "text",
+ "placeholders": {}
+ },
+ "message_sent": "Message sent",
+ "@message_sent": {
+ "type": "text",
+ "placeholders": {}
+ },
+ "error_message_sent": "Error message sent",
+ "@error_message_sent": {
+ "type": "text",
+ "placeholders": {}
+ },
+ "count_email_selected": "{count} selected",
+ "@count_email_selected": {
+ "type": "text",
+ "placeholders": {
+ "count": {}
+ }
+ },
+ "mark_as_unread": "Mark as unread",
+ "@mark_as_unread": {
+ "type": "text",
+ "placeholders": {}
+ },
+ "mark_as_read": "Mark as read",
+ "@mark_as_read": {
+ "type": "text",
+ "placeholders": {}
+ },
+ "move_to_trash": "Move to trash",
+ "@move_to_trash": {
+ "type": "text",
+ "placeholders": {}
+ },
+ "move_to_mailbox": "Move to mailbox",
+ "@move_to_mailbox": {
+ "type": "text",
+ "placeholders": {}
+ },
+ "mark_as_flag": "Star",
+ "@mark_as_flag": {
+ "type": "text",
+ "placeholders": {}
+ },
+ "move_to_spam": "Move to spam",
+ "@move_to_spam": {
+ "type": "text",
+ "placeholders": {}
}
}
\ No newline at end of file
diff --git a/lib/l10n/intl_messages.arb b/lib/l10n/intl_messages.arb
index 84ae33843..3a8c15b2e 100644
--- a/lib/l10n/intl_messages.arb
+++ b/lib/l10n/intl_messages.arb
@@ -1,5 +1,5 @@
{
- "@@last_modified": "2021-09-16T11:55:46.823676",
+ "@@last_modified": "2021-09-15T10:03:14.927099",
"initializing_data": "Initializing data...",
"@initializing_data": {
"type": "text",
@@ -197,5 +197,62 @@
"type": "text",
"placeholders_order": [],
"placeholders": {}
+ },
+ "your_email_being_sent": "Your email being sent...",
+ "@your_email_being_sent": {
+ "type": "text",
+ "placeholders": {}
+ },
+ "your_email_should_have_at_least_one_recipient": "Your email should have at least one recipient",
+ "@your_email_should_have_at_least_one_recipient": {
+ "type": "text",
+ "placeholders": {}
+ },
+ "message_sent": "Message sent",
+ "@message_sent": {
+ "type": "text",
+ "placeholders": {}
+ },
+ "error_message_sent": "Error message sent",
+ "@error_message_sent": {
+ "type": "text",
+ "placeholders": {}
+ },
+ "count_email_selected": "{count} selected",
+ "@count_email_selected": {
+ "type": "text",
+ "placeholders": {
+ "count": {}
+ }
+ },
+ "mark_as_unread": "Mark as unread",
+ "@mark_as_unread": {
+ "type": "text",
+ "placeholders": {}
+ },
+ "mark_as_read": "Mark as read",
+ "@mark_as_read": {
+ "type": "text",
+ "placeholders": {}
+ },
+ "move_to_trash": "Move to trash",
+ "@move_to_trash": {
+ "type": "text",
+ "placeholders": {}
+ },
+ "move_to_mailbox": "Move to mailbox",
+ "@move_to_mailbox": {
+ "type": "text",
+ "placeholders": {}
+ },
+ "mark_as_flag": "Star",
+ "@mark_as_flag": {
+ "type": "text",
+ "placeholders": {}
+ },
+ "move_to_spam": "Move to spam",
+ "@move_to_spam": {
+ "type": "text",
+ "placeholders": {}
}
}
\ No newline at end of file
diff --git a/lib/l10n/intl_ru.arb b/lib/l10n/intl_ru.arb
index b7c2f879a..3519fd2b1 100644
--- a/lib/l10n/intl_ru.arb
+++ b/lib/l10n/intl_ru.arb
@@ -142,5 +142,62 @@
"@prefix_forward_email": {
"type": "text",
"placeholders": {}
+ },
+ "your_email_being_sent": "Your email being sent...",
+ "@your_email_being_sent": {
+ "type": "text",
+ "placeholders": {}
+ },
+ "your_email_should_have_at_least_one_recipient": "Your email should have at least one recipient",
+ "@your_email_should_have_at_least_one_recipient": {
+ "type": "text",
+ "placeholders": {}
+ },
+ "message_sent": "Message sent",
+ "@message_sent": {
+ "type": "text",
+ "placeholders": {}
+ },
+ "error_message_sent": "Error message sent",
+ "@error_message_sent": {
+ "type": "text",
+ "placeholders": {}
+ },
+ "count_email_selected": "{count} selected",
+ "@count_email_selected": {
+ "type": "text",
+ "placeholders": {
+ "count": {}
+ }
+ },
+ "mark_as_unread": "Mark as unread",
+ "@mark_as_unread": {
+ "type": "text",
+ "placeholders": {}
+ },
+ "mark_as_read": "Mark as read",
+ "@mark_as_read": {
+ "type": "text",
+ "placeholders": {}
+ },
+ "move_to_trash": "Move to trash",
+ "@move_to_trash": {
+ "type": "text",
+ "placeholders": {}
+ },
+ "move_to_mailbox": "Move to mailbox",
+ "@move_to_mailbox": {
+ "type": "text",
+ "placeholders": {}
+ },
+ "mark_as_flag": "Star",
+ "@mark_as_flag": {
+ "type": "text",
+ "placeholders": {}
+ },
+ "move_to_spam": "Move to spam",
+ "@move_to_spam": {
+ "type": "text",
+ "placeholders": {}
}
}
\ No newline at end of file
diff --git a/lib/l10n/intl_vi.arb b/lib/l10n/intl_vi.arb
index b7c2f879a..3519fd2b1 100644
--- a/lib/l10n/intl_vi.arb
+++ b/lib/l10n/intl_vi.arb
@@ -142,5 +142,62 @@
"@prefix_forward_email": {
"type": "text",
"placeholders": {}
+ },
+ "your_email_being_sent": "Your email being sent...",
+ "@your_email_being_sent": {
+ "type": "text",
+ "placeholders": {}
+ },
+ "your_email_should_have_at_least_one_recipient": "Your email should have at least one recipient",
+ "@your_email_should_have_at_least_one_recipient": {
+ "type": "text",
+ "placeholders": {}
+ },
+ "message_sent": "Message sent",
+ "@message_sent": {
+ "type": "text",
+ "placeholders": {}
+ },
+ "error_message_sent": "Error message sent",
+ "@error_message_sent": {
+ "type": "text",
+ "placeholders": {}
+ },
+ "count_email_selected": "{count} selected",
+ "@count_email_selected": {
+ "type": "text",
+ "placeholders": {
+ "count": {}
+ }
+ },
+ "mark_as_unread": "Mark as unread",
+ "@mark_as_unread": {
+ "type": "text",
+ "placeholders": {}
+ },
+ "mark_as_read": "Mark as read",
+ "@mark_as_read": {
+ "type": "text",
+ "placeholders": {}
+ },
+ "move_to_trash": "Move to trash",
+ "@move_to_trash": {
+ "type": "text",
+ "placeholders": {}
+ },
+ "move_to_mailbox": "Move to mailbox",
+ "@move_to_mailbox": {
+ "type": "text",
+ "placeholders": {}
+ },
+ "mark_as_flag": "Star",
+ "@mark_as_flag": {
+ "type": "text",
+ "placeholders": {}
+ },
+ "move_to_spam": "Move to spam",
+ "@move_to_spam": {
+ "type": "text",
+ "placeholders": {}
}
}
\ No newline at end of file
diff --git a/lib/main/localizations/app_localizations.dart b/lib/main/localizations/app_localizations.dart
index 558b8f16c..ac6289179 100644
--- a/lib/main/localizations/app_localizations.dart
+++ b/lib/main/localizations/app_localizations.dart
@@ -227,5 +227,55 @@ class AppLocalizations {
name: 'error_message_sent',
);
}
+
+ String count_email_selected(int count) {
+ return Intl.message(
+ '$count selected',
+ name: 'count_email_selected',
+ args: [count]
+ );
+ }
+
+ String get mark_as_unread {
+ return Intl.message(
+ 'Mark as unread',
+ name: 'mark_as_unread',
+ );
+ }
+
+ String get mark_as_read {
+ return Intl.message(
+ 'Mark as read',
+ name: 'mark_as_read',
+ );
+ }
+
+ String get move_to_trash {
+ return Intl.message(
+ 'Move to trash',
+ name: 'move_to_trash',
+ );
+ }
+
+ String get move_to_mailbox {
+ return Intl.message(
+ 'Move to mailbox',
+ name: 'move_to_mailbox',
+ );
+ }
+
+ String get mark_as_flag {
+ return Intl.message(
+ 'Star',
+ name: 'mark_as_flag',
+ );
+ }
+
+ String get move_to_spam {
+ return Intl.message(
+ 'Move to spam',
+ name: 'move_to_spam',
+ );
+ }
}
diff --git a/model/lib/extensions/presentation_email_extension.dart b/model/lib/extensions/presentation_email_extension.dart
index 0fb97d9a0..efb91a13d 100644
--- a/model/lib/extensions/presentation_email_extension.dart
+++ b/model/lib/extensions/presentation_email_extension.dart
@@ -46,4 +46,42 @@ extension PresentationEmailExtension on PresentationEmail {
selectMode: selectMode
);
}
+
+ PresentationEmail toggleSelect() {
+ return PresentationEmail(
+ id,
+ keywords: keywords,
+ size: size,
+ receivedAt: receivedAt,
+ hasAttachment: hasAttachment,
+ preview: preview,
+ subject: subject,
+ sentAt: sentAt,
+ from: from,
+ to: to,
+ cc: cc,
+ bcc: bcc,
+ replyTo: replyTo,
+ selectMode: selectMode == SelectMode.INACTIVE ? SelectMode.ACTIVE : SelectMode.INACTIVE
+ );
+ }
+
+ PresentationEmail toSelectedEmail({required SelectMode selectMode}) {
+ return PresentationEmail(
+ id,
+ keywords: keywords,
+ size: size,
+ receivedAt: receivedAt,
+ hasAttachment: hasAttachment,
+ preview: preview,
+ subject: subject,
+ sentAt: sentAt,
+ from: from,
+ to: to,
+ cc: cc,
+ bcc: bcc,
+ replyTo: replyTo,
+ selectMode: selectMode
+ );
+ }
}
\ No newline at end of file