TF-1427 Create new mailbox search view on web

This commit is contained in:
dab246
2023-02-09 15:08:40 +07:00
committed by Dat Vu
parent e2c0cb52a6
commit 705dd5d28c
18 changed files with 1021 additions and 38 deletions
+5
View File
@@ -0,0 +1,5 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M9.9999 1.42859C14.7338 1.42859 18.5713 5.26615 18.5713 10C18.5713 14.7339 14.7338 18.5714 9.9999 18.5714C5.26603 18.5714 1.42847 14.7339 1.42847 10C1.42847 5.26615 5.26603 1.42859 9.9999 1.42859ZM9.9999 2.85716C6.055 2.85716 2.85704 6.05513 2.85704 10C2.85704 13.9449 6.055 17.1429 9.9999 17.1429C13.9448 17.1429 17.1428 13.9449 17.1428 10C17.1428 6.05513 13.9448 2.85716 9.9999 2.85716ZM6.99482 6.99494C7.27377 6.716 7.72603 6.716 8.00497 6.99494L9.9999 8.9893L11.9948 6.99494C12.2523 6.73745 12.6575 6.71765 12.9377 6.93552L13.005 6.99494C13.2839 7.27389 13.2839 7.72615 13.005 8.00509L11.0106 10L13.005 11.9949C13.2625 12.2524 13.2823 12.6576 13.0644 12.9378L13.005 13.0051C12.726 13.284 12.2738 13.284 11.9948 13.0051L9.9999 11.0107L8.00497 13.0051C7.74748 13.2626 7.34232 13.2824 7.06211 13.0645L6.99482 13.0051C6.71587 12.7261 6.71587 12.2739 6.99482 11.9949L8.98918 10L6.99482 8.00509C6.73733 7.74761 6.71752 7.34244 6.9354 7.06223L6.99482 6.99494Z"
fill="#AEB7C2" />
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

+11
View File
@@ -0,0 +1,11 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd"
d="M7.06297 2.85719C7.19862 2.85683 7.36943 2.85637 7.53752 2.89672C7.68329 2.93172 7.82264 2.98944 7.95046 3.06777C8.09785 3.15809 8.21831 3.2792 8.31397 3.37537L8.33971 3.4012L9.45595 4.51744C9.52212 4.58361 9.55526 4.61651 9.58034 4.6394L9.58224 4.64112L9.5848 4.64125C9.61872 4.6428 9.66542 4.64297 9.759 4.64297L14.458 4.64297C15.0329 4.64296 15.5075 4.64295 15.8941 4.67453C16.2956 4.70734 16.6646 4.77774 17.0113 4.95438C17.5489 5.2283 17.986 5.66539 18.2599 6.20299C18.4365 6.54966 18.507 6.91874 18.5398 7.32023C18.5713 7.7068 18.5713 8.18134 18.5713 8.75631V9.99997C18.5713 10.3945 18.2515 10.7143 17.857 10.7143C17.4625 10.7143 17.1428 10.3945 17.1428 9.99997V9.28582H2.85704V13.0001C2.85704 13.612 2.85759 14.0279 2.88386 14.3494C2.90945 14.6625 2.95582 14.8227 3.01274 14.9344C3.14971 15.2032 3.36825 15.4217 3.63705 15.5587C3.74877 15.6156 3.90891 15.662 4.22207 15.6876C4.54356 15.7138 4.95948 15.7144 5.57132 15.7144H7.85704C8.25153 15.7144 8.57132 16.0342 8.57132 16.4287C8.57132 16.8232 8.25153 17.143 7.85704 17.143H5.54181C4.96684 17.143 4.4923 17.143 4.10573 17.1114C3.70424 17.0786 3.33516 17.0082 2.9885 16.8316C2.45089 16.5576 2.0138 16.1205 1.73988 15.5829C1.56324 15.2363 1.49284 14.8672 1.46003 14.4657C1.42845 14.0791 1.42846 13.6046 1.42847 13.0296V6.9706C1.42846 6.39563 1.42845 5.92108 1.46003 5.53452C1.49284 5.13302 1.56324 4.76395 1.73988 4.41728C2.0138 3.87967 2.45089 3.44259 2.9885 3.16866C3.33516 2.99203 3.70424 2.92162 4.10574 2.88882C4.4923 2.85724 4.96685 2.85724 5.54183 2.85725L7.02651 2.85725L7.06297 2.85719ZM7.2007 4.28755C7.16678 4.286 7.12008 4.28582 7.02651 4.28582H5.57133C4.95948 4.28582 4.54356 4.28638 4.22207 4.31265C3.90891 4.33823 3.74877 4.38461 3.63705 4.44153C3.36825 4.57849 3.14971 4.79704 3.01274 5.06584C2.95582 5.17755 2.90945 5.3377 2.88386 5.65085C2.85759 5.97234 2.85704 6.38827 2.85704 7.00011V7.85725H17.1363C17.1324 7.69903 17.1261 7.56075 17.1159 7.43657C17.0903 7.12341 17.044 6.96327 16.987 6.85155C16.8501 6.58275 16.6315 6.36421 16.3627 6.22724C16.251 6.17032 16.0909 6.12395 15.7777 6.09836C15.4562 6.07209 15.0403 6.07154 14.4285 6.07154H9.759L9.72254 6.0716C9.58689 6.07197 9.41608 6.07242 9.24798 6.03207C9.10222 5.99707 8.96287 5.93935 8.83505 5.86102C8.68765 5.7707 8.56719 5.6496 8.47153 5.55342L8.4458 5.52759L7.32955 4.41135C7.26339 4.34519 7.23025 4.31228 7.20516 4.28939L7.20326 4.28767L7.2007 4.28755Z"
fill="#AEB7C2" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M10.2597 10.1883C10.5107 9.93721 10.9178 9.93721 11.1688 10.1883L18.3117 17.3311C18.5627 17.5822 18.5627 17.9892 18.3117 18.2403C18.0606 18.4913 17.6536 18.4913 17.4025 18.2403L16.381 17.2187C15.6693 17.5663 14.8288 17.7865 13.9285 17.7865C11.3643 17.7865 9.28561 16.0007 9.28561 14.5722C9.28561 13.7065 10.0489 12.7097 11.2209 12.0586L10.2597 11.0974C10.0086 10.8463 10.0086 10.4393 10.2597 10.1883ZM14.7454 15.5831L15.4019 16.2396C14.9544 16.4024 14.4548 16.5007 13.9285 16.5007C12.9395 16.5007 12.045 16.1537 11.4129 15.6834C10.7257 15.1723 10.5713 14.7042 10.5713 14.5722C10.5713 14.4402 10.7257 13.972 11.4129 13.4609C11.6375 13.2938 11.8952 13.1423 12.1786 13.0163L12.9883 13.8261C12.8168 14.04 12.7142 14.3117 12.7142 14.6073C12.7142 15.2976 13.2739 15.8573 13.9642 15.8573C14.2598 15.8573 14.5314 15.7547 14.7454 15.5831Z"
fill="#AEB7C2" />
<path
d="M14.9723 11.457C14.6039 11.3866 14.2856 11.6869 14.2856 12.062C14.2856 12.3993 14.5458 12.6754 14.8749 12.7499C15.4817 12.8873 16.0215 13.1466 16.4441 13.4609C17.1312 13.972 17.2856 14.4402 17.2856 14.5722C17.2856 14.6023 17.2776 14.65 17.2569 14.7117C17.1653 14.9861 17.1601 15.3038 17.3647 15.5084L17.374 15.5177C17.668 15.8117 18.1632 15.7977 18.3494 15.426C18.4935 15.1384 18.5713 14.8486 18.5713 14.5722C18.5713 13.3436 17.0338 11.8508 14.9723 11.457Z"
fill="#AEB7C2" />
</svg>

