TF-524 Create RecentSearchCache and TypeAHeadQuickSearch widget

This commit is contained in:
dab246
2022-05-23 18:48:29 +07:00
committed by Dat H. Pham
parent 5ca238153a
commit 3513c363ff
23 changed files with 2349 additions and 127 deletions
@@ -1,21 +1,24 @@
import 'package:core/core.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:flutter_typeahead/flutter_typeahead.dart';
import 'package:get/get.dart';
import 'package:model/model.dart';
import 'package:tmail_ui_user/features/base/mixin/network_connection_mixin.dart';
import 'package:tmail_ui_user/features/composer/presentation/composer_view_web.dart';
import 'package:tmail_ui_user/features/email/presentation/email_view.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/mailbox_view_web.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/model/recent_search.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/action/dashboard_action.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mailbox_dashboard_controller.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mixin/filter_email_popup_menu_mixin.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mixin/user_setting_popup_menu_mixin.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/email_quick_search_item_tile_widget.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/recent_search_item_tile_widget.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/model/app_setting.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/model/reading_pane.dart';
import 'package:tmail_ui_user/features/thread/presentation/extensions/filter_message_option_extension.dart';
import 'package:tmail_ui_user/features/thread/presentation/thread_view.dart';
import 'package:tmail_ui_user/features/thread/presentation/widgets/search_app_bar_widget.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
import 'package:tmail_ui_user/main/routes/app_routes.dart';
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
@@ -157,7 +160,9 @@ class MailboxDashBoardView extends GetWidget<MailboxDashBoardController> with Ne
}),
const SizedBox(width: 16),
Obx(() => !controller.isSearchActive() ? const Spacer() : const SizedBox.shrink()),
Obx(() => controller.isSearchActive() ? Expanded(child: _buildSearchForm(context)) : const SizedBox.shrink()),
Obx(() => controller.isSearchActive()
? Expanded(child: _buildSearchForm(context))
: const SizedBox.shrink()),
Obx(() => !controller.isSearchActive()
? (SearchBarView(_imagePaths)
..hintTextSearch(AppLocalizations.of(context).search_emails)
@@ -396,24 +401,119 @@ class MailboxDashBoardView extends GetWidget<MailboxDashBoardController> with Ne
}
Widget _buildSearchForm(BuildContext context) {
return (SearchAppBarWidget(context, _imagePaths, _responsiveUtils,
controller.searchQuery,
controller.searchFocus,
controller.searchInputController,
suggestionSearch: controller.suggestionSearch)
..addDecoration(const BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(10)),
color: AppColor.colorBgSearchBar))
..setMargin(const EdgeInsets.only(right: 10))
..setHeightSearchBar(45)
..setHintText(AppLocalizations.of(context).search_mail)
..addOnCancelSearchPressed(() {
controller.disableSearch();
controller.dispatchAction(CancelSelectionAllEmailAction());
})
..addOnClearTextSearchAction(() => controller.clearSearchText())
..addOnTextChangeSearchAction((query) => controller.addSuggestionSearch(query))
..addOnSearchTextAction((query) => controller.searchEmail(context, query)))
.build();
return Row(
children: [
buildIconWeb(
icon: SvgPicture.asset(_imagePaths.icBack, color: AppColor.colorTextButton, fit: BoxFit.fill),
onTap: () {
controller.disableSearch();
controller.dispatchAction(CancelSelectionAllEmailAction());
}),
Expanded(child: Container(
decoration: const BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(10)),
color: AppColor.colorBgSearchBar),
height: 45,
child: TypeAheadFormFieldQuickSearch<PresentationEmail, RecentSearch>(
textFieldConfiguration: QuickSearchTextFieldConfiguration(
controller: controller.searchInputController,
autofocus: true,
focusNode: controller.searchFocus,
textInputAction: TextInputAction.done,
decoration: InputDecoration(
border: InputBorder.none,
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
contentPadding: EdgeInsets.zero,
hintText: AppLocalizations.of(context).search_mail,
hintStyle: const TextStyle(color: AppColor.colorHintSearchBar, fontSize: 17.0),
labelStyle: const TextStyle(color: AppColor.colorHintSearchBar, fontSize: 17.0)
),
leftButton: buildIconWeb(
icon: SvgPicture.asset(_imagePaths.icSearchBar, width: 16, height: 16, fit: BoxFit.fill),
onTap: () => {}),
rightButton: buildIconWeb(
icon: SvgPicture.asset(_imagePaths.icComposerClose, width: 18, height: 18, fit: BoxFit.fill),
onTap: () {
controller.searchInputController.clear();
controller.clearSearchText();
})
),
suggestionsBoxDecoration: QuickSearchSuggestionsBoxDecoration(
color: Colors.white,
borderRadius: const BorderRadius.all(Radius.circular(16)),
constraints: BoxConstraints(
maxWidth: _responsiveUtils.isDesktop(context) ? 556 : double.infinity,
maxHeight: 322),
),
actionButton: Padding(
padding: const EdgeInsets.only(left: 24, top: 24, right: 24, bottom: 20),
child: Row(
children: [
(ButtonBuilder(_imagePaths.icAttachmentSB)
..decoration(BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: AppColor.colorButtonHeaderThread))
..paddingIcon(const EdgeInsets.only(right: 5))
..padding(const EdgeInsets.symmetric(horizontal: 12, vertical: 8))
..radiusSplash(10)
..size(16)
..textStyle(const TextStyle(fontSize: 13, color: AppColor.colorTextButtonHeaderThread))
..onPressActionClick(() => {})
..text(AppLocalizations.of(context).hasAttachment, isVertical: false))
.build(),
const SizedBox(width: 8),
(ButtonBuilder(_imagePaths.icCalendarSB)
..decoration(BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: AppColor.colorButtonHeaderThread))
..paddingIcon(const EdgeInsets.only(right: 5))
..padding(const EdgeInsets.symmetric(horizontal: 12, vertical: 8))
..radiusSplash(10)
..size(16)
..textStyle(const TextStyle(fontSize: 13, color: AppColor.colorTextButtonHeaderThread))
..onPressActionClick(() => {})
..text(AppLocalizations.of(context).last7Days, isVertical: false))
.build(),
const SizedBox(width: 8),
(ButtonBuilder(_imagePaths.icUserSB)
..decoration(BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: AppColor.colorButtonHeaderThread))
..paddingIcon(const EdgeInsets.only(right: 5))
..padding(const EdgeInsets.symmetric(horizontal: 12, vertical: 8))
..radiusSplash(10)
..size(16)
..textStyle(const TextStyle(fontSize: 13, color: AppColor.colorTextButtonHeaderThread))
..onPressActionClick(() => {})
..text(AppLocalizations.of(context).fromMe, isVertical: false))
.build(),
],
),
),
titleHeaderRecent: Padding(
padding: const EdgeInsets.only(left: 24, right: 24, bottom: 8),
child: Text(AppLocalizations.of(context).recent,
style: const TextStyle(fontSize: 13.0,
color: AppColor.colorTextButtonHeaderThread,
fontWeight: FontWeight.w500))),
getRecentCallback: (pattern) async {
return [];
},
itemRecentBuilder: (context, recent) {
return RecentSearchItemTileWidget(recent);
},
suggestionsCallback: (pattern) async {
return [];
},
itemBuilder: (context, email) {
return EmailQuickSearchItemTileWidget(email, controller.selectedMailbox.value);
},
onSuggestionSelected: (autoCompleteResult) async {
}),
)),
const SizedBox(width: 16),
]
);
}
}
@@ -0,0 +1,92 @@
import 'package:core/core.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart';
import 'package:model/email/presentation_email.dart';
import 'package:model/extensions/presentation_email_extension.dart';
import 'package:model/mailbox/presentation_mailbox.dart';
class EmailQuickSearchItemTileWidget extends StatelessWidget {
final imagePath = Get.find<ImagePaths>();
final PresentationEmail _presentationEmail;
final PresentationMailbox? _presentationMailbox;
EmailQuickSearchItemTileWidget(
this._presentationEmail,
this._presentationMailbox,
{Key? key}
) : super(key: key);
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SvgPicture.asset(
_presentationEmail.hasStarred ? imagePath.icStar : imagePath.icUnStar,
width: 20, height: 20, fit: BoxFit.fill),
const SizedBox(width: 8),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(mainAxisAlignment: MainAxisAlignment.center, children: [
Text(_getInformationSender(),
maxLines: 1,
overflow: BuildUtils.isWeb ? null : TextOverflow.ellipsis,
style: const TextStyle(
fontSize: 15,
fontWeight: FontWeight.w600,
color: Colors.black)),
const SizedBox(width: 16),
Expanded(
child: Text(_presentationEmail.getEmailTitle(),
maxLines: 1,
overflow: BuildUtils.isWeb ? null : TextOverflow.ellipsis,
style: const TextStyle(
fontSize: 13,
fontWeight: FontWeight.normal,
color: Colors.black)),
),
if (_presentationEmail.hasAttachment == true)
Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: SvgPicture.asset(imagePath.icAttachment, width: 14, height: 14, fit: BoxFit.fill),
),
Text(_presentationEmail.getReceivedAt(Localizations.localeOf(context).toLanguageTag()),
textAlign: TextAlign.right,
style: const TextStyle(
fontSize: 13,
fontWeight: FontWeight.normal,
color: Colors.black))
]),
const SizedBox(height: 3),
Text(_presentationEmail.getPartialContent(),
maxLines: 1,
overflow: BuildUtils.isWeb ? null : TextOverflow.ellipsis,
style: const TextStyle(
fontSize: 13,
fontWeight: FontWeight.normal,
color: AppColor.colorContentEmail))
]
),
),
],
),
);
}
String _getInformationSender() {
if (_presentationMailbox?.role == PresentationMailbox.roleSent
|| _presentationMailbox?.role == PresentationMailbox.roleDrafts
|| _presentationMailbox?.role == PresentationMailbox.roleOutbox) {
return _presentationEmail.recipientsName();
}
return _presentationEmail.getSenderName();
}
}
@@ -0,0 +1,35 @@
import 'package:core/core.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/model/recent_search.dart';
class RecentSearchItemTileWidget extends StatelessWidget {
final imagePath = Get.find<ImagePaths>();
final RecentSearch recentSearch;
RecentSearchItemTileWidget(this.recentSearch, {Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 10),
child: Row(
children: [
SvgPicture.asset(imagePath.icClockSB),
const SizedBox(width: 8),
Expanded(
child: Text(recentSearch.value,
style: const TextStyle(
fontSize: 15,
fontWeight: FontWeight.normal,
color: Colors.black)),
),
],
),
);
}
}