From 0d40f765e67bc76c897ee0c6d8d8067039b3ff04 Mon Sep 17 00:00:00 2001 From: dab246 Date: Mon, 16 May 2022 18:46:27 +0700 Subject: [PATCH] TF-561 Fix edit identity --- .../identity_creator_bindings.dart | 37 ++++- .../identity_creator_controller.dart | 136 ++++++++++++------ .../presentation/identity_creator_view.dart | 70 +++++---- .../identity_field_no_editable_builder.dart | 41 ++++++ .../widgets/identity_input_field_builder.dart | 8 +- .../datasource/manage_account_datasource.dart | 5 +- .../manage_account_datasource_impl.dart | 9 +- .../data/network/manage_account_api.dart | 12 +- .../manage_account_repository_impl.dart | 9 +- .../domain/model/edit_identity_request.dart | 7 +- .../repository/manage_account_repository.dart | 5 +- .../domain/state/edit_identity_state.dart | 7 +- .../usecases/edit_identity_interactor.dart | 9 +- .../get_all_identities_interactor.dart | 5 +- .../identities/identities_controller.dart | 18 ++- model/lib/extensions/identity_extension.dart | 15 ++ model/lib/identity/identity_request_dto.dart | 51 +++++++ model/lib/model.dart | 6 +- 18 files changed, 333 insertions(+), 117 deletions(-) create mode 100644 lib/features/identity_creator/presentation/widgets/identity_field_no_editable_builder.dart create mode 100644 model/lib/extensions/identity_extension.dart create mode 100644 model/lib/identity/identity_request_dto.dart diff --git a/lib/features/identity_creator/presentation/identity_creator_bindings.dart b/lib/features/identity_creator/presentation/identity_creator_bindings.dart index 8dc0c10ed..faf567b8d 100644 --- a/lib/features/identity_creator/presentation/identity_creator_bindings.dart +++ b/lib/features/identity_creator/presentation/identity_creator_bindings.dart @@ -2,28 +2,53 @@ import 'package:get/get.dart'; import 'package:tmail_ui_user/features/base/base_bindings.dart'; import 'package:tmail_ui_user/features/identity_creator/presentation/identity_creator_controller.dart'; import 'package:tmail_ui_user/features/mailbox_creator/domain/usecases/verify_name_interactor.dart'; +import 'package:tmail_ui_user/features/manage_account/data/datasource/manage_account_datasource.dart'; +import 'package:tmail_ui_user/features/manage_account/data/datasource_impl/manage_account_datasource_impl.dart'; +import 'package:tmail_ui_user/features/manage_account/data/network/manage_account_api.dart'; +import 'package:tmail_ui_user/features/manage_account/data/repository/manage_account_repository_impl.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/repository/manage_account_repository.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/usecases/get_all_identities_interactor.dart'; +import 'package:jmap_dart_client/http/http_client.dart' as jmap_http_client; class IdentityCreatorBindings extends BaseBindings { @override - void bindingsController() { - Get.lazyPut(() => IdentityCreatorController(Get.find())); + void dependencies() { + Get.lazyPut(() => ManageAccountAPI(Get.find())); + super.dependencies(); } @override - void bindingsDataSource() {} + void bindingsController() { + Get.lazyPut(() => IdentityCreatorController( + Get.find(), + Get.find(), + )); + } @override - void bindingsDataSourceImpl() {} + void bindingsDataSource() { + Get.lazyPut(() => Get.find()); + } + + @override + void bindingsDataSourceImpl() { + Get.lazyPut(() => ManageAccountDataSourceImpl(Get.find())); + } @override void bindingsInteractor() { Get.lazyPut(() => VerifyNameInteractor()); + Get.lazyPut(() => GetAllIdentitiesInteractor(Get.find())); } @override - void bindingsRepository() {} + void bindingsRepository() { + Get.lazyPut(() => Get.find()); + } @override - void bindingsRepositoryImpl() {} + void bindingsRepositoryImpl() { + Get.lazyPut(() => ManageAccountRepositoryImpl(Get.find())); + } } \ No newline at end of file diff --git a/lib/features/identity_creator/presentation/identity_creator_controller.dart b/lib/features/identity_creator/presentation/identity_creator_controller.dart index 506f88575..81d9b272c 100644 --- a/lib/features/identity_creator/presentation/identity_creator_controller.dart +++ b/lib/features/identity_creator/presentation/identity_creator_controller.dart @@ -4,6 +4,7 @@ import 'package:flutter/cupertino.dart'; import 'package:get/get.dart'; import 'package:html_editor_enhanced/html_editor.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; +import 'package:jmap_dart_client/jmap/core/properties/properties.dart'; import 'package:jmap_dart_client/jmap/identities/identity.dart'; import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; import 'package:model/model.dart'; @@ -14,12 +15,15 @@ import 'package:tmail_ui_user/features/mailbox_creator/domain/model/verification import 'package:tmail_ui_user/features/mailbox_creator/domain/state/verify_name_view_state.dart'; import 'package:tmail_ui_user/features/mailbox_creator/domain/usecases/verify_name_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_creator/presentation/extensions/validator_failure_extension.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/state/get_all_identities_state.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/usecases/get_all_identities_interactor.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/model/identity_action_type.dart'; import 'package:tmail_ui_user/main/routes/route_navigation.dart'; class IdentityCreatorController extends BaseController { final VerifyNameInteractor _verifyNameInteractor; + final GetAllIdentitiesInteractor _getAllIdentitiesInteractor; final noneEmailAddress = EmailAddress(null, 'None'); final signatureType = SignatureType.plainText.obs; @@ -29,6 +33,7 @@ class IdentityCreatorController extends BaseController { final emailOfIdentity = Rxn(); final replyToOfIdentity = Rxn(); final bccOfIdentity = Rxn(); + final actionType = IdentityActionType.create.obs; final HtmlEditorController signatureHtmlEditorController = HtmlEditorController(processNewLineAsBr: true); final TextEditingController signaturePlainEditorController = TextEditingController(); @@ -37,7 +42,6 @@ class IdentityCreatorController extends BaseController { AccountId? accountId; UserProfile? userProfile; - IdentityActionType? actionType; Identity? identity; String? _nameIdentity; String? _contentHtmlEditor; @@ -51,15 +55,17 @@ class IdentityCreatorController extends BaseController { String? get contentHtmlEditor => _contentHtmlEditor; - IdentityCreatorController(this._verifyNameInteractor); + IdentityCreatorController( + this._verifyNameInteractor, + this._getAllIdentitiesInteractor + ); @override void onReady() { _getArguments(); - if (actionType == IdentityActionType.edit && identity != null) { + _getAllIdentities(); + if (actionType.value == IdentityActionType.edit && identity != null) { _setUpValueFromIdentity(); - } else { - _setDefaultValueForIdentity(); } super.onReady(); } @@ -74,6 +80,18 @@ class IdentityCreatorController extends BaseController { @override void onDone() { + viewState.value.fold( + (failure) { + if (failure is GetAllIdentitiesFailure) { + _getALlIdentitiesFailure(failure); + } + }, + (success) { + if (success is GetAllIdentitiesSuccess) { + _getALlIdentitiesSuccess(success); + } + } + ); } @override @@ -84,55 +102,15 @@ class IdentityCreatorController extends BaseController { if (arguments is IdentityCreatorArguments) { accountId = arguments.accountId; userProfile = arguments.userProfile; - actionType = arguments.actionType; + actionType.value = arguments.actionType; identity = arguments.identity; } } - void _setDefaultValueForIdentity() { - listEmailAddressOfReplyTo.add(noneEmailAddress); - bccOfIdentity.value = noneEmailAddress; - replyToOfIdentity.value = noneEmailAddress; - - if (userProfile != null && userProfile?.email.isNotEmpty == true) { - final userEmailAddress = EmailAddress(null, userProfile!.email); - listEmailAddressDefault.add(userEmailAddress); - listEmailAddressOfReplyTo.add(userEmailAddress); - emailOfIdentity.value = userEmailAddress; - } - } - void _setUpValueFromIdentity() { - Set listEmailAddress = {}; - listEmailAddress.add(noneEmailAddress); - _nameIdentity = identity?.name ?? ''; inputNameIdentityController.text = identity?.name ?? ''; - if (identity?.replyTo?.isNotEmpty == true) { - replyToOfIdentity.value = identity!.replyTo!.first; - listEmailAddress.add(identity!.replyTo!.first); - } else { - replyToOfIdentity.value = noneEmailAddress; - } - - if (identity?.bcc?.isNotEmpty == true) { - bccOfIdentity.value = identity!.bcc!.first; - listEmailAddress.add(identity!.bcc!.first); - } else { - bccOfIdentity.value = noneEmailAddress; - } - - if (identity?.email?.isNotEmpty == true) { - emailOfIdentity.value = EmailAddress(null, identity?.email!); - listEmailAddress.add(EmailAddress(null, identity?.email!)); - } - - listEmailAddressOfReplyTo.value = listEmailAddress.toList(); - listEmailAddressDefault.value = listEmailAddress - .where((emailAddress) => emailAddress != noneEmailAddress) - .toList(); - if (identity?.textSignature?.value.isNotEmpty == true) { signaturePlainEditorController.text = identity?.textSignature?.value ?? ''; } @@ -143,6 +121,72 @@ class IdentityCreatorController extends BaseController { } } + void _getAllIdentities() { + if (accountId != null) { + consumeState(_getAllIdentitiesInteractor.execute( + accountId!, + properties: Properties({'email'}) + )); + } + } + + void _getALlIdentitiesSuccess(GetAllIdentitiesSuccess success) { + if (success.identities?.isNotEmpty == true) { + listEmailAddressDefault.value = success.identities + !.map((identity) => identity.toEmailAddressNoName()) + .toSet() + .toList(); + listEmailAddressOfReplyTo.add(noneEmailAddress); + listEmailAddressOfReplyTo.addAll(listEmailAddressDefault); + + _setUpAllFieldEmailAddress(); + } else { + _setDefaultEmailAddressList(); + } + } + + void _getALlIdentitiesFailure(GetAllIdentitiesFailure failure) { + _setDefaultEmailAddressList(); + } + + void _setDefaultEmailAddressList() { + listEmailAddressOfReplyTo.add(noneEmailAddress); + + if (userProfile != null && userProfile?.email.isNotEmpty == true) { + final userEmailAddress = EmailAddress(null, userProfile!.email); + listEmailAddressDefault.add(userEmailAddress); + listEmailAddressOfReplyTo.addAll(listEmailAddressDefault); + } + + _setUpAllFieldEmailAddress(); + } + + void _setUpAllFieldEmailAddress() { + if (actionType.value == IdentityActionType.edit && identity != null) { + replyToOfIdentity.value = identity?.replyTo?.isNotEmpty == true + ? identity!.replyTo!.first + : noneEmailAddress; + + bccOfIdentity.value = identity?.bcc?.isNotEmpty == true + ? identity!.bcc!.first + : noneEmailAddress; + + if (identity?.email?.isNotEmpty == true) { + emailOfIdentity.value = EmailAddress(null, identity?.email!); + } else { + emailOfIdentity.value = listEmailAddressDefault.isNotEmpty + ? listEmailAddressDefault.first + : null; + } + } else { + replyToOfIdentity.value = noneEmailAddress; + bccOfIdentity.value = noneEmailAddress; + emailOfIdentity.value = listEmailAddressDefault.isNotEmpty + ? listEmailAddressDefault.first + : null; + } + } + void selectSignatureType(SignatureType newSignatureType) { signatureType.value = newSignatureType; } diff --git a/lib/features/identity_creator/presentation/identity_creator_view.dart b/lib/features/identity_creator/presentation/identity_creator_view.dart index 6c50b1241..10e950e1d 100644 --- a/lib/features/identity_creator/presentation/identity_creator_view.dart +++ b/lib/features/identity_creator/presentation/identity_creator_view.dart @@ -6,6 +6,7 @@ import 'package:html_editor_enhanced/html_editor.dart'; import 'package:tmail_ui_user/features/identity_creator/presentation/identity_creator_controller.dart'; import 'package:tmail_ui_user/features/identity_creator/presentation/model/signature_type.dart'; import 'package:tmail_ui_user/features/identity_creator/presentation/widgets/identity_drop_list_field_builder.dart'; +import 'package:tmail_ui_user/features/identity_creator/presentation/widgets/identity_field_no_editable_builder.dart'; import 'package:tmail_ui_user/features/identity_creator/presentation/widgets/identity_input_field_builder.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/model/identity_action_type.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; @@ -105,8 +106,13 @@ class IdentityCreatorView extends GetWidget { Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: const EdgeInsets.only(left: 24, top: 24), - child: Text(AppLocalizations.of(context).new_identity.inCaps, - style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 24, color: Colors.black))), + child: Obx(() => Text(controller.actionType.value == IdentityActionType.create + ? AppLocalizations.of(context).new_identity.inCaps + : AppLocalizations.of(context).edit_identity.inCaps, + style: const TextStyle( + fontWeight: FontWeight.bold, + fontSize: 24, + color: Colors.black)))), const SizedBox(height: 8), Expanded(child: SingleChildScrollView( physics: const ClampingScrollPhysics(), @@ -115,8 +121,6 @@ class IdentityCreatorView extends GetWidget { child: Column(children: [ Row(crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded(child: Obx(() => (IdentityInputFieldBuilder( - context, - _responsiveUtils, AppLocalizations.of(context).name, controller.errorNameIdentity.value, editingController: controller.inputNameIdentityController, @@ -125,14 +129,23 @@ class IdentityCreatorView extends GetWidget { ..addOnChangeInputNameAction((value) => controller.updateNameIdentity(context, value))) .build())), const SizedBox(width: 24), - Expanded(child: Obx(() => (IdentityDropListFieldBuilder( - _imagePaths, + Expanded(child: Obx(() { + if (controller.actionType.value == IdentityActionType.create) { + return (IdentityDropListFieldBuilder( + _imagePaths, + AppLocalizations.of(context).email.inCaps, + controller.emailOfIdentity.value, + controller.listEmailAddressDefault) + ..addOnSelectEmailAddressDropListAction((emailAddress) => + controller.updateEmailOfIdentity(emailAddress)) + ).build(); + } else { + return IdentityFieldNoEditableBuilder( AppLocalizations.of(context).email.inCaps, - controller.emailOfIdentity.value, - controller.listEmailAddressDefault) - ..addOnSelectEmailAddressDropListAction((emailAddress) => - controller.updateEmailOfIdentity(emailAddress))) - .build())), + controller.emailOfIdentity.value + ).build(); + } + })), ]), const SizedBox(height: 24), Row(crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -265,12 +278,14 @@ class IdentityCreatorView extends GetWidget { radius: 10, onTap: () => controller.closeView(context)), const SizedBox(width: 12), - buildTextButton( - AppLocalizations.of(context).create, + Obx(() => buildTextButton( + controller.actionType.value == IdentityActionType.create + ? AppLocalizations.of(context).create + : AppLocalizations.of(context).save, width: 128, height: 44, radius: 10, - onTap: () => controller.createNewIdentity(context)), + onTap: () => controller.createNewIdentity(context))), ] ), ) @@ -299,8 +314,6 @@ class IdentityCreatorView extends GetWidget { padding: const EdgeInsets.all(24.0), child: Column(children: [ Obx(() => (IdentityInputFieldBuilder( - context, - _responsiveUtils, AppLocalizations.of(context).name, controller.errorNameIdentity.value, editingController: controller.inputNameIdentityController, @@ -309,14 +322,23 @@ class IdentityCreatorView extends GetWidget { ..addOnChangeInputNameAction((value) => controller.updateNameIdentity(context, value))) .build()), const SizedBox(height: 24), - Obx(() => (IdentityDropListFieldBuilder( - _imagePaths, + Obx(() { + if (controller.actionType.value == IdentityActionType.create) { + return (IdentityDropListFieldBuilder( + _imagePaths, + AppLocalizations.of(context).email.inCaps, + controller.emailOfIdentity.value, + controller.listEmailAddressDefault) + ..addOnSelectEmailAddressDropListAction((emailAddress) => + controller.updateEmailOfIdentity(emailAddress)) + ).build(); + } else { + return IdentityFieldNoEditableBuilder( AppLocalizations.of(context).email.inCaps, - controller.emailOfIdentity.value, - controller.listEmailAddressDefault) - ..addOnSelectEmailAddressDropListAction((emailAddress) => - controller.updateEmailOfIdentity(emailAddress))) - .build()), + controller.emailOfIdentity.value + ).build(); + } + }), const SizedBox(height: 24), Obx(() => (IdentityDropListFieldBuilder( _imagePaths, @@ -446,7 +468,7 @@ class IdentityCreatorView extends GetWidget { const SizedBox(width: 12), Expanded( child: Obx(() => buildTextButton( - controller.actionType == IdentityActionType.create + controller.actionType.value == IdentityActionType.create ? AppLocalizations.of(context).create : AppLocalizations.of(context).save, width: 128, diff --git a/lib/features/identity_creator/presentation/widgets/identity_field_no_editable_builder.dart b/lib/features/identity_creator/presentation/widgets/identity_field_no_editable_builder.dart new file mode 100644 index 000000000..3c1a7f060 --- /dev/null +++ b/lib/features/identity_creator/presentation/widgets/identity_field_no_editable_builder.dart @@ -0,0 +1,41 @@ + +import 'package:core/core.dart'; +import 'package:flutter/material.dart'; +import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; + +class IdentityFieldNoEditableBuilder { + + final String _label; + final EmailAddress? _emailAddressSelected; + + IdentityFieldNoEditableBuilder(this._label, this._emailAddressSelected); + + Widget build() { + return Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ + Text(_label, style: const TextStyle( + fontSize: 14, + fontWeight: FontWeight.normal, + color: AppColor.colorContentEmail)), + const SizedBox(height: 8), + Container( + height: 44, + alignment: Alignment.center, + width: double.infinity, + padding: const EdgeInsets.symmetric(horizontal: 12), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + border: Border.all(color: AppColor.colorInputBorderCreateMailbox, width: 0.5), + color: AppColor.colorInputBackgroundCreateMailbox), + child: Text( + _emailAddressSelected?.email ?? '', + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.normal, + color: AppColor.colorInputBorderCreateMailbox), + maxLines: 1, + overflow: BuildUtils.isWeb ? null : TextOverflow.ellipsis, + ) + ), + ]); + } +} \ No newline at end of file diff --git a/lib/features/identity_creator/presentation/widgets/identity_input_field_builder.dart b/lib/features/identity_creator/presentation/widgets/identity_input_field_builder.dart index 71d62e45d..6e671c87e 100644 --- a/lib/features/identity_creator/presentation/widgets/identity_input_field_builder.dart +++ b/lib/features/identity_creator/presentation/widgets/identity_input_field_builder.dart @@ -7,8 +7,6 @@ typedef OnChangeInputNameAction = Function(String? value); class IdentityInputFieldBuilder { - final BuildContext _context; - final ResponsiveUtils _responsiveUtils; final String _label; final String? _error; final TextEditingController? editingController; @@ -19,8 +17,6 @@ class IdentityInputFieldBuilder { OnChangeInputNameAction? onChangeInputNameAction; IdentityInputFieldBuilder( - this._context, - this._responsiveUtils, this._label, this._error, { this.isMandatory = false, @@ -48,8 +44,8 @@ class IdentityInputFieldBuilder { ..textStyle(const TextStyle(color: Colors.black, fontSize: 16)) ..keyboardType(inputType ?? TextInputType.text) ..textDecoration((IdentityInputDecorationBuilder() - ..setContentPadding(EdgeInsets.symmetric( - vertical: _responsiveUtils.isDesktop(_context) ? 16 : 12, + ..setContentPadding(const EdgeInsets.symmetric( + vertical: BuildUtils.isWeb ? 16 : 12, horizontal: 12)) ..setErrorText(_error)) .build())) diff --git a/lib/features/manage_account/data/datasource/manage_account_datasource.dart b/lib/features/manage_account/data/datasource/manage_account_datasource.dart index a7906d506..977a20dda 100644 --- a/lib/features/manage_account/data/datasource/manage_account_datasource.dart +++ b/lib/features/manage_account/data/datasource/manage_account_datasource.dart @@ -1,15 +1,16 @@ import 'package:jmap_dart_client/jmap/account_id.dart'; +import 'package:jmap_dart_client/jmap/core/properties/properties.dart'; import 'package:jmap_dart_client/jmap/identities/identity.dart'; import 'package:tmail_ui_user/features/manage_account/domain/model/create_new_identity_request.dart'; import 'package:tmail_ui_user/features/manage_account/domain/model/edit_identity_request.dart'; import 'package:tmail_ui_user/features/manage_account/domain/model/identities_response.dart'; abstract class ManageAccountDataSource { - Future getAllIdentities(AccountId accountId); + Future getAllIdentities(AccountId accountId, {Properties? properties}); Future createNewIdentity(AccountId accountId, CreateNewIdentityRequest identityRequest); Future deleteIdentity(AccountId accountId, IdentityId identityId); - Future editIdentity(AccountId accountId, EditIdentityRequest identityRequest); + Future editIdentity(AccountId accountId, EditIdentityRequest editIdentityRequest); } \ No newline at end of file diff --git a/lib/features/manage_account/data/datasource_impl/manage_account_datasource_impl.dart b/lib/features/manage_account/data/datasource_impl/manage_account_datasource_impl.dart index ec6d5531a..197f96c46 100644 --- a/lib/features/manage_account/data/datasource_impl/manage_account_datasource_impl.dart +++ b/lib/features/manage_account/data/datasource_impl/manage_account_datasource_impl.dart @@ -1,4 +1,5 @@ import 'package:jmap_dart_client/jmap/account_id.dart'; +import 'package:jmap_dart_client/jmap/core/properties/properties.dart'; import 'package:jmap_dart_client/jmap/identities/identity.dart'; import 'package:tmail_ui_user/features/manage_account/data/datasource/manage_account_datasource.dart'; import 'package:tmail_ui_user/features/manage_account/data/network/manage_account_api.dart'; @@ -13,9 +14,9 @@ class ManageAccountDataSourceImpl extends ManageAccountDataSource { ManageAccountDataSourceImpl(this.manageAccountAPI); @override - Future getAllIdentities(AccountId accountId) { + Future getAllIdentities(AccountId accountId, {Properties? properties}) { return Future.sync(() async { - return await manageAccountAPI.getAllIdentities(accountId); + return await manageAccountAPI.getAllIdentities(accountId, properties: properties); }).catchError((error) { throw error; }); @@ -40,9 +41,9 @@ class ManageAccountDataSourceImpl extends ManageAccountDataSource { } @override - Future editIdentity(AccountId accountId, EditIdentityRequest identityRequest) { + Future editIdentity(AccountId accountId, EditIdentityRequest editIdentityRequest) { return Future.sync(() async { - return await manageAccountAPI.editIdentity(accountId, identityRequest); + return await manageAccountAPI.editIdentity(accountId, editIdentityRequest); }).catchError((error) { throw error; }); diff --git a/lib/features/manage_account/data/network/manage_account_api.dart b/lib/features/manage_account/data/network/manage_account_api.dart index a5e3c42c4..302722e50 100644 --- a/lib/features/manage_account/data/network/manage_account_api.dart +++ b/lib/features/manage_account/data/network/manage_account_api.dart @@ -3,6 +3,7 @@ import 'dart:async'; 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/patch_object.dart'; +import 'package:jmap_dart_client/jmap/core/properties/properties.dart'; import 'package:jmap_dart_client/jmap/identities/get/get_identity_method.dart'; import 'package:jmap_dart_client/jmap/identities/get/get_identity_response.dart'; import 'package:jmap_dart_client/jmap/identities/identity.dart'; @@ -19,10 +20,13 @@ class ManageAccountAPI { ManageAccountAPI(this._httpClient); - Future getAllIdentities(AccountId accountId) async { + Future getAllIdentities(AccountId accountId, {Properties? properties}) async { final processingInvocation = ProcessingInvocation(); final jmapRequestBuilder = JmapRequestBuilder(_httpClient, processingInvocation); final getIdentityMethod = GetIdentityMethod(accountId); + if (properties != null) { + getIdentityMethod.addProperties(properties); + } final queryInvocation = jmapRequestBuilder.invocation(getIdentityMethod); final result = await (jmapRequestBuilder @@ -85,10 +89,10 @@ class ManageAccountAPI { }); } - Future editIdentity(AccountId accountId, EditIdentityRequest identityRequest) async { + Future editIdentity(AccountId accountId, EditIdentityRequest editIdentityRequest) async { final setIdentityMethod = SetIdentityMethod(accountId) ..addUpdates({ - identityRequest.identityId.id : PatchObject({}) + editIdentityRequest.identityId.id : PatchObject(editIdentityRequest.identityRequest.toJson()) }); final requestBuilder = JmapRequestBuilder(_httpClient, ProcessingInvocation()); @@ -105,7 +109,7 @@ class ManageAccountAPI { SetIdentityResponse.deserialize); return Future.sync(() async { - return setIdentityResponse!.updated![identityRequest.identityId]!; + return setIdentityResponse?.updated?.containsKey(editIdentityRequest.identityId.id) == true; }).catchError((error) { throw error; }); diff --git a/lib/features/manage_account/data/repository/manage_account_repository_impl.dart b/lib/features/manage_account/data/repository/manage_account_repository_impl.dart index f29392b67..4b880ec2a 100644 --- a/lib/features/manage_account/data/repository/manage_account_repository_impl.dart +++ b/lib/features/manage_account/data/repository/manage_account_repository_impl.dart @@ -1,4 +1,5 @@ import 'package:jmap_dart_client/jmap/account_id.dart'; +import 'package:jmap_dart_client/jmap/core/properties/properties.dart'; import 'package:jmap_dart_client/jmap/identities/identity.dart'; import 'package:tmail_ui_user/features/manage_account/data/datasource/manage_account_datasource.dart'; import 'package:tmail_ui_user/features/manage_account/domain/model/create_new_identity_request.dart'; @@ -13,8 +14,8 @@ class ManageAccountRepositoryImpl extends ManageAccountRepository { ManageAccountRepositoryImpl(this.dataSource); @override - Future getAllIdentities(AccountId accountId) { - return dataSource.getAllIdentities(accountId); + Future getAllIdentities(AccountId accountId, {Properties? properties}) { + return dataSource.getAllIdentities(accountId, properties: properties); } @override @@ -28,7 +29,7 @@ class ManageAccountRepositoryImpl extends ManageAccountRepository { } @override - Future editIdentity(AccountId accountId, EditIdentityRequest identityRequest) { - return dataSource.editIdentity(accountId, identityRequest); + Future editIdentity(AccountId accountId, EditIdentityRequest editIdentityRequest) { + return dataSource.editIdentity(accountId, editIdentityRequest); } } \ No newline at end of file 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 d1888d7df..7c4ebbbab 100644 --- a/lib/features/manage_account/domain/model/edit_identity_request.dart +++ b/lib/features/manage_account/domain/model/edit_identity_request.dart @@ -1,14 +1,15 @@ import 'package:equatable/equatable.dart'; import 'package:jmap_dart_client/jmap/identities/identity.dart'; +import 'package:model/model.dart'; class EditIdentityRequest with EquatableMixin { - final Identity newIdentity; + final IdentityRequestDto identityRequest; final IdentityId identityId; - EditIdentityRequest(this.identityId, this.newIdentity); + EditIdentityRequest({required this.identityId, required this.identityRequest}); @override - List get props => [identityId, newIdentity]; + List get props => [identityId, identityRequest]; } \ No newline at end of file diff --git a/lib/features/manage_account/domain/repository/manage_account_repository.dart b/lib/features/manage_account/domain/repository/manage_account_repository.dart index 2c44065e7..0591fb0ae 100644 --- a/lib/features/manage_account/domain/repository/manage_account_repository.dart +++ b/lib/features/manage_account/domain/repository/manage_account_repository.dart @@ -1,15 +1,16 @@ import 'package:jmap_dart_client/jmap/account_id.dart'; +import 'package:jmap_dart_client/jmap/core/properties/properties.dart'; import 'package:jmap_dart_client/jmap/identities/identity.dart'; import 'package:tmail_ui_user/features/manage_account/domain/model/create_new_identity_request.dart'; import 'package:tmail_ui_user/features/manage_account/domain/model/edit_identity_request.dart'; import 'package:tmail_ui_user/features/manage_account/domain/model/identities_response.dart'; abstract class ManageAccountRepository { - Future getAllIdentities(AccountId accountId); + Future getAllIdentities(AccountId accountId, {Properties? properties}); Future createNewIdentity(AccountId accountId, CreateNewIdentityRequest identityRequest); Future deleteIdentity(AccountId accountId, IdentityId identityId); - Future editIdentity(AccountId accountId, EditIdentityRequest identityRequest); + Future editIdentity(AccountId accountId, EditIdentityRequest editIdentityRequest); } \ No newline at end of file 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 31278007b..7c3827b30 100644 --- a/lib/features/manage_account/domain/state/edit_identity_state.dart +++ b/lib/features/manage_account/domain/state/edit_identity_state.dart @@ -1,14 +1,11 @@ import 'package:core/core.dart'; -import 'package:jmap_dart_client/jmap/identities/identity.dart'; class EditIdentitySuccess extends UIState { - final Identity newIdentity; - - EditIdentitySuccess(this.newIdentity); + EditIdentitySuccess(); @override - List get props => [newIdentity]; + List get props => []; } class EditIdentityFailure extends FeatureFailure { diff --git a/lib/features/manage_account/domain/usecases/edit_identity_interactor.dart b/lib/features/manage_account/domain/usecases/edit_identity_interactor.dart index 06f236712..9521c8777 100644 --- a/lib/features/manage_account/domain/usecases/edit_identity_interactor.dart +++ b/lib/features/manage_account/domain/usecases/edit_identity_interactor.dart @@ -12,10 +12,13 @@ class EditIdentityInteractor { EditIdentityInteractor(this.manageAccountRepository); - Stream> execute(AccountId accountId, EditIdentityRequest identityRequest) async* { + Stream> execute( + AccountId accountId, + EditIdentityRequest editIdentityRequest + ) async* { try { - final newIdentity = await manageAccountRepository.editIdentity(accountId, identityRequest); - yield Right(EditIdentitySuccess(newIdentity)); + final result = await manageAccountRepository.editIdentity(accountId, editIdentityRequest); + yield result ? Right(EditIdentitySuccess()) : Left(EditIdentityFailure(null)); } catch (exception) { yield Left(EditIdentityFailure(exception)); } diff --git a/lib/features/manage_account/domain/usecases/get_all_identities_interactor.dart b/lib/features/manage_account/domain/usecases/get_all_identities_interactor.dart index 38e2a7b60..320dd5054 100644 --- a/lib/features/manage_account/domain/usecases/get_all_identities_interactor.dart +++ b/lib/features/manage_account/domain/usecases/get_all_identities_interactor.dart @@ -3,6 +3,7 @@ import 'dart:core'; import 'package:core/core.dart'; import 'package:dartz/dartz.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; +import 'package:jmap_dart_client/jmap/core/properties/properties.dart'; import 'package:tmail_ui_user/features/manage_account/domain/repository/manage_account_repository.dart'; import 'package:tmail_ui_user/features/manage_account/domain/state/get_all_identities_state.dart'; @@ -11,10 +12,10 @@ class GetAllIdentitiesInteractor { GetAllIdentitiesInteractor(this.manageAccountRepository); - Stream> execute(AccountId accountId) async* { + Stream> execute(AccountId accountId, {Properties? properties}) async* { try { yield Right(LoadingState()); - final identitiesResponse = await manageAccountRepository.getAllIdentities(accountId); + final identitiesResponse = await manageAccountRepository.getAllIdentities(accountId, properties: properties); yield Right(GetAllIdentitiesSuccess(identitiesResponse.identities, identitiesResponse.state)); } catch (exception) { yield Left(GetAllIdentitiesFailure(exception)); diff --git a/lib/features/manage_account/presentation/profiles/identities/identities_controller.dart b/lib/features/manage_account/presentation/profiles/identities/identities_controller.dart index 7ffe76d8f..25a02bc04 100644 --- a/lib/features/manage_account/presentation/profiles/identities/identities_controller.dart +++ b/lib/features/manage_account/presentation/profiles/identities/identities_controller.dart @@ -1,12 +1,13 @@ import 'package:core/core.dart'; -import 'package:model/model.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:get/get.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; import 'package:jmap_dart_client/jmap/core/id.dart'; import 'package:jmap_dart_client/jmap/identities/identity.dart'; +import 'package:model/extensions/identity_extension.dart'; +import 'package:model/extensions/list_identities_extension.dart'; import 'package:tmail_ui_user/features/base/base_controller.dart'; import 'package:tmail_ui_user/features/identity_creator/presentation/model/identity_creator_arguments.dart'; import 'package:tmail_ui_user/features/manage_account/domain/model/create_new_identity_request.dart'; @@ -296,16 +297,23 @@ class IdentitiesController extends BaseController { identity: identity, actionType: IdentityActionType.edit)); - log('IdentitiesController::goToEditIdentity(): $newIdentity'); - _editIdentityAction(accountId, newIdentity); + if (newIdentity is Identity) { + log('IdentitiesController::goToEditIdentity(): $newIdentity'); + _editIdentityAction(accountId, EditIdentityRequest( + identityId: identity.id!, + identityRequest: newIdentity.toIdentityRequest() + )); + } } } - void _editIdentityAction(AccountId accountId, EditIdentityRequest identityRequest) async { - consumeState(_editIdentityInteractor.execute(accountId, identityRequest)); + void _editIdentityAction(AccountId accountId, EditIdentityRequest editIdentityRequest) async { + log('IdentitiesController::_editIdentityAction(): $editIdentityRequest'); + consumeState(_editIdentityInteractor.execute(accountId, editIdentityRequest)); } void _editIdentitySuccess(EditIdentitySuccess success) { + log('IdentitiesController::_editIdentitySuccess(): $success'); if (currentOverlayContext != null && currentContext != null) { _appToast.showToastWithIcon( currentOverlayContext!, diff --git a/model/lib/extensions/identity_extension.dart b/model/lib/extensions/identity_extension.dart new file mode 100644 index 000000000..cd64b736c --- /dev/null +++ b/model/lib/extensions/identity_extension.dart @@ -0,0 +1,15 @@ + +import 'package:jmap_dart_client/jmap/identities/identity.dart'; +import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; +import 'package:model/identity/identity_request_dto.dart'; + +extension IdentityExtension on Identity { + EmailAddress toEmailAddressNoName() => EmailAddress(null, email); + + IdentityRequestDto toIdentityRequest() => IdentityRequestDto( + name: name, + replyTo: replyTo, + bcc: bcc, + textSignature: textSignature, + htmlSignature: htmlSignature); +} \ No newline at end of file diff --git a/model/lib/identity/identity_request_dto.dart b/model/lib/identity/identity_request_dto.dart new file mode 100644 index 000000000..374cd6603 --- /dev/null +++ b/model/lib/identity/identity_request_dto.dart @@ -0,0 +1,51 @@ + +import 'package:equatable/equatable.dart'; +import 'package:jmap_dart_client/http/converter/identities/identity_id_nullable_converter.dart'; +import 'package:jmap_dart_client/http/converter/identities/signature_nullable_converter.dart'; +import 'package:jmap_dart_client/jmap/identities/identity.dart'; +import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; +import 'package:json_annotation/json_annotation.dart'; + +part 'identity_request_dto.g.dart'; + +@IdentityIdNullableConverter() +@SignatureNullableConverter() +@JsonSerializable() +class IdentityRequestDto with EquatableMixin { + + @JsonKey(includeIfNull: false) + final String? name; + + @JsonKey(includeIfNull: false) + final Set? bcc; + + @JsonKey(includeIfNull: false) + final Set? replyTo; + + @JsonKey(includeIfNull: false) + final Signature? textSignature; + + @JsonKey(includeIfNull: false) + final Signature? htmlSignature; + + IdentityRequestDto({ + this.name, + this.bcc, + this.replyTo, + this.textSignature, + this.htmlSignature, + }); + + factory IdentityRequestDto.fromJson(Map json) => _$IdentityRequestDtoFromJson(json); + + Map toJson() => _$IdentityRequestDtoToJson(this); + + @override + List get props => [ + name, + bcc, + replyTo, + textSignature, + htmlSignature, + ]; +} \ No newline at end of file diff --git a/model/lib/model.dart b/model/lib/model.dart index 2d40d27ae..a16f95a76 100644 --- a/model/lib/model.dart +++ b/model/lib/model.dart @@ -56,6 +56,7 @@ export 'extensions/list_attachment_extension.dart'; export 'extensions/list_presentation_email_extension.dart'; export 'extensions/list_email_content_extension.dart'; export 'extensions/list_identities_extension.dart'; +export 'extensions/identity_extension.dart'; // Download export 'download/download_task_id.dart'; @@ -70,4 +71,7 @@ export 'upload/upload_request.dart'; export 'upload/upload_response.dart'; // AutoComplete -export 'autocomplete/auto_complete_pattern.dart'; \ No newline at end of file +export 'autocomplete/auto_complete_pattern.dart'; + +// Identity +export 'identity/identity_request_dto.dart'; \ No newline at end of file