After

Width:  |  Height:  |  Size: 3.9 KiB

+4 -2
View File
@@ -1,3 +1,5 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6.50006 1C9.53765 1 12.0001 3.46256 12.0001 6.50029C12.0001 7.74868 11.5842 8.89993 10.8835 9.82304L14.7791 13.7233C15.0718 14.0164 15.0715 14.4913 14.7785 14.784C14.4854 15.0767 14.0105 15.0764 13.7178 14.7834L9.82266 10.8839C8.89959 11.5847 7.74839 12.0006 6.50006 12.0006C3.46246 12.0006 1 9.53802 1 6.50029C1 3.46256 3.46246 1 6.50006 1ZM6.50006 2.5C4.2909 2.5 2.5 4.29098 2.5 6.50029C2.5 8.70961 4.2909 10.5006 6.50006 10.5006C8.70921 10.5006 10.5001 8.70961 10.5001 6.50029C10.5001 4.29098 8.70921 2.5 6.50006 2.5Z" fill="#818C99"/>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd"
d="M11.143 3.42859C6.88251 3.42859 3.42871 6.88239 3.42871 11.1429C3.42871 15.4034 6.88251 18.8572 11.143 18.8572C12.9644 18.8572 14.6384 18.2259 15.9582 17.1702L19.9655 21.1775C20.3002 21.5123 20.8429 21.5123 21.1777 21.1775C21.5124 20.8428 21.5124 20.3001 21.1777 19.9654L17.1703 15.958C18.226 14.6383 18.8573 12.9643 18.8573 11.1429C18.8573 6.88239 15.4035 3.42859 11.143 3.42859ZM11.143 5.14287C7.82929 5.14287 5.143 7.82917 5.143 11.1429C5.143 14.4566 7.82929 17.1429 11.143 17.1429C14.4567 17.1429 17.143 14.4566 17.143 11.1429C17.143 7.82917 14.4567 5.14287 11.143 5.14287Z"
fill="#007AFF" />
</svg>

Before

Width:  |  Height:  |  Size: 652 B

After

Width:  |  Height:  |  Size: 769 B

