TF-3699 Thread Detail Next previous actions (#3843)
This commit is contained in:
@@ -127,6 +127,7 @@ import 'package:tmail_ui_user/features/thread_detail/presentation/action/thread_
|
||||
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/close_thread_detail_action.dart';
|
||||
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/focus_thread_detail_expanded_email.dart';
|
||||
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/mark_collapsed_email_unread_success.dart';
|
||||
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/on_thread_page_changed.dart';
|
||||
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/update_cached_list_email_loaded.dart';
|
||||
import 'package:tmail_ui_user/features/thread_detail/presentation/thread_detail_controller.dart';
|
||||
import 'package:tmail_ui_user/main/error/capability_validator.dart';
|
||||
@@ -204,6 +205,9 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
||||
: _threadDetailController?.emailIdsPresentation[_currentEmailId];
|
||||
}
|
||||
|
||||
bool get isOnlyEmailInThread =>
|
||||
_threadDetailController?.emailIdsPresentation.length == 1;
|
||||
|
||||
bool get calendarEventProcessing => viewState.value.fold(
|
||||
(failure) => false,
|
||||
(success) => success is CalendarEventReplying);
|
||||
@@ -680,14 +684,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
||||
emailUnsubscribe.value = null;
|
||||
}
|
||||
}
|
||||
if (currentEmail?.threadId != null &&
|
||||
currentEmail?.id == mailboxDashBoardController.selectedEmail.value?.id) {
|
||||
mailboxDashBoardController.dispatchThreadDetailUIAction(
|
||||
LoadThreadDetailAfterSelectedEmailAction(
|
||||
currentEmail!.threadId!,
|
||||
)
|
||||
);
|
||||
}
|
||||
_loadThreadOnGetEmailContentSuccess();
|
||||
}
|
||||
|
||||
void _getEmailContentSuccess(GetEmailContentSuccess success) {
|
||||
@@ -758,9 +755,14 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
||||
if ((_threadDetailController?.emailIdsPresentation.keys.length ?? 0) > 1 == true) {
|
||||
_jumpScrollViewToTopOfEmail();
|
||||
}
|
||||
_loadThreadOnGetEmailContentSuccess();
|
||||
}
|
||||
|
||||
void _loadThreadOnGetEmailContentSuccess() {
|
||||
if (currentEmail?.threadId != null &&
|
||||
currentEmail?.id == mailboxDashBoardController.selectedEmail.value?.id &&
|
||||
success is! GetEmailContentFromThreadCacheSuccess) {
|
||||
_threadDetailController?.loadThreadOnThreadChanged == true) {
|
||||
_threadDetailController?.loadThreadOnThreadChanged = false;
|
||||
mailboxDashBoardController.dispatchThreadDetailUIAction(
|
||||
LoadThreadDetailAfterSelectedEmailAction(
|
||||
currentEmail!.threadId!,
|
||||
@@ -2391,4 +2393,12 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
void onScrollHorizontalEnd(bool isLeftDirection) {
|
||||
if (isLeftDirection) {
|
||||
_threadDetailController?.onPreviousMobile();
|
||||
} else {
|
||||
_threadDetailController?.onNextMobile();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -214,7 +214,7 @@ class EmailView extends GetWidget<SingleEmailController> {
|
||||
);
|
||||
}
|
||||
|
||||
if (controller.currentEmail == null || !isInsideThreadDetailView) {
|
||||
if (controller.currentEmail == null || isFirstEmailInThreadDetail) {
|
||||
return const BoxDecoration(color: Colors.white);
|
||||
}
|
||||
|
||||
@@ -278,35 +278,38 @@ class EmailView extends GetWidget<SingleEmailController> {
|
||||
onEmailActionClick: (presentationEmail, actionType) => controller.handleEmailAction(context, presentationEmail, actionType),
|
||||
isInsideThreadDetailView: isInsideThreadDetailView,
|
||||
emailLoaded: controller.currentEmailLoaded.value,
|
||||
onMoreActionClick: (presentationEmail, position) => controller.emailActionReactor.handleMoreEmailAction(
|
||||
mailboxContain: controller.getMailboxContain(presentationEmail),
|
||||
presentationEmail: presentationEmail,
|
||||
position: position,
|
||||
responsiveUtils: controller.responsiveUtils,
|
||||
imagePaths: controller.imagePaths,
|
||||
username: controller.session?.username,
|
||||
handleEmailAction: (email, action) => controller.handleEmailAction(context, email, action),
|
||||
additionalActions: [
|
||||
EmailActionType.forward,
|
||||
EmailActionType.replyAll,
|
||||
EmailActionType.replyToList,
|
||||
EmailActionType.printAll,
|
||||
if (controller.responsiveUtils.isMobile(context))
|
||||
EmailActionType.moveToMailbox,
|
||||
if (!controller.responsiveUtils.isDesktop(context)) ...[
|
||||
EmailActionType.markAsStarred,
|
||||
EmailActionType.unMarkAsStarred,
|
||||
EmailActionType.moveToTrash,
|
||||
EmailActionType.deletePermanently,
|
||||
],
|
||||
],
|
||||
emailIsRead: presentationEmail.hasRead,
|
||||
),
|
||||
onMoreActionClick: controller.isOnlyEmailInThread
|
||||
? null
|
||||
: (presentationEmail, position) => controller.emailActionReactor.handleMoreEmailAction(
|
||||
mailboxContain: controller.getMailboxContain(presentationEmail),
|
||||
presentationEmail: presentationEmail,
|
||||
position: position,
|
||||
responsiveUtils: controller.responsiveUtils,
|
||||
imagePaths: controller.imagePaths,
|
||||
username: controller.session?.username,
|
||||
handleEmailAction: (email, action) => controller.handleEmailAction(context, email, action),
|
||||
additionalActions: [
|
||||
EmailActionType.forward,
|
||||
EmailActionType.replyAll,
|
||||
EmailActionType.replyToList,
|
||||
EmailActionType.printAll,
|
||||
if (controller.responsiveUtils.isMobile(context))
|
||||
EmailActionType.moveToMailbox,
|
||||
if (!controller.responsiveUtils.isDesktop(context)) ...[
|
||||
EmailActionType.markAsStarred,
|
||||
EmailActionType.unMarkAsStarred,
|
||||
EmailActionType.moveToTrash,
|
||||
EmailActionType.deletePermanently,
|
||||
],
|
||||
],
|
||||
emailIsRead: presentationEmail.hasRead,
|
||||
),
|
||||
onToggleThreadDetailCollapseExpand: onToggleThreadDetailCollapseExpand,
|
||||
onTapAvatarActionClick: onToggleThreadDetailCollapseExpand,
|
||||
mailboxContain: presentationEmail.findMailboxContain(
|
||||
controller.mailboxDashBoardController.mapMailboxById,
|
||||
),
|
||||
isOnlyEmailInThread: controller.isOnlyEmailInThread,
|
||||
)),
|
||||
Obx(() => MailUnsubscribedBanner(
|
||||
presentationEmail: controller.currentEmail,
|
||||
@@ -449,6 +452,7 @@ class EmailView extends GetWidget<SingleEmailController> {
|
||||
maxHtmlContentHeight: ConstantsUI.htmlContentMaxHeight,
|
||||
onMailtoDelegateAction: controller.openMailToLink,
|
||||
onHtmlContentClippedAction: controller.onHtmlContentClippedAction,
|
||||
onScrollHorizontalEnd: controller.onScrollHorizontalEnd,
|
||||
keepAlive: isInsideThreadDetailView,
|
||||
enableQuoteToggle: isInsideThreadDetailView,
|
||||
);
|
||||
@@ -489,6 +493,7 @@ class EmailView extends GetWidget<SingleEmailController> {
|
||||
onMailtoDelegateAction: controller.openMailToLink,
|
||||
keepAlive: isInsideThreadDetailView,
|
||||
enableQuoteToggle: isInsideThreadDetailView,
|
||||
onScrollHorizontalEnd: controller.onScrollHorizontalEnd,
|
||||
);
|
||||
})
|
||||
);
|
||||
|
||||
+8
-3
@@ -548,7 +548,7 @@ class EmailActionReactor with MessageDialogActionMixin, PopupContextMenuActionMi
|
||||
: EmailActionType.markAsStarred,
|
||||
if (additionalActions.contains(EmailActionType.moveToTrash) &&
|
||||
additionalActions.contains(EmailActionType.deletePermanently))
|
||||
_canDeletePermanently(presentationEmail)
|
||||
_canDeletePermanently(presentationEmail, mailboxContain)
|
||||
? EmailActionType.deletePermanently
|
||||
: EmailActionType.moveToTrash,
|
||||
if (emailIsRead)
|
||||
@@ -598,8 +598,13 @@ class EmailActionReactor with MessageDialogActionMixin, PopupContextMenuActionMi
|
||||
}
|
||||
}
|
||||
|
||||
bool _canDeletePermanently(PresentationEmail email) {
|
||||
return email.mailboxContain?.isTrash
|
||||
bool _canDeletePermanently(
|
||||
PresentationEmail email,
|
||||
PresentationMailbox? mailboxContain,
|
||||
) {
|
||||
return mailboxContain?.isTrash
|
||||
?? mailboxContain?.isSpam
|
||||
?? email.mailboxContain?.isTrash
|
||||
?? email.mailboxContain?.isSpam
|
||||
?? false;
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ class EmailViewAppBarWidget extends StatelessWidget {
|
||||
final EdgeInsetsGeometry? iconPadding;
|
||||
final EdgeInsetsGeometry? iconMargin;
|
||||
final EdgeInsetsGeometry? padding;
|
||||
final bool isOnlyEmailInThread;
|
||||
|
||||
EmailViewAppBarWidget({
|
||||
Key? key,
|
||||
@@ -51,6 +52,7 @@ class EmailViewAppBarWidget extends StatelessWidget {
|
||||
this.iconPadding,
|
||||
this.iconMargin,
|
||||
this.padding,
|
||||
this.isOnlyEmailInThread = false,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
@@ -251,19 +253,22 @@ class EmailViewAppBarWidget extends StatelessWidget {
|
||||
_getMoveEmailButton(appLocalizations),
|
||||
_getMarkStarButton(appLocalizations),
|
||||
_getDeleteButton(appLocalizations),
|
||||
_getMoreButton(appLocalizations, isScreenWithShortestSide),
|
||||
if (onMoreActionClick != null)
|
||||
_getMoreButton(appLocalizations, isScreenWithShortestSide),
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
_getReplyButton(appLocalizations),
|
||||
if (!isOnlyEmailInThread)
|
||||
_getReplyButton(appLocalizations),
|
||||
if (!isResponsiveMobile)
|
||||
_getMoveEmailButton(appLocalizations),
|
||||
if (isResponsiveDesktop) ...[
|
||||
_getMarkStarButton(appLocalizations),
|
||||
_getDeleteButton(appLocalizations),
|
||||
],
|
||||
_getMoreButton(appLocalizations, isScreenWithShortestSide),
|
||||
if (onMoreActionClick != null)
|
||||
_getMoreButton(appLocalizations, isScreenWithShortestSide),
|
||||
];
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -5,7 +5,6 @@ import 'package:core/presentation/utils/responsive_utils.dart';
|
||||
import 'package:core/presentation/utils/theme_utils.dart';
|
||||
import 'package:core/presentation/views/button/tmail_button_widget.dart';
|
||||
import 'package:core/presentation/views/image/avatar_builder.dart';
|
||||
import 'package:core/utils/platform_info.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
@@ -42,6 +41,7 @@ class InformationSenderAndReceiverBuilder extends StatelessWidget {
|
||||
final OnTapAvatarActionClick? onTapAvatarActionClick;
|
||||
final PresentationMailbox? mailboxContain;
|
||||
final bool showUnreadVisualization;
|
||||
final bool isOnlyEmailInThread;
|
||||
|
||||
const InformationSenderAndReceiverBuilder({
|
||||
Key? key,
|
||||
@@ -61,6 +61,7 @@ class InformationSenderAndReceiverBuilder extends StatelessWidget {
|
||||
this.onTapAvatarActionClick,
|
||||
this.mailboxContain,
|
||||
this.showUnreadVisualization = false,
|
||||
this.isOnlyEmailInThread = false,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
@@ -164,9 +165,7 @@ class InformationSenderAndReceiverBuilder extends StatelessWidget {
|
||||
SizedBox(
|
||||
height: IconUtils.defaultIconSize,
|
||||
child: OverflowBox(
|
||||
maxHeight: PlatformInfo.isIOS
|
||||
? EmailViewAppBarWidgetStyles.heightIOS(context, responsiveUtils)
|
||||
: EmailViewAppBarWidgetStyles.height,
|
||||
maxHeight: EmailViewAppBarWidgetStyles.height,
|
||||
fit: OverflowBoxFit.deferToChild,
|
||||
child: EmailViewAppBarWidget(
|
||||
key: const Key('email_view_app_bar_widget'),
|
||||
@@ -183,6 +182,7 @@ class InformationSenderAndReceiverBuilder extends StatelessWidget {
|
||||
iconPadding: const EdgeInsets.all(8),
|
||||
iconMargin: EdgeInsets.zero,
|
||||
padding: EdgeInsets.zero,
|
||||
isOnlyEmailInThread: isOnlyEmailInThread,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user