TF-517 Implement identity for FromEmailAddress in Composer on browser

This commit is contained in:
dab246
2022-04-27 15:19:52 +07:00
committed by Dat H. Pham
parent 2a8860a4c1
commit e4eca98483
6 changed files with 135 additions and 2 deletions
+4
View File
@@ -0,0 +1,4 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="24" height="24" rx="12" fill="#F4F5F6"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.9077 6.15032L6.48058 15.0925L6.27224 17.6609C6.25457 17.8791 6.44335 18.0568 6.65978 18.0259L9.21119 17.6659L17.6381 8.72309C17.7674 8.58623 17.7611 8.37043 17.6239 8.24119L15.3898 6.13573C15.2528 6.00644 15.0368 6.01281 14.9077 6.15032ZM7.37828 16.6816L7.47139 15.5332L13.4303 9.21002L14.6715 10.3796L8.71252 16.7028L7.57213 16.8641C7.46382 16.8792 7.36942 16.79 7.37828 16.6816ZM15.3732 9.63489L16.3087 8.64205C16.3732 8.5733 16.3702 8.46572 16.3015 8.40078L15.3087 7.46552C15.24 7.40058 15.1321 7.40374 15.0675 7.47249L14.1321 8.46533L15.3732 9.63489Z" fill="#99A2AD"/>
</svg>

After

Width:  |  Height:  |  Size: 783 B

