diff --git a/assets/images/ic_user.svg b/assets/images/ic_user.svg new file mode 100644 index 000000000..1d8da314e --- /dev/null +++ b/assets/images/ic_user.svg @@ -0,0 +1,5 @@ + + + diff --git a/core/lib/presentation/resources/image_paths.dart b/core/lib/presentation/resources/image_paths.dart index a0f761fe9..fde8e9b01 100644 --- a/core/lib/presentation/resources/image_paths.dart +++ b/core/lib/presentation/resources/image_paths.dart @@ -260,6 +260,7 @@ class ImagePaths { String get icInsertLink => _getImagePath('ic_insert_link.svg'); String get icRemoveLink => _getImagePath('ic_remove_link.svg'); String get icText => _getImagePath('ic_text.svg'); + String get icUser => _getImagePath('ic_user.svg'); String _getImagePath(String imageName) { return AssetsPaths.images + imageName; diff --git a/lib/features/manage_account/presentation/menu/settings/setting_user_info_widget.dart b/lib/features/manage_account/presentation/menu/settings/setting_user_info_widget.dart new file mode 100644 index 000000000..07ed4c874 --- /dev/null +++ b/lib/features/manage_account/presentation/menu/settings/setting_user_info_widget.dart @@ -0,0 +1,100 @@ +import 'package:core/presentation/extensions/color_extension.dart'; +import 'package:core/presentation/extensions/string_extension.dart'; +import 'package:core/presentation/resources/image_paths.dart'; +import 'package:core/presentation/utils/theme_utils.dart'; +import 'package:core/presentation/views/dialog/confirm_dialog_button.dart'; +import 'package:flutter/material.dart'; +import 'package:model/extensions/oidc_user_info_extension.dart'; +import 'package:model/oidc/response/oidc_user_info.dart'; +import 'package:tmail_ui_user/features/base/widget/user_avatar_builder.dart'; +import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; + +typedef OnOpenCommonSetting = void Function(OidcUserInfo oidcUserInfo); + +class SettingUserInfoWidget extends StatelessWidget { + final String ownEmailAddress; + final String ownDisplayName; + final OidcUserInfo? oidcUserInfo; + final ImagePaths imagePaths; + final OnOpenCommonSetting? onOpenCommonSetting; + + const SettingUserInfoWidget({ + Key? key, + required this.ownEmailAddress, + required this.imagePaths, + this.ownDisplayName = '', + this.oidcUserInfo, + this.onOpenCommonSetting, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.all(16), + color: Colors.white, + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Row( + children: [ + UserAvatarBuilder( + username: ownEmailAddress.firstLetterToUpperCase, + size: 94, + textStyle: ThemeUtils.textStyleInter500().copyWith( + fontSize: 50, + height: 80 / 50, + letterSpacing: 0.24, + color: Colors.white, + ), + ), + const SizedBox(width: 16), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + if (ownDisplayName.isNotEmpty) + Text( + ownDisplayName, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: ThemeUtils.textStyleInter600().copyWith( + fontSize: 22, + height: 28 / 22, + color: AppColor.gray424244, + ), + ), + Text( + ownEmailAddress, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: ThemeUtils.textStyleM3BodyMedium.copyWith( + color: AppColor.textSecondary.withValues(alpha: 0.48), + ), + ), + ], + ), + ), + ], + ), + if (oidcUserInfo?.isWorkplaceFqdnValid == true) + Container( + constraints: const BoxConstraints(minWidth: 253), + height: 40, + margin: const EdgeInsetsDirectional.only(top: 16), + child: ConfirmDialogButton( + label: AppLocalizations.of(context).manageYourTwakeAccount, + backgroundColor: Colors.white, + textColor: AppColor.primaryMain, + borderColor: AppColor.primaryMain, + icon: imagePaths.icUser, + iconSize: 18, + onTapAction: () => onOpenCommonSetting?.call(oidcUserInfo!), + ), + ) + ], + ), + ); + } +} 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 6cf0d6922..8af294c48 100644 --- a/lib/features/manage_account/presentation/menu/settings/settings_controller.dart +++ b/lib/features/manage_account/presentation/menu/settings/settings_controller.dart @@ -1,7 +1,10 @@ import 'package:core/presentation/resources/image_paths.dart'; import 'package:core/presentation/utils/responsive_utils.dart'; +import 'package:core/utils/app_logger.dart'; +import 'package:core/utils/web_link_generator.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; +import 'package:model/oidc/response/oidc_user_info.dart'; import 'package:tmail_ui_user/features/base/mixin/contact_support_mixin.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/profile_setting/profile_setting_action_type.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/extensions/export_trace_log_extension.dart'; @@ -9,6 +12,7 @@ import 'package:tmail_ui_user/features/manage_account/presentation/extensions/ha 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'; +import 'package:tmail_ui_user/main/utils/app_utils.dart'; class SettingsController extends GetxController with ContactSupportMixin { final manageAccountDashboardController = Get.find(); @@ -40,4 +44,13 @@ class SettingsController extends GetxController with ContactSupportMixin { void showExportTraceLogConfirmDialog(BuildContext context) { manageAccountDashboardController.showExportTraceLogConfirmDialog(context); } + + void goToCommonSetting(OidcUserInfo oidcUserInfo) { + final commonSettingUrl = WebLinkGenerator.safeGenerateWebLink( + workplaceFqdn: oidcUserInfo.workplaceFqdn!, + slug: 'settings', + ); + log('$runtimeType::goToCommonSetting: CommonSettingUrl is $commonSettingUrl'); + AppUtils.launchLink(commonSettingUrl); + } } \ No newline at end of file diff --git a/lib/features/manage_account/presentation/menu/settings/settings_first_level_view.dart b/lib/features/manage_account/presentation/menu/settings/settings_first_level_view.dart index d8de0eac7..646815f70 100644 --- a/lib/features/manage_account/presentation/menu/settings/settings_first_level_view.dart +++ b/lib/features/manage_account/presentation/menu/settings/settings_first_level_view.dart @@ -5,6 +5,7 @@ import 'package:get/get.dart'; import 'package:model/extensions/session_extension.dart'; import 'package:tmail_ui_user/features/home/domain/extensions/session_extensions.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/widgets/user_information_widget.dart'; +import 'package:tmail_ui_user/features/manage_account/presentation/menu/settings/setting_user_info_widget.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_utils.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/menu/widgets/setting_first_level_tile_builder.dart'; @@ -36,25 +37,46 @@ class SettingsFirstLevelView extends GetWidget { key: const Key('setting_menu'), child: Column(children: [ Obx(() { - String accountDisplayName = controller + String ownEmailAddress = controller .manageAccountDashboardController .ownEmailAddress .value; - if (accountDisplayName.trim().isEmpty) { - accountDisplayName = controller + if (ownEmailAddress.trim().isEmpty) { + ownEmailAddress = controller .manageAccountDashboardController .sessionCurrent ?.getOwnEmailAddressOrUsername() ?? ''; } - return UserInformationWidget( - ownEmailAddress: accountDisplayName, - padding: SettingsUtils.getPaddingInFirstLevel( - context, - controller.responsiveUtils, - ), - titlePadding: const EdgeInsetsDirectional.only(start: 16), - ); + + if (PlatformInfo.isMobile) { + final ownDisplayName = controller + .manageAccountDashboardController + .sessionCurrent + ?.getUserDisplayName() ?? ''; + + final oidcUserInfo = controller + .manageAccountDashboardController + .twakeAppManager + .oidcUserInfo; + + return SettingUserInfoWidget( + ownEmailAddress: ownEmailAddress, + ownDisplayName: ownDisplayName, + imagePaths: controller.imagePaths, + oidcUserInfo: oidcUserInfo, + onOpenCommonSetting: controller.goToCommonSetting, + ); + } else { + return UserInformationWidget( + ownEmailAddress: ownEmailAddress, + padding: SettingsUtils.getPaddingInFirstLevel( + context, + controller.responsiveUtils, + ), + titlePadding: const EdgeInsetsDirectional.only(start: 16), + ); + } }), divider, _buildSettingItem( diff --git a/lib/l10n/intl_messages.arb b/lib/l10n/intl_messages.arb index a0d8d52e1..dae6bb758 100644 --- a/lib/l10n/intl_messages.arb +++ b/lib/l10n/intl_messages.arb @@ -1,5 +1,5 @@ { - "@@last_modified": "2025-11-10T12:07:59.064737", + "@@last_modified": "2025-11-12T23:59:36.025917", "initializing_data": "Initializing data...", "@initializing_data": { "type": "text", @@ -5111,5 +5111,11 @@ "type": "text", "placeholders_order": [], "placeholders": {} + }, + "manageYourTwakeAccount": "Manage your Twake account", + "@manageYourTwakeAccount": { + "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 718f60a6e..241b9f9c5 100644 --- a/lib/main/localizations/app_localizations.dart +++ b/lib/main/localizations/app_localizations.dart @@ -5415,4 +5415,11 @@ class AppLocalizations { name: 'apply', ); } + + String get manageYourTwakeAccount { + return Intl.message( + 'Manage your Twake account', + name: 'manageYourTwakeAccount', + ); + } } diff --git a/model/lib/extensions/oidc_user_info_extension.dart b/model/lib/extensions/oidc_user_info_extension.dart new file mode 100644 index 000000000..d5bca2925 --- /dev/null +++ b/model/lib/extensions/oidc_user_info_extension.dart @@ -0,0 +1,5 @@ +import 'package:model/oidc/response/oidc_user_info.dart'; + +extension OidcUserInfoExtension on OidcUserInfo { + bool get isWorkplaceFqdnValid => workplaceFqdn?.trim().isNotEmpty == true; +} diff --git a/model/lib/model.dart b/model/lib/model.dart index 77fd5e9a3..972f1b572 100644 --- a/model/lib/model.dart +++ b/model/lib/model.dart @@ -62,6 +62,7 @@ export 'extensions/utc_date_extension.dart'; export 'extensions/contact_support_capability_extension.dart'; export 'extensions/list_id_extension.dart'; export 'extensions/set_email_body_part_extension.dart'; +export 'extensions/oidc_user_info_extension.dart'; // Identity export 'identity/identity_request_dto.dart'; export 'mailbox/expand_mode.dart';