@@ -172,6 +172,8 @@ extension AppColor on Color {
static const colorCreateNewIdentityButton = Color(0xFFEBEDF0);
static const colorSpamReportBox = Color(0xFFBFDEFF);
static const colorSubtitle = Color(0xFF6D7885);
static const colorBackgroundSearchMailboxInput = Color(0xFFEBEDF0);
static const colorMailboxPath = Color(0xFF818C99);
static const mapGradientColor = [
[Color(0xFF21D4FD), Color(0xFFB721FF)],
@@ -167,6 +167,8 @@ class ImagePaths {
String get icInfoCircleOutline => _getImagePath('ic_info_circle_outline.svg');
String get icSpamReportDisable => _getImagePath('ic_spam_report_disable.svg');
String get icSpamReportEnable => _getImagePath('ic_spam_report_enable.svg');
String get icClearSearchInput => _getImagePath('ic_clear_search_input.svg');
String get icHideFolder => _getImagePath('ic_hide_folder.svg');
String _getImagePath(String imageName) {
return AssetsPaths.images + imageName;
@@ -49,15 +49,14 @@ class SearchBarView extends StatelessWidget {
children: [
const SizedBox(width: 8),
buildIconWeb(
splashRadius: 15,
minSize: 40,
iconPadding: EdgeInsets.zero,
icon: SvgPicture.asset(
_imagePaths.icSearchBar,
width: 16,
height: 16,
fit: BoxFit.fill),
onTap: onOpenSearchViewAction),
minSize: 40,
iconPadding: EdgeInsets.zero,
icon: SvgPicture.asset(
_imagePaths.icSearchBar,
fit: BoxFit.fill
),
onTap: onOpenSearchViewAction
),
Expanded(
child: Text(
hintTextSearch ?? '',
@@ -125,12 +125,12 @@ class SearchEmailByQueryAction extends DashBoardAction {
@override
List<Object?> get props => [navigationRouter];
}
class OpenSpamMailboxAction extends DashBoardAction {
class OpenMailboxAction extends DashBoardAction {
final BuildContext context;
final PresentationMailbox presentationMailbox;
OpenSpamMailboxAction(this.context, this.presentationMailbox);
OpenMailboxAction(this.context, this.presentationMailbox);
@override
List<Object?> get props => [context, presentationMailbox];
@@ -159,6 +159,7 @@ class MailboxDashBoardController extends ReloadableController {
final vacationResponse = Rxn<VacationResponse>();
final routerParameters = Rxn<Map<String, String?>>();
final _isDraggingMailbox = RxBool(false);
final searchMailboxActivated = RxBool(false);
Session? sessionCurrent;
Map<Role, MailboxId> mapDefaultMailboxIdByRole = {};
Map<MailboxId, PresentationMailbox> mapMailboxById = {};
@@ -512,6 +513,14 @@ class MailboxDashBoardController extends ReloadableController {
scaffoldKey.currentState?.openEndDrawer();
}
void hideMailboxMenuWhenScreenSizeChange(BuildContext context) {
if (isDrawerOpen && _responsiveUtils.isWebDesktop(context)) {
WidgetsBinding.instance.addPostFrameCallback((_) {
closeMailboxMenuDrawer();
});
}
}
bool get isDrawerOpen => scaffoldKey.currentState?.isDrawerOpen == true;
bool isSelectionEnabled() => currentSelectMode.value == SelectMode.ACTIVE;
@@ -1526,8 +1535,8 @@ class MailboxDashBoardController extends ReloadableController {
emailsInCurrentMailbox.value = newEmailList;
}
void openSpamMailboxAction(BuildContext context, PresentationMailbox presentationMailbox){
dispatchAction(OpenSpamMailboxAction(context, presentationMailbox));
void openMailboxAction(BuildContext context, PresentationMailbox presentationMailbox) {
dispatchAction(OpenMailboxAction(context, presentationMailbox));
}
bool get enableSpamReport => spamReportController.enableSpamReport;
@@ -80,7 +80,7 @@ class SpamReportController extends BaseController {
void openMailbox(BuildContext context) {
final _mailboxDashBoardController = Get.find<MailboxDashBoardController>();
dismissSpamReportAction();
_mailboxDashBoardController.openSpamMailboxAction(context, _presentationSpamMailbox.value!);
_mailboxDashBoardController.openMailboxAction(context, _presentationSpamMailbox.value!);
}
void storeSpamReportStateAction(SpamReportState spamReportState) {
@@ -29,6 +29,7 @@ import 'package:tmail_ui_user/features/manage_account/presentation/extensions/va
import 'package:tmail_ui_user/features/manage_account/presentation/vacation/widgets/vacation_notification_message_widget.dart';
import 'package:tmail_ui_user/features/quotas/presentation/widget/quotas_warning_banner_widget.dart';
import 'package:tmail_ui_user/features/search/email/presentation/search_email_view.dart';
import 'package:tmail_ui_user/features/search/mailbox/presentation/search_mailbox_view.dart';
import 'package:tmail_ui_user/features/thread/domain/model/filter_message_option.dart';
import 'package:tmail_ui_user/features/thread/presentation/thread_view.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
@@ -48,11 +49,7 @@ class MailboxDashBoardView extends BaseMailboxDashBoardView {
@override
Widget build(BuildContext context) {
if (controller.isDrawerOpen && responsiveUtils.isDesktop(context)) {
WidgetsBinding.instance.addPostFrameCallback((_) {
controller.closeMailboxMenuDrawer();
});
}
controller.hideMailboxMenuWhenScreenSizeChange(context);
return Portal(
child: Stack(children: [
@@ -108,7 +105,15 @@ class MailboxDashBoardView extends BaseMailboxDashBoardView {
Column(children: [
_buildComposerButton(context),
Expanded(child: SizedBox(
child: MailboxView(),
child: Obx(() {
if (controller.searchMailboxActivated.isTrue) {
return const SearchMailboxView(
backgroundColor: AppColor.colorBgDesktop
);
} else {
return MailboxView();
}
}),
width: ResponsiveUtils.defaultSizeMenu
))
]),
@@ -183,7 +188,12 @@ class MailboxDashBoardView extends BaseMailboxDashBoardView {
),
Obx(() => controller.composerOverlayState.value == ComposerOverlayState.active
? ComposerView()
: const SizedBox.shrink()),
: const SizedBox.shrink()
),
Obx(() => controller.searchMailboxActivated.value == true && !responsiveUtils.isWebDesktop(context)
? const SearchMailboxView()
: const SizedBox.shrink()
),
_buildDownloadTaskStateWidget(),
]),
);
@@ -193,11 +203,11 @@ class MailboxDashBoardView extends BaseMailboxDashBoardView {
return Scaffold(
key: controller.scaffoldKey,
drawer: ResponsiveWidget(
responsiveUtils: responsiveUtils,
mobile: SizedBox(child: MailboxView(), width: ResponsiveUtils.defaultSizeDrawer),
tablet: SizedBox(child: MailboxView(), width: ResponsiveUtils.defaultSizeDrawer),
tabletLarge: SizedBox(child: MailboxView(), width: ResponsiveUtils.defaultSizeLeftMenuMobile),
desktop: const SizedBox.shrink()),
responsiveUtils: responsiveUtils,
mobile: SizedBox(child: MailboxView(), width: ResponsiveUtils.defaultSizeDrawer),
tabletLarge: SizedBox(child: MailboxView(), width: ResponsiveUtils.defaultSizeLeftMenuMobile),
desktop: const SizedBox.shrink()
),
body: body,
);
}
@@ -85,12 +85,14 @@ class SearchInputFormWidget extends StatelessWidget with AppLoaderMixin {
color: Colors.black,
fontSize: 16.0)
),
leftButton: buildIconWeb(
leftButton: Padding(
padding: const EdgeInsets.only(left: 8),
child: buildIconWeb(
minSize: 40,
iconPadding: EdgeInsets.zero,
icon: SvgPicture.asset(
imagePaths.icSearchBar,
width: 16,
height: 16,
fit: BoxFit.fill),
imagePaths.icSearchBar,
fit: BoxFit.fill),
onTap: () {
final keyword = controller.searchInputController.text.trim();
if (keyword.isNotEmpty) {
@@ -99,7 +101,9 @@ class SearchInputFormWidget extends StatelessWidget with AppLoaderMixin {
} else {
dashBoardController.clearSearchEmail();
}
}),
}
)
),
clearTextButton: buildIconWeb(
icon: SvgPicture.asset(
imagePaths.icClearTextSearch,
@@ -0,0 +1,50 @@
import 'package:get/get.dart';
import 'package:tmail_ui_user/features/base/base_bindings.dart';
import 'package:tmail_ui_user/features/mailbox/domain/usecases/delete_multiple_mailbox_interactor.dart';
import 'package:tmail_ui_user/features/mailbox/domain/usecases/get_all_mailbox_interactor.dart';
import 'package:tmail_ui_user/features/mailbox/domain/usecases/move_mailbox_interactor.dart';
import 'package:tmail_ui_user/features/mailbox/domain/usecases/refresh_all_mailbox_interactor.dart';
import 'package:tmail_ui_user/features/mailbox/domain/usecases/rename_mailbox_interactor.dart';
import 'package:tmail_ui_user/features/mailbox/domain/usecases/search_mailbox_interactor.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_tree_builder.dart';
import 'package:tmail_ui_user/features/mailbox_creator/domain/usecases/verify_name_interactor.dart';
import 'package:tmail_ui_user/features/search/mailbox/presentation/search_mailbox_controller.dart';
class SearchMailboxBindings extends BaseBindings {
@override
void bindingsController() {
Get.lazyPut(() => SearchMailboxController(
Get.find<GetAllMailboxInteractor>(),
Get.find<RefreshAllMailboxInteractor>(),
Get.find<SearchMailboxInteractor>(),
Get.find<RenameMailboxInteractor>(),
Get.find<MoveMailboxInteractor>(),
Get.find<DeleteMultipleMailboxInteractor>(),
Get.find<TreeBuilder>(),
Get.find<VerifyNameInteractor>()
));
}
@override
void bindingsDataSource() {}
@override
void bindingsDataSourceImpl() {}
@override
void bindingsInteractor() {
Get.lazyPut(() => SearchMailboxInteractor());
}
@override
void bindingsRepository() {}
@override
void bindingsRepositoryImpl() {}
void disposeBindings() {
Get.delete<SearchMailboxController>();
}
}
@@ -0,0 +1,383 @@
import 'package:core/presentation/extensions/color_extension.dart';
import 'package:core/presentation/resources/image_paths.dart';
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:core/presentation/utils/app_toast.dart';
import 'package:core/presentation/utils/responsive_utils.dart';
import 'package:core/utils/app_logger.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/mail/mailbox/mailbox.dart';
import 'package:model/mailbox/presentation_mailbox.dart';
import 'package:tmail_ui_user/features/base/base_mailbox_controller.dart';
import 'package:debounce_throttle/debounce_throttle.dart';
import 'package:tmail_ui_user/features/base/mixin/mailbox_action_handler_mixin.dart';
import 'package:tmail_ui_user/features/email/domain/model/move_action.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/move_mailbox_request.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/rename_mailbox_request.dart';
import 'package:tmail_ui_user/features/mailbox/domain/state/delete_multiple_mailbox_state.dart';
import 'package:tmail_ui_user/features/mailbox/domain/state/get_all_mailboxes_state.dart';
import 'package:tmail_ui_user/features/mailbox/domain/state/mark_as_mailbox_read_state.dart';
import 'package:tmail_ui_user/features/mailbox/domain/state/move_mailbox_state.dart';
import 'package:tmail_ui_user/features/mailbox/domain/state/refresh_changes_all_mailboxes_state.dart';
import 'package:tmail_ui_user/features/mailbox/domain/state/rename_mailbox_state.dart';
import 'package:tmail_ui_user/features/mailbox/domain/state/search_mailbox_state.dart';
import 'package:tmail_ui_user/features/mailbox/domain/usecases/delete_multiple_mailbox_interactor.dart';
import 'package:tmail_ui_user/features/mailbox/domain/usecases/get_all_mailbox_interactor.dart';
import 'package:tmail_ui_user/features/mailbox/domain/usecases/move_mailbox_interactor.dart';
import 'package:tmail_ui_user/features/mailbox/domain/usecases/refresh_all_mailbox_interactor.dart';
import 'package:tmail_ui_user/features/mailbox/domain/usecases/rename_mailbox_interactor.dart';
import 'package:tmail_ui_user/features/mailbox/domain/usecases/search_mailbox_interactor.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/action/mailbox_ui_action.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_actions.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_tree_builder.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/utils/mailbox_utils.dart';
import 'package:tmail_ui_user/features/mailbox_creator/domain/usecases/verify_name_interactor.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart';
import 'package:tmail_ui_user/features/search/mailbox/presentation/search_mailbox_bindings.dart';
import 'package:tmail_ui_user/features/thread/domain/model/search_query.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
import 'package:jmap_dart_client/jmap/core/state.dart' as jmap;
class SearchMailboxController extends BaseMailboxController with MailboxActionHandlerMixin {
final GetAllMailboxInteractor _getAllMailboxInteractor;
final RefreshAllMailboxInteractor _refreshAllMailboxInteractor;
final SearchMailboxInteractor _searchMailboxInteractor;
final RenameMailboxInteractor _renameMailboxInteractor;
final MoveMailboxInteractor _moveMailboxInteractor;
final DeleteMultipleMailboxInteractor _deleteMultipleMailboxInteractor;
final dashboardController = Get.find<MailboxDashBoardController>();
final responsiveUtils = Get.find<ResponsiveUtils>();
final imagePaths = Get.find<ImagePaths>();
final _appToast = Get.find<AppToast>();
final currentSearchQuery = RxString('');
final listMailboxSearched = RxList<PresentationMailbox>();
final textInputSearchController = TextEditingController();
late Debouncer<String> _deBouncerTime;
SearchMailboxController(
this._getAllMailboxInteractor,
this._refreshAllMailboxInteractor,
this._searchMailboxInteractor,
this._renameMailboxInteractor,
this._moveMailboxInteractor,
this._deleteMultipleMailboxInteractor,
TreeBuilder treeBuilder,
VerifyNameInteractor verifyNameInteractor
) : super(treeBuilder, verifyNameInteractor);
@override
void onInit() {
super.onInit();
_initializeDebounceTimeTextSearchChange();
_getAllMailboxAction();
}
@override
void onDone() {
viewState.value.fold(_handleFailureViewState, _handleSuccessViewState);
}
@override
void onData(Either<Failure, Success> newState) {
super.onData(newState);
newState.fold((failure) => null, (success) async {
if (success is GetAllMailboxSuccess) {
currentMailboxState = success.currentMailboxState;
buildTree(success.mailboxList);
} else if (success is RefreshChangesAllMailboxSuccess) {
currentMailboxState = success.currentMailboxState;
await refreshTree(success.mailboxList);
searchMailboxAction();
}
});
}
void _handleFailureViewState(Failure failure) {
if (failure is SearchMailboxFailure) {
_handleSearchMailboxFailure(failure);
}
}
void _handleSuccessViewState(Success success) {
if (success is SearchMailboxSuccess) {
_handleSearchMailboxSuccess(success);
} else if (success is MarkAsMailboxReadAllSuccess) {
refreshMailboxChanges(mailboxState: success.currentMailboxState);
} else if (success is MarkAsMailboxReadHasSomeEmailFailure) {
refreshMailboxChanges(mailboxState: success.currentMailboxState);
} else if (success is RenameMailboxSuccess) {
refreshMailboxChanges(mailboxState: success.currentMailboxState);
} else if (success is MoveMailboxSuccess) {
_moveMailboxSuccess(success);
}else if (success is DeleteMultipleMailboxAllSuccess) {
_deleteMultipleMailboxSuccess(success.listMailboxIdDeleted, success.currentMailboxState);
} else if (success is DeleteMultipleMailboxHasSomeSuccess) {
_deleteMultipleMailboxSuccess(success.listMailboxIdDeleted, success.currentMailboxState);
}
}
void _initializeDebounceTimeTextSearchChange() {
_deBouncerTime = Debouncer<String>(
const Duration(milliseconds: 300),
initialValue: ''
);
_deBouncerTime.values.listen((value) async {
log('SearchMailboxController::_initializeDebounceTimeTextSearchChange():query: $value');
currentSearchQuery.value = value;
searchMailboxAction();
});
}
void _getAllMailboxAction() {
final session = dashboardController.sessionCurrent;
final accountId = dashboardController.accountId.value;
if (session != null && accountId != null) {
consumeState(_getAllMailboxInteractor.execute(session, accountId));
}
}
void refreshMailboxChanges({jmap.State? mailboxState}) {
final newMailboxState = mailboxState ?? currentMailboxState;
dashboardController.dispatchMailboxUIAction(RefreshChangeMailboxAction(newMailboxState));
final accountId = dashboardController.accountId.value;
if (accountId != null && newMailboxState != null) {
consumeState(_refreshAllMailboxInteractor.execute(accountId, newMailboxState));
}
}
void searchMailboxAction() {
if (currentSearchQuery.value.isNotEmpty) {
consumeState(_searchMailboxInteractor.execute(
allMailboxes,
SearchQuery(currentSearchQuery.value)
));
} else {
listMailboxSearched.clear();
}
}
void _handleSearchMailboxSuccess(SearchMailboxSuccess success) {
final mailboxesSearchedWithPath = findMailboxPath(success.mailboxesSearched);
listMailboxSearched.value = mailboxesSearchedWithPath;
}
void _handleSearchMailboxFailure(SearchMailboxFailure failure) {
listMailboxSearched.clear();
}
void onTextSearchChange(String text) {
_deBouncerTime.value = text;
}
void setTextInputSearchForm(String value) {
textInputSearchController.text = value;
}
void submitSearchAction(BuildContext context, String query) {
}
void handleMailboxAction(BuildContext context, MailboxActions actions, PresentationMailbox mailbox) {
popBack();
switch(actions) {
case MailboxActions.openInNewTab:
openMailboxInNewTabAction(mailbox);
break;
case MailboxActions.disableSpamReport:
case MailboxActions.enableSpamReport:
dashboardController.storeSpamReportStateAction();
return;
case MailboxActions.markAsRead:
markAsReadMailboxAction(context, mailbox, dashboardController);
break;
case MailboxActions.rename:
openDialogRenameMailboxAction(
context,
mailbox,
responsiveUtils,
onRenameMailboxAction: _renameMailboxAction
);
break;
case MailboxActions.move:
moveMailboxAction(
context,
mailbox,
dashboardController,
onMovingMailboxAction: _invokeMovingMailboxAction
);
break;
case MailboxActions.delete:
openConfirmationDialogDeleteMailboxAction(
context,
responsiveUtils,
imagePaths,
mailbox,
onDeleteMailboxAction: _deleteMailboxAction
);
break;
default:
break;
}
}
void _renameMailboxAction(PresentationMailbox presentationMailbox, MailboxName newMailboxName) {
final accountId = dashboardController.accountId.value;
if (accountId != null) {
consumeState(_renameMailboxInteractor.execute(
accountId,
RenameMailboxRequest(presentationMailbox.id, newMailboxName)
));
}
}
void _invokeMovingMailboxAction(PresentationMailbox mailboxSelected, PresentationMailbox? destinationMailbox) {
final accountId = dashboardController.accountId.value;
if (accountId != null) {
_handleMovingMailbox(
accountId,
MoveAction.moving,
mailboxSelected,
destinationMailbox: destinationMailbox
);
}
}
void _handleMovingMailbox(
AccountId accountId,
MoveAction moveAction,
PresentationMailbox mailboxSelected,
{PresentationMailbox? destinationMailbox}
) {
consumeState(_moveMailboxInteractor.execute(
accountId,
MoveMailboxRequest(
mailboxSelected.id,
moveAction,
destinationMailboxId: destinationMailbox?.id,
destinationMailboxName: destinationMailbox?.name,
parentId: mailboxSelected.parentId
)
));
}
void _moveMailboxSuccess(MoveMailboxSuccess success) {
if (success.moveAction == MoveAction.moving && currentOverlayContext != null && currentContext != null) {
_appToast.showBottomToast(
currentOverlayContext!,
AppLocalizations.of(currentContext!).moved_to_mailbox(success.destinationMailboxName?.name ?? AppLocalizations.of(currentContext!).allMailboxes),
actionName: AppLocalizations.of(currentContext!).undo,
onActionClick: () {
_undoMovingMailbox(MoveMailboxRequest(
success.mailboxIdSelected,
MoveAction.undo,
destinationMailboxId: success.parentId,
parentId: success.destinationMailboxId)
);
},
leadingIcon: SvgPicture.asset(
imagePaths.icFolderMailbox,
width: 24,
height: 24,
color: Colors.white,
fit: BoxFit.fill),
backgroundColor: AppColor.toastSuccessBackgroundColor,
textColor: Colors.white,
textActionColor: Colors.white,
actionIcon: SvgPicture.asset(imagePaths.icUndo),
maxWidth: responsiveUtils.getMaxWidthToast(currentContext!)
);
}
refreshMailboxChanges(mailboxState: success.currentMailboxState);
}
void _undoMovingMailbox(MoveMailboxRequest newMoveRequest) {
final accountId = dashboardController.accountId.value;
if (accountId != null) {
consumeState(_moveMailboxInteractor.execute(accountId, newMoveRequest));
}
}
void _deleteMailboxAction(PresentationMailbox presentationMailbox) {
final accountId = dashboardController.accountId.value;
final session = dashboardController.sessionCurrent;
if (session != null && accountId != null) {
final tupleMap = MailboxUtils.generateMapDescendantIdsAndMailboxIdList(
[presentationMailbox],
defaultMailboxTree.value,
personalMailboxTree.value
);
final mapDescendantIds = tupleMap.value1;
final listMailboxId = tupleMap.value2;
consumeState(_deleteMultipleMailboxInteractor.execute(
session,
accountId,
mapDescendantIds,
listMailboxId
));
} else {
_deleteMailboxFailure(DeleteMultipleMailboxFailure(null));
}
popBack();
}
void _deleteMultipleMailboxSuccess(List<MailboxId> listMailboxIdDeleted, jmap.State? currentMailboxState) {
if (currentOverlayContext != null && currentContext != null) {
_appToast.showToastWithIcon(
currentOverlayContext!,
message: AppLocalizations.of(currentContext!).delete_mailboxes_successfully,
icon: imagePaths.icSelected
);
}
if (listMailboxIdDeleted.contains(dashboardController.selectedMailbox.value?.id)) {
dashboardController.selectedMailbox.value = null;
dashboardController.dispatchMailboxUIAction(SelectMailboxDefaultAction());
}
refreshMailboxChanges(mailboxState: currentMailboxState);
}
void _deleteMailboxFailure(DeleteMultipleMailboxFailure failure) {
if (currentOverlayContext != null && currentContext != null) {
_appToast.showToastWithIcon(
currentOverlayContext!,
message: AppLocalizations.of(currentContext!).delete_mailboxes_failure,
icon: imagePaths.icDeleteToast
);
}
}
void clearAllTextInputSearchForm() {
textInputSearchController.clear();
currentSearchQuery.value = '';
searchMailboxAction();
}
void closeSearchView(BuildContext context) {
clearAllTextInputSearchForm();
dashboardController.searchMailboxActivated.value = false;
SearchMailboxBindings().disposeBindings();
}
@override
void onClose() {
textInputSearchController.dispose();
_deBouncerTime.cancel();
super.onClose();
}
}
@@ -0,0 +1,293 @@
import 'package:core/presentation/extensions/color_extension.dart';
import 'package:core/presentation/views/button/icon_button_web.dart';
import 'package:core/presentation/views/text/text_field_builder.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart';
import 'package:model/mailbox/presentation_mailbox.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/mailbox/domain/state/search_mailbox_state.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/model/context_item_mailbox_action.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_actions.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/mailbox_bottom_sheet_action_tile_builder.dart';
import 'package:tmail_ui_user/features/search/mailbox/presentation/search_mailbox_controller.dart';
import 'package:tmail_ui_user/features/search/mailbox/presentation/utils/search_mailbox_utils.dart';
import 'package:tmail_ui_user/features/search/mailbox/presentation/widgets/mailbox_searched_item_builder.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
class SearchMailboxView extends GetWidget<SearchMailboxController>
with AppLoaderMixin, PopupMenuWidgetMixin {
final Color? backgroundColor;
const SearchMailboxView({
Key? key,
this.backgroundColor
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: GestureDetector(
onTap: () => FocusScope.of(context).unfocus(),
child: Container(
color: backgroundColor ?? Colors.white,
child: Column(children: [
Container(
color: Colors.transparent,
padding: SearchMailboxUtils.getPaddingAppBar(context, controller.responsiveUtils),
child: _buildSearchInputForm(context)
),
if (!controller.responsiveUtils.isWebDesktop(context))
const Divider(color: AppColor.colorDividerComposer, height: 1),
_buildLoadingView(),
Expanded(child: _buildMailboxListView())
]),
),
),
);
}
Widget _buildLoadingView() {
return Obx(() => controller.viewState.value.fold(
(failure) => const SizedBox.shrink(),
(success) {
if (success is LoadingSearchMailbox) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 16),
child: loadingWidget);
} else {
return const SizedBox.shrink();
}
}
));
}
Widget _buildSearchInputForm(BuildContext context) {
return Row(children: [
buildIconWeb(
minSize: 30,
iconPadding: EdgeInsets.zero,
splashRadius: 10,
icon: SvgPicture.asset(
controller.imagePaths.icBack,
color: AppColor.colorTextButton,
fit: BoxFit.fill
),
tooltip: AppLocalizations.of(context).back,
onTap: () => controller.closeSearchView(context)
),
Expanded(child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(controller.responsiveUtils.isWebDesktop(context) ? 12 : 0)),
color: controller.responsiveUtils.isWebDesktop(context)
? AppColor.colorBackgroundSearchMailboxInput
: Colors.transparent
),
alignment: Alignment.center,
child: Row(children: [
Padding(
padding: const EdgeInsets.only(left: 5, right: 2),
child: buildIconWeb(
minSize: 40,
iconPadding: EdgeInsets.zero,
icon: SvgPicture.asset(
controller.imagePaths.icSearchBar,
color: AppColor.colorTextButton,
fit: BoxFit.fill
),
tooltip: AppLocalizations.of(context).search,
onTap: controller.searchMailboxAction
),
),
Expanded(child: _buildTextFieldSearchInput(context)),
Obx(() {
if (controller.currentSearchQuery.isNotEmpty) {
return Padding(
padding: const EdgeInsets.only(right: 2),
child: buildIconWeb(
minSize: 40,
iconPadding: EdgeInsets.zero,
icon: SvgPicture.asset(
controller.imagePaths.icClearSearchInput,
width: 24,
height: 24,
fit: BoxFit.fill
),
tooltip: AppLocalizations.of(context).clearAll,
onTap: controller.clearAllTextInputSearchForm),
);
} else {
return const SizedBox.shrink();
}
})
])
))
]);
}
Widget _buildTextFieldSearchInput(BuildContext context) {
return (TextFieldBuilder()
..onChange(controller.onTextSearchChange)
..textInputAction(TextInputAction.search)
..addController(controller.textInputSearchController)
..textStyle(const TextStyle(
color: Colors.black,
fontSize: 15,
fontWeight: FontWeight.normal))
..keyboardType(TextInputType.text)
..onSubmitted((value) {
final query = value.trim();
if (query.isNotEmpty) {
controller.submitSearchAction(context, query);
}
})
..maxLines(1)
..textDecoration(InputDecoration(
contentPadding: EdgeInsets.zero,
hintText: AppLocalizations.of(context).searchForMailboxes,
hintStyle: const TextStyle(
color: AppColor.loginTextFieldHintColor,
fontSize: 15,
fontWeight: FontWeight.normal),
border: InputBorder.none
)
)).build();
}
Widget _buildMailboxListView() {
return Obx(() {
return ListView.builder(
padding: const EdgeInsets.only(left: 16, right: 16, bottom: 16),
key: const Key('list_mailbox_searched'),
itemCount: controller.listMailboxSearched.length,
shrinkWrap: true,
primary: false,
itemBuilder: (context, index) {
return MailboxSearchedItemBuilder(
controller.imagePaths,
controller.responsiveUtils,
controller.listMailboxSearched[index],
onDragEmailToMailboxAccepted: controller.dashboardController.dragSelectedMultipleEmailToMailboxAction,
onClickOpenMailboxAction: (mailbox) => controller.dashboardController.openMailboxAction(context, mailbox),
onClickOpenMenuMailboxAction: (position, mailbox) => _openMailboxMenuAction(context, position, mailbox),
);
}
);
});
}
MailboxActions mailboxActionForSpam() {
return controller.dashboardController.enableSpamReport
? MailboxActions.disableSpamReport
: MailboxActions.enableSpamReport;
}
void _openMailboxMenuAction(BuildContext context, RelativeRect position, PresentationMailbox mailbox) {
final mailboxActionsSupported = [
MailboxActions.openInNewTab,
if (mailbox.isPersonal && mailbox.isSpam)
mailboxActionForSpam(),
MailboxActions.markAsRead,
MailboxActions.move,
MailboxActions.rename,
MailboxActions.delete
];
final listContextMenuItemAction = mailboxActionsSupported
.map((action) => ContextMenuItemMailboxAction(action, action.getContextMenuItemState(mailbox)))
.toList();
if (controller.responsiveUtils.isScreenWithShortestSide(context)) {
controller.openContextMenuAction(
context,
_bottomSheetMailboxActionTiles(
context,
mailbox,
listContextMenuItemAction
)
);
} else {
controller.openPopupMenuAction(
context,
position,
_popupMenuMailboxActionTiles(
context,
mailbox,
listContextMenuItemAction
)
);
}
}
List<Widget> _bottomSheetMailboxActionTiles(
BuildContext context,
PresentationMailbox mailbox,
List<ContextMenuItemMailboxAction> contextMenuActions
) {
return contextMenuActions
.map((action) => _mailboxContextMenuActionTile(context, action, mailbox))
.toList();
}
Widget _mailboxContextMenuActionTile(
BuildContext context,
ContextMenuItemMailboxAction contextMenuItem,
PresentationMailbox mailbox
) {
return (MailboxBottomSheetActionTileBuilder(
Key('${contextMenuItem.action.name}_action'),
SvgPicture.asset(
contextMenuItem.action.getContextMenuIcon(controller.imagePaths),
color: contextMenuItem.action.getColorContextMenuIcon()
),
contextMenuItem.action.getTitleContextMenu(context),
mailbox,
absorbing: !contextMenuItem.isActivated,
opacity: !contextMenuItem.isActivated)
..actionTextStyle(textStyle: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
color: Colors.black))
..onActionClick((mailbox) => controller.handleMailboxAction(context, contextMenuItem.action, mailbox))
).build();
}
List<PopupMenuEntry> _popupMenuMailboxActionTiles(
BuildContext context,
PresentationMailbox mailbox,
List<ContextMenuItemMailboxAction> contextMenuActions
) {
return contextMenuActions
.map((action) => _mailboxPopupMenuActionTile(context, action, mailbox))
.toList();
}
PopupMenuItem _mailboxPopupMenuActionTile(
BuildContext context,
ContextMenuItemMailboxAction contextMenuItem,
PresentationMailbox mailbox
) {
return PopupMenuItem(
padding: EdgeInsets.zero,
child: AbsorbPointer(
absorbing: !contextMenuItem.isActivated,
child: Opacity(
opacity: contextMenuItem.isActivated ? 1.0 : 0.3,
child: popupItem(contextMenuItem.action.getContextMenuIcon(controller.imagePaths),
contextMenuItem.action.getTitleContextMenu(context),
colorIcon: contextMenuItem.action.getColorContextMenuIcon(),
styleName: TextStyle(
fontWeight: FontWeight.w500,
fontSize: 16,
color: contextMenuItem.action.getColorContextMenuTitle()
),
onCallbackAction: () => controller.handleMailboxAction(context, contextMenuItem.action, mailbox))
,
)
)
);
}
}
@@ -0,0 +1,16 @@
import 'package:core/presentation/utils/responsive_utils.dart';
import 'package:flutter/material.dart';
class SearchMailboxUtils {
static EdgeInsets getPaddingAppBar(BuildContext context, ResponsiveUtils responsiveUtils) {
if (responsiveUtils.isWebDesktop(context)) {
return const EdgeInsets.symmetric(vertical: 8, horizontal: 16);
} else {
if (responsiveUtils.isScreenWithShortestSide(context)) {
return const EdgeInsets.symmetric(horizontal: 10);
} else {
return const EdgeInsets.symmetric(horizontal: 32);
}
}
}
}
@@ -0,0 +1,181 @@
import 'package:core/presentation/extensions/color_extension.dart';
import 'package:core/presentation/resources/image_paths.dart';
import 'package:core/presentation/utils/responsive_utils.dart';
import 'package:core/presentation/utils/style_utils.dart';
import 'package:core/utils/build_utils.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:model/email/presentation_email.dart';
import 'package:model/mailbox/presentation_mailbox.dart';
import 'package:tmail_ui_user/features/mailbox/domain/extensions/presentation_mailbox_extension.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/utils/mailbox_method_action_define.dart';
class MailboxSearchedItemBuilder extends StatefulWidget {
final PresentationMailbox _presentationMailbox;
final ImagePaths _imagePaths;
final ResponsiveUtils _responsiveUtils;
final OnClickOpenMailboxAction? onClickOpenMailboxAction;
final OnClickOpenMenuMailboxAction? onClickOpenMenuMailboxAction;
final OnDragEmailToMailboxAccepted? onDragEmailToMailboxAccepted;
const MailboxSearchedItemBuilder(
this._imagePaths,
this._responsiveUtils,
this._presentationMailbox,
{
Key? key,
this.onClickOpenMailboxAction,
this.onClickOpenMenuMailboxAction,
this.onDragEmailToMailboxAccepted
}
) : super(key: key);
@override
State<MailboxSearchedItemBuilder> createState() => _MailboxSearchedItemBuilderState();
}
class _MailboxSearchedItemBuilderState extends State<MailboxSearchedItemBuilder> {
bool isHoverItem = false;
@override
Widget build(BuildContext context) {
if (BuildUtils.isWeb) {
return DragTarget<List<PresentationEmail>>(
builder: (_, __, ___) {
return _buildMailboxItem(context);
},
onAccept: (emails) {
widget.onDragEmailToMailboxAccepted?.call(emails, widget._presentationMailbox);
}
);
} else {
return _buildMailboxItem(context);
}
}
Widget _buildMailboxItem(BuildContext context) {
if (BuildUtils.isWeb) {
return InkWell(
onTap: _onTapMailboxAction,
onHover: (value) => setState(() => isHoverItem = value),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
color: getBackgroundColorItem(context)
),
padding: const EdgeInsets.all(8),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildMailboxIcon(),
Expanded(child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildTitleItem(),
_buildSubtitleItem()
]
)
)),
if (widget._presentationMailbox.isSubscribed?.value == true)
_buildMenuIcon(context)
]
),
)
);
} else {
return ListTile(
contentPadding: const EdgeInsets.symmetric(horizontal: 8),
onTap: _onTapMailboxAction,
leading: _buildMailboxIcon(),
title: _buildTitleItem(),
subtitle: _buildSubtitleItem()
);
}
}
void _onTapMailboxAction() {
if (widget._presentationMailbox.isSubscribed?.value == true) {
widget.onClickOpenMailboxAction?.call(widget._presentationMailbox);
}
}
Widget _buildMailboxIcon() {
return SvgPicture.asset(
widget._presentationMailbox.isSubscribed?.value == true
? widget._presentationMailbox.getMailboxIcon(widget._imagePaths)
: widget._imagePaths.icHideFolder,
width: 20,
height: 20,
fit: BoxFit.fill
);
}
Widget _buildTitleItem() {
return Text(
widget._presentationMailbox.name?.name ?? '',
maxLines: 1,
overflow: CommonTextStyle.defaultTextOverFlow,
softWrap: CommonTextStyle.defaultSoftWrap,
style: const TextStyle(
fontSize: 15,
color: Colors.black
),
);
}
Widget _buildSubtitleItem() {
if (widget._presentationMailbox.mailboxPath?.isNotEmpty == true) {
return Text(
widget._presentationMailbox.mailboxPath ?? '',
maxLines: 1,
overflow: CommonTextStyle.defaultTextOverFlow,
softWrap: CommonTextStyle.defaultSoftWrap,
style: const TextStyle(
fontSize: 11,
color: AppColor.colorMailboxPath
),
);
} else {
return const SizedBox.shrink();
}
}
Widget _buildMenuIcon(BuildContext context) {
if (isHoverItem) {
return InkWell(
onTapDown: (detail) {
final screenSize = MediaQuery.of(context).size;
final offset = detail.globalPosition;
final position = RelativeRect.fromLTRB(
offset.dx,
offset.dy,
screenSize.width - offset.dx,
screenSize.height - offset.dy,
);
widget.onClickOpenMenuMailboxAction?.call(position, widget._presentationMailbox);
},
child: SvgPicture.asset(
widget._imagePaths.icComposerMenu,
width: 20,
height: 20,
fit: BoxFit.fill
)
);
} else {
return const SizedBox.shrink();
}
}
Color getBackgroundColorItem(BuildContext context) {
if (isHoverItem) {
return AppColor.colorBgMailboxSelected;
} else {
return widget._responsiveUtils.isDesktop(context)
? AppColor.colorBgDesktop
: Colors.transparent;
}
}
}
@@ -145,8 +145,17 @@ class SearchAppBarWidget {
}
Widget _buildSearchButton() {
return buildIconWeb(
icon: SvgPicture.asset(_imagePaths.icSearchBar, width: 16, height: 16, fit: BoxFit.fill),
onTap: () => _onSearchTextAction?.call(_searchInputController?.text ?? ''));
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: buildIconWeb(
minSize: 40,
iconPadding: EdgeInsets.zero,
icon: SvgPicture.asset(
_imagePaths.icSearchBar,
fit: BoxFit.fill
),
onTap: () => _onSearchTextAction?.call(_searchInputController?.text ?? '')
),
);
}
}
@@ -2779,10 +2779,17 @@ class AppLocalizations {
name: 'thisImageCannotBeAdded'
);
}
String get toastMsgHideMailboxSuccess {
return Intl.message(
'This mailbox has been hidden from your primary mailbox',
name: 'toastMsgHideMailboxSuccess');
}
String get searchForMailboxes {
return Intl.message(
'Search for mailboxes',
name: 'searchForMailboxes'
);
}
}