diff --git a/assets/images/ic_arrow_back.svg b/assets/images/ic_arrow_back.svg new file mode 100644 index 000000000..5e37af032 --- /dev/null +++ b/assets/images/ic_arrow_back.svg @@ -0,0 +1,3 @@ + + + diff --git a/core/lib/presentation/resources/image_paths.dart b/core/lib/presentation/resources/image_paths.dart index 9a0640c99..379370f16 100644 --- a/core/lib/presentation/resources/image_paths.dart +++ b/core/lib/presentation/resources/image_paths.dart @@ -231,7 +231,10 @@ class ImagePaths { String get icDoubleArrowDown => _getImagePath('ic_double_arrow_down.svg'); String get icRefreshQuotas => _getImagePath('ic_refresh_quotas.svg'); String get icCreateFilter => _getImagePath('ic_create_filter.svg'); + String get icArrowBack => _getImagePath('ic_arrow_back.svg'); + String get icTwakeWorkplace => _getIconPath('icon_twp.png'); + String get animLottieTmail => _getAnimationPath('lottie-tmail.json'); String _getImagePath(String imageName) { diff --git a/core/lib/presentation/utils/theme_utils.dart b/core/lib/presentation/utils/theme_utils.dart index 4779e69ec..1ca480027 100644 --- a/core/lib/presentation/utils/theme_utils.dart +++ b/core/lib/presentation/utils/theme_utils.dart @@ -280,6 +280,15 @@ class ThemeUtils { color: AppColor.textSecondary.withOpacity(0.48), ); + static const TextStyle textStyleM3BodyLarge = TextStyle( + fontFamily: ConstantsUI.fontApp, + fontWeight: FontWeight.w500, + letterSpacing: 00.15, + fontSize: 17, + height: 24 / 17, + color: AppColor.m3SurfaceBackground, + ); + static TextStyle textStyleAppShortcut() => const TextStyle( fontFamily: ConstantsUI.fontApp, fontWeight: FontWeight.normal, diff --git a/core/lib/utils/logger/log_tracking.dart b/core/lib/utils/logger/log_tracking.dart index de05fb61e..f6a64009f 100644 --- a/core/lib/utils/logger/log_tracking.dart +++ b/core/lib/utils/logger/log_tracking.dart @@ -23,6 +23,7 @@ class LogTracking { final Queue _messagesQueue = Queue(); bool _isScheduled = false; + bool isEnabled = false; Future addLog({required String message}) async { try { diff --git a/lib/features/manage_account/presentation/email_rules/widgets/email_rules_header_widget.dart b/lib/features/manage_account/presentation/email_rules/widgets/email_rules_header_widget.dart index e2d92b149..990e24141 100644 --- a/lib/features/manage_account/presentation/email_rules/widgets/email_rules_header_widget.dart +++ b/lib/features/manage_account/presentation/email_rules/widgets/email_rules_header_widget.dart @@ -35,7 +35,10 @@ class EmailRulesHeaderWidget extends StatelessWidget { if (responsiveUtils.isWebDesktop(context)) const SettingHeaderWidget(menuItem: AccountMenuItem.emailRules) else - const SettingExplanationWidget(menuItem: AccountMenuItem.emailRules), + const SettingExplanationWidget( + menuItem: AccountMenuItem.emailRules, + padding: EdgeInsets.all(16), + ), Padding( padding: const EdgeInsets.all(16), child: _buildButtonAddNewRule(context), diff --git a/lib/features/manage_account/presentation/language_and_region/extensions/locale_extension.dart b/lib/features/manage_account/presentation/language_and_region/extensions/locale_extension.dart index d5254461c..d4e5a7483 100644 --- a/lib/features/manage_account/presentation/language_and_region/extensions/locale_extension.dart +++ b/lib/features/manage_account/presentation/language_and_region/extensions/locale_extension.dart @@ -4,22 +4,22 @@ import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; extension LocaleExtension on Locale { - String getLanguageNameByCurrentLocale(BuildContext context) { + String getLanguageNameByCurrentLocale(AppLocalizations appLocalizations) { switch(languageCode) { case 'fr': - return AppLocalizations.of(context).languageFrench; + return appLocalizations.languageFrench; case 'en': - return AppLocalizations.of(context).languageEnglish; + return appLocalizations.languageEnglish; case 'vi': - return AppLocalizations.of(context).languageVietnamese; + return appLocalizations.languageVietnamese; case 'ru': - return AppLocalizations.of(context).languageRussian; + return appLocalizations.languageRussian; case 'ar': - return AppLocalizations.of(context).languageArabic; + return appLocalizations.languageArabic; case 'it': - return AppLocalizations.of(context).languageItalian; + return appLocalizations.languageItalian; case 'de': - return AppLocalizations.of(context).languageGerman; + return appLocalizations.languageGerman; default: return ''; } diff --git a/lib/features/manage_account/presentation/language_and_region/language_and_region_controller.dart b/lib/features/manage_account/presentation/language_and_region/language_and_region_controller.dart index b3706d158..cae7ebe6c 100644 --- a/lib/features/manage_account/presentation/language_and_region/language_and_region_controller.dart +++ b/lib/features/manage_account/presentation/language_and_region/language_and_region_controller.dart @@ -1,8 +1,6 @@ - -import 'dart:ui'; - import 'package:core/presentation/state/success.dart'; import 'package:core/utils/app_logger.dart'; +import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:server_settings/server_settings/capability_server_settings.dart'; import 'package:tmail_ui_user/features/base/base_controller.dart'; @@ -11,8 +9,11 @@ import 'package:tmail_ui_user/features/manage_account/domain/state/save_language import 'package:tmail_ui_user/features/manage_account/domain/usecases/save_language_interactor.dart'; import 'package:tmail_ui_user/features/manage_account/domain/usecases/save_language_to_server_settings_interactor.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/manage_account_dashboard_controller.dart'; +import 'package:tmail_ui_user/features/manage_account/presentation/model/language/context_item_language_action.dart'; import 'package:tmail_ui_user/main/error/capability_validator.dart'; +import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; import 'package:tmail_ui_user/main/localizations/localization_service.dart'; +import 'package:tmail_ui_user/main/routes/route_navigation.dart'; class LanguageAndRegionController extends BaseController { @@ -75,4 +76,24 @@ class LanguageAndRegionController extends BaseController { localeCurrent, )); } + + void openLanguageContextMenu(BuildContext context) { + final contextMenuActions = listSupportedLanguages.map((language) { + return ContextItemLanguageAction( + language, + languageSelected.value, + AppLocalizations.of(context), + imagePaths, + ); + }).toList(); + + openBottomSheetContextMenuAction( + context: context, + itemActions: contextMenuActions, + onContextMenuActionClick: (menuAction) { + popBack(); + selectLanguage(menuAction.action); + }, + ); + } } \ No newline at end of file diff --git a/lib/features/manage_account/presentation/language_and_region/language_and_region_view.dart b/lib/features/manage_account/presentation/language_and_region/language_and_region_view.dart index 02b8535a2..d93236d82 100644 --- a/lib/features/manage_account/presentation/language_and_region/language_and_region_view.dart +++ b/lib/features/manage_account/presentation/language_and_region/language_and_region_view.dart @@ -45,11 +45,20 @@ class LanguageAndRegionView extends GetWidget { else const SettingExplanationWidget( menuItem: AccountMenuItem.languageAndRegion, + padding: EdgeInsetsDirectional.only( + start: 16, + end: 16, + bottom: 16, + ), + isCenter: true, ), - const Expanded( + Expanded( child: Padding( - padding: EdgeInsets.only(top: 39), - child: ChangeLanguageButtonWidget(), + padding: const EdgeInsets.only(top: 39), + child: ChangeLanguageButtonWidget( + onOpenLanguageContextMenu: + controller.openLanguageContextMenu, + ), ), ), ], diff --git a/lib/features/manage_account/presentation/language_and_region/widgets/change_language_button_widget.dart b/lib/features/manage_account/presentation/language_and_region/widgets/change_language_button_widget.dart index 3f71e29b1..a2784b12d 100644 --- a/lib/features/manage_account/presentation/language_and_region/widgets/change_language_button_widget.dart +++ b/lib/features/manage_account/presentation/language_and_region/widgets/change_language_button_widget.dart @@ -12,9 +12,16 @@ import 'package:tmail_ui_user/features/manage_account/presentation/language_and_ import 'package:tmail_ui_user/features/manage_account/presentation/language_and_region/widgets/language_menu_overlay.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; +typedef OnOpenLanguageContextMenuAction = Function(BuildContext context); + class ChangeLanguageButtonWidget extends StatefulWidget { - const ChangeLanguageButtonWidget({Key? key}) : super(key: key); + final OnOpenLanguageContextMenuAction? onOpenLanguageContextMenu; + + const ChangeLanguageButtonWidget({ + Key? key, + this.onOpenLanguageContextMenu, + }) : super(key: key); @override State createState() => _ChangeLanguageButtonWidgetState(); @@ -44,15 +51,19 @@ class _ChangeLanguageButtonWidgetState extends State ], ); } else { - return Scaffold( - body: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - _buildTitleLanguageWidget(context), - const SizedBox(height: 8), - _buildLanguageMenu(context, double.infinity), - ], - ), + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: _getMobileTitlePadding(context), + child: _buildTitleLanguageWidget(context), + ), + const SizedBox(height: 12), + Padding( + padding: _getMobileLanguageMenuPadding(context), + child: _buildMobileLanguageMenu(context), + ), + ], ); } } @@ -90,7 +101,7 @@ class _ChangeLanguageButtonWidgetState extends State widthFactor: 1, ), ), - portalFollower: Obx(() => LanguageRegionOverlay( + portalFollower: LanguageRegionOverlay( imagePaths: _imagePaths, responsiveUtils: _responsiveUtils, listSupportedLanguages: _languageAndRegionController.listSupportedLanguages, @@ -100,13 +111,13 @@ class _ChangeLanguageButtonWidgetState extends State _toggleLanguageMenuOverlay(false); _languageAndRegionController.selectLanguage(language); }, - )), + ), visible: isVisible, child: TMailDropDownWidget( text: _languageAndRegionController .languageSelected .value - .getLanguageNameByCurrentLocale(context), + .getLanguageNameByCurrentLocale(AppLocalizations.of(context)), dropDownIcon: _imagePaths.icDropDown, backgroundColor: isVisible ? AppColor.lightGrayEBEDF0.withOpacity(0.6) @@ -119,13 +130,38 @@ class _ChangeLanguageButtonWidgetState extends State ); } + Widget _buildMobileLanguageMenu(BuildContext context) { + return Obx(() => TMailDropDownWidget( + text: _languageAndRegionController + .languageSelected + .value + .getLanguageNameByCurrentLocale(AppLocalizations.of(context)), + dropDownIcon: _imagePaths.icDropDown, + onTap: () => widget.onOpenLanguageContextMenu?.call(context), + )); + } + void _toggleLanguageMenuOverlay(bool visible) { _languageMenuIsVisibleNotifier.value = visible; } - @override - void dispose() { - _languageMenuIsVisibleNotifier.dispose(); - super.dispose(); + EdgeInsetsGeometry _getMobileTitlePadding(BuildContext context) { + if (_responsiveUtils.isPortraitMobile(context)) { + return const EdgeInsetsDirectional.symmetric(horizontal: 28); + } else if (_responsiveUtils.isLandscapeMobile(context)) { + return const EdgeInsetsDirectional.symmetric(horizontal: 40); + } else { + return const EdgeInsetsDirectional.symmetric(horizontal: 50); + } + } + + EdgeInsetsGeometry _getMobileLanguageMenuPadding(BuildContext context) { + if (_responsiveUtils.isPortraitMobile(context)) { + return const EdgeInsetsDirectional.symmetric(horizontal: 20); + } else if (_responsiveUtils.isLandscapeMobile(context)) { + return const EdgeInsetsDirectional.symmetric(horizontal: 24); + } else { + return const EdgeInsetsDirectional.symmetric(horizontal: 44); + } } } \ No newline at end of file diff --git a/lib/features/manage_account/presentation/language_and_region/widgets/lanuage_item_widget.dart b/lib/features/manage_account/presentation/language_and_region/widgets/lanuage_item_widget.dart index da28d5e89..9b1e290d5 100644 --- a/lib/features/manage_account/presentation/language_and_region/widgets/lanuage_item_widget.dart +++ b/lib/features/manage_account/presentation/language_and_region/widgets/lanuage_item_widget.dart @@ -4,6 +4,7 @@ import 'package:core/presentation/utils/theme_utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/language_and_region/extensions/locale_extension.dart'; +import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; typedef OnSelectLanguageAction = Function(Locale? localeSelected); @@ -35,7 +36,7 @@ class LanguageItemWidget extends StatelessWidget { height: 51, child: Row(children: [ Expanded(child: Text( - '${localeCurrent.getLanguageNameByCurrentLocale(context)} - ${localeCurrent.getSourceLanguageName()}', + '${localeCurrent.getLanguageNameByCurrentLocale(AppLocalizations.of(context))} - ${localeCurrent.getSourceLanguageName()}', style: ThemeUtils.textStyleInter400.copyWith( letterSpacing: -0.15, fontSize: 16, diff --git a/lib/features/manage_account/presentation/manage_account_dashboard_controller.dart b/lib/features/manage_account/presentation/manage_account_dashboard_controller.dart index 8ae32f154..413eb4cb2 100644 --- a/lib/features/manage_account/presentation/manage_account_dashboard_controller.dart +++ b/lib/features/manage_account/presentation/manage_account_dashboard_controller.dart @@ -62,7 +62,7 @@ class ManageAccountDashBoardController extends ReloadableController { void onInit() { BackButtonInterceptor.add(_onBackButtonInterceptor, name: AppRoutes.settings); super.onInit(); - if (AppConfig.isApiLoggingEnabled) { + if (LogTracking().isEnabled) { injectTraceLogDependencies(); } } @@ -405,7 +405,7 @@ class ManageAccountDashBoardController extends ReloadableController { @override void onClose() { BackButtonInterceptor.removeByName(AppRoutes.settings); - if (AppConfig.isApiLoggingEnabled) { + if (LogTracking().isEnabled) { disposeTraceLogDependencies(); } super.onClose(); diff --git a/lib/features/manage_account/presentation/manage_account_dashboard_view.dart b/lib/features/manage_account/presentation/manage_account_dashboard_view.dart index c1d56131a..2311874e3 100644 --- a/lib/features/manage_account/presentation/manage_account_dashboard_view.dart +++ b/lib/features/manage_account/presentation/manage_account_dashboard_view.dart @@ -102,11 +102,7 @@ class ManageAccountDashBoardView extends GetWidget - controller.backToMailboxDashBoard(context: context)), - ) + mobile: const SafeArea(child: SettingsView()) ), ), ), diff --git a/lib/features/manage_account/presentation/menu/settings/setting_app_bar.dart b/lib/features/manage_account/presentation/menu/settings/setting_app_bar.dart new file mode 100644 index 000000000..0ddb0bd29 --- /dev/null +++ b/lib/features/manage_account/presentation/menu/settings/setting_app_bar.dart @@ -0,0 +1,45 @@ +import 'package:core/presentation/resources/image_paths.dart'; +import 'package:core/presentation/utils/responsive_utils.dart'; +import 'package:flutter/material.dart'; +import 'package:tmail_ui_user/features/manage_account/presentation/menu/settings/setting_first_level_app_bar.dart'; +import 'package:tmail_ui_user/features/manage_account/presentation/menu/settings/universal_setting_app_bar.dart'; +import 'package:tmail_ui_user/features/manage_account/presentation/model/account_menu_item.dart'; +import 'package:tmail_ui_user/features/manage_account/presentation/model/settings_page_level.dart'; + +class SettingAppBar extends StatelessWidget { + final SettingsPageLevel pageLevel; + final AccountMenuItem accountMenuItem; + final ImagePaths imagePaths; + final ResponsiveUtils responsiveUtils; + final VoidCallback onBackAction; + final VoidCallback? onExportTraceLogAction; + + const SettingAppBar({ + super.key, + required this.pageLevel, + required this.accountMenuItem, + required this.imagePaths, + required this.responsiveUtils, + required this.onBackAction, + this.onExportTraceLogAction, + }); + + @override + Widget build(BuildContext context) { + if (pageLevel == SettingsPageLevel.universal) { + return UniversalSettingAppBar( + imagePaths: imagePaths, + responsiveUtils: responsiveUtils, + onBackAction: onBackAction, + onExportTraceLogAction: onExportTraceLogAction, + ); + } else { + return SettingFirstLevelAppBar( + accountMenuItem: accountMenuItem, + imagePaths: imagePaths, + responsiveUtils: responsiveUtils, + onBackAction: onBackAction, + ); + } + } +} diff --git a/lib/features/manage_account/presentation/menu/settings/setting_first_level_app_bar.dart b/lib/features/manage_account/presentation/menu/settings/setting_first_level_app_bar.dart new file mode 100644 index 000000000..917c9280a --- /dev/null +++ b/lib/features/manage_account/presentation/menu/settings/setting_first_level_app_bar.dart @@ -0,0 +1,67 @@ +import 'package:core/presentation/resources/image_paths.dart'; +import 'package:core/presentation/utils/responsive_utils.dart'; +import 'package:core/presentation/utils/theme_utils.dart'; +import 'package:core/presentation/views/button/tmail_button_widget.dart'; +import 'package:flutter/material.dart'; +import 'package:tmail_ui_user/features/manage_account/presentation/model/account_menu_item.dart'; +import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; + +class SettingFirstLevelAppBar extends StatelessWidget { + final AccountMenuItem accountMenuItem; + final ImagePaths imagePaths; + final ResponsiveUtils responsiveUtils; + final VoidCallback onBackAction; + + const SettingFirstLevelAppBar({ + super.key, + required this.accountMenuItem, + required this.imagePaths, + required this.responsiveUtils, + required this.onBackAction, + }); + + @override + Widget build(BuildContext context) { + final appLocalizations = AppLocalizations.of(context); + + return Container( + height: 64, + padding: _getPadding(context), + child: Stack( + alignment: Alignment.center, + children: [ + PositionedDirectional( + start: 0, + child: TMailButtonWidget.fromIcon( + icon: imagePaths.icArrowBack, + tooltipMessage: appLocalizations.back, + backgroundColor: Colors.transparent, + onTapActionCallback: onBackAction, + ), + ), + Center( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 50), + child: Text( + accountMenuItem.getName(appLocalizations), + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: ThemeUtils.textStyleM3BodyLarge, + ), + ), + ), + ], + ), + ); + } + + EdgeInsetsGeometry _getPadding(BuildContext context) { + if (responsiveUtils.isPortraitMobile(context)) { + return const EdgeInsetsDirectional.symmetric(horizontal: 16); + } else if (responsiveUtils.isLandscapeMobile(context)) { + return const EdgeInsetsDirectional.symmetric(horizontal: 24); + } else { + return const EdgeInsetsDirectional.symmetric(horizontal: 32); + } + } +} diff --git a/lib/features/manage_account/presentation/menu/settings/settings_controller.dart b/lib/features/manage_account/presentation/menu/settings/settings_controller.dart index a1bb5e454..e467bac82 100644 --- a/lib/features/manage_account/presentation/menu/settings/settings_controller.dart +++ b/lib/features/manage_account/presentation/menu/settings/settings_controller.dart @@ -1,9 +1,12 @@ import 'package:core/presentation/resources/image_paths.dart'; import 'package:core/presentation/utils/responsive_utils.dart'; +import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:tmail_ui_user/features/base/mixin/contact_support_mixin.dart'; +import 'package:tmail_ui_user/features/manage_account/presentation/extensions/export_trace_log_extension.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/manage_account_dashboard_controller.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/model/account_menu_item.dart'; +import 'package:tmail_ui_user/features/manage_account/presentation/model/settings_page_level.dart'; class SettingsController extends GetxController with ContactSupportMixin { final manageAccountDashboardController = Get.find(); @@ -13,4 +16,17 @@ class SettingsController extends GetxController with ContactSupportMixin { void selectSettings(AccountMenuItem accountMenuItem) => manageAccountDashboardController.selectSettings(accountMenuItem); void backToUniversalSettings() => manageAccountDashboardController.backToUniversalSettings(); + + void onBackSettingAction(BuildContext context) { + if (manageAccountDashboardController.settingsPageLevel.value == + SettingsPageLevel.universal) { + manageAccountDashboardController.backToMailboxDashBoard(context: context); + } else { + backToUniversalSettings(); + } + } + + void showExportTraceLogConfirmDialog(BuildContext context) { + manageAccountDashboardController.showExportTraceLogConfirmDialog(context); + } } \ No newline at end of file diff --git a/lib/features/manage_account/presentation/menu/settings/settings_view.dart b/lib/features/manage_account/presentation/menu/settings/settings_view.dart index 2fd808022..0900f1a73 100644 --- a/lib/features/manage_account/presentation/menu/settings/settings_view.dart +++ b/lib/features/manage_account/presentation/menu/settings/settings_view.dart @@ -1,21 +1,13 @@ -import 'package:core/presentation/extensions/color_extension.dart'; -import 'package:core/presentation/utils/style_utils.dart'; -import 'package:core/presentation/utils/theme_utils.dart'; -import 'package:core/presentation/views/button/icon_button_web.dart'; -import 'package:core/presentation/views/button/multi_click_widget.dart'; -import 'package:core/utils/direction_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/manage_account/presentation/email_rules/email_rules_view.dart'; -import 'package:tmail_ui_user/features/manage_account/presentation/extensions/export_trace_log_extension.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/extensions/vacation_response_extension.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/forward/forward_view.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/language_and_region/language_and_region_view.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/mailbox_visibility/mailbox_visibility_view.dart'; +import 'package:tmail_ui_user/features/manage_account/presentation/menu/settings/setting_app_bar.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/menu/settings/settings_controller.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/menu/settings/settings_first_level_view.dart'; -import 'package:tmail_ui_user/features/manage_account/presentation/menu/settings_utils.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/model/account_menu_item.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/model/settings_page_level.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/notification/notification_view.dart'; @@ -23,27 +15,30 @@ import 'package:tmail_ui_user/features/manage_account/presentation/preferences/p import 'package:tmail_ui_user/features/manage_account/presentation/profiles/profiles_view.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/vacation/vacation_view.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/vacation/widgets/vacation_notification_message_widget.dart'; -import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; -import 'package:tmail_ui_user/main/utils/app_config.dart'; - -typedef CloseSettingsViewAction = void Function(); class SettingsView extends GetWidget { - const SettingsView({Key? key, this.closeAction}) : super(key: key); - - final CloseSettingsViewAction? closeAction; + const SettingsView({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - SizedBox.fromSize( - size: const Size.fromHeight(52), - child: Padding( - padding: SettingsUtils.getPaddingAppBar(context, controller.responsiveUtils), - child: _buildAppbar(context))), - const Divider(color: AppColor.colorDividerComposer, height: 1), + Obx(() => SettingAppBar( + pageLevel: controller + .manageAccountDashboardController + .settingsPageLevel + .value, + accountMenuItem: controller + .manageAccountDashboardController + .accountMenuItemSelected + .value, + imagePaths: controller.imagePaths, + responsiveUtils: controller.responsiveUtils, + onBackAction: () => controller.onBackSettingAction(context), + onExportTraceLogAction: () => + controller.showExportTraceLogConfirmDialog(context), + )), Obx(() { if (controller.manageAccountDashboardController.vacationResponse.value?.vacationResponderIsValid == true) { return VacationNotificationMessageWidget( @@ -77,110 +72,6 @@ class SettingsView extends GetWidget { ); } - Widget _buildAppbar(BuildContext context) { - return Obx(() { - if (controller.manageAccountDashboardController.settingsPageLevel.value == SettingsPageLevel.universal) { - return _buildUniversalSettingAppBar(context); - } else { - return _buildSettingLevel1AppBar(context); - } - }); - } - - Widget _buildUniversalSettingAppBar(BuildContext context) { - final appBarWidget = Stack( - alignment: Alignment.center, - children: [ - Positioned(left: 0,child: _buildCloseSettingButton(context)), - Padding( - padding: const EdgeInsets.only(left: 50, right: 50), - child: Text( - AppLocalizations.of(context).settings, - maxLines: 1, - softWrap: CommonTextStyle.defaultSoftWrap, - overflow: CommonTextStyle.defaultTextOverFlow, - style: ThemeUtils.defaultTextStyleInterFont.copyWith( - fontSize: 20, - color: AppColor.colorNameEmail, - fontWeight: FontWeight.w700, - ), - ), - ), - ], - ); - - if (AppConfig.isApiLoggingEnabled) { - return MultiClickWidget( - onMultiTap: () => controller - .manageAccountDashboardController - .showExportTraceLogConfirmDialog(context), - child: appBarWidget, - ); - } else { - return appBarWidget; - } - } - - Widget _buildSettingLevel1AppBar(BuildContext context) { - return Row(children: [ - Material( - color: Colors.transparent, - child: InkWell( - onTap: controller.backToUniversalSettings, - customBorder: const RoundedRectangleBorder( - borderRadius: BorderRadius.all(Radius.circular(15))), - child: Tooltip( - message: AppLocalizations.of(context).back, - child: Container( - color: Colors.transparent, - height: 40, - padding: const EdgeInsets.symmetric(horizontal: 4), - child: Row(mainAxisSize: MainAxisSize.min, children: [ - SvgPicture.asset( - DirectionUtils.isDirectionRTLByLanguage(context) - ? controller.imagePaths.icCollapseFolder - : controller.imagePaths.icBack, - colorFilter: AppColor.colorTextButton.asFilter(), - fit: BoxFit.fill), - Container( - margin: const EdgeInsetsDirectional.only(start: 4), - constraints: const BoxConstraints(maxWidth: 80), - child: Text( - AppLocalizations.of(context).settings, - maxLines: 1, - overflow: CommonTextStyle.defaultTextOverFlow, - softWrap: CommonTextStyle.defaultSoftWrap, - style: ThemeUtils.defaultTextStyleInterFont.copyWith(fontSize: 17, color: AppColor.colorTextButton) - ) - ), - ]), - ), - ), - ), - ), - Expanded(child: Text( - controller.manageAccountDashboardController.accountMenuItemSelected.value.getName(AppLocalizations.of(context)), - maxLines: 1, - textAlign: TextAlign.center, - overflow: CommonTextStyle.defaultTextOverFlow, - softWrap: CommonTextStyle.defaultSoftWrap, - style: ThemeUtils.defaultTextStyleInterFont.copyWith( - fontSize: 20, - color: Colors.black, - fontWeight: FontWeight.bold - ) - )), - Container(constraints: const BoxConstraints(maxWidth: 80)) - ]); - } - - Widget _buildCloseSettingButton(BuildContext context) { - return buildIconWeb( - icon: SvgPicture.asset(controller.imagePaths.icClose, width: 28, height: 28, fit: BoxFit.fill), - tooltip: AppLocalizations.of(context).close, - onTap: closeAction); - } - Widget _bodySettingsScreen() { return Obx(() { switch (controller.manageAccountDashboardController.settingsPageLevel.value) { diff --git a/lib/features/manage_account/presentation/menu/settings/universal_setting_app_bar.dart b/lib/features/manage_account/presentation/menu/settings/universal_setting_app_bar.dart new file mode 100644 index 000000000..da7808e46 --- /dev/null +++ b/lib/features/manage_account/presentation/menu/settings/universal_setting_app_bar.dart @@ -0,0 +1,86 @@ +import 'package:core/presentation/resources/image_paths.dart'; +import 'package:core/presentation/utils/responsive_utils.dart'; +import 'package:core/presentation/utils/theme_utils.dart'; +import 'package:core/presentation/views/button/multi_click_widget.dart'; +import 'package:core/presentation/views/button/tmail_button_widget.dart'; +import 'package:core/utils/logger/log_tracking.dart'; +import 'package:flutter/material.dart'; +import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; + +class UniversalSettingAppBar extends StatelessWidget { + final ImagePaths imagePaths; + final ResponsiveUtils responsiveUtils; + final VoidCallback onBackAction; + final VoidCallback? onExportTraceLogAction; + + const UniversalSettingAppBar({ + super.key, + required this.imagePaths, + required this.responsiveUtils, + required this.onBackAction, + this.onExportTraceLogAction, + }); + + @override + Widget build(BuildContext context) { + final appLocalizations = AppLocalizations.of(context); + + Widget appBarWidget = Column( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + height: 52, + padding: _getPadding(context), + child: Stack( + alignment: Alignment.center, + children: [ + PositionedDirectional( + start: 24, + child: TMailButtonWidget.fromIcon( + icon: imagePaths.icClose, + iconSize: 28, + padding: const EdgeInsets.all(5), + tooltipMessage: appLocalizations.close, + backgroundColor: Colors.transparent, + onTapActionCallback: onBackAction, + ), + ), + Center( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 60), + child: Text( + appLocalizations.settings, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: ThemeUtils.textStyleInter700().copyWith( + fontSize: 20, + height: 24 / 20, + ), + ), + ), + ), + ], + ), + ), + const Divider(color: Colors.black12), + ], + ); + + if (onExportTraceLogAction != null && LogTracking().isEnabled) { + return MultiClickWidget( + onMultiTap: onExportTraceLogAction!, + child: appBarWidget, + ); + } else { + return appBarWidget; + } + } + + EdgeInsetsGeometry _getPadding(BuildContext context) { + if (responsiveUtils.isPortraitMobile(context)) { + return EdgeInsetsDirectional.zero; + } else { + return const EdgeInsetsDirectional.symmetric(horizontal: 16); + } + } +} diff --git a/lib/features/manage_account/presentation/menu/settings_utils.dart b/lib/features/manage_account/presentation/menu/settings_utils.dart index 8fbb18d6b..30b9d9bf9 100644 --- a/lib/features/manage_account/presentation/menu/settings_utils.dart +++ b/lib/features/manage_account/presentation/menu/settings_utils.dart @@ -22,16 +22,6 @@ class SettingsUtils { } } - static EdgeInsets getPaddingAppBar(BuildContext context, ResponsiveUtils responsiveUtils) { - if (responsiveUtils.isPortraitMobile(context)) { - return const EdgeInsets.symmetric(horizontal: 16); - } else if (responsiveUtils.isLandscapeMobile(context)) { - return const EdgeInsets.symmetric(horizontal: 12); - } else { - return const EdgeInsets.symmetric(horizontal: 32); - } - } - static EdgeInsets getMarginViewForSettingDetails(BuildContext context, ResponsiveUtils responsiveUtils) { if (PlatformInfo.isWeb) { if (responsiveUtils.isDesktop(context)) { diff --git a/lib/features/manage_account/presentation/model/language/context_item_language_action.dart b/lib/features/manage_account/presentation/model/language/context_item_language_action.dart new file mode 100644 index 000000000..edfe9f59c --- /dev/null +++ b/lib/features/manage_account/presentation/model/language/context_item_language_action.dart @@ -0,0 +1,24 @@ +import 'package:core/presentation/resources/image_paths.dart'; +import 'package:flutter/material.dart'; +import 'package:tmail_ui_user/features/base/widget/context_menu/context_menu_item_action.dart'; +import 'package:tmail_ui_user/features/manage_account/presentation/language_and_region/extensions/locale_extension.dart'; +import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; + +class ContextItemLanguageAction + extends ContextMenuItemActionRequiredSelectedIcon { + final AppLocalizations appLocalizations; + final ImagePaths imagePaths; + + ContextItemLanguageAction( + super.action, + super.selectedAction, + this.appLocalizations, + this.imagePaths, + ); + + @override + String get actionName => '${action.getLanguageNameByCurrentLocale(appLocalizations)} - ${action.getSourceLanguageName()}'; + + @override + String get selectedIcon => imagePaths.icFilterSelected; +} diff --git a/lib/features/manage_account/presentation/widgets/setting_explanation_widget.dart b/lib/features/manage_account/presentation/widgets/setting_explanation_widget.dart index c56be4cd6..5864158f6 100644 --- a/lib/features/manage_account/presentation/widgets/setting_explanation_widget.dart +++ b/lib/features/manage_account/presentation/widgets/setting_explanation_widget.dart @@ -7,21 +7,31 @@ import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; class SettingExplanationWidget extends StatelessWidget { final AccountMenuItem menuItem; final EdgeInsetsGeometry? padding; + final bool isCenter; const SettingExplanationWidget({ Key? key, required this.menuItem, + this.isCenter = false, this.padding, }) : super(key: key); @override Widget build(BuildContext context) { - return Padding( - padding: padding ?? const EdgeInsets.all(16), - child: Text( - menuItem.getExplanation(AppLocalizations.of(context)), - style: ThemeUtils.textStyleBodyBody1(color: AppColor.steelGray400), - ), + Widget child = Text( + menuItem.getExplanation(AppLocalizations.of(context)), + style: ThemeUtils.textStyleM3BodyMedium1 + .copyWith(color: AppColor.gray424244.withOpacity(0.64)), ); + + if (isCenter) { + child = Center(child: child); + } + + if (padding != null) { + child = Padding(padding: padding!, child: child); + } + + return child; } -} \ No newline at end of file +} diff --git a/lib/features/thread/data/network/thread_api.dart b/lib/features/thread/data/network/thread_api.dart index 5772f7bf4..c9d3d2abb 100644 --- a/lib/features/thread/data/network/thread_api.dart +++ b/lib/features/thread/data/network/thread_api.dart @@ -1,7 +1,6 @@ import 'dart:async'; import 'package:core/utils/app_logger.dart'; -import 'package:core/utils/logger/log_tracking.dart'; import 'package:jmap_dart_client/http/http_client.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; import 'package:jmap_dart_client/jmap/core/filter/filter.dart'; @@ -31,7 +30,6 @@ import 'package:tmail_ui_user/features/thread/data/model/email_change_response.d import 'package:tmail_ui_user/features/thread/domain/model/email_response.dart'; import 'package:tmail_ui_user/features/thread/domain/model/search_emails_response.dart'; import 'package:tmail_ui_user/main/error/capability_validator.dart'; -import 'package:tmail_ui_user/main/utils/app_config.dart'; class ThreadAPI { @@ -103,12 +101,7 @@ class ThreadAPI { ?.notFound ?.toEmailIds() .toList(); - log('ThreadAPI::getAllEmail:notFoundEmailIds = $notFoundEmailIds'); - if (notFoundEmailIds?.isNotEmpty == true && AppConfig.isApiLoggingEnabled) { - await LogTracking().addLog( - message: 'ThreadAPI::getAllEmail:notFoundEmailIds = ${notFoundEmailIds!.asListString.toString()} | NewState = ${responseOfGetEmailMethod?.state.value}', - ); - } + log('ThreadAPI::getAllEmail:notFoundEmailIds = ${notFoundEmailIds!.asListString.toString()} | NewState = ${responseOfGetEmailMethod?.state.value}'); return EmailsResponse( emailList: emailList, notFoundEmailIds: notFoundEmailIds, @@ -309,12 +302,7 @@ class ThreadAPI { log('ThreadAPI::getChanges:notFoundIdsUpdated = $notFoundIdsUpdated'); if (notFoundIdsUpdated.isNotEmpty) { destroyedEmailIds.addAll(notFoundIdsUpdated); - - if (AppConfig.isApiLoggingEnabled) { - await LogTracking().addLog( - message: 'ThreadAPI::getChanges:notFoundIdsUpdated = ${notFoundIdsUpdated.asListString.toString()} | SinceState = ${sinceState.value}', - ); - } + log('ThreadAPI::getChanges:notFoundIdsUpdated = ${notFoundIdsUpdated.asListString.toString()} | SinceState = ${sinceState.value}'); } } @@ -329,12 +317,7 @@ class ThreadAPI { log('ThreadAPI::getChanges:notFoundIdsCreated = $notFoundIdsCreated'); if (notFoundIdsCreated.isNotEmpty) { destroyedEmailIds.addAll(notFoundIdsCreated); - - if (AppConfig.isApiLoggingEnabled) { - await LogTracking().addLog( - message: 'ThreadAPI::getChanges:notFoundIdsCreated = ${notFoundIdsCreated.asListString.toString()} | SinceState = ${sinceState.value}', - ); - } + log('ThreadAPI::getChanges:notFoundIdsCreated = ${notFoundIdsCreated.asListString.toString()} | SinceState = ${sinceState.value}'); } } log('ThreadAPI::getChanges:newStateChanges = $newStateChanges | newStateEmail = $newStateEmail | hasMoreChanges = $hasMoreChanges'); diff --git a/lib/main/utils/app_config.dart b/lib/main/utils/app_config.dart index a5b3e5526..0883dda31 100644 --- a/lib/main/utils/app_config.dart +++ b/lib/main/utils/app_config.dart @@ -1,6 +1,5 @@ import 'dart:io'; -import 'package:core/utils/platform_info.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; @@ -14,9 +13,6 @@ class AppConfig { static const int warningAttachmentFileSizeInMegabytes = 10; static const int defaultLimitAutocomplete = 8; - // For testing - static bool isApiLoggingEnabled = PlatformInfo.isAndroid; - static const String envFileName = 'env.file'; static const String appDashboardConfigurationPath = "configurations/app_dashboard.json"; static const String appFCMConfigurationPath = "configurations/env.fcm";