From bab0331fe01c1302ee32a8b463f34ad3971ecdee Mon Sep 17 00:00:00 2001 From: dab246 Date: Mon, 2 Jun 2025 16:33:37 +0700 Subject: [PATCH] TF-3764 Update new empty view for folder Signed-off-by: dab246 --- assets/images/ic_empty_folder.svg | 17 +++++ .../extensions/color_extension.dart | 1 + .../presentation/resources/image_paths.dart | 2 +- core/lib/presentation/utils/theme_utils.dart | 18 ++++++ .../styles/empty_emails_widget_styles.dart | 26 +------- .../thread/presentation/thread_view.dart | 1 - .../widgets/empty_emails_widget.dart | 63 +++++-------------- lib/l10n/intl_messages.arb | 14 ++++- lib/main/localizations/app_localizations.dart | 14 +++++ .../widgets/empty_email_widget_test.dart | 19 +++--- 10 files changed, 91 insertions(+), 84 deletions(-) create mode 100644 assets/images/ic_empty_folder.svg diff --git a/assets/images/ic_empty_folder.svg b/assets/images/ic_empty_folder.svg new file mode 100644 index 000000000..e992cf019 --- /dev/null +++ b/assets/images/ic_empty_folder.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/core/lib/presentation/extensions/color_extension.dart b/core/lib/presentation/extensions/color_extension.dart index 1a52d90ed..8327fc769 100644 --- a/core/lib/presentation/extensions/color_extension.dart +++ b/core/lib/presentation/extensions/color_extension.dart @@ -256,6 +256,7 @@ extension AppColor on Color { static const textPrimary = Color(0xFF424244); static const iconFolder = Color(0xFF297EF2); static const folderDivider = Color(0xFFE4E8EC); + static const color424244 = Color(0xFF424244); static const mapGradientColor = [ [Color(0xFF21D4FD), Color(0xFFB721FF)], diff --git a/core/lib/presentation/resources/image_paths.dart b/core/lib/presentation/resources/image_paths.dart index 2afbdde78..72eb97f6a 100644 --- a/core/lib/presentation/resources/image_paths.dart +++ b/core/lib/presentation/resources/image_paths.dart @@ -12,7 +12,7 @@ class ImagePaths { String get icDownload => _getImagePath('ic_download.svg'); String get icMore => _getImagePath('ic_more.svg'); String get icPhotoLibrary => _getImagePath('ic_photo_library.svg'); - String get icEmptyEmail => _getImagePath('ic_empty_email.svg'); + String get icEmptyFolder => _getImagePath('ic_empty_folder.svg'); String get icStar => _getImagePath('ic_star.svg'); String get icUnStar => _getImagePath('ic_unstar.svg'); String get icAttachment => _getImagePath('ic_attachment.svg'); diff --git a/core/lib/presentation/utils/theme_utils.dart b/core/lib/presentation/utils/theme_utils.dart index ab7339c38..67e78b9df 100644 --- a/core/lib/presentation/utils/theme_utils.dart +++ b/core/lib/presentation/utils/theme_utils.dart @@ -270,6 +270,24 @@ class ThemeUtils { color: AppColor.steelGray400, ); + static TextStyle textStyleInter600() => TextStyle( + fontFamily: ConstantsUI.fontApp, + fontWeight: FontWeight.w600, + letterSpacing: 0.0, + fontSize: 24, + height: 28.01 / 24, + color: AppColor.color424244.withOpacity(0.9), + ); + + static TextStyle textStyleInter400() => TextStyle( + fontFamily: ConstantsUI.fontApp, + fontWeight: FontWeight.w400, + letterSpacing: -0.15, + fontSize: 16, + height: 21.01 / 16, + color: AppColor.color424244.withOpacity(0.64), + ); + static TextSelectionThemeData get _textSelectionTheme { return const TextSelectionThemeData( cursorColor: AppColor.primaryColor, diff --git a/lib/features/thread/presentation/styles/empty_emails_widget_styles.dart b/lib/features/thread/presentation/styles/empty_emails_widget_styles.dart index c3781946c..7f139a0a3 100644 --- a/lib/features/thread/presentation/styles/empty_emails_widget_styles.dart +++ b/lib/features/thread/presentation/styles/empty_emails_widget_styles.dart @@ -1,30 +1,10 @@ -import 'package:core/presentation/extensions/color_extension.dart'; import 'package:flutter/material.dart'; class EmptyEmailsWidgetStyles { - static const double mobileIconSize = 160; - static const double tabletIconSize = 180; - static const double desktopIconSize = 212; - static const double labelTextSize = 20; - static const double messageTextSize = 15; - static const double createFilterLabelTextSize = 22; - static const double createFilterButtonTextSize = 17; - static const double maxWidth = 490; - static const double createFilterButtonBorderRadius = 10; - - static const FontWeight labelFontWeight = FontWeight.w400; - static const FontWeight messageFontWeight = FontWeight.w400; - static const FontWeight createFilterLabelFontWeight = FontWeight.w600; - static const FontWeight createFilterButtonFontWeight = FontWeight.w500; - - static const Color labelTextColor = Colors.black; - static const Color messageTextColor = AppColor.colorSubtitle; - static const Color createFilterButtonTextColor = AppColor.primaryColor; - static const Color createFilterButtonBackgroundColor = AppColor.colorCreateFiltersButton; + static const double iconSize = 160; + static const double maxWidth = 352.07; static const EdgeInsetsGeometry padding = EdgeInsetsDirectional.all(16); - static const EdgeInsetsGeometry labelPadding = EdgeInsetsDirectional.symmetric(vertical: 12); - static const EdgeInsetsGeometry createFilterButtonPadding = EdgeInsetsDirectional.symmetric(vertical: 12, horizontal: 24); - static const EdgeInsetsGeometry createFilterButtonMargin = EdgeInsetsDirectional.only(top: 12); + static const EdgeInsetsGeometry labelPadding = EdgeInsetsDirectional.only(top: 16, bottom: 8); } \ No newline at end of file diff --git a/lib/features/thread/presentation/thread_view.dart b/lib/features/thread/presentation/thread_view.dart index 8112d670d..17169f398 100644 --- a/lib/features/thread/presentation/thread_view.dart +++ b/lib/features/thread/presentation/thread_view.dart @@ -737,7 +737,6 @@ class ThreadView extends GetWidget isNetworkConnectionAvailable: controller.networkConnectionController.isNetworkConnectionAvailable(), isSearchActive: controller.isSearchActive, isFilterMessageActive: controller.mailboxDashBoardController.filterMessageOption.value != FilterMessageOption.all, - onCreateFiltersActionCallback: controller.goToCreateEmailRuleView ), ); } diff --git a/lib/features/thread/presentation/widgets/empty_emails_widget.dart b/lib/features/thread/presentation/widgets/empty_emails_widget.dart index 84f2f65f4..372e0a306 100644 --- a/lib/features/thread/presentation/widgets/empty_emails_widget.dart +++ b/lib/features/thread/presentation/widgets/empty_emails_widget.dart @@ -1,20 +1,17 @@ import 'package:core/presentation/resources/image_paths.dart'; import 'package:core/presentation/utils/responsive_utils.dart'; -import 'package:core/presentation/views/button/tmail_button_widget.dart'; +import 'package:core/presentation/utils/theme_utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:get/get.dart'; import 'package:tmail_ui_user/features/thread/presentation/styles/empty_emails_widget_styles.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; -typedef OnCreateFiltersActionCallback = Function(); - class EmptyEmailsWidget extends StatelessWidget { final bool isSearchActive; final bool isFilterMessageActive; final bool isNetworkConnectionAvailable; - final OnCreateFiltersActionCallback? onCreateFiltersActionCallback; final _responsiveUtils = Get.find(); final _imagePaths = Get.find(); @@ -24,7 +21,6 @@ class EmptyEmailsWidget extends StatelessWidget { this.isSearchActive = false, this.isFilterMessageActive = false, this.isNetworkConnectionAvailable = true, - this.onCreateFiltersActionCallback, }) : super(key: key); @override @@ -37,9 +33,9 @@ class EmptyEmailsWidget extends StatelessWidget { : MainAxisAlignment.center, children: [ SvgPicture.asset( - _imagePaths.icEmptyEmail, - width: _getIconSize(context, _responsiveUtils), - height: _getIconSize(context, _responsiveUtils), + _imagePaths.icEmptyFolder, + width: EmptyEmailsWidgetStyles.iconSize, + height: EmptyEmailsWidgetStyles.iconSize, fit: BoxFit.fill ), Padding( @@ -47,31 +43,17 @@ class EmptyEmailsWidget extends StatelessWidget { child: Text( key: const Key('empty_email_message'), _getMessageEmptyEmail(context), - style: const TextStyle( - color: EmptyEmailsWidgetStyles.labelTextColor, - fontSize: EmptyEmailsWidgetStyles.createFilterLabelTextSize, - fontWeight: EmptyEmailsWidgetStyles.createFilterLabelFontWeight - ), + style: ThemeUtils.textStyleInter600(), textAlign: TextAlign.center, ), ), - if (_validateShowCreateRuleButton) - TMailButtonWidget.fromText( - key: const Key('create_filter_rule_button_within_empty_email'), - text: AppLocalizations.of(context).createFilters, - padding: EmptyEmailsWidgetStyles.createFilterButtonPadding, - margin: EmptyEmailsWidgetStyles.createFilterButtonMargin, - backgroundColor: EmptyEmailsWidgetStyles.createFilterButtonBackgroundColor, - borderRadius: EmptyEmailsWidgetStyles.createFilterButtonBorderRadius, - width: _responsiveUtils.isPortraitMobile(context) ? double.infinity : null, + if (_showEmailSubMessage) + Text( + key: const Key('empty_email_sub_message'), + AppLocalizations.of(context).startToComposeEmails, + style: ThemeUtils.textStyleInter400(), textAlign: TextAlign.center, - textStyle: const TextStyle( - fontSize: EmptyEmailsWidgetStyles.createFilterButtonTextSize, - fontWeight: EmptyEmailsWidgetStyles.createFilterButtonFontWeight, - color: EmptyEmailsWidgetStyles.createFilterButtonTextColor - ), - onTapActionCallback: onCreateFiltersActionCallback, - ) + ), ], ), ); @@ -88,18 +70,9 @@ class EmptyEmailsWidget extends StatelessWidget { ); } - double _getIconSize(BuildContext context, ResponsiveUtils responsiveUtils) { - if (responsiveUtils.isMobile(context)) { - return EmptyEmailsWidgetStyles.mobileIconSize; - } else if (responsiveUtils.isDesktop(context)) { - return EmptyEmailsWidgetStyles.desktopIconSize; - } else { - return EmptyEmailsWidgetStyles.tabletIconSize; - } - } - - bool get _validateShowCreateRuleButton => isNetworkConnectionAvailable - && !isFilterMessageActive && !isSearchActive && onCreateFiltersActionCallback != null; + bool get _showEmailSubMessage => isNetworkConnectionAvailable && + !isFilterMessageActive && + !isSearchActive; String _getMessageEmptyEmail(BuildContext context) { if (!isNetworkConnectionAvailable) { @@ -108,12 +81,10 @@ class EmptyEmailsWidget extends StatelessWidget { if (isSearchActive) { return AppLocalizations.of(context).no_emails_matching_your_search; + } else if (isFilterMessageActive) { + return AppLocalizations.of(context).noEmailMatchYourCurrentFilter; } else { - if (isFilterMessageActive) { - return AppLocalizations.of(context).noEmailMatchYourCurrentFilter; - } else { - return AppLocalizations.of(context).noEmailInYourCurrentFolder; - } + return AppLocalizations.of(context).youDoNotHaveAnyEmailInYourCurrentFolder; } } } \ No newline at end of file diff --git a/lib/l10n/intl_messages.arb b/lib/l10n/intl_messages.arb index 10975419e..281b0c70f 100644 --- a/lib/l10n/intl_messages.arb +++ b/lib/l10n/intl_messages.arb @@ -1,5 +1,5 @@ { - "@@last_modified": "2025-05-27T01:35:50.697124", + "@@last_modified": "2025-06-02T16:27:17.653715", "initializing_data": "Initializing data...", "@initializing_data": { "type": "text", @@ -4527,5 +4527,17 @@ "type": "text", "placeholders_order": [], "placeholders": {} + }, + "youDoNotHaveAnyEmailInYourCurrentFolder": "You don’t have any emails in this folder.", + "@youDoNotHaveAnyEmailInYourCurrentFolder": { + "type": "text", + "placeholders_order": [], + "placeholders": {} + }, + "startToComposeEmails": "Start to compose emails.", + "@startToComposeEmails": { + "type": "text", + "placeholders_order": [], + "placeholders": {} } } \ No newline at end of file diff --git a/lib/main/localizations/app_localizations.dart b/lib/main/localizations/app_localizations.dart index 5b15fe711..e5fe3f8a5 100644 --- a/lib/main/localizations/app_localizations.dart +++ b/lib/main/localizations/app_localizations.dart @@ -4766,4 +4766,18 @@ class AppLocalizations { name: 'deleteRecipientsFailed', ); } + + String get youDoNotHaveAnyEmailInYourCurrentFolder { + return Intl.message( + 'You don’t have any emails\n in this folder.', + name: 'youDoNotHaveAnyEmailInYourCurrentFolder', + ); + } + + String get startToComposeEmails { + return Intl.message( + 'Start to compose emails.', + name: 'startToComposeEmails', + ); + } } diff --git a/test/features/thread/presentation/widgets/empty_email_widget_test.dart b/test/features/thread/presentation/widgets/empty_email_widget_test.dart index 5e3438bbc..e4424e701 100644 --- a/test/features/thread/presentation/widgets/empty_email_widget_test.dart +++ b/test/features/thread/presentation/widgets/empty_email_widget_test.dart @@ -42,7 +42,6 @@ void main() { child: EmptyEmailsWidget( isSearchActive: false, isFilterMessageActive: false, - onCreateFiltersActionCallback: () {}, ), ); @@ -51,14 +50,14 @@ void main() { await tester.pumpAndSettle(); expect( - find.byKey(const Key('create_filter_rule_button_within_empty_email')), + find.byKey(const Key('empty_email_sub_message')), findsOneWidget); final emptyEmailMessageWidgetFinder = find.byKey(const Key('empty_email_message')); final emptyEmailMessageWidget = tester.widget(emptyEmailMessageWidgetFinder); expect( emptyEmailMessageWidget.data, - 'We\'re sorry, there are no emails in your current folder'); + 'You don’t have any emails\n in this folder.'); }); testWidgets( @@ -77,7 +76,7 @@ void main() { await tester.pumpAndSettle(); expect( - find.byKey(const Key('create_filter_rule_button_within_empty_email')), + find.byKey(const Key('empty_email_sub_message')), findsNothing); final emptyEmailMessageWidgetFinder = find.byKey(const Key('empty_email_message')); @@ -102,7 +101,7 @@ void main() { await tester.pumpAndSettle(); expect( - find.byKey(const Key('create_filter_rule_button_within_empty_email')), + find.byKey(const Key('empty_email_sub_message')), findsNothing); final emptyEmailMessageWidgetFinder = find.byKey(const Key('empty_email_message')); @@ -126,7 +125,7 @@ void main() { await tester.pumpAndSettle(); expect( - find.byKey(const Key('create_filter_rule_button_within_empty_email')), + find.byKey(const Key('empty_email_sub_message')), findsNothing); final emptyEmailMessageWidgetFinder = find.byKey(const Key('empty_email_message')); @@ -151,7 +150,7 @@ void main() { await tester.pumpAndSettle(); expect( - find.byKey(const Key('create_filter_rule_button_within_empty_email')), + find.byKey(const Key('empty_email_sub_message')), findsNothing); final emptyEmailMessageWidgetFinder = find.byKey(const Key('empty_email_message')); @@ -176,7 +175,7 @@ void main() { await tester.pumpAndSettle(); expect( - find.byKey(const Key('create_filter_rule_button_within_empty_email')), + find.byKey(const Key('empty_email_sub_message')), findsNothing); final emptyEmailMessageWidgetFinder = find.byKey(const Key('empty_email_message')); @@ -200,10 +199,6 @@ void main() { await tester.pumpAndSettle(); - expect( - find.byKey(const Key('create_filter_rule_button_within_empty_email')), - findsNothing); - final emptyEmailMessageWidgetFinder = find.byKey(const Key('empty_email_message')); final emptyEmailMessageWidget = tester.widget(emptyEmailMessageWidgetFinder); expect(