@@ -111,6 +111,7 @@ extension AppColor on Color {
static const colorBgMailboxSelected = Color(0xFF99E4E8EC);
static const colorLoading = Color(0x2999A2AD);
static const colorActionButtonHover = Color(0xFFA2AAB3);
static const colorBgMenuItemDropDownSelected = Color(0x80DEE2E7);
static const mapGradientColor = [
[Color(0xFF21D4FD), Color(0xFFB721FF)],
@@ -100,6 +100,7 @@ class ImagePaths {
String get icMoreVertical => _getImagePath('ic_more_vertical.svg');
String get icEmail => _getImagePath('ic_email.svg');
String get icReplyTo => _getImagePath('ic_reply_to.svg');
String get icEditIdentity => _getImagePath('ic_edit_identity.svg');
String _getImagePath(String imageName) {
return AssetsPaths.images + imageName;
@@ -37,8 +37,15 @@ import 'package:tmail_ui_user/features/email/data/network/email_api.dart';
import 'package:tmail_ui_user/features/email/data/repository/email_repository_impl.dart';
import 'package:tmail_ui_user/features/email/domain/repository/email_repository.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/get_email_content_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:tmail_ui_user/features/upload/domain/usecases/local_file_picker_interactor.dart';
import 'package:uuid/uuid.dart';
import 'package:jmap_dart_client/http/http_client.dart' as jmap_http_client;
class ComposerBindings extends BaseBindings {
@override
@@ -50,6 +57,7 @@ class ComposerBindings extends BaseBindings {
void _bindingsUtils() {
Get.lazyPut(() => EmailAddressDatabaseManager(Get.find<DatabaseClient>()));
Get.lazyPut(() => const Uuid());
Get.lazyPut(() => ManageAccountAPI(Get.find<jmap_http_client.HttpClient>()));
}
@override
@@ -64,6 +72,7 @@ class ComposerBindings extends BaseBindings {
Get.find<HtmlAnalyzer>(),
Get.find<DioClient>()
));
Get.lazyPut(() => ManageAccountDataSourceImpl(Get.find<ManageAccountAPI>()));
}
@override
@@ -73,6 +82,7 @@ class ComposerBindings extends BaseBindings {
Get.lazyPut<ContactDataSource>(() => Get.find<ContactDataSourceImpl>());
Get.lazyPut<EmailDataSource>(() => Get.find<EmailDataSourceImpl>());
Get.lazyPut<HtmlDataSource>(() => Get.find<HtmlDataSourceImpl>());
Get.lazyPut<ManageAccountDataSource>(() => Get.find<ManageAccountDataSourceImpl>());
}
@override
@@ -90,6 +100,7 @@ class ComposerBindings extends BaseBindings {
Get.find<EmailDataSource>(),
Get.find<HtmlDataSource>()
));
Get.lazyPut(() => ManageAccountRepositoryImpl(Get.find<ManageAccountDataSource>()));
}
@override
@@ -98,6 +109,7 @@ class ComposerBindings extends BaseBindings {
Get.lazyPut<AutoCompleteRepository>(() => Get.find<AutoCompleteRepositoryImpl>());
Get.lazyPut<ContactRepository>(() => Get.find<ContactRepositoryImpl>());
Get.lazyPut<EmailRepository>(() => Get.find<EmailRepositoryImpl>());
Get.lazyPut<ManageAccountRepository>(() => Get.find<ManageAccountRepositoryImpl>());
}
@override
@@ -116,6 +128,7 @@ class ComposerBindings extends BaseBindings {
Get.lazyPut(() => SaveEmailAsDraftsInteractor(Get.find<EmailRepository>()));
Get.lazyPut(() => GetEmailContentInteractor(Get.find<EmailRepository>()));
Get.lazyPut(() => UpdateEmailDraftsInteractor(Get.find<EmailRepository>()));
Get.lazyPut(() => GetAllIdentitiesInteractor(Get.find<ManageAccountRepository>()));
}
@override
@@ -132,6 +145,7 @@ class ComposerBindings extends BaseBindings {
Get.find<SaveEmailAsDraftsInteractor>(),
Get.find<GetEmailContentInteractor>(),
Get.find<UpdateEmailDraftsInteractor>(),
Get.find<GetAllIdentitiesInteractor>(),
));
}
}
@@ -15,6 +15,7 @@ import 'package:get/get.dart';
import 'package:html_editor_enhanced/html_editor.dart' as html_editor_browser;
import 'package:http_parser/http_parser.dart';
import 'package:jmap_dart_client/jmap/core/id.dart';
import 'package:jmap_dart_client/jmap/identities/identity.dart';
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
import 'package:jmap_dart_client/jmap/mail/email/email_body_part.dart';
@@ -44,6 +45,8 @@ import 'package:tmail_ui_user/features/email/domain/usecases/get_email_content_i
import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/action/dashboard_action.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mailbox_dashboard_controller.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/upload/domain/state/local_file_picker_state.dart';
import 'package:tmail_ui_user/features/upload/domain/usecases/local_file_picker_interactor.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
@@ -68,6 +71,8 @@ class ComposerController extends BaseController {
final toAddressExpandMode = ExpandMode.EXPAND.obs;
final ccAddressExpandMode = ExpandMode.EXPAND.obs;
final bccAddressExpandMode = ExpandMode.EXPAND.obs;
final identitySelected = Rxn<Identity>();
final listIdentities = <Identity>[].obs;
final SendEmailInteractor _sendEmailInteractor;
final SaveEmailAddressesInteractor _saveEmailAddressInteractor;
@@ -80,6 +85,7 @@ class ComposerController extends BaseController {
final SaveEmailAsDraftsInteractor _saveEmailAsDraftsInteractor;
final GetEmailContentInteractor _getEmailContentInteractor;
final UpdateEmailDraftsInteractor _updateEmailDraftsInteractor;
final GetAllIdentitiesInteractor _getAllIdentitiesInteractor;
List<EmailAddress> listToEmailAddress = <EmailAddress>[];
List<EmailAddress> listCcEmailAddress = <EmailAddress>[];
@@ -126,6 +132,7 @@ class ComposerController extends BaseController {
this._saveEmailAsDraftsInteractor,
this._getEmailContentInteractor,
this._updateEmailDraftsInteractor,
this._getAllIdentitiesInteractor,
);
@override
@@ -138,10 +145,10 @@ class ComposerController extends BaseController {
@override
void onReady() async {
super.onReady();
_initEmail();
_getAllIdentities();
Future.delayed(const Duration(milliseconds: 500), () => _checkContactPermission());
super.onReady();
}
@override
@@ -173,6 +180,11 @@ class ComposerController extends BaseController {
_uploadAttachmentsSuccess(success);
} else if (success is GetEmailContentSuccess) {
_getEmailContentSuccess(success);
} if (success is GetAllIdentitiesSuccess) {
if (success.identities?.isNotEmpty == true) {
listIdentities.value = success.identities ?? [];
setIdentityDefault();
}
}
});
}
@@ -216,6 +228,13 @@ class ComposerController extends BaseController {
initialAttachments = arguments.attachments ?? [];
}
void _getAllIdentities() {
final accountId = mailboxDashBoardController.accountId.value;
if (accountId != null) {
consumeState(_getAllIdentitiesInteractor.execute(accountId));
}
}
String? getContentEmail(BuildContext context) {
if (composerArguments.value != null) {
switch(composerArguments.value!.emailActionType) {
@@ -883,6 +902,19 @@ class ComposerController extends BaseController {
}
}
void setIdentityDefault() {
try {
final identityDefault = listIdentities.firstWhere((identity) => identity.mayDelete == false);
selectIdentity(identityDefault);
} catch (exception) {
selectIdentity(listIdentities.first);
}
}
void selectIdentity(Identity? newIdentity) {
identitySelected.value = newIdentity;
}
void closeComposer() {
FocusManager.instance.primaryFocus?.unfocus();
popBack();
@@ -1,4 +1,5 @@
import 'package:core/core.dart';
import 'package:dropdown_button2/dropdown_button2.dart';
import 'package:file_picker/file_picker.dart';
import 'package:filesize/filesize.dart';
import 'package:flutter/cupertino.dart';
@@ -6,6 +7,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart';
import 'package:html_editor_enhanced/html_editor.dart' as html_editor_browser;
import 'package:jmap_dart_client/jmap/identities/identity.dart';
import 'package:model/model.dart';
import 'package:pointer_interceptor/pointer_interceptor.dart';
import 'package:tmail_ui_user/features/composer/domain/state/upload_attachment_state.dart';
@@ -37,6 +39,12 @@ class ComposerView extends GetWidget<ComposerController> {
children: [
Obx(() => _buildAppBarForMobile(context, controller.isEnableEmailSendButton.value)),
const Divider(color: AppColor.colorDividerComposer, height: 1),
Obx(() => controller.identitySelected.value != null
? _buildFromEmailAddress(context)
: const SizedBox.shrink()),
Obx(() => controller.identitySelected.value != null
? const Divider(color: AppColor.colorDividerComposer, height: 1)
: const SizedBox.shrink()),
_buildEmailAddress(context, constraints),
const Divider(color: AppColor.colorDividerComposer, height: 1),
Padding(padding: const EdgeInsets.symmetric(horizontal: 16), child: _buildSubjectEmail(context)),
@@ -273,6 +281,12 @@ class ComposerView extends GetWidget<ComposerController> {
Expanded(child: Padding(
padding: const EdgeInsets.only(left: 12),
child: Column(children: [
Obx(() => controller.identitySelected.value != null
? _buildFromEmailAddress(context)
: const SizedBox.shrink()),
Obx(() => controller.identitySelected.value != null
? const Divider(color: AppColor.colorDividerComposer, height: 1)
: const SizedBox.shrink()),
_buildEmailAddress(context, constraints),
const Divider(color: AppColor.colorDividerComposer, height: 1),
Padding(padding: const EdgeInsets.only(right: 16), child: _buildSubjectEmail(context)),
@@ -301,6 +315,73 @@ class ComposerView extends GetWidget<ComposerController> {
));
}
Widget _buildFromEmailAddress(BuildContext context) {
return Padding(
padding: EdgeInsets.only(
left: responsiveUtils.isMobile(context) ? 16 : 0,
top: 12,
bottom: 12),
child: Row(children: [
Text('${AppLocalizations.of(context).from_email_address_prefix}:',
style: const TextStyle(fontSize: 15, color: AppColor.colorHintEmailAddressInput)),
const SizedBox(width: 12),
DropdownButtonHideUnderline(
child: DropdownButton2<Identity>(
isExpanded: true,
customButton: SvgPicture.asset(imagePaths.icEditIdentity),
items: controller.listIdentities.map((item) => DropdownMenuItem<Identity>(
value: item,
child: Container(
alignment: Alignment.centerLeft,
padding: const EdgeInsets.symmetric(horizontal: 8),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
color: item == controller.identitySelected.value ? AppColor.colorBgMenuItemDropDownSelected : Colors.transparent),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(
item.name ?? '',
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.normal, color: Colors.black),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
Text(
item.email ?? '',
style: const TextStyle(fontSize: 13, fontWeight: FontWeight.normal, color: AppColor.colorHintSearchBar),
maxLines: 1,
overflow: TextOverflow.ellipsis,
)
]
),
),
)).toList(),
onChanged: (newIdentity) => controller.selectIdentity(newIdentity),
itemPadding: const EdgeInsets.symmetric(horizontal: 8),
customItemsHeight: 55,
dropdownMaxHeight: 240,
dropdownWidth: 370,
dropdownDecoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.white),
dropdownElevation: 4,
scrollbarRadius: const Radius.circular(40),
scrollbarThickness: 6,
),
),
Expanded(child: Padding(
padding: const EdgeInsets.only(right: 8, left: 12),
child: Text(
controller.identitySelected.value?.email ?? '',
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: const TextStyle(fontSize: 17, fontWeight: FontWeight.normal, color: AppColor.colorEmailAddressPrefix),
))),
]),
);
}
Widget _buildEmailAddress(BuildContext context, BoxConstraints constraints) {
log('ComposerView::_buildEmailAddress(): height: ${constraints.maxHeight}');
return ConstrainedBox(