diff --git a/assets/images/ic_help.svg b/assets/images/ic_help.svg new file mode 100644 index 000000000..07b88fa8f --- /dev/null +++ b/assets/images/ic_help.svg @@ -0,0 +1,3 @@ + + + diff --git a/core/lib/presentation/resources/image_paths.dart b/core/lib/presentation/resources/image_paths.dart index 52b6013b1..51206955e 100644 --- a/core/lib/presentation/resources/image_paths.dart +++ b/core/lib/presentation/resources/image_paths.dart @@ -221,6 +221,7 @@ class ImagePaths { String get icBadSignature => _getImagePath('ic_bad_signature.svg'); String get icDeleteSelection => _getImagePath('ic_delete_selection.svg'); String get icLogoTwakeWelcome => _getImagePath('ic_logo_twake_welcome.svg'); + String get icHelp => _getImagePath('ic_help.svg'); String _getImagePath(String imageName) { return AssetsPaths.images + imageName; diff --git a/lib/features/home/domain/extensions/session_extensions.dart b/lib/features/home/domain/extensions/session_extensions.dart index cb01440fb..98e0b88a7 100644 --- a/lib/features/home/domain/extensions/session_extensions.dart +++ b/lib/features/home/domain/extensions/session_extensions.dart @@ -9,6 +9,7 @@ import 'package:get/get.dart'; import 'package:jmap_dart_client/http/converter/state_converter.dart'; import 'package:jmap_dart_client/http/converter/user_name_converter.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; +import 'package:jmap_dart_client/jmap/core/capability/capability_identifier.dart'; import 'package:jmap_dart_client/jmap/core/session/session.dart'; import 'package:jmap_dart_client/jmap/core/unsigned_int.dart'; import 'package:model/model.dart'; @@ -18,6 +19,7 @@ import 'package:tmail_ui_user/features/home/domain/converter/session_capabilitie import 'package:tmail_ui_user/features/home/domain/converter/session_primary_account_converter.dart'; extension SessionExtensions on Session { + static final CapabilityIdentifier linagoraContactSupportCapability = CapabilityIdentifier(Uri.parse('com:linagora:params:jmap:contact:support')); Map toJson() { final val = {}; @@ -79,4 +81,18 @@ extension SessionExtensions on Session { return null; } } + + ContactSupportCapability? getContactSupportCapability(AccountId accountId) { + try { + final contactSupportCapability = getCapabilityProperties( + accountId, + linagoraContactSupportCapability, + ); + log('SessionExtensions::getContactSupport:contactSupportCapability = $contactSupportCapability'); + return contactSupportCapability; + } catch (e) { + logError('SessionExtensions::getContactSupportCapability():[Exception] $e'); + return null; + } + } } \ No newline at end of file diff --git a/lib/features/mailbox_dashboard/presentation/mailbox_dashboard_view_web.dart b/lib/features/mailbox_dashboard/presentation/mailbox_dashboard_view_web.dart index 9b3e329e2..c214085f2 100644 --- a/lib/features/mailbox_dashboard/presentation/mailbox_dashboard_view_web.dart +++ b/lib/features/mailbox_dashboard/presentation/mailbox_dashboard_view_web.dart @@ -11,6 +11,7 @@ import 'package:tmail_ui_user/features/base/widget/scrollbar_list_view.dart'; import 'package:tmail_ui_user/features/composer/presentation/composer_view_web.dart'; import 'package:tmail_ui_user/features/email/presentation/email_view.dart'; import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart'; +import 'package:tmail_ui_user/features/home/domain/extensions/session_extensions.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/mailbox_view_web.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/action/dashboard_action.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/base_mailbox_dashboard_view.dart'; @@ -66,7 +67,9 @@ class MailboxDashBoardView extends BaseMailboxDashBoardView { return const SizedBox.shrink(); } else { return NavigationBarWidget( + imagePaths: controller.imagePaths, avatarUserName: controller.sessionCurrent?.username.firstCharacter ?? '', + contactSupportCapability: controller.sessionCurrent?.getContactSupportCapability(accountId), searchForm: SearchInputFormWidget(), appGridController: controller.appGridDashboardController, onShowAppDashboardAction: controller.showAppDashboardAction, diff --git a/lib/features/mailbox_dashboard/presentation/widgets/app_dashboard/app_grid_dashboard_icon.dart b/lib/features/mailbox_dashboard/presentation/widgets/app_dashboard/app_grid_dashboard_icon.dart index 5d393bbed..885fdfbae 100644 --- a/lib/features/mailbox_dashboard/presentation/widgets/app_dashboard/app_grid_dashboard_icon.dart +++ b/lib/features/mailbox_dashboard/presentation/widgets/app_dashboard/app_grid_dashboard_icon.dart @@ -9,15 +9,15 @@ import 'package:tmail_ui_user/main/utils/app_utils.dart'; class AppGridDashboardIcon extends StatelessWidget { - final ImagePaths _imagePaths = Get.find(); - + final ImagePaths imagePaths; final AppGridDashboardController appGridController; final VoidCallback? onShowAppDashboardAction; - AppGridDashboardIcon({ + const AppGridDashboardIcon({ super.key, + required this.imagePaths, required this.appGridController, - this.onShowAppDashboardAction + this.onShowAppDashboardAction, }); @override @@ -48,7 +48,7 @@ class AppGridDashboardIcon extends StatelessWidget { }), visible: isAppGridOpen, child: TMailButtonWidget.fromIcon( - icon: _imagePaths.icAppDashboard, + icon: imagePaths.icAppDashboard, backgroundColor: Colors.transparent, iconSize: 30, padding: const EdgeInsets.all(6), diff --git a/lib/features/mailbox_dashboard/presentation/widgets/navigation_bar/navigation_bar_widget.dart b/lib/features/mailbox_dashboard/presentation/widgets/navigation_bar/navigation_bar_widget.dart index 21d4ba7c6..2c0207d60 100644 --- a/lib/features/mailbox_dashboard/presentation/widgets/navigation_bar/navigation_bar_widget.dart +++ b/lib/features/mailbox_dashboard/presentation/widgets/navigation_bar/navigation_bar_widget.dart @@ -1,16 +1,22 @@ 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/views/button/tmail_button_widget.dart'; import 'package:core/presentation/views/image/avatar_builder.dart'; import 'package:flutter/material.dart'; +import 'package:model/support/contact_support_capability.dart'; import 'package:tmail_ui_user/features/base/widget/application_logo_with_text_widget.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/app_grid_dashboard_controller.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/styles/navigation_bar_style.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/app_dashboard/app_grid_dashboard_icon.dart'; +import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; import 'package:tmail_ui_user/main/utils/app_config.dart'; class NavigationBarWidget extends StatelessWidget { + final ImagePaths imagePaths; final String avatarUserName; + final ContactSupportCapability? contactSupportCapability; final Widget? searchForm; final AppGridDashboardController? appGridController; final VoidCallback? onTapApplicationLogoAction; @@ -19,7 +25,9 @@ class NavigationBarWidget extends StatelessWidget { const NavigationBarWidget({ super.key, + required this.imagePaths, required this.avatarUserName, + this.contactSupportCapability, this.searchForm, this.appGridController, this.onShowAppDashboardAction, @@ -54,12 +62,24 @@ class NavigationBarWidget extends StatelessWidget { child: searchForm ), const Spacer(), - if (AppConfig.appGridDashboardAvailable && appGridController != null) - AppGridDashboardIcon( - appGridController: appGridController!, - onShowAppDashboardAction: onShowAppDashboardAction, + if (contactSupportCapability != null) + TMailButtonWidget.fromIcon( + icon: imagePaths.icHelp, + iconColor: AppColor.messageDialogColor, + backgroundColor: Colors.transparent, + margin: const EdgeInsetsDirectional.only(end: 8), + tooltipMessage: AppLocalizations.of(context).getHelpOrReportABug, + onTapActionCallback: () {}, + ), + if (AppConfig.appGridDashboardAvailable && appGridController != null) + Padding( + padding: const EdgeInsetsDirectional.only(end: 16), + child: AppGridDashboardIcon( + imagePaths: imagePaths, + appGridController: appGridController!, + onShowAppDashboardAction: onShowAppDashboardAction, + ), ), - const SizedBox(width: 16), (AvatarBuilder() ..text(avatarUserName) ..backgroundColor(Colors.white) @@ -82,12 +102,24 @@ class NavigationBarWidget extends StatelessWidget { else ...[ const Spacer(), - if (AppConfig.appGridDashboardAvailable && appGridController != null) - AppGridDashboardIcon( - appGridController: appGridController!, - onShowAppDashboardAction: onShowAppDashboardAction, + if (contactSupportCapability != null) + TMailButtonWidget.fromIcon( + icon: imagePaths.icHelp, + iconColor: AppColor.messageDialogColor, + backgroundColor: Colors.transparent, + margin: const EdgeInsetsDirectional.only(end: 8), + tooltipMessage: AppLocalizations.of(context).getHelpOrReportABug, + onTapActionCallback: () {}, + ), + if (AppConfig.appGridDashboardAvailable && appGridController != null) + Padding( + padding: const EdgeInsetsDirectional.only(end: 16), + child: AppGridDashboardIcon( + imagePaths: imagePaths, + appGridController: appGridController!, + onShowAppDashboardAction: onShowAppDashboardAction, + ), ), - const SizedBox(width: 16), (AvatarBuilder() ..text(avatarUserName) ..backgroundColor(Colors.white) 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 bfe29c01a..f1e3e74a1 100644 --- a/lib/features/manage_account/presentation/manage_account_dashboard_view.dart +++ b/lib/features/manage_account/presentation/manage_account_dashboard_view.dart @@ -5,6 +5,7 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:model/model.dart'; import 'package:tmail_ui_user/features/base/state/banner_state.dart'; +import 'package:tmail_ui_user/features/home/domain/extensions/session_extensions.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/navigation_bar/navigation_bar_widget.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/always_read_receipt/always_read_receipt_view.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/email_rules/email_rules_view.dart'; @@ -41,7 +42,9 @@ class ManageAccountDashBoardView extends GetWidget controller.backToMailboxDashBoard(context: context), onTapAvatarAction: (position) => controller.handleClickAvatarAction(context, position), ); diff --git a/lib/l10n/intl_messages.arb b/lib/l10n/intl_messages.arb index d4d794eb1..ababfd56d 100644 --- a/lib/l10n/intl_messages.arb +++ b/lib/l10n/intl_messages.arb @@ -4071,5 +4071,11 @@ "type": "text", "placeholders_order": [], "placeholders": {} + }, + "getHelpOrReportABug": "Get help or report a bug", + "@getHelpOrReportABug": { + "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 9dac836f6..01ff076bd 100644 --- a/lib/main/localizations/app_localizations.dart +++ b/lib/main/localizations/app_localizations.dart @@ -4273,4 +4273,11 @@ class AppLocalizations { name: 'createTwakeIdFailed', ); } + + String get getHelpOrReportABug { + return Intl.message( + 'Get help or report a bug', + name: 'getHelpOrReportABug', + ); + } } diff --git a/model/lib/model.dart b/model/lib/model.dart index 2835ec4df..1cfbf702b 100644 --- a/model/lib/model.dart +++ b/model/lib/model.dart @@ -79,4 +79,6 @@ export 'oidc/token_id.dart'; export 'oidc/token_oidc.dart'; // Upload export 'upload/file_info.dart'; -export 'upload/upload_response.dart'; \ No newline at end of file +export 'upload/upload_response.dart'; +// Support +export 'support/contact_support_capability.dart'; \ No newline at end of file diff --git a/model/lib/support/contact_support_capability.dart b/model/lib/support/contact_support_capability.dart new file mode 100644 index 000000000..214243661 --- /dev/null +++ b/model/lib/support/contact_support_capability.dart @@ -0,0 +1,24 @@ + +import 'package:jmap_dart_client/jmap/core/capability/capability_properties.dart'; +import 'package:json_annotation/json_annotation.dart'; + +part 'contact_support_capability.g.dart'; + +@JsonSerializable(explicitToJson: true, includeIfNull: false) +class ContactSupportCapability extends CapabilityProperties { + final String? httpLink; + final String? supportMailAddress; + + ContactSupportCapability({this.httpLink, this.supportMailAddress}); + + factory ContactSupportCapability.fromJson(Map json) => _$ContactSupportCapabilityFromJson(json); + + Map toJson() => _$ContactSupportCapabilityToJson(this); + + static ContactSupportCapability deserialize(Map json) { + return ContactSupportCapability.fromJson(json); + } + + @override + List get props => [httpLink, supportMailAddress]; +} \ No newline at end of file