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:core/utils/build_utils.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: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 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: BuildUtils.isWeb ? _buildSearchBody(context) : SafeArea(child: _buildSearchBody(context)), ), ); } Widget _buildSearchBody(BuildContext context) { return 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(context)) ]), ); } 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: SearchMailboxUtils.getIconSize(context, controller.responsiveUtils), iconPadding: EdgeInsets.zero, splashRadius: SearchMailboxUtils.getIconSplashRadius(context, controller.responsiveUtils), 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: SearchMailboxUtils.getPaddingInputSearchIcon(context, controller.responsiveUtils), 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.handleSearchButtonPressed(context) ), ), 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) ..autoFocus(true) ..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(BuildContext context) { return Obx(() { return ListView.builder( padding: SearchMailboxUtils.getPaddingListViewMailboxSearched(context, controller.responsiveUtils), key: const Key('list_mailbox_searched'), itemCount: controller.listMailboxSearched.length, shrinkWrap: true, primary: false, itemBuilder: (context, index) { return LayoutBuilder(builder: (context, constraints) { final mailboxCurrent = controller.listMailboxSearched[index]; return MailboxSearchedItemBuilder( controller.imagePaths, controller.responsiveUtils, 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 mailboxActionsSupported = mailbox.isSubscribed?.value == true ? _listActionForMailboxSubscribed(mailbox) : _listActionForMailboxUnsubscribed(); final listContextMenuItemAction = mailboxActionsSupported .map((action) => ContextMenuItemMailboxAction(action, action.getContextMenuItemState(mailbox))) .toList(); return listContextMenuItemAction .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, isFocusedMenu: true ), title: Expanded( child: AbsorbPointer( absorbing: !contextMenuItem.isActivated, child: Opacity( opacity: contextMenuItem.isActivated ? 1.0 : 0.3, child: Row(children: [ SvgPicture.asset( contextMenuItem.action.getContextMenuIcon(controller.imagePaths), width: 24, height: 24, fit: BoxFit.fill, color: contextMenuItem.action.getColorContextMenuIcon() ), const SizedBox(width: 12), Expanded(child: Text( contextMenuItem.action.getTitleContextMenu(context), style: TextStyle( fontWeight: FontWeight.w500, fontSize: 16, color: contextMenuItem.action.getColorContextMenuTitle() ) )), ]), ), ), ) ); } MailboxActions _mailboxActionForSpam() { return controller.dashboardController.enableSpamReport ? MailboxActions.disableSpamReport : MailboxActions.enableSpamReport; } List _listActionForMailboxUnsubscribed() { return [ MailboxActions.markAsRead ]; } List _listActionForMailboxSubscribed(PresentationMailbox mailbox) { return [ if (BuildUtils.isWeb) MailboxActions.openInNewTab, if (mailbox.isSpam) _mailboxActionForSpam(), MailboxActions.markAsRead, MailboxActions.move, MailboxActions.rename, MailboxActions.delete, MailboxActions.disableMailbox ]; } void _openMailboxMenuAction( BuildContext context, PresentationMailbox mailbox, {RelativeRect? position} ) { final mailboxActionsSupported = mailbox.isSubscribed?.value == true ? _listActionForMailboxSubscribed(mailbox) : _listActionForMailboxUnsubscribed(); final listContextMenuItemAction = mailboxActionsSupported .map((action) => ContextMenuItemMailboxAction(action, action.getContextMenuItemState(mailbox))) .toList(); if (controller.responsiveUtils.isScreenWithShortestSide(context) || position == null) { controller.openContextMenuAction( context, _bottomSheetMailboxActionTiles( context, mailbox, listContextMenuItemAction ) ); } else { controller.openPopupMenuAction( context, position, _popupMenuMailboxActionTiles( context, mailbox, listContextMenuItemAction ) ); } } List _bottomSheetMailboxActionTiles( BuildContext context, PresentationMailbox mailbox, List 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), width: 24, height: 24, 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 _popupMenuMailboxActionTiles( BuildContext context, PresentationMailbox mailbox, List 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(), iconSize: 24, styleName: TextStyle( fontWeight: FontWeight.w500, fontSize: 16, color: contextMenuItem.action.getColorContextMenuTitle() ), onCallbackAction: () => controller.handleMailboxAction(context, contextMenuItem.action, mailbox)) , ) ) ); } }