diff --git a/core/lib/presentation/views/search/search_bar_view.dart b/core/lib/presentation/views/search/search_bar_view.dart index 38b2b1dc2..9b2ff5867 100644 --- a/core/lib/presentation/views/search/search_bar_view.dart +++ b/core/lib/presentation/views/search/search_bar_view.dart @@ -47,7 +47,7 @@ class SearchBarView { Widget build() { return Container( key: Key('search_bar_widget'), - alignment: Alignment.topCenter, + alignment: Alignment.center, height: _heightSearchBar ?? 40, width: _maxSizeWidth ?? double.infinity, decoration: BoxDecoration( @@ -58,24 +58,23 @@ class SearchBarView { child: InkWell( onTap: () => _onOpenSearchViewAction?.call(), borderRadius: BorderRadius.all(Radius.circular(10)), - child: MediaQuery( - data: MediaQueryData(padding: EdgeInsets.zero), child: Row( - crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, children: [ + SizedBox(width: 8), buildIconWeb( - splashRadius: 12, + splashRadius: 15, + minSize: 40, + iconPadding: EdgeInsets.zero, icon: SvgPicture.asset(_imagePaths.icSearchBar, width: 16, height: 16, fit: BoxFit.fill), onTap: () => _onOpenSearchViewAction?.call()), Expanded(child: - Transform(transform: Matrix4.translationValues(-5, 0.0, 0.0), - child: Text( + Text( _hintTextSearch ?? '', maxLines: 1, - style: TextStyle(fontSize: kIsWeb ? 15 : 17, color: AppColor.colorHintSearchBar)))) + style: TextStyle(fontSize: kIsWeb ? 15 : 17, color: AppColor.colorHintSearchBar))) ] - ) - )), + )), ); } } \ No newline at end of file diff --git a/lib/features/destination_picker/presentation/destination_picker_view.dart b/lib/features/destination_picker/presentation/destination_picker_view.dart index 3d374b686..9bc4bfa3f 100644 --- a/lib/features/destination_picker/presentation/destination_picker_view.dart +++ b/lib/features/destination_picker/presentation/destination_picker_view.dart @@ -283,7 +283,9 @@ class DestinationPickerView extends GetWidget { primary: false, itemBuilder: (context, index) => Obx(() => (MailboxSearchTileBuilder( + context, _imagePaths, + _responsiveUtils, controller.listMailboxSearched[index], lastMailbox: controller.listMailboxSearched.last) ..addOnOpenMailboxAction((mailbox) => controller.selectMailboxAction(mailbox))) @@ -347,7 +349,8 @@ class DestinationPickerView extends GetWidget { Padding(padding: const EdgeInsets.only(left: 5), child: buildIconWeb( icon: SvgPicture.asset(_imagePaths.icBack, color: AppColor.colorTextButton, fit: BoxFit.fill), onTap: () => controller.disableSearch(context))), - Expanded(child: (SearchAppBarWidget(context, _imagePaths, _responsiveUtils, + Expanded(child: (SearchAppBarWidget( + _imagePaths, controller.searchQuery.value, controller.searchFocus, controller.searchInputController, diff --git a/lib/features/mailbox/presentation/mailbox_view.dart b/lib/features/mailbox/presentation/mailbox_view.dart index 6f7bb06c9..43c32e3c2 100644 --- a/lib/features/mailbox/presentation/mailbox_view.dart +++ b/lib/features/mailbox/presentation/mailbox_view.dart @@ -364,9 +364,7 @@ class MailboxView extends GetWidget { children: [ _buildBackSearchButton(context), Expanded(child: (SearchAppBarWidget( - context, _imagePaths, - _responsiveUtils, controller.searchQuery.value, controller.searchFocus, controller.searchInputController, @@ -411,7 +409,9 @@ class MailboxView extends GetWidget { primary: false, itemBuilder: (context, index) => Obx(() => (MailboxSearchTileBuilder( + context, _imagePaths, + _responsiveUtils, controller.listMailboxSearched[index], allSelectMode: controller.currentSelectMode.value, lastMailbox: controller.listMailboxSearched.last) diff --git a/lib/features/mailbox/presentation/mailbox_view_web.dart b/lib/features/mailbox/presentation/mailbox_view_web.dart index a38787bda..c83546e38 100644 --- a/lib/features/mailbox/presentation/mailbox_view_web.dart +++ b/lib/features/mailbox/presentation/mailbox_view_web.dart @@ -179,8 +179,11 @@ class MailboxView extends GetWidget with AppLoaderMixin, Popu Row(children: [ Expanded(child: _buildSearchBarWidget(context)), Padding( - padding: const EdgeInsets.only(right: 8), + padding: EdgeInsets.only(right: _responsiveUtils.isDesktop(context) ? 0 : 12), child: buildIconWeb( + minSize: 40, + iconPadding: EdgeInsets.zero, + splashRadius: 15, icon: SvgPicture.asset(_imagePaths.icAddNewFolder, color: AppColor.colorTextButton, fit: BoxFit.fill), tooltip: AppLocalizations.of(context).new_mailbox, onTap: () => controller.goToCreateNewMailboxView())), @@ -294,23 +297,39 @@ class MailboxView extends GetWidget with AppLoaderMixin, Popu Widget _buildInputSearchFormWidget(BuildContext context) { return Padding( padding: const EdgeInsets.only(top: 16), - child: Row( - children: [ - buildIconWeb( - icon: SvgPicture.asset(_imagePaths.icBack, color: AppColor.colorTextButton, fit: BoxFit.fill), - onTap: () => controller.disableSearch(context)), - Expanded(child: (SearchAppBarWidget(context, _imagePaths, _responsiveUtils, controller.searchQuery.value, - controller.searchFocus, controller.searchInputController, hasBackButton: false, hasSearchButton: true) - ..addPadding(EdgeInsets.zero) - ..setMargin(const EdgeInsets.only(right: 16)) - ..addDecoration(BoxDecoration(borderRadius: BorderRadius.circular(12), color: AppColor.colorBgSearchBar)) - ..addIconClearText(SvgPicture.asset(_imagePaths.icClearTextSearch, width: 16, height: 16, fit: BoxFit.fill)) - ..setHintText(AppLocalizations.of(context).hint_search_mailboxes) - ..addOnClearTextSearchAction(() => controller.clearSearchText()) - ..addOnTextChangeSearchAction((query) => controller.searchMailbox(query)) - ..addOnSearchTextAction((query) => controller.searchMailbox(query))) - .build()) - ] + child: Transform( + transform: Matrix4.translationValues( + _responsiveUtils.isDesktop(context) ? -10.0 : 0.0, + 0.0, + 0.0), + child: Row( + children: [ + if (!_responsiveUtils.isDesktop(context)) + const SizedBox(width: 10), + buildIconWeb( + iconPadding: EdgeInsets.zero, + minSize: 40, + splashRadius: 15, + icon: SvgPicture.asset(_imagePaths.icBack, color: AppColor.colorTextButton), + onTap: () => controller.disableSearch(context)), + Expanded(child: (SearchAppBarWidget( + _imagePaths, + controller.searchQuery.value, + controller.searchFocus, + controller.searchInputController, + hasBackButton: false, + hasSearchButton: true) + ..addPadding(EdgeInsets.zero) + ..setMargin(EdgeInsets.only(right: _responsiveUtils.isDesktop(context) ? 8 : 16)) + ..addDecoration(BoxDecoration(borderRadius: BorderRadius.circular(12), color: AppColor.colorBgSearchBar)) + ..addIconClearText(SvgPicture.asset(_imagePaths.icClearTextSearch, width: 16, height: 16, fit: BoxFit.fill)) + ..setHintText(AppLocalizations.of(context).hint_search_mailboxes) + ..addOnClearTextSearchAction(() => controller.clearSearchText()) + ..addOnTextChangeSearchAction((query) => controller.searchMailbox(query)) + ..addOnSearchTextAction((query) => controller.searchMailbox(query))) + .build()) + ] + ), ) ); } @@ -320,17 +339,24 @@ class MailboxView extends GetWidget with AppLoaderMixin, Popu margin: EdgeInsets.zero, color: _responsiveUtils.isDesktop(context) ? AppColor.colorBgDesktop : Colors.white, child: ListView.builder( - padding: const EdgeInsets.only(right: 16), + padding: EdgeInsets.only( + right: 16, + left: _responsiveUtils.isDesktop(context) ? 0 : 16, + bottom: 16, + top: _responsiveUtils.isDesktop(context) ? 0 : 16), key: const Key('list_mailbox_searched'), itemCount: listMailbox.length, shrinkWrap: true, primary: false, itemBuilder: (context, index) => Obx(() => (MailboxSearchTileBuilder( + context, _imagePaths, + _responsiveUtils, listMailbox[index], lastMailbox: controller.listMailboxSearched.last) ..addOnOpenMailboxAction((mailbox) => controller.openMailbox(context, mailbox)) + ..addOnMenuActionClick((position, mailbox) => _openMailboxMenuAction(context, position, mailbox)) ..addOnSelectMailboxActionClick((mailbox) => controller.selectMailboxSearched(context, mailbox))) .build())) ); diff --git a/lib/features/mailbox/presentation/widgets/mailbox_folder_tile_builder.dart b/lib/features/mailbox/presentation/widgets/mailbox_folder_tile_builder.dart index 7f3045cef..25850e71c 100644 --- a/lib/features/mailbox/presentation/widgets/mailbox_folder_tile_builder.dart +++ b/lib/features/mailbox/presentation/widgets/mailbox_folder_tile_builder.dart @@ -61,6 +61,15 @@ class MailBoxFolderTileBuilder { } Widget build() { + return Theme( + data: ThemeData( + splashColor: Colors.transparent, + highlightColor: Colors.transparent), + child: _buildMailboxItem() + ); + } + + Widget _buildMailboxItem() { if (BuildUtils.isWeb) { if (mailboxDisplayed == MailboxDisplayed.mailbox) { return StatefulBuilder( diff --git a/lib/features/mailbox/presentation/widgets/mailbox_search_tile_builder.dart b/lib/features/mailbox/presentation/widgets/mailbox_search_tile_builder.dart index 76edce3da..f981a1dcb 100644 --- a/lib/features/mailbox/presentation/widgets/mailbox_search_tile_builder.dart +++ b/lib/features/mailbox/presentation/widgets/mailbox_search_tile_builder.dart @@ -1,5 +1,4 @@ import 'package:core/core.dart'; -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:model/model.dart'; @@ -7,6 +6,7 @@ import 'package:tmail_ui_user/features/mailbox/domain/extensions/presentation_ma typedef OnOpenMailboxActionClick = void Function(PresentationMailbox); typedef OnSelectMailboxActionClick = void Function(PresentationMailbox); +typedef OnOpenMenuActionClick = void Function(RelativeRect, PresentationMailbox); class MailboxSearchTileBuilder { @@ -14,14 +14,19 @@ class MailboxSearchTileBuilder { final PresentationMailbox? lastMailbox; final SelectMode allSelectMode; final ImagePaths _imagePaths; + final ResponsiveUtils _responsiveUtils; + final BuildContext _context; - bool isHoverIcon = false; + bool isHoverItem = false; OnOpenMailboxActionClick? _onOpenMailboxActionClick; OnSelectMailboxActionClick? _onSelectMailboxActionClick; + OnOpenMenuActionClick? _onMenuActionClick; MailboxSearchTileBuilder( + this._context, this._imagePaths, + this._responsiveUtils, this._presentationMailbox, { this.allSelectMode = SelectMode.INACTIVE, @@ -37,96 +42,155 @@ class MailboxSearchTileBuilder { _onSelectMailboxActionClick = onSelectMailboxActionClick; } + void addOnMenuActionClick(OnOpenMenuActionClick onOpenMenuActionClick) { + _onMenuActionClick = onOpenMenuActionClick; + } + Widget build() { return Theme( data: ThemeData( splashColor: Colors.transparent, highlightColor: Colors.transparent), - child: Container( - key: const Key('mailbox_list_tile'), - alignment: Alignment.center, - child: MediaQuery( - data: const MediaQueryData(padding: EdgeInsets.zero), - child: Column(children: [ - ListTile( - contentPadding: EdgeInsets.zero, - onTap: () => allSelectMode == SelectMode.ACTIVE - ? _onSelectMailboxActionClick?.call(_presentationMailbox) - : _onOpenMailboxActionClick?.call(_presentationMailbox), - leading: _buildLeadingIcon(), - title: Row(children: [ - if (allSelectMode == SelectMode.ACTIVE) - Transform( - transform: Matrix4.translationValues(-24.0, 0.0, 0.0), - child: _buildMailboxIcon()), - Expanded(child: Transform( - transform: Matrix4.translationValues(allSelectMode == SelectMode.ACTIVE ? -16.0 : -20.0, 0.0, 0.0), - child: Text( - _presentationMailbox.name?.name ?? '', - maxLines: 1, - overflow:TextOverflow.ellipsis, - style: const TextStyle(fontSize: 17, color: AppColor.colorNameEmail, fontWeight: FontWeight.normal), - ))), - ]), - subtitle: _presentationMailbox.mailboxPath?.isNotEmpty == true - ? Transform( - transform: Matrix4.translationValues(allSelectMode == SelectMode.ACTIVE ? 12.0 : -20.0, 0.0, 0.0), - child: Text( - _presentationMailbox.mailboxPath ?? '', - maxLines: 1, - overflow:TextOverflow.ellipsis, - style: const TextStyle(fontSize: 13, color: AppColor.colorContentEmail), - ), - ) - : null, - ), - if (lastMailbox?.id != _presentationMailbox.id && !kIsWeb) - Padding( - padding: EdgeInsets.only(left: allSelectMode == SelectMode.ACTIVE ? 50 : 35), - child: const Divider(color: AppColor.lineItemListColor, height: 0.5, thickness: 0.2)), - ]), - ) - ) + child: _buildMailboxItem() ); } + Widget _buildMailboxItem() { + if (BuildUtils.isWeb) { + return StatefulBuilder( + builder: (BuildContext context, StateSetter setState) { + return InkWell( + onTap: () {}, + onHover: (value) => setState(() => isHoverItem = value), + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: backgroundColorItem), + child: ListTile( + contentPadding: const EdgeInsets.only(left: 8), + onTap: () => _onOpenMailboxActionClick?.call(_presentationMailbox), + leading: _buildLeadingIcon(), + title: _buildTitleItem(), + subtitle: _buildSubtitleItem(), + trailing: _buildMenuIcon(), + ), + ) + ); + }); + } else { + return Column(children: [ + ListTile( + contentPadding: EdgeInsets.zero, + onTap: () => allSelectMode == SelectMode.ACTIVE + ? _onSelectMailboxActionClick?.call(_presentationMailbox) + : _onOpenMailboxActionClick?.call(_presentationMailbox), + leading: _buildLeadingIcon(), + title: _buildTitleItem(), + subtitle: _buildSubtitleItem(), + ), + if (lastMailbox?.id != _presentationMailbox.id) + Padding( + padding: EdgeInsets.only(left: allSelectMode == SelectMode.ACTIVE ? 50 : 35), + child: const Divider(color: AppColor.lineItemListColor, height: 0.5, thickness: 0.2)), + ]); + } + } + Widget _buildLeadingIcon() { - if (kIsWeb) { - return _presentationMailbox.selectMode == SelectMode.ACTIVE ? _buildSelectModeIcon() : _buildMailboxIcon(); + if (BuildUtils.isWeb) { + return _buildMailboxIcon(); } else { return allSelectMode == SelectMode.ACTIVE ? _buildSelectModeIcon() : _buildMailboxIcon(); } } Widget _buildMailboxIcon() { - if (kIsWeb) { - return StatefulBuilder( - builder: (BuildContext context, StateSetter setState) { - return InkWell( - onTap: () {}, - onHover: (value) => setState(() => isHoverIcon = value), - child: isHoverIcon - ? _buildSelectModeIcon() - : SvgPicture.asset(_presentationMailbox.getMailboxIcon(_imagePaths), width: 28, height: 28, fit: BoxFit.fill) - ); - }); - } else { - return SvgPicture.asset(_presentationMailbox.getMailboxIcon(_imagePaths), width: 28, height: 28, fit: BoxFit.fill); - } + return SvgPicture.asset(_presentationMailbox.getMailboxIcon(_imagePaths), + width: BuildUtils.isWeb ? 20 : 24, + height: BuildUtils.isWeb ? 20 : 24, + fit: BoxFit.fill); } Widget _buildSelectModeIcon() { return Container( color: Colors.transparent, child: Transform( - transform: Matrix4.translationValues(kIsWeb ? -8.0 : -10.0, 0.0, 0.0), + transform: Matrix4.translationValues(BuildUtils.isWeb ? -8.0 : -10.0, 0.0, 0.0), child: buildIconWeb( icon: SvgPicture.asset( _presentationMailbox.selectMode == SelectMode.ACTIVE ? _imagePaths.icSelected : _imagePaths.icUnSelected, - width: kIsWeb ? 20 : 24, - height: kIsWeb ? 20 : 24, + width: BuildUtils.isWeb ? 20 : 24, + height: BuildUtils.isWeb ? 20 : 24, fit: BoxFit.fill), onTap: () => _onSelectMailboxActionClick?.call(_presentationMailbox))), ); } + + Widget _buildTitleItem() { + return Row(children: [ + if (allSelectMode == SelectMode.ACTIVE) + Transform( + transform: Matrix4.translationValues(-24.0, 0.0, 0.0), + child: _buildMailboxIcon()), + Expanded(child: Transform( + transform: Matrix4.translationValues(allSelectMode == SelectMode.ACTIVE ? -16.0 : -20.0, 0.0, 0.0), + child: Text( + _presentationMailbox.name?.name ?? '', + maxLines: 1, + overflow:TextOverflow.ellipsis, + style: const TextStyle(fontSize: 17, color: AppColor.colorNameEmail, fontWeight: FontWeight.normal), + ))), + ]); + } + + Widget? _buildSubtitleItem() { + if (_presentationMailbox.mailboxPath?.isNotEmpty == true) { + return Transform( + transform: Matrix4.translationValues(allSelectMode == SelectMode.ACTIVE ? 12.0 : -20.0, 0.0, 0.0), + child: Text( + _presentationMailbox.mailboxPath ?? '', + maxLines: 1, + overflow:TextOverflow.ellipsis, + style: const TextStyle(fontSize: 13, color: AppColor.colorContentEmail), + ), + ); + } + return null; + } + + Widget? _buildMenuIcon() { + if (isHoverItem) { + return Padding( + padding: const EdgeInsets.only(right: 8), + child: 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, + ); + _onMenuActionClick?.call(position, _presentationMailbox); + }, + onTap: () => {}, + child: SvgPicture.asset(_imagePaths.icComposerMenu, + width: 20, + height: 20, + fit: BoxFit.fill)), + ); + } + return null; + } + + Color get backgroundColorItem { + if (isHoverItem) { + return AppColor.colorBgMailboxSelected; + } else { + return _responsiveUtils.isDesktop(_context) + ? AppColor.colorBgDesktop + : Colors.white; + } + } } \ No newline at end of file diff --git a/lib/features/thread/presentation/widgets/search_app_bar_widget.dart b/lib/features/thread/presentation/widgets/search_app_bar_widget.dart index 3e4b30e9b..b5c4709d3 100644 --- a/lib/features/thread/presentation/widgets/search_app_bar_widget.dart +++ b/lib/features/thread/presentation/widgets/search_app_bar_widget.dart @@ -15,9 +15,7 @@ class SearchAppBarWidget { OnClearTextSearchAction? _onClearTextSearchAction; OnSearchTextAction? _onSearchTextAction; - final BuildContext _context; final ImagePaths _imagePaths; - final ResponsiveUtils _responsiveUtils; final SearchQuery? _searchQuery; final TextEditingController? _searchInputController; final FocusNode? _searchFocusNode; @@ -33,9 +31,7 @@ class SearchAppBarWidget { Widget? _iconClearText; SearchAppBarWidget( - this._context, this._imagePaths, - this._responsiveUtils, this._searchQuery, this._searchFocusNode, this._searchInputController, @@ -93,20 +89,15 @@ class SearchAppBarWidget { decoration: _decoration, padding: _padding ?? EdgeInsets.zero, margin: _margin, - child: MediaQuery( - data: const MediaQueryData(padding: EdgeInsets.zero), - child: Row( - children: [ - if (hasBackButton) _buildBackButton(), - if (hasSearchButton) _buildSearchButton(), - Expanded(child: Transform( - transform: Matrix4.translationValues(0.0, _responsiveUtils.isDesktop(_context) ? -2.0 : 0.0, 0.0), - child: _buildSearchInputForm(), - )), - if (suggestionSearch?.isNotEmpty == true || (_searchQuery != null && _searchQuery!.value.isNotEmpty)) - _buildClearTextSearchButton(), - ] - ) + child: Row( + children: [ + if (hasBackButton) _buildBackButton(), + if (hasSearchButton) _buildSearchButton(), + Expanded(child: _buildSearchInputForm()), + if (suggestionSearch?.isNotEmpty == true + || (_searchQuery != null && _searchQuery!.value.isNotEmpty)) + _buildClearTextSearchButton(), + ] ) ); }