TF-933 Implement search contact when select contact filter in search view

This commit is contained in:
dab246
2022-09-20 13:45:48 +07:00
committed by Dat H. Pham
parent 09fa15289d
commit 7fe899daf5
14 changed files with 587 additions and 23 deletions
@@ -145,6 +145,7 @@ extension AppColor on Color {
static const colorBackgroundNotificationVacationSetting= Color(0xFFFFF5C2);
static const colorDivider = Color(0xFFE7E8EC);
static const colorDividerVertical = Color(0xFF99A2AD);
static const colorCloseButton = Color(0xFF818C99);
static const mapGradientColor = [
[Color(0xFF21D4FD), Color(0xFFB721FF)],
@@ -0,0 +1,11 @@
import 'package:get/get.dart';
import 'package:tmail_ui_user/features/contact/presentation/contact_controller.dart';
class ContactBindings extends Bindings {
@override
void dependencies() {
Get.lazyPut(() => ContactController());
}
}
@@ -0,0 +1,150 @@
import 'package:core/utils/app_logger.dart';
import 'package:core/utils/build_utils.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/core/session/session.dart';
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
import 'package:model/autocomplete/auto_complete_pattern.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:debounce_throttle/debounce_throttle.dart';
import 'package:tmail_ui_user/features/composer/domain/model/contact_suggestion_source.dart';
import 'package:tmail_ui_user/features/composer/domain/state/get_autocomplete_state.dart';
import 'package:tmail_ui_user/features/composer/domain/usecases/get_autocomplete_interactor.dart';
import 'package:tmail_ui_user/features/composer/domain/usecases/get_autocomplete_with_device_contact_interactor.dart';
import 'package:tmail_ui_user/features/composer/presentation/extensions/session_extension.dart';
import 'package:tmail_ui_user/features/contact/presentation/model/contact_arguments.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/bindings/autocomplete_bindings.dart';
import 'package:tmail_ui_user/features/thread/domain/model/search_query.dart';
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
class ContactController extends GetxController {
final textInputSearchController = TextEditingController();
final textInputSearchFocus = FocusNode();
ContactSuggestionSource _contactSuggestionSource = ContactSuggestionSource.tMailContact;
final searchQuery = SearchQuery.initial().obs;
final listContactSearched = RxList<EmailAddress>();
late GetAutoCompleteWithDeviceContactInteractor _getAutoCompleteWithDeviceContactInteractor;
late GetAutoCompleteInteractor _getAutoCompleteInteractor;
late Debouncer<String> _deBouncerTime;
late AccountId _accountId;
late Session _session;
EmailAddress? contactSelected;
@override
void onInit() {
super.onInit();
_initializeDebounceTimeTextSearchChange();
}
@override
void onReady() async {
textInputSearchFocus.requestFocus();
final arguments = Get.arguments;
if (arguments is ContactArguments) {
_accountId = arguments.accountId;
_session = arguments.session;
final listContactSelected = arguments.listContactSelected;
if (listContactSelected.isNotEmpty) {
contactSelected = EmailAddress(listContactSelected.first, listContactSelected.first);
}
}
if (!BuildUtils.isWeb) {
Future.delayed(
const Duration(milliseconds: 500),
() => _checkContactPermission());
}
super.onReady();
}
@override
void onClose() {
textInputSearchController.dispose();
_deBouncerTime.cancel();
super.onClose();
}
void _initializeDebounceTimeTextSearchChange() {
_deBouncerTime = Debouncer<String>(
const Duration(milliseconds: 500),
initialValue: '');
_deBouncerTime.values.listen((value) async {
searchQuery.value = SearchQuery(value);
_searchContactByNameOrEmail(searchQuery.value.value);
});
}
void onTextSearchChange(String text) {
_deBouncerTime.value = text;
}
void clearAllTextInputSearchForm() {
textInputSearchController.clear();
searchQuery.value = SearchQuery.initial();
textInputSearchFocus.requestFocus();
}
void _checkContactPermission() async {
final permissionStatus = await Permission.contacts.status;
if (permissionStatus.isGranted) {
_contactSuggestionSource = ContactSuggestionSource.all;
} else if (!permissionStatus.isPermanentlyDenied) {
final requestedPermission = await Permission.contacts.request();
_contactSuggestionSource = requestedPermission == PermissionStatus.granted
? ContactSuggestionSource.all
: _contactSuggestionSource;
}
}
void _searchContactByNameOrEmail(String query) async {
log('ContactController::_searchContactByNameOrEmail(): query: $query');
final listContact = await _getAutoCompleteSuggestion(query);
listContactSearched.value = listContact;
}
Future<List<EmailAddress>> _getAutoCompleteSuggestion(String query) async {
if(_session.hasSupportTmailAutoComplete != true) return <EmailAddress>[];
if (!Get.isRegistered<GetAutoCompleteWithDeviceContactInteractor>() ||
!Get.isRegistered<GetAutoCompleteInteractor>()) {
AutoCompleteBindings().dependencies();
}
_getAutoCompleteWithDeviceContactInteractor = Get.find<GetAutoCompleteWithDeviceContactInteractor>();
_getAutoCompleteInteractor = Get.find<GetAutoCompleteInteractor>();
if (_contactSuggestionSource == ContactSuggestionSource.all) {
return await _getAutoCompleteWithDeviceContactInteractor
.execute(AutoCompletePattern(word: query, limit: 30, accountId: _accountId))
.then((value) => value.fold(
(failure) => <EmailAddress>[],
(success) => success is GetAutoCompleteSuccess
? success.listEmailAddress
: <EmailAddress>[]));
}
return await _getAutoCompleteInteractor
.execute(AutoCompletePattern(word: query, limit: 30, accountId: _accountId))
.then((value) => value.fold(
(failure) => <EmailAddress>[],
(success) => success is GetAutoCompleteSuccess
? success.listEmailAddress
: <EmailAddress>[]));
}
void selectContact(BuildContext context, EmailAddress emailAddress) {
FocusScope.of(context).unfocus();
popBack(result: emailAddress);
}
void closeContactView(BuildContext context) {
clearAllTextInputSearchForm();
FocusScope.of(context).unfocus();
popBack();
}
}
@@ -0,0 +1,190 @@
import 'package:core/presentation/extensions/color_extension.dart';
import 'package:core/presentation/resources/image_paths.dart';
import 'package:core/presentation/utils/responsive_utils.dart';
import 'package:core/presentation/utils/style_utils.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart';
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
import 'package:model/extensions/email_address_extension.dart';
import 'package:tmail_ui_user/features/contact/presentation/contact_controller.dart';
import 'package:tmail_ui_user/features/contact/presentation/utils/contact_utils.dart';
import 'package:tmail_ui_user/features/contact/presentation/widgets/app_bar_contact_widget.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';
class ContactView extends GetWidget<ContactController> {
final _responsiveUtils = Get.find<ResponsiveUtils>();
final _imagePaths = Get.find<ImagePaths>();
ContactView({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
if (_responsiveUtils.isWebDesktop(context)) {
WidgetsBinding.instance.addPostFrameCallback((_) {
controller.closeContactView(context);
});
}
return Scaffold(
backgroundColor: Colors.black38,
body: GestureDetector(
onTap: () => FocusScope.of(context).unfocus(),
child: SafeArea(
bottom: false,
left: false,
right: false,
top: ContactUtils.supportAppBarTopBorder(context, _responsiveUtils),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(ContactUtils.getRadiusBorderAppBarTop(
context,
_responsiveUtils)),
topRight: Radius.circular(ContactUtils.getRadiusBorderAppBarTop(
context,
_responsiveUtils))),
color: Colors.white),
child: ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(ContactUtils.getRadiusBorderAppBarTop(
context,
_responsiveUtils)),
topRight: Radius.circular(ContactUtils.getRadiusBorderAppBarTop(
context,
_responsiveUtils))),
child: SafeArea(child: Container(
color: Colors.white,
child: Column(children: [
Container(
height: 52,
color: Colors.white,
padding: ContactUtils.getPaddingAppBar(context, _responsiveUtils),
child: AppBarContactWidget(
onCloseContactView: () => controller.closeContactView(context))
),
const Divider(color: AppColor.colorDividerComposer, height: 1),
(SearchAppBarWidget(
_imagePaths,
controller.searchQuery.value,
controller.textInputSearchFocus,
controller.textInputSearchController,
hasBackButton: false,
hasSearchButton: true)
..addPadding(EdgeInsets.zero)
..setHeightSearchBar(44)
..setMargin(ContactUtils.getPaddingSearchInputForm(context, _responsiveUtils))
..addDecoration(BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: AppColor.colorBgSearchBar))
..addIconClearText(SvgPicture.asset(
_imagePaths.icClearTextSearch,
width: 18,
height: 18,
fit: BoxFit.fill))
..setHintText(AppLocalizations.of(context).hintSearchInputContact)
..addOnClearTextSearchAction(() => controller.clearAllTextInputSearchForm())
..addOnTextChangeSearchAction(controller.onTextSearchChange)
..addOnSearchTextAction((query) => {}))
.build(),
Expanded(child: Obx(() {
if (controller.listContactSearched.isNotEmpty) {
return Container(
color: Colors.white,
child: ListView.separated(
itemCount: controller.listContactSearched.length,
separatorBuilder: (context, index) {
return Padding(
padding: ContactUtils.getPaddingDividerSearchResultList(context, _responsiveUtils),
child: const Divider(
height: 1,
color: AppColor.colorDivider),
);
},
itemBuilder: (context, index) {
final emailAddress = controller.listContactSearched[index];
return _buildItemSearchContact(context, emailAddress);
}
)
);
} else {
return const SizedBox.shrink();
}
})),
]),
))
)
),
),
)
);
}
Widget _buildItemSearchContact(BuildContext context, EmailAddress emailAddress) {
return Material(
color: Colors.transparent,
child: ListTile(
onTap: () => controller.selectContact(context, emailAddress),
contentPadding: ContactUtils.getPaddingSearchInputForm(context, _responsiveUtils),
leading: Container(
width: 44,
height: 44,
alignment: Alignment.center,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(44) * 0.5,
border: Border.all(color: Colors.transparent),
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
stops: const [0.0, 1.0],
colors: emailAddress.avatarColors),
color: AppColor.avatarColor
),
child: Text(
emailAddress.asString().isNotEmpty
? emailAddress.asString()[0].toUpperCase()
: '',
style: const TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.w600))),
title: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
emailAddress.asString(),
maxLines: 1,
overflow: CommonTextStyle.defaultTextOverFlow,
softWrap: CommonTextStyle.defaultSoftWrap,
style: const TextStyle(
color: Colors.black,
fontSize: 15,
fontWeight: FontWeight.normal)),
if (emailAddress.displayName.isNotEmpty && emailAddress.emailAddress.isNotEmpty)
Padding(
padding: const EdgeInsets.only(top: 4),
child: Text(
emailAddress.emailAddress,
maxLines: 1,
overflow: CommonTextStyle.defaultTextOverFlow,
softWrap: CommonTextStyle.defaultSoftWrap,
style: const TextStyle(
color: AppColor.colorContentEmail,
fontSize: 13,
fontWeight: FontWeight.normal)))
]
),
trailing: controller.contactSelected?.email == emailAddress.email
? SvgPicture.asset(_imagePaths.icFilterSelected,
width: 24,
height: 24,
fit: BoxFit.fill)
: null,
),
);
}
}
@@ -0,0 +1,15 @@
import 'package:equatable/equatable.dart';
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/core/session/session.dart';
class ContactArguments with EquatableMixin {
final AccountId accountId;
final Session session;
final Set<String> listContactSelected;
ContactArguments(this.accountId, this.session, this.listContactSelected);
@override
List<Object?> get props => [accountId, session, listContactSelected];
}
@@ -0,0 +1,69 @@
import 'package:core/presentation/utils/responsive_utils.dart';
import 'package:core/utils/build_utils.dart';
import 'package:flutter/material.dart';
class ContactUtils {
static EdgeInsets getPaddingAppBar(BuildContext context, ResponsiveUtils responsiveUtils) {
if (BuildUtils.isWeb) {
return const EdgeInsets.symmetric(horizontal: 16);
} else {
if (responsiveUtils.isScreenWithShortestSide(context)) {
return const EdgeInsets.symmetric(horizontal: 10);
} else {
return const EdgeInsets.symmetric(horizontal: 32);
}
}
}
static EdgeInsets getPaddingSearchInputForm(BuildContext context, ResponsiveUtils responsiveUtils) {
if (BuildUtils.isWeb) {
return const EdgeInsets.symmetric(horizontal: 16, vertical: 10);
} else {
if (responsiveUtils.isScreenWithShortestSide(context)) {
return const EdgeInsets.symmetric(horizontal: 16, vertical: 10);
} else {
return const EdgeInsets.symmetric(horizontal: 32, vertical: 10);
}
}
}
static EdgeInsets getPaddingSearchResultList(BuildContext context, ResponsiveUtils responsiveUtils) {
if (BuildUtils.isWeb) {
return const EdgeInsets.symmetric(horizontal: 16, vertical: 10);
} else {
if (responsiveUtils.isScreenWithShortestSide(context)) {
return const EdgeInsets.symmetric(horizontal: 16, vertical: 10);
} else {
return const EdgeInsets.symmetric(horizontal: 32, vertical: 10);
}
}
}
static EdgeInsets getPaddingDividerSearchResultList(BuildContext context, ResponsiveUtils responsiveUtils) {
if (BuildUtils.isWeb) {
return const EdgeInsets.symmetric(horizontal: 16);
} else {
if (responsiveUtils.isScreenWithShortestSide(context)) {
return const EdgeInsets.symmetric(horizontal: 16);
} else {
return const EdgeInsets.symmetric(horizontal: 32);
}
}
}
static bool supportAppBarTopBorder(BuildContext context, ResponsiveUtils responsiveUtils) {
if (BuildUtils.isWeb || responsiveUtils.isLandscapeMobile(context)) {
return false;
}
return true;
}
static double getRadiusBorderAppBarTop(BuildContext context, ResponsiveUtils responsiveUtils) {
if (supportAppBarTopBorder(context, responsiveUtils)) {
return 16;
} else {
return 0;
}
}
}
@@ -0,0 +1,47 @@
import 'package:core/presentation/extensions/color_extension.dart';
import 'package:core/presentation/resources/image_paths.dart';
import 'package:core/presentation/views/button/icon_button_web.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
class AppBarContactWidget extends StatelessWidget {
final _imagePaths = Get.find<ImagePaths>();
final Function()? onCloseContactView;
AppBarContactWidget({
Key? key,
this.onCloseContactView,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Stack(alignment: Alignment.center, children: [
Positioned(
left: 0,
child: buildIconWeb(
icon: SvgPicture.asset(_imagePaths.icCloseComposer,
color: AppColor.colorCloseButton,
width: 24,
height: 24,
fit: BoxFit.fill),
minSize: 25,
iconSize: 25,
iconPadding: const EdgeInsets.all(5),
splashRadius: 15,
tooltip: AppLocalizations.of(context).close,
onTap: onCloseContactView),
),
Center(child: Text(
AppLocalizations.of(context).contains,
style: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.black))),
]);
}
}
@@ -138,12 +138,12 @@ extension SearchEmailFilterExtension on SimpleSearchFilter {
}
}
String getNameContactApplied(PrefixEmailAddress prefixEmailAddress) {
String getNameContactApplied(BuildContext context, PrefixEmailAddress prefixEmailAddress) {
switch(prefixEmailAddress) {
case PrefixEmailAddress.from:
return from.first;
return '${AppLocalizations.of(context).from_email_address_prefix} ${from.first}';
case PrefixEmailAddress.to:
return to.first;
return '${AppLocalizations.of(context).to_email_address_prefix} ${to.first}';
default:
return '';
}
@@ -7,13 +7,16 @@ import 'package:debounce_throttle/debounce_throttle.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/core/session/session.dart';
import 'package:jmap_dart_client/jmap/core/unsigned_int.dart';
import 'package:jmap_dart_client/jmap/core/sort/comparator.dart';
import 'package:jmap_dart_client/jmap/core/utc_date.dart';
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
import 'package:jmap_dart_client/jmap/mail/email/email_comparator.dart';
import 'package:jmap_dart_client/jmap/mail/email/email_comparator_property.dart';
import 'package:model/model.dart';
import 'package:tmail_ui_user/features/base/base_controller.dart';
import 'package:tmail_ui_user/features/contact/presentation/model/contact_arguments.dart';
import 'package:tmail_ui_user/features/destination_picker/presentation/model/destination_picker_arguments.dart';
import 'package:tmail_ui_user/features/email/domain/state/delete_email_permanently_state.dart';
import 'package:tmail_ui_user/features/email/domain/state/delete_multiple_emails_permanently_state.dart';
@@ -81,6 +84,8 @@ class SearchEmailController extends BaseController
AccountId? get accountId => mailboxDashBoardController.accountId.value;
Session? get session => mailboxDashBoardController.sessionCurrent;
UserProfile? get userProfile => mailboxDashBoardController.userProfile.value;
SearchQuery? get searchQuery => simpleSearchFilter.value.text;
@@ -355,9 +360,6 @@ class SearchEmailController extends BaseController
}
bool checkQuickSearchFilterSelected(QuickSearchFilter filter) {
log('SearchEmailController::checkQuickSearchFilterSelected(): filter: $filter');
log('SearchEmailController::checkQuickSearchFilterSelected(): simpleSearchFilter: ${simpleSearchFilter.value.from}');
log('SearchEmailController::checkQuickSearchFilterSelected(): userProfile: ${userProfile!.email}');
switch (filter) {
case QuickSearchFilter.hasAttachment:
return simpleSearchFilter.value.hasAttachment == true;
@@ -366,16 +368,13 @@ class SearchEmailController extends BaseController
return true;
}
return simpleSearchFilter.value.emailReceiveTimeType == EmailReceiveTimeType.last7Days;
case QuickSearchFilter.fromMe:
return userProfile != null &&
simpleSearchFilter.value.from.contains(userProfile!.email) &&
simpleSearchFilter.value.from.length == 1;
default:
return false;
}
}
void _selectQuickSearchFilter(QuickSearchFilter filter) {
final filterSelected = checkQuickSearchFilterSelected(filter);
log('SearchEmailController::_selectQuickSearchFilter(): filterSelected: $filterSelected');
switch (filter) {
case QuickSearchFilter.hasAttachment:
_updateSimpleSearchFilter(hasAttachment: !filterSelected);
@@ -389,14 +388,7 @@ class SearchEmailController extends BaseController
_updateSimpleSearchFilter(emailReceiveTimeType: EmailReceiveTimeType.last7Days);
}
break;
case QuickSearchFilter.fromMe:
if (userProfile != null) {
filterSelected
? simpleSearchFilter.value.from.removeWhere((e) => e == userProfile!.email)
: simpleSearchFilter.value.from.add(userProfile!.email);
log('SearchEmailController::_selectQuickSearchFilter(): from: ${simpleSearchFilter.value.from}');
_updateSimpleSearchFilter(from: simpleSearchFilter.value.from);
}
default:
break;
}
}
@@ -445,11 +437,60 @@ class SearchEmailController extends BaseController
BuildContext context,
PrefixEmailAddress prefixEmailAddress
) async {
if (accountId != null && session != null) {
final listContactSelected = simpleSearchFilter.value.getContactApplied(prefixEmailAddress);
final newContact = await push(
AppRoutes.CONTACT,
arguments: ContactArguments(accountId!, session!, listContactSelected));
if (newContact is EmailAddress) {
if (listContactSelected.isNotEmpty) {
switch(prefixEmailAddress) {
case PrefixEmailAddress.from:
listContactSelected.first == newContact.email
? simpleSearchFilter.value.from.removeWhere((e) => e == newContact.email!)
: simpleSearchFilter.value.from.add(newContact.email!);
break;
case PrefixEmailAddress.to:
listContactSelected.first == newContact.email
? simpleSearchFilter.value.to.removeWhere((e) => e == newContact.email!)
: simpleSearchFilter.value.to.add(newContact.email!);
break;
default:
break;
}
} else {
switch(prefixEmailAddress) {
case PrefixEmailAddress.from:
simpleSearchFilter.value.from.add(newContact.email!);
break;
case PrefixEmailAddress.to:
simpleSearchFilter.value.to.add(newContact.email!);
break;
default:
break;
}
}
switch(prefixEmailAddress) {
case PrefixEmailAddress.from:
_updateSimpleSearchFilter(from: simpleSearchFilter.value.from);
break;
case PrefixEmailAddress.to:
_updateSimpleSearchFilter(to: simpleSearchFilter.value.to);
break;
default:
break;
}
_searchEmailAction(context);
}
}
}
void _updateSimpleSearchFilter({
Set<String>? from,
Set<String>? to,
SearchQuery? text,
PresentationMailbox? mailbox,
EmailReceiveTimeType? emailReceiveTimeType,
@@ -458,6 +499,7 @@ class SearchEmailController extends BaseController
}) {
simpleSearchFilter.value = simpleSearchFilter.value.copyWith(
from: from,
to: to,
text: text,
mailbox: mailbox,
emailReceiveTimeType: emailReceiveTimeType,
@@ -42,6 +42,12 @@ class SearchEmailView extends GetWidget<SearchEmailController>
@override
Widget build(BuildContext context) {
if (_responsiveUtils.isWebDesktop(context)) {
WidgetsBinding.instance.addPostFrameCallback((_) {
controller.closeSearchView(context);
});
}
return Scaffold(
body: GestureDetector(
onTap: () => FocusScope.of(context).unfocus(),
@@ -129,7 +135,6 @@ class SearchEmailView extends GetWidget<SearchEmailController>
..textDecoration(InputDecoration(
contentPadding: const EdgeInsets.all(12),
hintText: AppLocalizations.of(context).search_emails,
fillColor: Colors.redAccent,
hintStyle: const TextStyle(
color: AppColor.loginTextFieldHintColor,
fontSize: 16),
@@ -590,7 +595,7 @@ class SearchEmailView extends GetWidget<SearchEmailController>
const SizedBox(width: 4),
Text(
filterSelected
? controller.simpleSearchFilter.value.getNameContactApplied(prefixEmailAddress)
? controller.simpleSearchFilter.value.getNameContactApplied(context, prefixEmailAddress)
: controller.simpleSearchFilter.value.getNameContactDefault(context, prefixEmailAddress),
maxLines: 1,
overflow: CommonTextStyle.defaultTextOverFlow,
+13 -1
View File
@@ -1,5 +1,5 @@
{
"@@last_modified": "2022-09-16T03:16:09.866930",
"@@last_modified": "2022-09-20T13:44:48.613115",
"initializing_data": "Initializing data...",
"@initializing_data": {
"type": "text",
@@ -2185,5 +2185,17 @@
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"contact": "Contact",
"@contact": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"hintSearchInputContact": "Enter name or email",
"@hintSearchInputContact": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
}
}
+13 -1
View File
@@ -2252,11 +2252,23 @@ class AppLocalizations {
);
}
String get clearAll {
return Intl.message(
'Clear all',
name: 'clearAll',
);
}
String get contact {
return Intl.message(
'Contact',
name: 'contact');
}
String get hintSearchInputContact {
return Intl.message(
'Enter name or email',
name: 'hintSearchInputContact'
);
}
}
+9
View File
@@ -2,6 +2,7 @@ import 'package:get/get.dart';
import 'package:get/get_navigation/src/routes/get_route.dart';
import 'package:tmail_ui_user/features/composer/presentation/composer_bindings.dart';
import 'package:tmail_ui_user/features/composer/presentation/composer_view.dart' deferred as composer;
import 'package:tmail_ui_user/features/contact/presentation/contact_bindings.dart';
import 'package:tmail_ui_user/features/destination_picker/presentation/destination_picker_bindings.dart';
import 'package:tmail_ui_user/features/destination_picker/presentation/destination_picker_view.dart' deferred as destination_picker;
import 'package:tmail_ui_user/features/email/presentation/email_view.dart' deferred as email;
@@ -11,6 +12,7 @@ import 'package:tmail_ui_user/features/identity_creator/presentation/identity_cr
import 'package:tmail_ui_user/features/identity_creator/presentation/identity_creator_view.dart' deferred as identity_creator;
import 'package:tmail_ui_user/features/emails_forward_creator/presentation/emails_forward_creator_binding.dart';
import 'package:tmail_ui_user/features/emails_forward_creator/presentation/emails_forward_creator_view.dart' deferred as emails_forward_creator;
import 'package:tmail_ui_user/features/contact/presentation/contact_view.dart' deferred as contact_view;
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/rules_filter_creator_bindings.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/rules_filter_creator_view.dart' deferred as rules_filter_creator;
import 'package:tmail_ui_user/features/login/presentation/login_bindings.dart';
@@ -89,5 +91,12 @@ class AppPages {
emails_forward_creator.loadLibrary,
() => emails_forward_creator.EmailsForwardCreatorView()),
binding: EmailsForwardCreatorBindings()),
GetPage(
name: AppRoutes.CONTACT,
opaque: false,
page: () => DeferredWidget(
contact_view.loadLibrary,
() => contact_view.ContactView()),
binding: ContactBindings()),
];
}
+1
View File
@@ -14,4 +14,5 @@ abstract class AppRoutes {
static const RULES_FILTER_CREATOR = '$MANAGE_ACCOUNT/rules_filter_creator';
static const EMAILS_FORWARD_CREATOR = '$MANAGE_ACCOUNT/emails_forward_creator';
static const SEARCH_EMAIL = '$MAILBOX_DASHBOARD/search_email';
static const CONTACT = '$MAILBOX_DASHBOARD/contact';
}