TF-3953 Close several modals when click outside

This commit is contained in:
DatDang
2025-08-07 14:14:50 +07:00
committed by Dat H. Pham
parent 44c17bc762
commit 9e7298bc76
34 changed files with 575 additions and 580 deletions
@@ -10,7 +10,6 @@ import 'package:core/utils/html/html_utils.dart';
import 'package:core/presentation/utils/html_transformer/dom/sanitize_hyper_link_tag_in_html_transformers.dart';
import 'package:dartz/dartz.dart';
import 'package:dio/dio.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_file_dialog/flutter_file_dialog.dart';
@@ -40,6 +39,7 @@ import 'package:pointer_interceptor/pointer_interceptor.dart';
import 'package:share_plus/share_plus.dart';
import 'package:tmail_ui_user/features/base/base_controller.dart';
import 'package:tmail_ui_user/features/base/mixin/app_loader_mixin.dart';
import 'package:tmail_ui_user/features/base/mixin/message_dialog_action_manager.dart';
import 'package:tmail_ui_user/features/base/state/button_state.dart';
import 'package:tmail_ui_user/features/email/domain/exceptions/email_exceptions.dart';
import 'package:tmail_ui_user/features/email/domain/extensions/list_attachments_extension.dart';
@@ -772,7 +772,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
void _handleReadReceipt() {
if (currentContext != null) {
showConfirmDialogAction(currentContext!,
MessageDialogActionManager().showConfirmDialogAction(currentContext!,
AppLocalizations.of(currentContext!).subTitleReadReceiptRequestNotificationMessage,
AppLocalizations.of(currentContext!).yes,
onConfirmAction: () => _handleSendReceiptToSenderAction(currentContext!),
@@ -13,11 +13,13 @@ import 'package:model/extensions/list_email_address_extension.dart';
import 'package:model/extensions/presentation_email_extension.dart';
import 'package:model/mailbox/presentation_mailbox.dart';
import 'package:pointer_interceptor/pointer_interceptor.dart';
import 'package:tmail_ui_user/features/base/mixin/message_dialog_action_manager.dart';
import 'package:tmail_ui_user/features/base/widget/optional_expanded.dart';
import 'package:tmail_ui_user/features/base/widget/optional_scroll.dart';
import 'package:tmail_ui_user/features/email/presentation/controller/single_email_controller.dart';
import 'package:tmail_ui_user/features/email/presentation/extensions/calendar_event_extension.dart';
import 'package:tmail_ui_user/features/email/presentation/styles/email_view_styles.dart';
import 'package:tmail_ui_user/features/email/presentation/utils/email_action_reactor/email_action_reactor.dart';
import 'package:tmail_ui_user/features/email/presentation/widgets/calendar_event/calendar_event_action_banner_widget.dart';
import 'package:tmail_ui_user/features/email/presentation/widgets/calendar_event/calendar_event_detail_widget.dart';
import 'package:tmail_ui_user/features/email/presentation/widgets/calendar_event/calendar_event_information_widget.dart';
@@ -529,7 +531,9 @@ class EmailView extends GetWidget<SingleEmailController> {
),
),
Obx(() {
if (controller.mailboxDashBoardController.isDisplayedOverlayViewOnIFrame) {
if (controller.mailboxDashBoardController.isDisplayedOverlayViewOnIFrame ||
MessageDialogActionManager().isDialogOpened ||
EmailActionReactor.isDialogOpened) {
return Positioned.fill(
child: PointerInterceptor(
child: const SizedBox.expand(),
@@ -11,7 +11,6 @@ import 'package:core/presentation/utils/html_transformer/transform_configuration
import 'package:core/presentation/utils/responsive_utils.dart';
import 'package:core/presentation/utils/theme_utils.dart';
import 'package:core/presentation/views/bottom_popup/confirmation_dialog_action_sheet_builder.dart';
import 'package:core/presentation/views/dialog/confirmation_dialog_builder.dart';
import 'package:core/utils/app_logger.dart';
import 'package:core/utils/platform_info.dart';
import 'package:dartz/dartz.dart';
@@ -36,8 +35,7 @@ import 'package:model/extensions/presentation_email_extension.dart';
import 'package:model/extensions/presentation_mailbox_extension.dart';
import 'package:model/extensions/session_extension.dart';
import 'package:model/mailbox/presentation_mailbox.dart';
import 'package:pointer_interceptor/pointer_interceptor.dart';
import 'package:tmail_ui_user/features/base/mixin/message_dialog_action_mixin.dart';
import 'package:tmail_ui_user/features/base/mixin/message_dialog_action_manager.dart';
import 'package:tmail_ui_user/features/base/widget/context_menu/context_menu_item_action.dart';
import 'package:tmail_ui_user/features/base/widget/popup_menu/popup_menu_item_action_widget.dart';
import 'package:tmail_ui_user/features/destination_picker/presentation/model/destination_picker_arguments.dart';
@@ -88,8 +86,8 @@ typedef OpenPopUpContextMenuAction = Future<void> Function(
List<PopupMenuEntry> popupMenuItems,
);
class EmailActionReactor with MessageDialogActionMixin {
const EmailActionReactor(
class EmailActionReactor {
EmailActionReactor(
this._markAsEmailReadInteractor,
this._markAsStarEmailInteractor,
this._createNewEmailRuleFilterInteractor,
@@ -105,6 +103,9 @@ class EmailActionReactor with MessageDialogActionMixin {
final GetEmailContentInteractor _getEmailContentInteractor;
final DownloadAttachmentForWebInteractor _downloadAttachmentForWebInteractor;
static final _isEmailAddressDialogOpened = false.obs;
static bool get isDialogOpened => _isEmailAddressDialogOpened.value;
Stream<Either<Failure, Success>> markAsEmailRead(
Session session,
AccountId accountId,
@@ -210,19 +211,16 @@ class EmailActionReactor with MessageDialogActionMixin {
)
).show();
} else {
await Get.dialog(
PointerInterceptor(child: ConfirmationDialogBuilder(
key: const Key('confirm_dialog_delete_email_permanently'),
imagePath: imagePaths,
title: DeleteActionType.single.getTitleDialog(currentContext!),
textContent: DeleteActionType.single.getContentDialog(currentContext!),
cancelText: DeleteActionType.single.getConfirmActionName(currentContext!),
confirmText: AppLocalizations.of(currentContext!).cancel,
onCancelButtonAction: () => onDeleteEmailRequest.call(presentationEmail),
onConfirmButtonAction: popBack,
onCloseButtonAction: popBack,
)),
barrierColor: AppColor.colorDefaultCupertinoActionSheet,
await MessageDialogActionManager().showConfirmDialogAction(
key: const Key('confirm_dialog_delete_email_permanently'),
currentContext!,
title: DeleteActionType.single.getTitleDialog(currentContext!),
DeleteActionType.single.getContentDialog(currentContext!),
cancelTitle: DeleteActionType.single.getConfirmActionName(currentContext!),
AppLocalizations.of(currentContext!).cancel,
onCancelAction: () => onDeleteEmailRequest.call(presentationEmail),
onConfirmAction: popBack,
onCloseButtonAction: popBack,
);
}
}
@@ -331,7 +329,7 @@ class EmailActionReactor with MessageDialogActionMixin {
}) async {
if (currentContext == null || !currentContext!.mounted) return;
await showConfirmDialogAction(
await MessageDialogActionManager().showConfirmDialogAction(
currentContext!,
'',
AppLocalizations.of(currentContext!).unsubscribe,
@@ -656,7 +654,7 @@ class EmailActionReactor with MessageDialogActionMixin {
}).toList();
}
void openEmailAddressDialog(
Future<void> openEmailAddressDialog(
Session session,
AccountId accountId, {
required EmailAddress emailAddress,
@@ -665,24 +663,25 @@ class EmailActionReactor with MessageDialogActionMixin {
required AppToast appToast,
required void Function(EmailAddress emailAddress) onComposeEmailFromEmailAddressRequest,
required void Function(Stream<Either<Failure, Success>> quickCreateRuleStream) onQuickCreateRuleRequest,
}) {
}) async {
if (currentContext?.mounted != true) return;
if (PlatformInfo.isWeb) {
_isEmailAddressDialogOpened.value = true;
}
if (responsiveUtils.isScreenWithShortestSide(currentContext!)) {
Get.bottomSheet(
PointerInterceptor(
child: EmailAddressBottomSheetBuilder(
imagePaths: imagePaths,
emailAddress: emailAddress,
onCloseDialogAction: popBack,
onCopyEmailAddressAction: (emailAddress) =>
_copyEmailAddress(currentContext!, emailAddress, appToast),
onComposeEmailAction: (emailAddress) =>
onComposeEmailFromEmailAddressRequest(emailAddress),
onQuickCreatingRuleEmailDialogAction: (emailAddress) =>
onQuickCreateRuleRequest(
quickCreateRule(session, accountId, emailAddress: emailAddress),
),
await Get.bottomSheet(
EmailAddressBottomSheetBuilder(
imagePaths: imagePaths,
emailAddress: emailAddress,
onCloseDialogAction: popBack,
onCopyEmailAddressAction: (emailAddress) =>
_copyEmailAddress(currentContext!, emailAddress, appToast),
onComposeEmailAction: (emailAddress) =>
onComposeEmailFromEmailAddressRequest(emailAddress),
onQuickCreatingRuleEmailDialogAction: (emailAddress) =>
onQuickCreateRuleRequest(
quickCreateRule(session, accountId, emailAddress: emailAddress),
),
),
useRootNavigator: true,
@@ -697,25 +696,25 @@ class EmailActionReactor with MessageDialogActionMixin {
backgroundColor: Colors.transparent,
);
} else {
Get.dialog(
PointerInterceptor(
child: EmailAddressDialogBuilder(
imagePaths: imagePaths,
emailAddress: emailAddress,
onCloseDialogAction: popBack,
onCopyEmailAddressAction: (emailAddress) =>
_copyEmailAddress(currentContext!, emailAddress, appToast),
onComposeEmailAction: (emailAddress) =>
onComposeEmailFromEmailAddressRequest(emailAddress),
onQuickCreatingRuleEmailDialogAction: (emailAddress) =>
onQuickCreateRuleRequest(
quickCreateRule(session, accountId, emailAddress: emailAddress),
),
await Get.dialog(
EmailAddressDialogBuilder(
imagePaths: imagePaths,
emailAddress: emailAddress,
onCloseDialogAction: popBack,
onCopyEmailAddressAction: (emailAddress) =>
_copyEmailAddress(currentContext!, emailAddress, appToast),
onComposeEmailAction: (emailAddress) =>
onComposeEmailFromEmailAddressRequest(emailAddress),
onQuickCreatingRuleEmailDialogAction: (emailAddress) =>
onQuickCreateRuleRequest(
quickCreateRule(session, accountId, emailAddress: emailAddress),
),
),
barrierColor: AppColor.colorDefaultCupertinoActionSheet,
);
}
_isEmailAddressDialogOpened.value = false;
}
void _copyEmailAddress(