TF-524 Apply quick search for mobile and tablet

This commit is contained in:
dab246
2022-05-24 11:56:50 +07:00
committed by Dat H. Pham
parent 9a142a0e23
commit 11c9a8713a
30 changed files with 647 additions and 2429 deletions
@@ -1,9 +1,9 @@
import 'package:flutter/cupertino.dart';
import 'package:model/email/email_action_type.dart';
import 'package:model/email/filter_message_option.dart';
import 'package:model/email/presentation_email.dart';
import 'package:tmail_ui_user/features/base/action/ui_action.dart';
import 'package:tmail_ui_user/features/thread/domain/model/filter_message_option.dart';
import 'package:tmail_ui_user/main/routes/router_arguments.dart';
class DashBoardAction extends UIAction {
@@ -97,4 +97,12 @@ class OpenEmailDetailedAction extends DashBoardAction {
@override
List<Object?> get props => [presentationEmail];
}
class DisableSearchEmailAction extends DashBoardAction {
DisableSearchEmailAction();
@override
List<Object?> get props => [];
}
@@ -1,34 +0,0 @@
import 'package:core/core.dart';
import 'package:flutter/cupertino.dart';
import 'package:model/model.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
extension FilterMessageOptionExtension on FilterMessageOption {
String getName(BuildContext context) {
switch(this) {
case FilterMessageOption.all:
return '';
case FilterMessageOption.unread:
return AppLocalizations.of(context).unread;
case FilterMessageOption.attachments:
return AppLocalizations.of(context).with_attachments;
case FilterMessageOption.starred:
return AppLocalizations.of(context).starred;
}
}
String getIcon(ImagePaths imagePaths) {
switch(this) {
case FilterMessageOption.all:
return '';
case FilterMessageOption.unread:
return imagePaths.icUnread;
case FilterMessageOption.attachments:
return imagePaths.icAttachment;
case FilterMessageOption.starred:
return imagePaths.icStar;
}
}
}
@@ -50,6 +50,7 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/emai
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/quick_search_filter.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/model/manage_account_arguments.dart';
import 'package:tmail_ui_user/features/thread/domain/constants/thread_constants.dart';
import 'package:tmail_ui_user/features/thread/domain/model/filter_message_option.dart';
import 'package:tmail_ui_user/features/thread/domain/model/search_query.dart';
import 'package:tmail_ui_user/features/thread/domain/state/search_email_state.dart';
import 'package:tmail_ui_user/features/thread/presentation/model/search_state.dart';
@@ -82,7 +83,6 @@ class MailboxDashBoardController extends ReloadableController {
final accountId = Rxn<AccountId>();
final userProfile = Rxn<UserProfile>();
final searchState = SearchState.initial().obs;
final suggestionSearch = <String>[].obs;
final dashBoardAction = Rxn<UIAction>();
final routePath = AppRoutes.MAILBOX_DASHBOARD.obs;
final appInformation = Rxn<PackageInfo>();
@@ -286,35 +286,40 @@ class MailboxDashBoardController extends ReloadableController {
void disableSearch() {
searchState.value = searchState.value.disableSearchState();
searchQuery = SearchQuery.initial();
clearSuggestionSearch();
searchInputController.clear();
listFilterQuickSearch.clear();
emailReceiveTimeType.value = null;
FocusManager.instance.primaryFocus?.unfocus();
}
void clearSearchText() {
void clearTextSearch() {
searchQuery = SearchQuery.initial();
clearSuggestionSearch();
searchInputController.clear();
searchFocus.requestFocus();
}
void clearSuggestionSearch() {
suggestionSearch.clear();
}
void addSuggestionSearch(String query) {
if (query.trim().isNotEmpty) {
suggestionSearch.value = [query];
} else {
clearSearchText();
}
void updateTextSearch(String value) {
searchInputController.text = value;
}
void searchEmail(BuildContext context, String value) {
searchQuery = SearchQuery(value);
dispatchState(Right(SearchEmailNewQuery(searchQuery ?? SearchQuery.initial())));
clearSuggestionSearch();
FocusScope.of(context).unfocus();
if (searchInsideEmailDetailedViewIsActive(context)) {
closeEmailDetailedView();
}
}
bool searchInsideEmailDetailedViewIsActive(BuildContext context) {
return BuildUtils.isWeb
&& _responsiveUtils.isDesktop(context)
&& routePath.value == AppRoutes.EMAIL;
}
void closeEmailDetailedView() {
dispatchRoute(AppRoutes.THREAD);
clearSelectedEmail();
}
void _saveEmailAsDraftsSuccess(SaveEmailAsDraftsSuccess success) {
@@ -472,6 +477,36 @@ class MailboxDashBoardController extends ReloadableController {
emailReceiveTimeType.value = receiveTimeType;
}
bool quickSearchFilterForLast7DaysIsActive () {
return listFilterQuickSearch.contains(QuickSearchFilter.last7Days)
&& emailReceiveTimeType.value != null;
}
bool quickSearchFilterForHasAttachmentIsActive () {
return listFilterQuickSearch.contains(QuickSearchFilter.hasAttachment)
|| filterMessageOption.value == FilterMessageOption.attachments;
}
bool quickSearchFilterForFromMeIsActive () {
return listFilterQuickSearch.contains(QuickSearchFilter.fromMe);
}
bool filterForHasAttachmentIsActive () {
return quickSearchFilterForHasAttachmentIsActive() || filterMessageWithAttachmentIsActive();
}
bool filterMessageWithAttachmentIsActive () {
return filterMessageOption.value == FilterMessageOption.attachments;
}
bool filterMessageUnreadIsActive () {
return filterMessageOption.value == FilterMessageOption.unread;
}
bool filterMessageStarredIsActive () {
return filterMessageOption.value == FilterMessageOption.starred;
}
void composeEmailAction() {
if (kIsWeb) {
if (dashBoardAction.value is! ComposeEmailAction) {
@@ -1,7 +1,6 @@
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/composer/presentation/composer_view_web.dart';
@@ -15,7 +14,7 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/em
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/domain/model/filter_message_option.dart';
import 'package:tmail_ui_user/features/thread/presentation/thread_view.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
import 'package:tmail_ui_user/main/routes/app_routes.dart';
@@ -396,17 +395,17 @@ class MailboxDashBoardView extends BaseMailboxDashBoardView {
return Row(
children: [
buildIconWeb(
icon: SvgPicture.asset(imagePaths.icBack, color: AppColor.colorTextButton, fit: BoxFit.fill),
onTap: () {
controller.disableSearch();
controller.dispatchAction(CancelSelectionAllEmailAction());
}),
icon: SvgPicture.asset(
imagePaths.icBack,
color: AppColor.colorTextButton,
fit: BoxFit.fill),
onTap: () => controller.dispatchAction(DisableSearchEmailAction())),
Expanded(child: Container(
decoration: const BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(10)),
color: AppColor.colorBgSearchBar),
height: 45,
child: TypeAheadFormFieldQuickSearch<PresentationEmail, RecentSearch>(
child: QuickSearchInputForm<PresentationEmail, RecentSearch>(
textFieldConfiguration: QuickSearchTextFieldConfiguration(
controller: controller.searchInputController,
autofocus: true,
@@ -414,7 +413,7 @@ class MailboxDashBoardView extends BaseMailboxDashBoardView {
textInputAction: TextInputAction.done,
onSubmitted: (keyword) {
if (keyword.trim().isNotEmpty) {
controller.saveRecentSearch(RecentSearch(keyword, DateTime.now()));
controller.saveRecentSearch(RecentSearch.now(keyword));
}
controller.searchEmail(context, keyword);
},
@@ -424,30 +423,43 @@ class MailboxDashBoardView extends BaseMailboxDashBoardView {
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)
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),
icon: SvgPicture.asset(
imagePaths.icSearchBar,
width: 16,
height: 16,
fit: BoxFit.fill),
onTap: () {
final keyword = controller.searchInputController.text;
if (keyword.trim().isNotEmpty) {
controller.saveRecentSearch(RecentSearch(keyword, DateTime.now()));
controller.saveRecentSearch(RecentSearch.now(keyword));
}
controller.searchEmail(context, keyword);
}),
clearTextButton: buildIconWeb(
icon: SvgPicture.asset(imagePaths.icClearTextSearch, width: 16, height: 16, fit: BoxFit.fill),
icon: SvgPicture.asset(
imagePaths.icClearTextSearch,
width: 16,
height: 16,
fit: BoxFit.fill),
onTap: () {
controller.searchInputController.clear();
controller.clearSearchText();
controller.clearTextSearch();
})
),
suggestionsBoxDecoration: QuickSearchSuggestionsBoxDecoration(
color: Colors.white,
borderRadius: const BorderRadius.all(Radius.circular(16)),
constraints: BoxConstraints(
maxWidth: responsiveUtils.isDesktop(context) ? 556 : double.infinity),
maxWidth: responsiveUtils.isDesktop(context)
? 556
: double.infinity),
),
debounceDuration: const Duration(milliseconds: 500),
listActionButton: const [
@@ -463,12 +475,18 @@ class MailboxDashBoardView extends BaseMailboxDashBoardView {
},
buttonActionCallback: (filterAction) {
if (filterAction is QuickSearchFilter) {
controller.selectQuickSearchFilter(filterAction, fromSuggestionBox: true);
controller.selectQuickSearchFilter(
filterAction,
fromSuggestionBox: true);
}
},
listActionPadding: const EdgeInsets.only(left: 24, top: 24, right: 24, bottom: 16),
listActionPadding: const EdgeInsets.only(
left: 24,
top: 24,
right: 24,
bottom: 16),
titleHeaderRecent: Padding(
padding: const EdgeInsets.only(left: 24, right: 24, bottom: 8, top: 8),
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 8),
child: Text(AppLocalizations.of(context).recent,
style: const TextStyle(fontSize: 13.0,
color: AppColor.colorTextButtonHeaderThread,
@@ -480,12 +498,14 @@ class MailboxDashBoardView extends BaseMailboxDashBoardView {
return InkWell(
onTap: () {
if (keyword.trim().isNotEmpty) {
controller.saveRecentSearch(RecentSearch(keyword, DateTime.now()));
controller.saveRecentSearch(RecentSearch.now(keyword));
}
controller.searchEmail(context, keyword);
},
child: Padding(
padding: const EdgeInsets.only(left: 24, right: 24, top: 14, bottom: 14),
padding: const EdgeInsets.symmetric(
horizontal: 24,
vertical: 14),
child: Row(children: [
Text(AppLocalizations.of(context).showingResultsFor,
style: const TextStyle(fontSize: 13.0,
@@ -523,10 +543,12 @@ class MailboxDashBoardView extends BaseMailboxDashBoardView {
return controller.quickSearchEmailsAction(pattern);
},
itemBuilder: (context, email) {
return EmailQuickSearchItemTileWidget(email, controller.selectedMailbox.value);
return EmailQuickSearchItemTileWidget(
email, controller.selectedMailbox.value);
},
onSuggestionSelected: (presentationEmail) async {
controller.dispatchAction(OpenEmailDetailedAction(context, presentationEmail));
controller.dispatchAction(
OpenEmailDetailedAction(context, presentationEmail));
}),
)),
const SizedBox(width: 16),
@@ -3,8 +3,7 @@ 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/model.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/filter_message_option_extension.dart';
import 'package:tmail_ui_user/features/thread/domain/model/filter_message_option.dart';
mixin FilterEmailPopupMenuMixin {
final _imagePaths = Get.find<ImagePaths>();
@@ -38,15 +37,24 @@ mixin FilterEmailPopupMenuMixin {
width: 20,
height: 20,
fit: BoxFit.fill,
color: option != FilterMessageOption.starred ? AppColor.colorTextButton : null),
color: option != FilterMessageOption.starred
? AppColor.colorTextButton
: null),
const SizedBox(width: 12),
Expanded(child: Text(
option.getName(context),
style: const TextStyle(fontSize: 15, color: Colors.black, fontWeight: FontWeight.w500))),
style: const TextStyle(
fontSize: 15,
color: Colors.black,
fontWeight: FontWeight.w500))),
if (optionSelected == option)
const SizedBox(width: 12),
if (optionSelected == option)
SvgPicture.asset(_imagePaths.icFilterSelected, width: 16, height: 16, fit: BoxFit.fill),
... [
const SizedBox(width: 12),
SvgPicture.asset(_imagePaths.icFilterSelected,
width: 16,
height: 16,
fit: BoxFit.fill),
]
])
),
)