TF-3761 Update search bar for search mailbox in left menu

Signed-off-by: dab246 <tdvu@linagora.com>
This commit is contained in:
dab246
2025-06-02 03:29:07 +07:00
committed by Dat H. Pham
parent 34cc7abe9b
commit b625894c39
5 changed files with 71 additions and 120 deletions
@@ -162,7 +162,7 @@ extension AppColor on Color {
static const colorSpamReportBannerLabelColor = Color(0xFF626D7A); static const colorSpamReportBannerLabelColor = Color(0xFF626D7A);
static const colorSpamReportBannerButtonBackground = Color(0xFFEBEDF0); static const colorSpamReportBannerButtonBackground = Color(0xFFEBEDF0);
static const colorSubtitle = Color(0xFF6D7885); static const colorSubtitle = Color(0xFF6D7885);
static const colorBackgroundSearchMailboxInput = Color(0xFFEBEDF0); static const searchInputBackground = Color(0xFFE0E9F1);
static const colorMailboxHovered = Color(0xFFEBEDF0); static const colorMailboxHovered = Color(0xFFEBEDF0);
static const colorMailboxPath = Color(0xFF818C99); static const colorMailboxPath = Color(0xFF818C99);
static const colorIconUnSubscribedMailbox = Color(0xFFAEB7C2); static const colorIconUnSubscribedMailbox = Color(0xFFAEB7C2);
@@ -660,7 +660,7 @@ class _TypeAheadFieldQuickSearchState<T, P, R>
) )
: const BoxDecoration( : const BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(12)), borderRadius: BorderRadius.all(Radius.circular(12)),
color: AppColor.colorBgDesktop, color: AppColor.searchInputBackground,
), ),
height: widget.maxHeight, height: widget.maxHeight,
child: Row( child: Row(
@@ -3,6 +3,7 @@ import 'package:core/presentation/extensions/color_extension.dart';
import 'package:core/presentation/resources/image_paths.dart'; import 'package:core/presentation/resources/image_paths.dart';
import 'package:core/presentation/utils/responsive_utils.dart'; import 'package:core/presentation/utils/responsive_utils.dart';
import 'package:core/presentation/views/button/icon_button_web.dart'; import 'package:core/presentation/views/button/icon_button_web.dart';
import 'package:core/presentation/views/button/tmail_button_widget.dart';
import 'package:core/presentation/views/quick_search/quick_search_input_form.dart'; import 'package:core/presentation/views/quick_search/quick_search_input_form.dart';
import 'package:core/presentation/views/quick_search/quick_search_suggestion_box_decoration.dart'; import 'package:core/presentation/views/quick_search/quick_search_suggestion_box_decoration.dart';
import 'package:core/presentation/views/quick_search/quick_search_suggestion_list.dart'; import 'package:core/presentation/views/quick_search/quick_search_suggestion_list.dart';
@@ -221,12 +222,15 @@ class SearchInputFormWidget extends StatelessWidget with AppLoaderMixin {
labelStyle: const TextStyle(color: Colors.black, fontSize: 16.0) labelStyle: const TextStyle(color: Colors.black, fontSize: 16.0)
), ),
leftButton: Padding( leftButton: Padding(
padding: const EdgeInsetsDirectional.only(start: 8), padding: const EdgeInsetsDirectional.symmetric(horizontal: 12),
child: buildIconWeb( child: TMailButtonWidget.fromIcon(
minSize: 40, icon: _imagePaths.icSearchBar,
iconPadding: EdgeInsets.zero, iconColor: AppColor.steelGray400,
icon: SvgPicture.asset(_imagePaths.icSearchBar, fit: BoxFit.fill), iconSize: 28,
onTap: () => _invokeSearchEmailAction(_searchController.searchInputController.text.trim()) backgroundColor: Colors.transparent,
padding: const EdgeInsets.all(4),
tooltipMessage: AppLocalizations.of(context).search,
onTapActionCallback: () => _invokeSearchEmailAction(_searchController.searchInputController.text.trim())
) )
), ),
clearTextButton: buildIconWeb( clearTextButton: buildIconWeb(
@@ -234,6 +238,7 @@ class SearchInputFormWidget extends StatelessWidget with AppLoaderMixin {
_imagePaths.icClearTextSearch, _imagePaths.icClearTextSearch,
width: 16, width: 16,
height: 16, height: 16,
colorFilter: AppColor.steelGray400.asFilter(),
fit: BoxFit.fill fit: BoxFit.fill
), ),
onTap: _searchController.clearTextSearch onTap: _searchController.clearTextSearch
@@ -1,6 +1,7 @@
import 'package:core/presentation/extensions/color_extension.dart'; import 'package:core/presentation/extensions/color_extension.dart';
import 'package:core/presentation/views/button/icon_button_web.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/presentation/views/text/text_field_builder.dart';
import 'package:core/utils/direction_utils.dart'; import 'package:core/utils/direction_utils.dart';
import 'package:core/utils/platform_info.dart'; import 'package:core/utils/platform_info.dart';
@@ -17,7 +18,6 @@ import 'package:tmail_ui_user/features/mailbox/presentation/model/context_item_m
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_actions.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/presentation/utils/mailbox_utils.dart';
import 'package:tmail_ui_user/features/search/mailbox/presentation/search_mailbox_controller.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/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/localizations/app_localizations.dart';
@@ -45,20 +45,23 @@ class SearchMailboxView extends GetWidget<SearchMailboxController>
} }
Widget _buildSearchBody(BuildContext context) { Widget _buildSearchBody(BuildContext context) {
return Container( return ColoredBox(
color: backgroundColor ?? Colors.white, color: backgroundColor ?? Colors.white,
padding: const EdgeInsets.symmetric(horizontal: 4),
child: Column(children: [ child: Column(children: [
Container( Padding(
color: Colors.transparent, padding: const EdgeInsetsDirectional.only(
padding: SearchMailboxUtils.getPaddingAppBar(context, controller.responsiveUtils), start: 16,
child: _buildSearchInputForm(context) end: 16,
top: 12,
),
child: _buildSearchInputForm(context),
), ),
if (!controller.responsiveUtils.isWebDesktop(context))
const Divider(color: AppColor.colorDividerComposer, height: 1),
_buildLoadingView(), _buildLoadingView(),
Expanded( Expanded(
child: _buildMailboxListView(context) child: Padding(
padding: const EdgeInsets.only(top: 12),
child: _buildMailboxListView(context),
)
) )
]), ]),
); );
@@ -70,7 +73,7 @@ class SearchMailboxView extends GetWidget<SearchMailboxController>
(success) { (success) {
if (success is LoadingSearchMailbox) { if (success is LoadingSearchMailbox) {
return Padding( return Padding(
padding: const EdgeInsets.symmetric(vertical: 16), padding: const EdgeInsets.only(top: 12),
child: loadingWidget); child: loadingWidget);
} else { } else {
return const SizedBox.shrink(); return const SizedBox.shrink();
@@ -81,57 +84,50 @@ class SearchMailboxView extends GetWidget<SearchMailboxController>
Widget _buildSearchInputForm(BuildContext context) { Widget _buildSearchInputForm(BuildContext context) {
return Row(children: [ return Row(children: [
buildIconWeb( TMailButtonWidget.fromIcon(
minSize: SearchMailboxUtils.getIconSize(context, controller.responsiveUtils), icon: controller.imagePaths.icBack,
iconPadding: EdgeInsets.zero, iconColor: AppColor.steelGray400,
splashRadius: SearchMailboxUtils.getIconSplashRadius(context, controller.responsiveUtils), backgroundColor: Colors.transparent,
icon: SvgPicture.asset( width: 36,
controller.imagePaths.icBack, height: 36,
colorFilter: AppColor.colorTextButton.asFilter(), margin: const EdgeInsetsDirectional.only(end: 8),
fit: BoxFit.fill padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 14),
), tooltipMessage: AppLocalizations.of(context).back,
tooltip: AppLocalizations.of(context).back, onTapActionCallback: () => controller.closeSearchView(context),
onTap: () => controller.closeSearchView(context)
), ),
Expanded(child: Container( Expanded(child: Container(
decoration: BoxDecoration( decoration: const BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(controller.responsiveUtils.isWebDesktop(context) ? 12 : 0)), borderRadius: BorderRadius.all(Radius.circular(12)),
color: controller.responsiveUtils.isWebDesktop(context) color: AppColor.searchInputBackground
? AppColor.colorBackgroundSearchMailboxInput
: Colors.transparent
), ),
alignment: Alignment.center, alignment: Alignment.center,
child: Row(children: [ child: Row(children: [
Padding( Padding(
padding: SearchMailboxUtils.getPaddingInputSearchIcon(context, controller.responsiveUtils), padding: const EdgeInsets.symmetric(horizontal: 12),
child: buildIconWeb( child: TMailButtonWidget.fromIcon(
minSize: 40, icon: controller.imagePaths.icSearchBar,
iconPadding: EdgeInsets.zero, iconColor: AppColor.steelGray400,
icon: SvgPicture.asset( iconSize: 28,
controller.imagePaths.icSearchBar, backgroundColor: Colors.transparent,
colorFilter: AppColor.colorTextButton.asFilter(), padding: const EdgeInsets.all(4),
fit: BoxFit.fill tooltipMessage: AppLocalizations.of(context).search,
), onTapActionCallback: () =>
tooltip: AppLocalizations.of(context).search, controller.handleSearchButtonPressed(context)
onTap: () => controller.handleSearchButtonPressed(context)
), ),
), ),
Expanded(child: _buildTextFieldSearchInput(context)), Expanded(child: _buildTextFieldSearchInput(context)),
Obx(() { Obx(() {
if (controller.currentSearchQuery.isNotEmpty) { if (controller.currentSearchQuery.isNotEmpty) {
return Padding( return Padding(
padding: const EdgeInsets.only(right: 2), padding: const EdgeInsetsDirectional.only(end: 12),
child: buildIconWeb( child: TMailButtonWidget.fromIcon(
minSize: 40, icon: controller.imagePaths.icClearSearchInput,
iconPadding: EdgeInsets.zero, iconColor: AppColor.steelGray400,
icon: SvgPicture.asset( iconSize: 28,
controller.imagePaths.icClearSearchInput, padding: const EdgeInsets.all(4),
width: 24, tooltipMessage: AppLocalizations.of(context).clearAll,
height: 24, onTapActionCallback: controller.clearAllTextInputSearchForm,
fit: BoxFit.fill ),
),
tooltip: AppLocalizations.of(context).clearAll,
onTap: controller.clearAllTextInputSearchForm),
); );
} else { } else {
return const SizedBox.shrink(); return const SizedBox.shrink();
@@ -150,19 +146,21 @@ class SearchMailboxView extends GetWidget<SearchMailboxController>
maxLines: 1, maxLines: 1,
controller: controller.textInputSearchController, controller: controller.textInputSearchController,
textDirection: DirectionUtils.getDirectionByLanguage(context), textDirection: DirectionUtils.getDirectionByLanguage(context),
textStyle: const TextStyle( textStyle: ThemeUtils.textStyleBodyBody2(
color: Colors.black, color: Colors.black,
fontSize: 15, ),
fontWeight: FontWeight.normal),
keyboardType: TextInputType.text, keyboardType: TextInputType.text,
onTextSubmitted: (text) => controller.onTextSearchSubmitted(context, text), onTextSubmitted: (text) => controller.onTextSearchSubmitted(context, text),
decoration: InputDecoration( decoration: InputDecoration(
contentPadding: EdgeInsets.zero, contentPadding: const EdgeInsetsDirectional.only(
end: 12,
bottom: 14,
top: 14,
),
hintText: AppLocalizations.of(context).searchForFolders, hintText: AppLocalizations.of(context).searchForFolders,
hintStyle: const TextStyle( hintStyle: ThemeUtils.textStyleBodyBody2(
color: AppColor.loginTextFieldHintColor, color: AppColor.steelGray400,
fontSize: 15, ),
fontWeight: FontWeight.normal),
border: InputBorder.none border: InputBorder.none
), ),
); );
@@ -171,9 +169,9 @@ class SearchMailboxView extends GetWidget<SearchMailboxController>
Widget _buildMailboxListView(BuildContext context) { Widget _buildMailboxListView(BuildContext context) {
return Obx(() { return Obx(() {
return ListView.builder( return ListView.builder(
padding: SearchMailboxUtils.getPaddingListViewMailboxSearched(context, controller.responsiveUtils),
key: const Key('list_mailbox_searched'), key: const Key('list_mailbox_searched'),
itemCount: controller.listMailboxSearched.length, itemCount: controller.listMailboxSearched.length,
padding: const EdgeInsets.symmetric(horizontal: 16),
shrinkWrap: true, shrinkWrap: true,
primary: false, primary: false,
itemBuilder: (context, index) { itemBuilder: (context, index) {
@@ -2,58 +2,6 @@ import 'package:core/presentation/utils/responsive_utils.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class SearchMailboxUtils { 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: 12, vertical: 8);
} else {
return const EdgeInsets.symmetric(horizontal: 28, vertical: 8);
}
}
}
static EdgeInsets getPaddingInputSearchIcon(BuildContext context, ResponsiveUtils responsiveUtils) {
if (responsiveUtils.isWebDesktop(context)) {
return const EdgeInsets.only(left: 5, right: 2);
} else {
if (responsiveUtils.isScreenWithShortestSide(context)) {
return const EdgeInsets.only(left: 6, right: 14);
} else {
return const EdgeInsets.only(left: 8, right: 16);
}
}
}
static double getIconSize(BuildContext context, ResponsiveUtils responsiveUtils) {
if (responsiveUtils.isWebDesktop(context)) {
return 30;
} else {
return 40;
}
}
static double getIconSplashRadius(BuildContext context, ResponsiveUtils responsiveUtils) {
if (responsiveUtils.isWebDesktop(context)) {
return 10;
} else {
return 15;
}
}
static EdgeInsets getPaddingListViewMailboxSearched(BuildContext context, ResponsiveUtils responsiveUtils) {
if (responsiveUtils.isWebDesktop(context)) {
return const EdgeInsets.only(left: 16, right: 16, bottom: 16);
} else {
if (responsiveUtils.isScreenWithShortestSide(context)) {
return const EdgeInsets.all(16);
} else {
return const EdgeInsets.symmetric(horizontal: 32, vertical: 16);
}
}
}
static EdgeInsets getPaddingItemListView(BuildContext context, ResponsiveUtils responsiveUtils) { static EdgeInsets getPaddingItemListView(BuildContext context, ResponsiveUtils responsiveUtils) {
if (responsiveUtils.isWebDesktop(context)) { if (responsiveUtils.isWebDesktop(context)) {
return const EdgeInsets.all(8); return const EdgeInsets.all(8);