import 'package:core/presentation/extensions/color_extension.dart'; import 'package:core/presentation/utils/theme_utils.dart'; import 'package:core/presentation/views/button/tmail_button_widget.dart'; import 'package:core/presentation/views/text/text_field_builder.dart'; import 'package:core/utils/direction_utils.dart'; import 'package:core/utils/platform_info.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:focused_menu_custom/modals.dart'; import 'package:get/get.dart'; import 'package:model/mailbox/presentation_mailbox.dart'; import 'package:pointer_interceptor/pointer_interceptor.dart'; import 'package:tmail_ui_user/features/base/mixin/app_loader_mixin.dart'; import 'package:tmail_ui_user/features/base/widget/popup_menu/popup_menu_item_action_widget.dart'; import 'package:tmail_ui_user/features/home/domain/extensions/session_extensions.dart'; import 'package:tmail_ui_user/features/mailbox/domain/state/search_mailbox_state.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/mixin/mailbox_widget_mixin.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/utils/mailbox_utils.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/handle_open_context_menu_extension.dart'; import 'package:tmail_ui_user/features/search/mailbox/presentation/search_mailbox_controller.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'; import 'package:tmail_ui_user/main/routes/route_navigation.dart'; class SearchMailboxView extends GetWidget with AppLoaderMixin, MailboxWidgetMixin { final Color? backgroundColor; const SearchMailboxView({ Key? key, this.backgroundColor }) : super(key: key); @override Widget build(BuildContext context) { if (PlatformInfo.isWeb) { return Scaffold( body: PointerInterceptor(child: _buildSearchBody(context)), ); } else { return Scaffold( body: GestureDetector( onTap: FocusScope.of(context).unfocus, child: SafeArea(child: _buildSearchBody(context)), ), ); } } Widget _buildSearchBody(BuildContext context) { return ColoredBox( color: backgroundColor ?? Colors.white, child: Column(children: [ Padding( padding: const EdgeInsetsDirectional.only( start: 16, end: 16, top: 12, ), child: _buildSearchInputForm(context), ), _buildLoadingView(), Expanded( child: Padding( padding: const EdgeInsets.only(top: 12), child: _buildMailboxListView(context), ) ) ]), ); } Widget _buildLoadingView() { return Obx(() => controller.viewState.value.fold( (failure) => const SizedBox.shrink(), (success) { if (success is LoadingSearchMailbox) { return Padding( padding: const EdgeInsets.only(top: 12), child: loadingWidget); } else { return const SizedBox.shrink(); } } )); } Widget _buildSearchInputForm(BuildContext context) { return Row(children: [ TMailButtonWidget.fromIcon( icon: controller.imagePaths.icBack, iconColor: AppColor.steelGray400, backgroundColor: Colors.transparent, width: 36, height: 36, margin: const EdgeInsetsDirectional.only(end: 8), padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 14), tooltipMessage: AppLocalizations.of(context).back, onTapActionCallback: () => controller.closeSearchView(context), ), Expanded(child: Container( decoration: const BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(12)), color: AppColor.searchInputBackground ), alignment: Alignment.center, child: Row(children: [ Padding( padding: const EdgeInsets.symmetric(horizontal: 12), child: TMailButtonWidget.fromIcon( icon: controller.imagePaths.icSearchBar, iconColor: AppColor.steelGray400, iconSize: 22, backgroundColor: Colors.transparent, padding: const EdgeInsets.all(4), tooltipMessage: AppLocalizations.of(context).search, onTapActionCallback: () => controller.handleSearchButtonPressed(context) ), ), Expanded(child: _buildTextFieldSearchInput(context)), Obx(() { if (controller.currentSearchQuery.isNotEmpty) { return Padding( padding: const EdgeInsetsDirectional.only(end: 12), child: TMailButtonWidget.fromIcon( icon: controller.imagePaths.icClearSearchInput, iconColor: AppColor.steelGray400, iconSize: 22, backgroundColor: Colors.transparent, padding: const EdgeInsets.all(4), tooltipMessage: AppLocalizations.of(context).clearAll, onTapActionCallback: controller.clearAllTextInputSearchForm, ), ); } else { return const SizedBox.shrink(); } }) ]) )) ]); } Widget _buildTextFieldSearchInput(BuildContext context) { return TextFieldBuilder( onTextChange: controller.onTextSearchChange, textInputAction: TextInputAction.search, autoFocus: true, maxLines: 1, controller: controller.textInputSearchController, focusNode: controller.searchFocusNode, textDirection: DirectionUtils.getDirectionByLanguage(context), textStyle: ThemeUtils.textStyleBodyBody2( color: Colors.black, ), keyboardType: TextInputType.text, onTextSubmitted: (text) => controller.onTextSearchSubmitted(context, text), decoration: InputDecoration( contentPadding: const EdgeInsetsDirectional.only( end: 12, bottom: 14, top: 14, ), hintText: AppLocalizations.of(context).searchForFolders, hintStyle: ThemeUtils.textStyleBodyBody2( color: AppColor.steelGray400, ), border: InputBorder.none ), ); } Widget _buildMailboxListView(BuildContext context) { return Obx(() { return ListView.builder( key: const Key('list_mailbox_searched'), itemCount: controller.listMailboxSearched.length, padding: const EdgeInsets.symmetric(horizontal: 16), shrinkWrap: true, primary: false, itemBuilder: (context, index) { return LayoutBuilder(builder: (context, constraints) { final mailboxCurrent = controller.listMailboxSearched[index]; return MailboxSearchedItemBuilder( presentationMailbox: mailboxCurrent, maxWidth: constraints.maxWidth, onDragEmailToMailboxAccepted: controller.dashboardController.dragSelectedMultipleEmailToMailboxAction, onClickOpenMailboxAction: (mailbox) => controller.openMailboxAction(context, mailbox), onClickOpenMenuMailboxAction: (position, mailbox) => _openMailboxMenuAction(context, mailbox, position: position), onLongPressMailboxAction: (mailbox) => _openMailboxMenuAction(context, mailbox), listPopupMenuItemAction: _listPopupMenuItemAction(context, mailboxCurrent) ); }); } ); }); } List _listPopupMenuItemAction(BuildContext context, PresentationMailbox mailbox) { final session = controller.dashboardController.sessionCurrent; final accountId = controller.dashboardController.accountId.value; final deletedMessageVaultSupported = MailboxUtils.isDeletedMessageVaultSupported(session, accountId); final isSubAddressingSupported = session?.isSubAddressingSupported(accountId) ?? false; final contextMenuActions = listContextMenuItemAction( mailbox, controller.dashboardController.enableSpamReport, deletedMessageVaultSupported, isSubAddressingSupported, controller.imagePaths, AppLocalizations.of(context), ); return contextMenuActions .map((action) => _mailboxFocusedMenuItem(context, action, mailbox)) .toList(); } FocusedMenuItem _mailboxFocusedMenuItem( BuildContext context, ContextMenuItemMailboxAction contextMenuItem, PresentationMailbox mailbox ) { return FocusedMenuItem( backgroundColor: Colors.white, onPressed: () => controller.handleMailboxAction( context, contextMenuItem.action, mailbox, ), title: Expanded( child: Row(children: [ SvgPicture.asset( contextMenuItem.action.getContextMenuIcon(controller.imagePaths), width: 24, height: 24, fit: BoxFit.fill, colorFilter: contextMenuItem.action.getPopupMenuIconColor().asFilter() ), const SizedBox(width: 12), Expanded(child: Text( contextMenuItem.action.getContextMenuTitle(AppLocalizations.of(context)), style: ThemeUtils.defaultTextStyleInterFont.copyWith( fontWeight: FontWeight.w500, fontSize: 16, color: contextMenuItem.action.getPopupMenuTitleColor() ) )), ]), ) ); } Future _openMailboxMenuAction( BuildContext context, PresentationMailbox mailbox, {RelativeRect? position} ) { final session = controller.dashboardController.sessionCurrent; final accountId = controller.dashboardController.accountId.value; final deletedMessageVaultSupported = MailboxUtils.isDeletedMessageVaultSupported(session, accountId); final isSubAddressingSupported = session?.isSubAddressingSupported(accountId) ?? false; if (position == null) { final contextMenuActions = listContextMenuItemAction( mailbox, controller.dashboardController.enableSpamReport, deletedMessageVaultSupported, isSubAddressingSupported, controller.imagePaths, AppLocalizations.of(context), ); if (contextMenuActions.isEmpty) return Future.value(); controller.clearSearchInputFocus(); return controller.dashboardController.openBottomSheetContextMenu( context: context, itemActions: contextMenuActions, onContextMenuActionClick: (menuAction) { popBack(); controller.handleMailboxAction( context, menuAction.action, mailbox, ); }, ); } else { final popupMenuActions = getListPopupMenuItemAction( AppLocalizations.of(context), controller.imagePaths, mailbox, controller.dashboardController.enableSpamReport, deletedMessageVaultSupported, isSubAddressingSupported, ); if (popupMenuActions.isEmpty) Future.value(); controller.clearSearchInputFocus(); final popupMenuItems = popupMenuActions.map((menuAction) { return PopupMenuItem( padding: EdgeInsets.zero, child: PopupMenuItemActionWidget( menuAction: menuAction, menuActionClick: (menuAction) { popBack(); controller.handleMailboxAction( context, menuAction.action, mailbox, ); }, ), ); }).toList(); return controller.dashboardController.openPopupMenu( context, position, popupMenuItems, ); } } }