From 038aba0af39348134e82dd467af92b8c0b73dceb Mon Sep 17 00:00:00 2001 From: dab246 Date: Mon, 29 Sep 2025 18:10:44 +0700 Subject: [PATCH] TF-4068 Change profile (set identity as default) in setting --- .../widgets/login_message_widget.dart | 23 ++--- .../model/edit_default_identity_request.dart | 1 + .../domain/model/edit_identity_request.dart | 16 ++- .../state/edit_default_identity_state.dart | 11 ++- .../domain/state/edit_identity_state.dart | 13 ++- .../edit_default_identity_interactor.dart | 11 ++- .../change_identity_as_default_extension.dart | 45 +++++++++ .../extensions/identity_extension.dart | 30 ++++++ .../identities/identities_controller.dart | 27 +++-- .../identities/identities_view.dart | 68 ++++++++----- .../widgets/identity_list_tile_builder.dart | 80 ++++++++++----- lib/l10n/intl_messages.arb | 6 ++ lib/main/localizations/app_localizations.dart | 7 ++ lib/main/utils/toast_manager.dart | 98 ++++++++++--------- 14 files changed, 313 insertions(+), 123 deletions(-) create mode 100644 lib/features/manage_account/presentation/extensions/change_identity_as_default_extension.dart diff --git a/lib/features/login/presentation/widgets/login_message_widget.dart b/lib/features/login/presentation/widgets/login_message_widget.dart index 0ced7fe9c..43fb8242c 100644 --- a/lib/features/login/presentation/widgets/login_message_widget.dart +++ b/lib/features/login/presentation/widgets/login_message_widget.dart @@ -35,6 +35,7 @@ class LoginMessageWidget extends StatelessWidget { @override Widget build(BuildContext context) { + final appLocalizations = AppLocalizations.of(context); return Padding( padding: const EdgeInsetsDirectional.only( top: 11, @@ -50,34 +51,34 @@ class LoginMessageWidget extends StatelessWidget { viewState.fold( (failure) { if (failure is FeatureFailure && failure.exception is NoNetworkError) { - return AppLocalizations.of(context).youAreOffline; + return appLocalizations.youAreOffline; } if (failure is GetOIDCConfigurationFailure) { - return AppLocalizations.of(context).canNotVerifySSOConfiguration; + return appLocalizations.canNotVerifySSOConfiguration; } else if (failure is DNSLookupToGetJmapUrlFailure) { - return AppLocalizations.of(context).dnsLookupLoginMessage; + return appLocalizations.dnsLookupLoginMessage; } else if (failure is GetTokenOIDCFailure && failure.exception is NoSuitableBrowserForOIDCException) { - return AppLocalizations.of(context).noSuitableBrowserForOIDC; + return appLocalizations.noSuitableBrowserForOIDC; } else if (failure is FeatureFailure) { return _toastManager?.getMessageByException( - context, + appLocalizations, failure.exception, useDefaultMessage: true, - ) ?? AppLocalizations.of(context).unknownError; + ) ?? appLocalizations.unknownError; } else { - return AppLocalizations.of(context).unknownError; + return appLocalizations.unknownError; } }, (success) { if (formType == LoginFormType.credentialForm) { - return AppLocalizations.of(context).loginInputCredentialMessage; + return appLocalizations.loginInputCredentialMessage; } else if (formType == LoginFormType.dnsLookupForm) { - return AppLocalizations.of(context).dnsLookupLoginMessage; + return appLocalizations.dnsLookupLoginMessage; } else if (formType == LoginFormType.passwordForm) { - return AppLocalizations.of(context).enterYourPasswordToSignIn; + return appLocalizations.enterYourPasswordToSignIn; } else if (formType == LoginFormType.baseUrlForm) { - return AppLocalizations.of(context).loginInputUrlMessage; + return appLocalizations.loginInputUrlMessage; } else { return ''; } diff --git a/lib/features/manage_account/domain/model/edit_default_identity_request.dart b/lib/features/manage_account/domain/model/edit_default_identity_request.dart index 82f64636f..275cd5ee8 100644 --- a/lib/features/manage_account/domain/model/edit_default_identity_request.dart +++ b/lib/features/manage_account/domain/model/edit_default_identity_request.dart @@ -10,6 +10,7 @@ class EditDefaultIdentityRequest extends EditIdentityRequest { required super.identityId, required super.identityRequest, required super.isDefaultIdentity, + required super.isSetAsDefault, this.oldDefaultIdentityIds, super.publicAssetsInIdentityArguments }); diff --git a/lib/features/manage_account/domain/model/edit_identity_request.dart b/lib/features/manage_account/domain/model/edit_identity_request.dart index 1ef5b272e..1f26f1149 100644 --- a/lib/features/manage_account/domain/model/edit_identity_request.dart +++ b/lib/features/manage_account/domain/model/edit_identity_request.dart @@ -10,19 +10,33 @@ class EditIdentityRequest with EquatableMixin { final IdentityId identityId; final bool isDefaultIdentity; final PublicAssetsInIdentityArguments? publicAssetsInIdentityArguments; + final bool isSetAsDefault; EditIdentityRequest({ required this.identityId, required this.identityRequest, this.isDefaultIdentity = false, + this.isSetAsDefault = false, this.publicAssetsInIdentityArguments }); + factory EditIdentityRequest.fromIdentityWithoutPublicAssets( + Identity identity, + ) { + return EditIdentityRequest( + identityId: identity.id!, + identityRequest: identity.toIdentityRequest(), + isDefaultIdentity: true, + isSetAsDefault: true, + ); + } + @override List get props => [ identityId, identityRequest, isDefaultIdentity, - publicAssetsInIdentityArguments + publicAssetsInIdentityArguments, + isSetAsDefault, ]; } \ No newline at end of file diff --git a/lib/features/manage_account/domain/state/edit_default_identity_state.dart b/lib/features/manage_account/domain/state/edit_default_identity_state.dart index 2ff80c326..912113f3c 100644 --- a/lib/features/manage_account/domain/state/edit_default_identity_state.dart +++ b/lib/features/manage_account/domain/state/edit_default_identity_state.dart @@ -2,12 +2,19 @@ import 'package:core/presentation/state/failure.dart'; import 'package:core/presentation/state/success.dart'; import 'package:tmail_ui_user/features/manage_account/domain/state/edit_identity_state.dart'; -class EditDefaultIdentityLoading extends UIState {} +class EditDefaultIdentityLoading extends LoadingState { + final bool isSetAsDefault; + + EditDefaultIdentityLoading({this.isSetAsDefault = false}); + + @override + List get props => [isSetAsDefault]; +} class EditDefaultIdentitySuccess extends EditIdentitySuccess { EditDefaultIdentitySuccess( super.identityId, - {super.publicAssetsInIdentityArguments}); + {super.publicAssetsInIdentityArguments, super.isSetAsDefault = false}); } class EditDefaultIdentityFailure extends FeatureFailure { diff --git a/lib/features/manage_account/domain/state/edit_identity_state.dart b/lib/features/manage_account/domain/state/edit_identity_state.dart index 1c123288e..9f278dab8 100644 --- a/lib/features/manage_account/domain/state/edit_identity_state.dart +++ b/lib/features/manage_account/domain/state/edit_identity_state.dart @@ -8,13 +8,20 @@ class EditIdentityLoading extends UIState {} class EditIdentitySuccess extends UIState { final IdentityId identityId; final PublicAssetsInIdentityArguments? publicAssetsInIdentityArguments; + final bool isSetAsDefault; EditIdentitySuccess( - this.identityId, - {this.publicAssetsInIdentityArguments}); + this.identityId, { + this.publicAssetsInIdentityArguments, + this.isSetAsDefault = false, + }); @override - List get props => [identityId, publicAssetsInIdentityArguments]; + List get props => [ + identityId, + publicAssetsInIdentityArguments, + isSetAsDefault, + ]; } class EditIdentityFailure extends FeatureFailure { diff --git a/lib/features/manage_account/domain/usecases/edit_default_identity_interactor.dart b/lib/features/manage_account/domain/usecases/edit_default_identity_interactor.dart index aab50275f..37ecd6fff 100644 --- a/lib/features/manage_account/domain/usecases/edit_default_identity_interactor.dart +++ b/lib/features/manage_account/domain/usecases/edit_default_identity_interactor.dart @@ -27,7 +27,11 @@ class EditDefaultIdentityInteractor { EditIdentityRequest editIdentityRequest ) async* { try { - yield Right(EditDefaultIdentityLoading()); + yield Right( + EditDefaultIdentityLoading( + isSetAsDefault: editIdentityRequest.isSetAsDefault, + ), + ); final defaultIdentities = await _getDefaultIdentities(session, accountId); _removeEditIdentityFromDefaultIdentities(defaultIdentities, editIdentityRequest.identityId); @@ -36,6 +40,7 @@ class EditDefaultIdentityInteractor { identityId: editIdentityRequest.identityId, identityRequest: editIdentityRequest.identityRequest, isDefaultIdentity: editIdentityRequest.isDefaultIdentity, + isSetAsDefault: editIdentityRequest.isSetAsDefault, publicAssetsInIdentityArguments: editIdentityRequest.publicAssetsInIdentityArguments, oldDefaultIdentityIds: defaultIdentities ?.map((identity) => identity.id!) @@ -45,7 +50,9 @@ class EditDefaultIdentityInteractor { yield result ? Right(EditDefaultIdentitySuccess( editDefaultRequest.identityId, - publicAssetsInIdentityArguments: editDefaultRequest.publicAssetsInIdentityArguments)) + publicAssetsInIdentityArguments: editDefaultRequest.publicAssetsInIdentityArguments, + isSetAsDefault: editDefaultRequest.isSetAsDefault, + )) : Left(EditDefaultIdentityFailure(null)); } catch (exception) { yield Left(EditDefaultIdentityFailure(exception)); diff --git a/lib/features/manage_account/presentation/extensions/change_identity_as_default_extension.dart b/lib/features/manage_account/presentation/extensions/change_identity_as_default_extension.dart new file mode 100644 index 000000000..cdaf3ffc1 --- /dev/null +++ b/lib/features/manage_account/presentation/extensions/change_identity_as_default_extension.dart @@ -0,0 +1,45 @@ +import 'package:dartz/dartz.dart'; +import 'package:jmap_dart_client/jmap/core/capability/capability_identifier.dart'; +import 'package:jmap_dart_client/jmap/identities/identity.dart'; +import 'package:tmail_ui_user/features/mailbox/domain/exceptions/null_session_or_accountid_exception.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/model/edit_identity_request.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/state/edit_default_identity_state.dart'; +import 'package:tmail_ui_user/features/manage_account/presentation/extensions/identity_extension.dart'; +import 'package:tmail_ui_user/features/manage_account/presentation/identities/identities_controller.dart'; +import 'package:tmail_ui_user/main/error/capability_validator.dart'; + +extension VerifyDefaultIdentitySupportedExtension on IdentitiesController { + bool get isDefaultIdentitySupported { + final accountId = accountDashBoardController.accountId.value; + final session = accountDashBoardController.sessionCurrent; + if (session != null && accountId != null) { + return [CapabilityIdentifier.jamesSortOrder].isSupported( + session, + accountId, + ); + } else { + return false; + } + } + + void changeIdentityAsDefault(Identity identity) { + final accountId = accountDashBoardController.accountId.value; + final session = accountDashBoardController.sessionCurrent; + + if (session != null && accountId != null && identity.id != null) { + editIdentityAction( + session, + accountId, + EditIdentityRequest.fromIdentityWithoutPublicAssets( + identity.asDefault(), + ), + ); + } else { + consumeState( + Stream.value( + Left(EditDefaultIdentityFailure(NullSessionOrAccountIdException())), + ), + ); + } + } +} diff --git a/lib/features/manage_account/presentation/extensions/identity_extension.dart b/lib/features/manage_account/presentation/extensions/identity_extension.dart index c7cec5fe0..ab505bfa7 100644 --- a/lib/features/manage_account/presentation/extensions/identity_extension.dart +++ b/lib/features/manage_account/presentation/extensions/identity_extension.dart @@ -1,4 +1,6 @@ +import 'package:jmap_dart_client/jmap/core/unsigned_int.dart'; import 'package:jmap_dart_client/jmap/identities/identity.dart'; +import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; import 'package:tmail_ui_user/features/manage_account/domain/model/identity_signature.dart'; extension IdentityExtension on Identity { @@ -16,4 +18,32 @@ extension IdentityExtension on Identity { IdentitySignature? toIdentitySignature() => id != null ? IdentitySignature(identityId: id!, signature: signatureAsString) : null; + + Identity asDefault() => copyWith(sortOrder: UnsignedInt(0)); + + Identity copyWith({ + IdentityId? id, + String? description, + String? name, + String? email, + Set? bcc, + Set? replyTo, + Signature? textSignature, + Signature? htmlSignature, + bool? mayDelete, + UnsignedInt? sortOrder, + }) { + return Identity( + id: id ?? this.id, + description: description ?? this.description, + name: name ?? this.name, + email: email ?? this.email, + bcc: bcc ?? this.bcc, + replyTo: replyTo ?? this.replyTo, + textSignature: textSignature ?? this.textSignature, + htmlSignature: htmlSignature ?? this.htmlSignature, + mayDelete: mayDelete ?? this.mayDelete, + sortOrder: sortOrder ?? this.sortOrder, + ); + } } diff --git a/lib/features/manage_account/presentation/identities/identities_controller.dart b/lib/features/manage_account/presentation/identities/identities_controller.dart index 6811c67a8..7ded0ee27 100644 --- a/lib/features/manage_account/presentation/identities/identities_controller.dart +++ b/lib/features/manage_account/presentation/identities/identities_controller.dart @@ -236,7 +236,7 @@ class IdentitiesController extends ReloadableController implements BeforeReconne if (newIdentityArguments is CreateNewIdentityRequest) { _createNewIdentityAction(session, accountId, newIdentityArguments); } else if (newIdentityArguments is EditIdentityRequest) { - _editIdentityAction(session, accountId, newIdentityArguments); + editIdentityAction(session, accountId, newIdentityArguments); } } } @@ -388,12 +388,12 @@ class IdentitiesController extends ReloadableController implements BeforeReconne if (newIdentityArguments is CreateNewIdentityRequest) { _createNewIdentityAction(session, accountId, newIdentityArguments); } else if (newIdentityArguments is EditIdentityRequest) { - _editIdentityAction(session, accountId, newIdentityArguments); + editIdentityAction(session, accountId, newIdentityArguments); } } } - void _editIdentityAction( + void editIdentityAction( Session session, AccountId accountId, EditIdentityRequest editIdentityRequest @@ -406,19 +406,18 @@ class IdentitiesController extends ReloadableController implements BeforeReconne } void _editIdentitySuccess(EditIdentitySuccess success) { - _removeIdentityCache(); + toastManager.showMessageSuccess(success); - if (currentOverlayContext != null && currentContext != null) { - appToast.showToastSuccessMessage( - currentOverlayContext!, - AppLocalizations.of(currentContext!).you_are_changed_your_identity_successfully); + if (!success.isSetAsDefault) { + _removeIdentityCache(); + + _cleanUpPublicAssets( + success.identityId, + IdentityActionType.edit, + success.publicAssetsInIdentityArguments, + ); } - _cleanUpPublicAssets( - success.identityId, - IdentityActionType.edit, - success.publicAssetsInIdentityArguments); - _refreshAllIdentities(); } @@ -491,7 +490,7 @@ class IdentitiesController extends ReloadableController implements BeforeReconne if (newIdentityArguments is CreateNewIdentityRequest) { _createNewIdentityAction(session, accountId, newIdentityArguments); } else if (newIdentityArguments is EditIdentityRequest) { - _editIdentityAction(session, accountId, newIdentityArguments); + editIdentityAction(session, accountId, newIdentityArguments); } } diff --git a/lib/features/manage_account/presentation/identities/identities_view.dart b/lib/features/manage_account/presentation/identities/identities_view.dart index 5e6fda633..4f6509df3 100644 --- a/lib/features/manage_account/presentation/identities/identities_view.dart +++ b/lib/features/manage_account/presentation/identities/identities_view.dart @@ -1,9 +1,12 @@ +import 'package:core/presentation/extensions/either_view_state_extension.dart'; import 'package:core/presentation/utils/theme_utils.dart'; import 'package:core/presentation/views/list/no_stretch_scroll_behavior.dart'; import 'package:core/utils/platform_info.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/state/edit_default_identity_state.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/base/setting_detail_view_builder.dart'; +import 'package:tmail_ui_user/features/manage_account/presentation/extensions/change_identity_as_default_extension.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/identities/identities_controller.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/identities/widgets/create_new_identity_button_widget.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/identities/widgets/identity_list_tile_builder.dart'; @@ -88,41 +91,60 @@ class IdentitiesView extends GetWidget { )), Expanded( child: Obx(() { + final identities = controller.listAllIdentities; + final isDefaultIdentitySupported = controller.isDefaultIdentitySupported; + final identitySelected = controller.identitySelected.value; + final Widget listView = ListView.separated( shrinkWrap: true, - itemCount: controller.listAllIdentities.length + 1, + itemCount: identities.length + 1, controller: controller.listIdentityScrollController, - padding: const EdgeInsetsDirectional.only( - start: 24, + padding: EdgeInsetsDirectional.only( + start: isDefaultIdentitySupported ? 12 : 24, end: 24, bottom: 24, ), itemBuilder: (context, index) { - if (index == controller.listAllIdentities.length) { + if (index == identities.length) { return const SizedBox.shrink(); } - final identity = controller.listAllIdentities[index]; - final isSelected = identity == controller.identitySelected.value; - return Obx(() => IdentityListTileBuilder( - imagePaths: controller.imagePaths, - identity: identity, - isSelected: isSelected, - mapIdentitySignatures: controller.mapIdentitySignatures, - signatureViewState: controller.signatureViewState.value, - isDesktop: isDesktop, - scrollController: controller.listIdentityScrollController, - onEditIdentityAction: (identitySelected) => - controller.goToEditIdentity(context, identitySelected), - onDeleteIdentityAction: (identitySelected) => - controller.openConfirmationDialogDeleteIdentityAction( - context, - identitySelected, - ), - )); + final identity = identities[index]; + final isSelected = identity == identitySelected; + + return Obx(() { + final loadingState = controller.viewState.value + .foldSuccessWithResult(); + + bool isItemLoading = + loadingState is EditDefaultIdentityLoading && + loadingState.isSetAsDefault; + + return IdentityListTileBuilder( + imagePaths: controller.imagePaths, + identity: identity, + isSelected: isSelected, + isDefaultIdentitySupported: isDefaultIdentitySupported, + mapIdentitySignatures: controller.mapIdentitySignatures, + signatureViewState: controller.signatureViewState.value, + isDesktop: isDesktop, + isItemLoading: isItemLoading, + scrollController: controller.listIdentityScrollController, + onEditIdentityAction: (identitySelected) => + controller.goToEditIdentity(context, identitySelected), + onDeleteIdentityAction: (identitySelected) => + controller.openConfirmationDialogDeleteIdentityAction( + context, + identitySelected, + ), + onChangeIdentityAsDefaultAction: controller.changeIdentityAsDefault, + ); + }); }, separatorBuilder: (_, index) => Padding( - padding: const EdgeInsets.symmetric(vertical: 24), + padding: isDefaultIdentitySupported + ? const EdgeInsets.only(top: 24, bottom: 12) + : const EdgeInsets.symmetric(vertical: 24), child: Divider(color: Colors.black.withValues(alpha: 0.08)), ), ); diff --git a/lib/features/manage_account/presentation/identities/widgets/identity_list_tile_builder.dart b/lib/features/manage_account/presentation/identities/widgets/identity_list_tile_builder.dart index 8cf438072..4e7fe0111 100644 --- a/lib/features/manage_account/presentation/identities/widgets/identity_list_tile_builder.dart +++ b/lib/features/manage_account/presentation/identities/widgets/identity_list_tile_builder.dart @@ -3,9 +3,9 @@ import 'package:core/presentation/resources/image_paths.dart'; import 'package:core/presentation/state/failure.dart'; import 'package:core/presentation/state/success.dart'; import 'package:core/presentation/utils/theme_utils.dart'; +import 'package:core/presentation/views/button/tmail_button_widget.dart'; import 'package:dartz/dartz.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_svg/flutter_svg.dart'; import 'package:jmap_dart_client/jmap/identities/identity.dart'; import 'package:model/extensions/list_email_address_extension.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/extensions/identity_extension.dart'; @@ -14,6 +14,8 @@ import 'package:tmail_ui_user/features/manage_account/presentation/identities/wi import 'package:tmail_ui_user/features/manage_account/presentation/identities/widgets/signature_loading_widget.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; +typedef OnChangeIdentityAsDefaultAction = Function(Identity identity); + class IdentityListTileBuilder extends StatelessWidget { const IdentityListTileBuilder({ @@ -26,7 +28,10 @@ class IdentityListTileBuilder extends StatelessWidget { required this.onDeleteIdentityAction, this.isDesktop = false, this.isSelected = false, + this.isDefaultIdentitySupported = false, + this.isItemLoading = false, this.scrollController, + this.onChangeIdentityAsDefaultAction, }) : super(key: key); final Identity identity; @@ -35,17 +40,26 @@ class IdentityListTileBuilder extends StatelessWidget { final ImagePaths imagePaths; final bool isSelected; final bool isDesktop; + final bool isDefaultIdentitySupported; + final bool isItemLoading; final OnEditIdentityAction onEditIdentityAction; final OnDeleteIdentityAction onDeleteIdentityAction; + final OnChangeIdentityAsDefaultAction? onChangeIdentityAsDefaultAction; final ScrollController? scrollController; @override Widget build(BuildContext context) { - final selectedIcon = SvgPicture.asset( - isSelected ? imagePaths.icRadioSelected : imagePaths.icRadio, - width: 18, - height: 18, - fit: BoxFit.fill, + final selectedIcon = AbsorbPointer( + absorbing: isItemLoading, + child: TMailButtonWidget.fromIcon( + icon: isSelected ? imagePaths.icRadioSelected : imagePaths.icRadio, + iconSize: 18, + padding: const EdgeInsets.all(12), + backgroundColor: Colors.transparent, + borderRadius: 100, + onTapActionCallback: () => + onChangeIdentityAsDefaultAction?.call(identity), + ), ); final signatureContent = mapIdentitySignatures[identity.id!] ?? @@ -113,18 +127,30 @@ class IdentityListTileBuilder extends StatelessWidget { return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - selectedIcon, + if (isDefaultIdentitySupported) + Padding( + padding: const EdgeInsetsDirectional.only(end: 6), + child: selectedIcon, + ), Container( width: 280, - padding: const EdgeInsetsDirectional.only(start: 18, end: 12), + padding: EdgeInsetsDirectional.only( + end: 12, + top: isDefaultIdentitySupported ? 10 : 0, + ), child: identityContent, ), - ListIdentityItemActionsWidget( - identity: identity, - imagePaths: imagePaths, - onEditIdentityAction: onEditIdentityAction, - onDeleteIdentityAction: onDeleteIdentityAction, - isDesktop: isDesktop, + Padding( + padding: isDefaultIdentitySupported + ? const EdgeInsetsDirectional.only(top: 10) + : EdgeInsetsDirectional.zero, + child: ListIdentityItemActionsWidget( + identity: identity, + imagePaths: imagePaths, + onEditIdentityAction: onEditIdentityAction, + onDeleteIdentityAction: onDeleteIdentityAction, + isDesktop: isDesktop, + ), ), const Spacer(), ], @@ -134,14 +160,24 @@ class IdentityListTileBuilder extends StatelessWidget { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - selectedIcon, - const SizedBox(width: 18), - Expanded(child: identityContent), - ], - ), + if (isDefaultIdentitySupported) + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsetsDirectional.only(end: 6), + child: selectedIcon, + ), + Expanded( + child: Padding( + padding: const EdgeInsetsDirectional.only(top: 10), + child: identityContent, + ), + ), + ], + ) + else + identityContent, const SizedBox(height: 24), ListIdentityItemActionsWidget( identity: identity, diff --git a/lib/l10n/intl_messages.arb b/lib/l10n/intl_messages.arb index 09627c5ce..e2d105bbf 100644 --- a/lib/l10n/intl_messages.arb +++ b/lib/l10n/intl_messages.arb @@ -4887,5 +4887,11 @@ "placeholders": { "count": {} } + }, + "defaultIdentitySetupSuccessful": "Default identity setup successful", + "@defaultIdentitySetupSuccessful": { + "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 f82ee052c..865c512ce 100644 --- a/lib/main/localizations/app_localizations.dart +++ b/lib/main/localizations/app_localizations.dart @@ -5161,4 +5161,11 @@ class AppLocalizations { args: [count], ); } + + String get defaultIdentitySetupSuccessful { + return Intl.message( + 'Default identity setup successful', + name: 'defaultIdentitySetupSuccessful', + ); + } } diff --git a/lib/main/utils/toast_manager.dart b/lib/main/utils/toast_manager.dart index 27f3f1d3c..be0c826bb 100644 --- a/lib/main/utils/toast_manager.dart +++ b/lib/main/utils/toast_manager.dart @@ -6,7 +6,6 @@ import 'package:core/presentation/state/failure.dart'; import 'package:core/presentation/state/success.dart'; import 'package:core/presentation/utils/app_toast.dart'; import 'package:core/utils/app_logger.dart'; -import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_appauth_web/authorization_exception.dart'; import 'package:jmap_dart_client/jmap/core/error/method/error_method_response.dart'; @@ -27,9 +26,10 @@ import 'package:tmail_ui_user/features/login/domain/exceptions/authentication_ex import 'package:tmail_ui_user/features/login/domain/exceptions/oauth_authorization_error.dart'; import 'package:tmail_ui_user/features/mailbox/domain/state/clear_mailbox_state.dart'; import 'package:tmail_ui_user/features/manage_account/domain/state/add_recipient_in_forwarding_state.dart'; -import 'package:tmail_ui_user/features/manage_account/domain/state/delete_recipient_in_forwarding_state.dart'; -import 'package:tmail_ui_user/features/manage_account/domain/state/edit_local_copy_in_forwarding_state.dart'; import 'package:tmail_ui_user/features/manage_account/domain/state/create_new_rule_filter_state.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/state/delete_recipient_in_forwarding_state.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/state/edit_identity_state.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/state/edit_local_copy_in_forwarding_state.dart'; import 'package:tmail_ui_user/features/manage_account/domain/state/export_trace_log_state.dart'; import 'package:tmail_ui_user/features/starting_page/domain/state/sign_in_twake_workplace_state.dart'; import 'package:tmail_ui_user/features/starting_page/domain/state/sign_up_twake_workplace_state.dart'; @@ -46,47 +46,48 @@ class ToastManager { ToastManager(this.appToast); - String getDefaultMessageByException(BuildContext context, dynamic exception) { + String getDefaultMessageByException( + AppLocalizations appLocalizations, + dynamic exception, + ) { try { - return AppLocalizations.of(context).unexpectedError(exception.message); + return appLocalizations.unexpectedError(exception.message); } catch (_) { - return AppLocalizations.of(context).unexpectedError( - exception.toString(), - ); + return appLocalizations.unexpectedError(exception.toString()); } } String? getMessageByException( - BuildContext context, + AppLocalizations appLocalizations, dynamic exception, { bool useDefaultMessage = false, }) { if (exception is CanNotFoundBaseUrl) { - return AppLocalizations.of(context).requiredUrl; + return appLocalizations.requiredUrl; } else if (exception is CanNotFoundUserName) { - return AppLocalizations.of(context).requiredEmail; + return appLocalizations.requiredEmail; } else if (exception is CanNotFoundPassword) { - return AppLocalizations.of(context).requiredPassword; + return appLocalizations.requiredPassword; } else if (exception is CanNotFoundOIDCLinks) { - return AppLocalizations.of(context).ssoNotAvailable; + return appLocalizations.ssoNotAvailable; } else if (exception is CanNotFindToken) { - return AppLocalizations.of(context).canNotGetToken; + return appLocalizations.canNotGetToken; } else if (exception is ConnectionTimeout || exception is BadGateway || exception is SocketError) { - return AppLocalizations.of(context).wrongUrlMessage; + return appLocalizations.wrongUrlMessage; } else if (exception is BadCredentialsException) { - return AppLocalizations.of(context).badCredentials; + return appLocalizations.badCredentials; } else if (exception is ConnectionError) { - return AppLocalizations.of(context).connectionError; + return appLocalizations.connectionError; } else if (exception is UnknownError && exception.message != null) { return '[${exception.code ?? ''}] ${exception.message}'; } else if (exception is NotFoundSessionException) { - return AppLocalizations.of(context).notFoundSession; + return appLocalizations.notFoundSession; } else if (exception is NoNetworkError) { - return AppLocalizations.of(context).youAreOffline; + return appLocalizations.youAreOffline; } else if (exception is HandshakeException) { - return AppLocalizations.of(context) + return appLocalizations .handshakeException(exception.osError?.message ?? ''); } else if (exception is SetMethodException && exception.mapErrors.isNotEmpty) { @@ -104,12 +105,11 @@ class ToastManager { exception.message?.isNotEmpty == true) { return exception.message!; } else if (exception is NotGrantedPermissionStorageException) { - return AppLocalizations.of(context) - .youNeedToGrantFilesPermissionToExportFile; + return appLocalizations.youNeedToGrantFilesPermissionToExportFile; } else if (exception is NotFoundFileInFolderException) { - return AppLocalizations.of(context).noLogsHaveBeenRecordedYet; + return appLocalizations.noLogsHaveBeenRecordedYet; } else if (exception is CannotOpenNewWindowException) { - return AppLocalizations.of(context).cannotOpenNewWindow; + return appLocalizations.cannotOpenNewWindow; } else if (exception is CannotReplyCalendarEventException) { final mapErrors = exception.mapErrors ?? {}; if (mapErrors.isNotEmpty) { @@ -125,7 +125,7 @@ class ToastManager { } if (useDefaultMessage) { - return getDefaultMessageByException(context, exception); + return getDefaultMessageByException(appLocalizations, exception); } else { return null; } @@ -140,50 +140,51 @@ class ToastManager { } final exception = failure.exception; - String? message = getMessageByException(context, exception); - + final appLocalizations = AppLocalizations.of(context); + String? message = getMessageByException(appLocalizations, exception); + if (failure is GetSessionFailure) { message = message ?? getMessageByException( - context, + appLocalizations, exception, useDefaultMessage: true, ); } else if (_isEmptySpamFolderFailure(exception)) { - message = message ?? AppLocalizations.of(context).emptySpamFolderFailed; + message = message ?? appLocalizations.emptySpamFolderFailed; } else if (_isEmptyTrashFolderFailure(failure)) { - message = message ?? AppLocalizations.of(context).emptyTrashFolderFailed; + message = message ?? appLocalizations.emptyTrashFolderFailed; } else if (_isMarkAsSpamFailure(failure)) { - message = message ?? AppLocalizations.of(context).markAsSpamFailed; + message = message ??appLocalizations.markAsSpamFailed; } else if (_isArchiveMessagesFailure(failure)) { - message = message ?? AppLocalizations.of(context).archiveMessagesFailed; + message = message ?? appLocalizations.archiveMessagesFailed; } else if (failure is SignInTwakeWorkplaceFailure) { - message = message ?? AppLocalizations.of(context).sigInSaasFailed; + message = message ?? appLocalizations.sigInSaasFailed; } else if (failure is SignUpTwakeWorkplaceFailure) { - message = message ?? AppLocalizations.of(context).createTwakeIdFailed; + message = message ?? appLocalizations.createTwakeIdFailed; } else if (failure is ParseEmailByBlobIdFailure) { message = - message ?? AppLocalizations.of(context).parseEmailByBlobIdFailed; + message ?? appLocalizations.parseEmailByBlobIdFailed; } else if (failure is PreviewEmailFromEmlFileFailure) { message = - message ?? AppLocalizations.of(context).previewEmailFromEMLFileFailed; + message ?? appLocalizations.previewEmailFromEMLFileFailed; } else if (failure is ExportTraceLogFailure) { - message = message ?? AppLocalizations.of(context).exportTraceLogFailed; + message = message ?? appLocalizations.exportTraceLogFailed; } else if (failure is AddRecipientsInForwardingFailure || failure is AddRecipientsInForwardingSuccessWithSomeCaseFailure) { - message = message ?? AppLocalizations.of(context).addRecipientsFailed; + message = message ?? appLocalizations.addRecipientsFailed; } else if (failure is EditLocalCopyInForwardingFailure || failure is EditLocalCopyInForwardingSuccessWithSomeCaseFailure) { message = - message ?? AppLocalizations.of(context).editLocalCopyInForwardFailed; + message ?? appLocalizations.editLocalCopyInForwardFailed; } else if (failure is DeleteRecipientInForwardingFailure || failure is DeleteRecipientInForwardingSuccessWithSomeCaseFailure) { - message = message ?? AppLocalizations.of(context).deleteRecipientsFailed; + message = message ?? appLocalizations.deleteRecipientsFailed; } else if (failure is CreateNewRuleFilterFailure) { - message = message ?? AppLocalizations.of(context).createFilterRuleFailed; + message = message ?? appLocalizations.createFilterRuleFailed; } else if (failure is CalendarEventReplyFailure) { message = message ?? - AppLocalizations.of(context).eventReplyWasSentUnsuccessfully; + appLocalizations.eventReplyWasSentUnsuccessfully; } log('ToastManager::showMessageFailure: Message: $message'); if (message?.trim().isNotEmpty == true) { @@ -224,18 +225,25 @@ class ToastManager { } String? message; + final appLocalizations = AppLocalizations.of(context); if (success is ClearMailboxSuccess || success is EmptySpamFolderSuccess || success is EmptyTrashFolderSuccess) { message = - AppLocalizations.of(context).toast_message_empty_trash_folder_success; + appLocalizations.toast_message_empty_trash_folder_success; } else if (success is ExportTraceLogSuccess) { - message = AppLocalizations.of(context).exportTraceLogSuccess( + message = appLocalizations.exportTraceLogSuccess( success.savePath, ); } else if (success is CreateNewRuleFilterSuccess) { - message = AppLocalizations.of(context).newFilterWasCreated; + message = appLocalizations.newFilterWasCreated; + } else if (success is EditIdentitySuccess) { + if (success.isSetAsDefault) { + message = appLocalizations.defaultIdentitySetupSuccessful; + } else { + message = appLocalizations.you_are_changed_your_identity_successfully; + } } log('ToastManager::showMessageSuccess: Message: $message'); if (message?.trim().isNotEmpty == true) {