diff --git a/core/lib/presentation/views/html_viewer/html_content_viewer_widget.dart b/core/lib/presentation/views/html_viewer/html_content_viewer_widget.dart
index 5ccac6cac..1ada91dec 100644
--- a/core/lib/presentation/views/html_viewer/html_content_viewer_widget.dart
+++ b/core/lib/presentation/views/html_viewer/html_content_viewer_widget.dart
@@ -360,6 +360,7 @@ class HtmlContentViewState extends State with AutomaticKeepAl
void dispose() {
_loadingBarNotifier.dispose();
_htmlData = null;
+ _webViewController.dispose();
super.dispose();
}
diff --git a/lib/features/email/presentation/controller/single_email_controller.dart b/lib/features/email/presentation/controller/single_email_controller.dart
index 991767bd6..8f388b9ca 100644
--- a/lib/features/email/presentation/controller/single_email_controller.dart
+++ b/lib/features/email/presentation/controller/single_email_controller.dart
@@ -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();
+ }
+ }
}
\ No newline at end of file
diff --git a/lib/features/email/presentation/email_view.dart b/lib/features/email/presentation/email_view.dart
index e48cc48bf..4a775c379 100644
--- a/lib/features/email/presentation/email_view.dart
+++ b/lib/features/email/presentation/email_view.dart
@@ -214,7 +214,7 @@ class EmailView extends GetWidget {
);
}
- if (controller.currentEmail == null || !isInsideThreadDetailView) {
+ if (controller.currentEmail == null || isFirstEmailInThreadDetail) {
return const BoxDecoration(color: Colors.white);
}
@@ -278,35 +278,38 @@ class EmailView extends GetWidget {
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 {
maxHtmlContentHeight: ConstantsUI.htmlContentMaxHeight,
onMailtoDelegateAction: controller.openMailToLink,
onHtmlContentClippedAction: controller.onHtmlContentClippedAction,
+ onScrollHorizontalEnd: controller.onScrollHorizontalEnd,
keepAlive: isInsideThreadDetailView,
enableQuoteToggle: isInsideThreadDetailView,
);
@@ -489,6 +493,7 @@ class EmailView extends GetWidget {
onMailtoDelegateAction: controller.openMailToLink,
keepAlive: isInsideThreadDetailView,
enableQuoteToggle: isInsideThreadDetailView,
+ onScrollHorizontalEnd: controller.onScrollHorizontalEnd,
);
})
);
diff --git a/lib/features/email/presentation/utils/email_action_reactor/email_action_reactor.dart b/lib/features/email/presentation/utils/email_action_reactor/email_action_reactor.dart
index 182cb9a42..db1e47456 100644
--- a/lib/features/email/presentation/utils/email_action_reactor/email_action_reactor.dart
+++ b/lib/features/email/presentation/utils/email_action_reactor/email_action_reactor.dart
@@ -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;
}
diff --git a/lib/features/email/presentation/widgets/email_view_app_bar_widget.dart b/lib/features/email/presentation/widgets/email_view_app_bar_widget.dart
index 34b6ab842..cf1b5eac3 100644
--- a/lib/features/email/presentation/widgets/email_view_app_bar_widget.dart
+++ b/lib/features/email/presentation/widgets/email_view_app_bar_widget.dart
@@ -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),
];
}
}
\ No newline at end of file
diff --git a/lib/features/email/presentation/widgets/information_sender_and_receiver_builder.dart b/lib/features/email/presentation/widgets/information_sender_and_receiver_builder.dart
index a03aa2ec5..0710c3bbd 100644
--- a/lib/features/email/presentation/widgets/information_sender_and_receiver_builder.dart
+++ b/lib/features/email/presentation/widgets/information_sender_and_receiver_builder.dart
@@ -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,
),
),
),
diff --git a/lib/features/thread_detail/domain/state/get_thread_by_id_state.dart b/lib/features/thread_detail/domain/state/get_thread_by_id_state.dart
index 6903c0475..553999919 100644
--- a/lib/features/thread_detail/domain/state/get_thread_by_id_state.dart
+++ b/lib/features/thread_detail/domain/state/get_thread_by_id_state.dart
@@ -13,16 +13,28 @@ class GettingThreadById extends LoadingState {
class GetThreadByIdSuccess extends UIState {
final List emailIds;
+ final ThreadId? threadId;
final bool updateCurrentThreadDetail;
+ final bool skipLoadingMetadata;
- GetThreadByIdSuccess(this.emailIds, {this.updateCurrentThreadDetail = false});
+ GetThreadByIdSuccess(
+ this.emailIds, {
+ required this.threadId,
+ this.updateCurrentThreadDetail = false,
+ this.skipLoadingMetadata = false,
+ });
@override
- List