Files
workavia-mail-front/lib/features/thread/presentation/thread_view.dart
T

928 lines
39 KiB
Dart

import 'package:core/core.dart';
import 'package:flutter/material.dart';
import 'package:flutter_portal/flutter_portal.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart';
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
import 'package:model/model.dart';
import 'package:tmail_ui_user/features/base/mixin/app_loader_mixin.dart';
import 'package:tmail_ui_user/features/base/mixin/popup_menu_widget_mixin.dart';
import 'package:tmail_ui_user/features/base/widget/compose_floating_button.dart';
import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart';
import 'package:tmail_ui_user/features/email/presentation/widgets/email_action_cupertino_action_sheet_action_builder.dart';
import 'package:tmail_ui_user/features/mailbox/domain/state/mark_as_mailbox_read_state.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mixin/filter_email_popup_menu_mixin.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/recover_deleted_message_loading_banner_widget.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/extensions/vacation_response_extension.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/vacation/widgets/vacation_notification_message_widget.dart';
import 'package:tmail_ui_user/features/network_connection/presentation/network_connection_banner_widget.dart';
import 'package:tmail_ui_user/features/quotas/presentation/widget/quotas_banner_widget.dart';
import 'package:tmail_ui_user/features/thread/domain/model/filter_message_option.dart';
import 'package:tmail_ui_user/features/thread/domain/state/get_all_email_state.dart';
import 'package:tmail_ui_user/features/thread/domain/state/search_email_state.dart';
import 'package:tmail_ui_user/features/thread/presentation/model/delete_action_type.dart';
import 'package:tmail_ui_user/features/thread/presentation/model/loading_more_status.dart';
import 'package:tmail_ui_user/features/thread/presentation/styles/banner_delete_all_spam_emails_styles.dart';
import 'package:tmail_ui_user/features/thread/presentation/styles/banner_empty_trash_styles.dart';
import 'package:tmail_ui_user/features/thread/presentation/styles/item_email_tile_styles.dart';
import 'package:tmail_ui_user/features/thread/presentation/styles/scroll_to_top_button_widget_styles.dart';
import 'package:tmail_ui_user/features/thread/presentation/thread_controller.dart';
import 'package:tmail_ui_user/features/thread/presentation/widgets/app_bar/app_bar_thread_widget.dart';
import 'package:tmail_ui_user/features/thread/presentation/widgets/banner_delete_all_spam_emails_widget.dart';
import 'package:tmail_ui_user/features/thread/presentation/widgets/banner_empty_trash_widget.dart';
import 'package:tmail_ui_user/features/thread/presentation/widgets/bottom_bar_thread_selection_widget.dart';
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/features/thread/presentation/widgets/empty_emails_widget.dart';
import 'package:tmail_ui_user/features/thread/presentation/widgets/filter_message_cupertino_action_sheet_action_builder.dart';
import 'package:tmail_ui_user/features/thread/presentation/widgets/scroll_to_top_button_widget.dart';
import 'package:tmail_ui_user/features/thread/presentation/widgets/spam_banner/spam_report_banner_widget.dart';
import 'package:tmail_ui_user/features/thread/presentation/widgets/thread_view_loading_bar_widget.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
class ThreadView extends GetWidget<ThreadController>
with AppLoaderMixin,
FilterEmailPopupMenuMixin,
PopupMenuWidgetMixin {
ThreadView({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: FocusManager.instance.primaryFocus?.unfocus,
child: Scaffold(
resizeToAvoidBottomInset: false,
backgroundColor: Colors.white,
body: Portal(
child: Row(children: [
if (_supportVerticalDivider(context))
const VerticalDivider(),
Expanded(child: SafeArea(
right: controller.responsiveUtils.isLandscapeMobile(context),
left: controller.responsiveUtils.isLandscapeMobile(context),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (!controller.responsiveUtils.isWebDesktop(context))
... [
Obx(() {
return AppBarThreadWidget(
mailboxSelected: controller.selectedMailbox,
listEmailSelected: controller.mailboxDashBoardController.emailsInCurrentMailbox.listEmailSelected,
selectMode: controller.mailboxDashBoardController.currentSelectMode.value,
filterOption: controller.mailboxDashBoardController.filterMessageOption.value,
openMailboxAction: controller.openMailboxLeftMenu,
cancelEditThreadAction: controller.cancelSelectEmail,
emailSelectionAction: (actionType, selectionEmail) {
return controller.pressEmailSelectionAction(
context,
actionType,
selectionEmail
);
},
onContextMenuFilterEmailAction: controller.responsiveUtils.isScreenWithShortestSide(context)
? (filterOption) => controller.openContextMenuAction(
context,
_filterMessagesCupertinoActionTile(context, filterOption)
)
: null,
onPopupMenuFilterEmailAction: !controller.responsiveUtils.isScreenWithShortestSide(context)
? (filterOption, position) => controller.openPopupMenuAction(
context,
position,
popupMenuFilterEmailActionTile(
context,
filterOption,
(option) => controller.filterMessagesAction(context, option)
)
)
: null
);
}),
if (PlatformInfo.isMobile)
Obx(() {
if (!controller.networkConnectionController.isNetworkConnectionAvailable()) {
return NetworkConnectionBannerWidget();
} else {
return const SizedBox.shrink();
}
}),
SearchBarView(
key: const Key('email_search_bar_view'),
imagePaths: controller.imagePaths,
margin: _getBannerMargin(context, controller.responsiveUtils),
hintTextSearch: AppLocalizations.of(context).search_emails,
onOpenSearchViewAction: controller.goToSearchView
),
SpamReportBannerWidget(
spamReportController: controller.mailboxDashBoardController.spamReportController,
margin: _getBannerMargin(context, controller.responsiveUtils),
),
QuotasBannerWidget(
margin: _getBannerMargin(context, controller.responsiveUtils),
),
Obx(() {
final vacation = controller.mailboxDashBoardController.vacationResponse.value;
if (vacation?.vacationResponderIsValid == true) {
return VacationNotificationMessageWidget(
margin: _getBannerMargin(context, controller.responsiveUtils),
vacationResponse: vacation!,
actionGotoVacationSetting: controller.mailboxDashBoardController.goToVacationSetting,
actionEndNow: controller.mailboxDashBoardController.disableVacationResponder
);
} else {
return const SizedBox.shrink();
}
}),
Obx(() => RecoverDeletedMessageLoadingBannerWidget(
isLoading: controller.mailboxDashBoardController.isRecoveringDeletedMessage.value,
horizontalLoadingWidget: horizontalLoadingWidget,
responsiveUtils: controller.responsiveUtils,
)),
],
Obx(() {
final presentationMailbox = controller.mailboxDashBoardController.selectedMailbox.value;
if (controller.mailboxDashBoardController.isEmptyTrashBannerEnabledOnMobile(context, presentationMailbox)) {
return Padding(
padding: const EdgeInsetsDirectional.symmetric(
horizontal: BannerEmptyTrashStyles.mobileMargin
),
child: BannerEmptyTrashWidget(
onTapAction: () => controller.deleteSelectionEmailsPermanently(context, DeleteActionType.all)
),
);
} else {
return const SizedBox.shrink();
}
}),
Obx(() {
final presentationMailbox = controller.mailboxDashBoardController.selectedMailbox.value;
if (controller.mailboxDashBoardController.isEmptySpamBannerEnabledOnMobile(context, presentationMailbox)) {
return Padding(
padding: const EdgeInsetsDirectional.symmetric(
horizontal: BannerDeleteAllSpamEmailsStyles.mobileMargin
),
child: BannerDeleteAllSpamEmailsWidget(
onTapAction: () => controller.mailboxDashBoardController.openDialogEmptySpamFolder(context)
),
);
} else {
return const SizedBox.shrink();
}
}),
if (!controller.responsiveUtils.isDesktop(context))
_buildMarkAsMailboxReadLoading(context),
Obx(() => ThreadViewLoadingBarWidget(viewState: controller.viewState.value)),
Expanded(
child: Container(
alignment: Alignment.center,
color: Colors.white,
child: Obx(() {
return Visibility(
visible: controller.openingEmail.isFalse,
child: _buildResultListEmail(
context,
controller.mailboxDashBoardController.emailsInCurrentMailbox
)
);
})
)
),
_buildListButtonSelectionForMobile(context),
]
)
))
]),
),
floatingActionButton: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Container(
padding: const EdgeInsetsDirectional.only(end: 4.0),
child: ScrollToTopButtonWidget(
scrollController: controller.listEmailController,
onTap: controller.scrollToTop,
responsiveUtils: controller.responsiveUtils,
icon: SvgPicture.asset(
controller.imagePaths.icArrowUpOutline,
width: ScrollToTopButtonWidgetStyles.iconWidth,
height: ScrollToTopButtonWidgetStyles.iconHeight,
fit: BoxFit.fill,
colorFilter: Colors.white.asFilter(),
),
),
),
const SizedBox(height: 24),
_buildFloatingButtonCompose(context),
],
),
),
);
}
EdgeInsetsGeometry _getBannerMargin(BuildContext context, ResponsiveUtils responsiveUtils) {
if (PlatformInfo.isWeb) {
if (responsiveUtils.isMobile(context) || responsiveUtils.isTabletLarge(context)) {
return const EdgeInsetsDirectional.only(start: 12, end: 12, bottom: 8);
} else {
return const EdgeInsetsDirectional.only(start: 24, end: 24, bottom: 8);
}
} else {
if (responsiveUtils.isPortraitMobile(context) || responsiveUtils.isLandscapeTablet(context)) {
return const EdgeInsetsDirectional.only(start: 16, end: 16, bottom: 8);
} else {
return const EdgeInsetsDirectional.only(start: 32, end: 32, bottom: 8);
}
}
}
bool _supportVerticalDivider(BuildContext context) {
if (PlatformInfo.isWeb) {
return controller.responsiveUtils.isTabletLarge(context);
} else {
return controller.responsiveUtils.isDesktop(context) ||
controller.responsiveUtils.isTabletLarge(context) ||
controller.responsiveUtils.isLandscapeTablet(context);
}
}
Widget _buildListButtonSelectionForMobile(BuildContext context) {
return Obx(() {
final listEmailSelected = controller.mailboxDashBoardController.emailsInCurrentMailbox.listEmailSelected;
final currentSelectMode = controller.mailboxDashBoardController.currentSelectMode.value;
final isSearchEmailRunning = controller.searchController.simpleSearchIsActivated.isTrue
|| controller.searchController.advancedSearchIsActivated.isTrue;
if (_validateDisplayBottomBarSelection(
context: context,
listEmailSelected: listEmailSelected,
isSearchEmailRunning: isSearchEmailRunning,
currentSelectMode: currentSelectMode
)) {
return BottomBarThreadSelectionWidget(
controller.imagePaths,
controller.responsiveUtils,
listEmailSelected,
controller.mailboxDashBoardController.selectedMailbox.value,
onPressEmailSelectionActionClick: (actionType, selectionEmail) =>
controller.pressEmailSelectionAction(
context,
actionType,
selectionEmail
)
);
} else {
return const SizedBox.shrink();
}
});
}
bool _validateDisplayBottomBarSelection({
required BuildContext context,
required List<PresentationEmail> listEmailSelected,
required bool isSearchEmailRunning,
required SelectMode currentSelectMode,
}) {
if (PlatformInfo.isMobile && listEmailSelected.isNotEmpty) {
return true;
}
if (PlatformInfo.isWeb
&& currentSelectMode == SelectMode.ACTIVE
&& isSearchEmailRunning
&& !controller.responsiveUtils.isDesktop(context)
&& listEmailSelected.isNotEmpty
) {
return true;
}
return false;
}
Widget _buildFloatingButtonCompose(BuildContext context) {
if (controller.responsiveUtils.isWebDesktop(context)) {
return const SizedBox.shrink();
}
return Obx(() {
final isAdvancedSearchViewOpen = controller.searchController.isAdvancedSearchViewOpen.value;
final isTrashViewOpen = controller.isMailboxTrash;
final isSelectModeActive = controller.mailboxDashBoardController.currentSelectMode.value == SelectMode.ACTIVE;
if (
!controller.searchController.isSearchActive()
&& !isAdvancedSearchViewOpen
&& !isTrashViewOpen
&& !isSelectModeActive
) {
return Container(
padding: PlatformInfo.isMobile && controller.listEmailSelected.isNotEmpty
? EdgeInsets.only(bottom: controller.responsiveUtils.isTabletLarge(context) ? 85 : 70)
: EdgeInsets.zero,
child: ComposeFloatingButton(
scrollController: controller.listEmailController,
onTap: () => controller.mailboxDashBoardController.goToComposer(ComposerArguments())
),
);
} else {
return const SizedBox.shrink();
}
});
}
List<Widget> _filterMessagesCupertinoActionTile(BuildContext context, FilterMessageOption optionCurrent) {
final listFilter = [
FilterMessageOption.attachments,
FilterMessageOption.unread,
FilterMessageOption.starred,
];
return listFilter.map((filter) => (FilterMessageCupertinoActionSheetActionBuilder(
Key('filter_email_${filter.name}'),
SvgPicture.asset(
filter.getIcon(controller.imagePaths),
width: 20,
height: 20,
fit: BoxFit.fill,
colorFilter: filter == FilterMessageOption.attachments
? AppColor.colorTextButton.asFilter()
: null),
filter.getName(context),
filter,
optionCurrent: optionCurrent,
iconLeftPadding: controller.responsiveUtils.isMobile(context)
? const EdgeInsets.only(left: 12, right: 16)
: const EdgeInsets.only(right: 12),
iconRightPadding: controller.responsiveUtils.isMobile(context)
? const EdgeInsets.only(right: 12)
: EdgeInsets.zero,
actionSelected: SvgPicture.asset(
controller.imagePaths.icFilterSelected,
width: 20,
height: 20,
fit: BoxFit.fill))
..onActionClick((option) => controller.filterMessagesAction(context, option)))
.build()).toList();
}
Widget _buildResultListEmail(BuildContext context, List<PresentationEmail> listPresentationEmail) {
if (controller.mailboxDashBoardController.currentSelectMode.value == SelectMode.INACTIVE) {
return listPresentationEmail.isNotEmpty
? RefreshIndicator(
color: AppColor.colorTextButton,
onRefresh: () async => controller.refreshAllEmail(),
child: _buildListEmailBody(context, listPresentationEmail))
: RefreshIndicator(
color: AppColor.colorTextButton,
onRefresh: () async => controller.refreshAllEmail(),
child: _buildEmptyEmail(context));
} else {
return listPresentationEmail.isNotEmpty
? _buildListEmailBody(context, listPresentationEmail)
: _buildEmptyEmail(context);
}
}
Widget _buildListEmailBody(BuildContext context, List<PresentationEmail> listPresentationEmail) {
return NotificationListener<ScrollNotification>(
onNotification: _handleScrollNotificationListener,
child: PlatformInfo.isMobile
? ListView.separated(
key: const PageStorageKey('list_presentation_email_in_threads'),
controller: controller.listEmailController,
physics: const AlwaysScrollableScrollPhysics(),
itemCount: listPresentationEmail.length + 2,
itemBuilder: (context, index) => Obx(() {
if (index == listPresentationEmail.length) {
return _buildLoadMoreButton(
context,
controller.loadingMoreStatus.value);
}
if (index == listPresentationEmail.length + 1) {
return _buildLoadMoreProgressBar(controller.loadingMoreStatus.value);
}
return _buildEmailItemNotDraggable(
context,
listPresentationEmail[index]);
}),
separatorBuilder: (context, index) {
if (index < listPresentationEmail.length - 1) {
return Padding(
padding: ItemEmailTileStyles.getMobilePaddingItemList(context, controller.responsiveUtils),
child: const Divider());
} else {
return const SizedBox.shrink();
}
},
)
: Focus(
focusNode: controller.focusNodeKeyBoard,
autofocus: true,
onKeyEvent: controller.handleKeyEvent,
child: ListView.separated(
key: const PageStorageKey('list_presentation_email_in_threads'),
controller: controller.listEmailController,
physics: const AlwaysScrollableScrollPhysics(),
itemCount: listPresentationEmail.length + 2,
itemBuilder: (context, index) => Obx(() {
if (index == listPresentationEmail.length) {
return _buildLoadMoreButton(
context,
controller.loadingMoreStatus.value);
}
if (index == listPresentationEmail.length + 1) {
return _buildLoadMoreProgressBar(controller.loadingMoreStatus.value);
}
return _buildEmailItem(
context,
listPresentationEmail[index]);
}),
separatorBuilder: (context, index) {
return Padding(
padding: ItemEmailTileStyles.getPaddingDividerWeb(context, controller.responsiveUtils),
child: Divider(
color: index < listPresentationEmail.length - 1 &&
controller.mailboxDashBoardController.currentSelectMode.value == SelectMode.INACTIVE
? null
: Colors.white,
)
);
},
),
)
);
}
bool _handleScrollNotificationListener(ScrollNotification scrollInfo) {
if (scrollInfo is ScrollEndNotification &&
scrollInfo.metrics.pixels == scrollInfo.metrics.maxScrollExtent &&
!controller.loadingMoreStatus.value.isRunning
) {
controller.handleLoadMoreEmailsRequest();
}
return false;
}
Widget _buildLoadMoreButton(BuildContext context, LoadingMoreStatus loadingMoreStatus) {
if (((controller.canLoadMore && !controller.isSearchActive) ||
(controller.canSearchMore && controller.isSearchActive)) &&
!loadingMoreStatus.isRunning) {
return Center(
child: OutlinedButton(
style: OutlinedButton.styleFrom(
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
),
onPressed: controller.handleLoadMoreEmailsRequest,
child: Text(
AppLocalizations.of(context).loadMore,
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
color: Colors.black
)
),
),
);
}
return const SizedBox.shrink();
}
Widget _buildLoadMoreProgressBar(LoadingMoreStatus loadingMoreStatus) {
if (loadingMoreStatus.isRunning) {
return const CupertinoLoadingWidget();
}
return const SizedBox.shrink();
}
Widget _buildEmailItem(BuildContext context, PresentationEmail presentationEmail) {
if (controller.responsiveUtils.isWebDesktop(context)) {
return _buildEmailItemDraggable(context, presentationEmail);
} else {
return _buildEmailItemNotDraggable(context, presentationEmail);
}
}
Widget _buildEmailItemDraggable(BuildContext context, PresentationEmail presentationEmail) {
return GestureDetector(
behavior: HitTestBehavior.translucent,
onSecondaryTapDown: (_) {},
onTapDown: (_) {},
child: Draggable<List<PresentationEmail>>(
data: controller.listEmailDrag,
feedback: _buildFeedBackWidget(context),
childWhenDragging: _buildEmailItemWhenDragging(context, presentationEmail),
dragAnchorStrategy: pointerDragAnchorStrategy,
onDragStarted: () {
controller.calculateDragValue(presentationEmail);
controller.onDragMailBox(true);
},
onDragEnd: (_) => controller.onDragMailBox(false),
onDraggableCanceled: (_,__) => controller.onDragMailBox(false),
child: _buildEmailItemNotDraggable(context, presentationEmail)
),
);
}
Widget _buildEmailItemWhenDragging(BuildContext context, PresentationEmail presentationEmail) {
final isShowingEmailContent = controller.mailboxDashBoardController.selectedEmail.value?.id == presentationEmail.id;
final selectModeAll = controller.mailboxDashBoardController.currentSelectMode.value;
return EmailTileBuilder(
key: Key('email_tile_builder_${presentationEmail.id?.asString}'),
presentationEmail: presentationEmail,
selectAllMode: selectModeAll,
isShowingEmailContent: isShowingEmailContent,
searchQuery: controller.searchQuery,
mailboxContain: presentationEmail.mailboxContain,
isSearchEmailRunning: controller.searchController.isSearchEmailRunning,
isDrag: true
);
}
Widget _buildEmailItemNotDraggable(BuildContext context, PresentationEmail presentationEmail) {
final isShowingEmailContent = controller.mailboxDashBoardController.selectedEmail.value?.id == presentationEmail.id;
final selectModeAll = controller.mailboxDashBoardController.currentSelectMode.value;
return Dismissible(
key: ValueKey<EmailId?>(presentationEmail.id),
direction: controller.getSwipeDirection(
controller.responsiveUtils.isWebDesktop(context),
selectModeAll,
presentationEmail
),
background: Container(
color: AppColor.colorItemRecipientSelected,
padding: const EdgeInsetsDirectional.only(start: 16),
alignment: AlignmentDirectional.centerStart,
child: Row(
children: [
CircleAvatar(
backgroundColor: AppColor.colorSpamReportBannerBackground,
radius: 24,
child: !presentationEmail.hasRead
? SvgPicture.asset(
controller.imagePaths.icMarkAsRead,
fit: BoxFit.fill,
)
: SvgPicture.asset(
controller.imagePaths.icUnreadEmail,
fit: BoxFit.fill,
colorFilter: AppColor.primaryColor.asFilter(),
),
),
const SizedBox(width: 11),
Text(
!presentationEmail.hasRead
? AppLocalizations.of(context).mark_as_read
: AppLocalizations.of(context).mark_as_unread,
style: const TextStyle(
fontSize: 15,
color: AppColor.primaryColor,
),
),
],
),
),
secondaryBackground: controller.isInArchiveMailbox(presentationEmail) == false
? Container(
color: AppColor.colorItemRecipientSelected,
padding: const EdgeInsetsDirectional.only(end: 16),
alignment: AlignmentDirectional.centerEnd,
child: Row(
children: [
const Spacer(),
CircleAvatar(
backgroundColor: AppColor.colorSpamReportBannerBackground,
radius: 24,
child: SvgPicture.asset(
controller.imagePaths.icMailboxArchived,
fit: BoxFit.fill,
)
),
const SizedBox(width: 11),
Text(
AppLocalizations.of(context).archiveMessage,
style: const TextStyle(
fontSize: 15,
color: AppColor.primaryColor,
),
),
],
),
)
: null,
confirmDismiss: (direction) => controller.swipeEmailAction(context, presentationEmail, direction),
child: EmailTileBuilder(
key: Key('email_tile_builder_${presentationEmail.id?.asString}'),
presentationEmail: presentationEmail,
selectAllMode: selectModeAll,
isShowingEmailContent: isShowingEmailContent,
searchQuery: controller.searchQuery,
mailboxContain: presentationEmail.mailboxContain,
isSearchEmailRunning: controller.searchController.isSearchEmailRunning,
emailActionClick: (action, email) => _handleEmailActionClicked(context, email, action),
onMoreActionClick: (email, position) => _handleEmailContextMenuAction(context, email, position),
),
);
}
void _handleEmailActionClicked(
BuildContext context,
PresentationEmail presentationEmail,
EmailActionType actionType
) {
controller.handleEmailActionType(
actionType,
presentationEmail,
mailboxContain: presentationEmail.mailboxContain,
context: context
);
}
void _handleEmailContextMenuAction(
BuildContext context,
PresentationEmail presentationEmail,
RelativeRect? position
) {
if (controller.responsiveUtils.isScreenWithShortestSide(context)) {
controller.openContextMenuAction(
context,
_contextMenuActionTile(context, presentationEmail)
);
} else {
controller.openPopupMenuAction(
context,
position,
_popupMenuActionTile(context, presentationEmail)
);
}
}
Widget _buildFeedBackWidget(BuildContext context) {
return SizedBox(
height: 60,
child: Material(
clipBehavior: Clip.hardEdge,
borderRadius: BorderRadius.circular(10),
color: AppColor.colorTextButton,
child: Padding(
padding: const EdgeInsets.all(16),
child: Row(
children: [
SvgPicture.asset(
controller.imagePaths.icFilterMessageAll,
width: 24,
height: 24,
fit: BoxFit.fill,
colorFilter: Colors.white.asFilter(),
),
const SizedBox(width: 10),
Obx(
() => Text(
AppLocalizations.of(context).moveConversation(controller.listEmailDrag.length),
overflow: TextOverflow.clip,
style: const TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
),
maxLines: 1,
),
),
],
),
),
),
);
}
Widget _buildEmptyEmail(BuildContext context) {
return Obx(() => controller.viewState.value.fold(
(failure) => const SizedBox.shrink(),
(success) {
if (success is GetAllEmailLoading || success is SearchingState) {
return const SizedBox.shrink();
}
if (success is GetAllEmailSuccess
&& success.currentMailboxId != controller.selectedMailboxId) {
return const SizedBox.shrink();
} else {
return EmptyEmailsWidget(
key: const Key('empty_thread_view'),
isNetworkConnectionAvailable: controller.networkConnectionController.isNetworkConnectionAvailable(),
isSearchActive: controller.isSearchActive,
isFilterMessageActive: controller.mailboxDashBoardController.filterMessageOption.value != FilterMessageOption.all,
onCreateFiltersActionCallback: controller.goToCreateEmailRuleView
);
}
}
));
}
List<Widget> _contextMenuActionTile(BuildContext context, PresentationEmail email) {
final mailboxContain = email.mailboxContain;
return <Widget>[
_openInNewTabContextMenuItemAction(context, email),
if (mailboxContain?.isDrafts == false && mailboxContain?.isChildOfTeamMailboxes == false)
_markAsEmailSpamOrUnSpamContextMenuItemAction(context, email, mailboxContain),
if (mailboxContain?.isArchive == false)
_archiveMessageContextMenuItemAction(context, email),
];
}
Widget _markAsEmailSpamOrUnSpamContextMenuItemAction(
BuildContext context,
PresentationEmail email,
PresentationMailbox? mailboxContain
) {
return (EmailActionCupertinoActionSheetActionBuilder(
const Key('mark_as_spam_or_un_spam_action'),
SvgPicture.asset(
mailboxContain?.isSpam == true ? controller.imagePaths.icNotSpam : controller.imagePaths.icSpam,
width: 24,
height: 24,
fit: BoxFit.fill,
colorFilter: AppColor.colorTextButton.asFilter()),
mailboxContain?.isSpam == true
? AppLocalizations.of(context).remove_from_spam
: AppLocalizations.of(context).mark_as_spam,
email,
iconLeftPadding: controller.responsiveUtils.isMobile(context)
? const EdgeInsets.only(left: 12, right: 16)
: const EdgeInsets.only(right: 12),
iconRightPadding: controller.responsiveUtils.isMobile(context)
? const EdgeInsets.only(right: 12)
: EdgeInsets.zero)
..onActionClick((email) => controller.handleEmailActionType(
mailboxContain?.isSpam == true ? EmailActionType.unSpam : EmailActionType.moveToSpam,
email,
mailboxContain: mailboxContain,
context: context,
))
).build();
}
Widget _openInNewTabContextMenuItemAction(BuildContext context, PresentationEmail email) {
return (EmailActionCupertinoActionSheetActionBuilder(
const Key('open_in_new_tab_action'),
SvgPicture.asset(
controller.imagePaths.icOpenInNewTab,
width: 24,
height: 24,
fit: BoxFit.fill,
colorFilter: AppColor.colorTextButton.asFilter()),
AppLocalizations.of(context).openInNewTab,
email,
iconLeftPadding: controller.responsiveUtils.isMobile(context)
? const EdgeInsets.only(left: 12, right: 16)
: const EdgeInsets.only(right: 12),
iconRightPadding: controller.responsiveUtils.isMobile(context)
? const EdgeInsets.only(right: 12)
: EdgeInsets.zero)
..onActionClick((email) {
popBack();
controller.openEmailInNewTabAction(context, email);
})
).build();
}
Widget _archiveMessageContextMenuItemAction(BuildContext context, PresentationEmail email) {
return (
EmailActionCupertinoActionSheetActionBuilder(
const Key('archive_message_action'),
SvgPicture.asset(
controller.imagePaths.icMailboxArchived,
width: 24,
height: 24,
fit: BoxFit.fill,
colorFilter: AppColor.colorTextButton.asFilter()
),
AppLocalizations.of(context).archiveMessage,
email,
iconLeftPadding: controller.responsiveUtils.isMobile(context)
? const EdgeInsetsDirectional.only(start: 12, end: 16)
: const EdgeInsetsDirectional.only(start: 12),
iconRightPadding: controller.responsiveUtils.isMobile(context)
? const EdgeInsetsDirectional.only(start: 12)
: EdgeInsets.zero
)
..onActionClick((email) => controller.archiveMessage(context, email))
).build();
}
List<PopupMenuEntry> _popupMenuActionTile(BuildContext context, PresentationEmail email) {
final mailboxContain = email.mailboxContain;
return [
_buildOpenInNewTabPopupMenuItem(context, email, mailboxContain),
if (mailboxContain?.isDrafts == false && mailboxContain?.isChildOfTeamMailboxes == false)
_buildMarkAsSpamPopupMenuItem(context, email, mailboxContain),
if (mailboxContain?.isArchive == false)
_buildArchiveMessagePopupMenuItem(context, email),
];
}
PopupMenuEntry _buildMarkAsSpamPopupMenuItem(
BuildContext context,
PresentationEmail email,
PresentationMailbox? mailboxContain
) {
return PopupMenuItem(
padding: EdgeInsets.zero,
child: popupItem(
mailboxContain?.isSpam == true ? controller.imagePaths.icNotSpam : controller.imagePaths.icSpam,
mailboxContain?.isSpam == true
? AppLocalizations.of(context).remove_from_spam
: AppLocalizations.of(context).mark_as_spam,
colorIcon: AppColor.colorTextButton,
styleName: const TextStyle(
fontWeight: FontWeight.w500,
fontSize: 16,
color: Colors.black
),
onCallbackAction: () => controller.handleEmailActionType(
mailboxContain?.isSpam == true ? EmailActionType.unSpam : EmailActionType.moveToSpam,
email,
mailboxContain: mailboxContain,
context: context
)
)
);
}
PopupMenuEntry _buildOpenInNewTabPopupMenuItem(
BuildContext context,
PresentationEmail email,
PresentationMailbox? mailboxContain
) {
return PopupMenuItem(
padding: EdgeInsets.zero,
child: popupItem(
controller.imagePaths.icOpenInNewTab,
AppLocalizations.of(context).openInNewTab,
colorIcon: AppColor.colorTextButton,
styleName: const TextStyle(
fontWeight: FontWeight.w500,
fontSize: 16,
color: Colors.black
),
onCallbackAction: () {
popBack();
controller.openEmailInNewTabAction(context, email);
}
)
);
}
PopupMenuEntry _buildArchiveMessagePopupMenuItem(
BuildContext context,
PresentationEmail email
) {
return PopupMenuItem(
padding: EdgeInsets.zero,
child: popupItem(
controller.imagePaths.icMailboxArchived,
AppLocalizations.of(context).archiveMessage,
colorIcon: AppColor.colorTextButton,
styleName: const TextStyle(
fontWeight: FontWeight.w500,
fontSize: 16,
color: Colors.black
),
onCallbackAction: () {
popBack();
controller.archiveMessage(context, email);
}
)
);
}
Widget _buildMarkAsMailboxReadLoading(BuildContext context) {
return Obx(() {
final viewState = controller.mailboxDashBoardController.viewStateMarkAsReadMailbox.value;
return viewState.fold(
(failure) => const SizedBox.shrink(),
(success) {
if (success is MarkAsMailboxReadLoading) {
return Padding(
padding: EdgeInsets.only(
top: controller.responsiveUtils.isDesktop(context) ? 16 : 0,
left: 16,
right: 16,
bottom: controller.responsiveUtils.isDesktop(context) ? 0 : 16),
child: horizontalLoadingWidget);
} else if (success is UpdatingMarkAsMailboxReadState) {
final percent = success.countRead / success.totalUnread;
return Padding(
padding: EdgeInsets.only(
top: controller.responsiveUtils.isDesktop(context) ? 16 : 0,
left: 16,
right: 16,
bottom: controller.responsiveUtils.isDesktop(context) ? 0 : 16),
child: horizontalPercentLoadingWidget(percent));
}
return const SizedBox.shrink();
});
});
}
}