TF-495 Implement linter for composer

This commit is contained in:
dab246
2022-04-22 09:51:36 +07:00
committed by Dat H. Pham
parent d8f236a89c
commit a305ba1826
15 changed files with 223 additions and 221 deletions
@@ -12,7 +12,7 @@ class GetAutoCompleteSuccess extends UIState {
} }
class GetAutoCompleteFailure extends FeatureFailure { class GetAutoCompleteFailure extends FeatureFailure {
final exception; final dynamic exception;
GetAutoCompleteFailure(this.exception); GetAutoCompleteFailure(this.exception);
@@ -12,7 +12,7 @@ class GetDeviceContactSuggestionsSuccess extends UIState {
} }
class GetDeviceContactSuggestionsFailure extends FeatureFailure { class GetDeviceContactSuggestionsFailure extends FeatureFailure {
final exception; final dynamic exception;
GetDeviceContactSuggestionsFailure(this.exception); GetDeviceContactSuggestionsFailure(this.exception);
@@ -9,7 +9,7 @@ class SaveEmailAddressSuccess extends UIState {
} }
class SaveEmailAddressFailure extends FeatureFailure { class SaveEmailAddressFailure extends FeatureFailure {
final exception; final dynamic exception;
SaveEmailAddressFailure(this.exception); SaveEmailAddressFailure(this.exception);
@@ -12,7 +12,7 @@ class SaveEmailAsDraftsSuccess extends UIState {
} }
class SaveEmailAsDraftsFailure extends FeatureFailure { class SaveEmailAsDraftsFailure extends FeatureFailure {
final exception; final dynamic exception;
SaveEmailAsDraftsFailure(this.exception); SaveEmailAsDraftsFailure(this.exception);
@@ -16,7 +16,7 @@ class SendEmailSuccess extends UIState {
} }
class SendEmailFailure extends FeatureFailure { class SendEmailFailure extends FeatureFailure {
final exception; final dynamic exception;
SendEmailFailure(this.exception); SendEmailFailure(this.exception);
@@ -12,7 +12,7 @@ class UpdateEmailDraftsSuccess extends UIState {
} }
class UpdateEmailDraftsFailure extends FeatureFailure { class UpdateEmailDraftsFailure extends FeatureFailure {
final exception; final dynamic exception;
UpdateEmailDraftsFailure(this.exception); UpdateEmailDraftsFailure(this.exception);
@@ -19,7 +19,7 @@ class UploadAttachmentSuccess extends UIState {
} }
class UploadAttachmentFailure extends FeatureFailure { class UploadAttachmentFailure extends FeatureFailure {
final exception; final dynamic exception;
UploadAttachmentFailure(this.exception); UploadAttachmentFailure(this.exception);
@@ -25,7 +25,7 @@ class UploadMultipleAttachmentInteractor {
final listResultSuccess = listResult.where((either) => either.isRight()).toList(); final listResultSuccess = listResult.where((either) => either.isRight()).toList();
if (listResultSuccess.length == listResult.length) { if (listResultSuccess.length == listResult.length) {
yield Right<Failure, Success>(UploadMultipleAttachmentAllSuccess(listResultSuccess)); yield Right<Failure, Success>(UploadMultipleAttachmentAllSuccess(listResultSuccess));
} else if (listResultSuccess.length == 0) { } else if (listResultSuccess.isEmpty) {
yield Left<Failure, Success>(UploadMultipleAttachmentAllFailure(listResult)); yield Left<Failure, Success>(UploadMultipleAttachmentAllFailure(listResult));
} else { } else {
yield Right<Failure, Success>(UploadMultipleAttachmentHasSomeFailure(listResultSuccess)); yield Right<Failure, Success>(UploadMultipleAttachmentHasSomeFailure(listResultSuccess));
@@ -49,7 +49,7 @@ class ComposerBindings extends BaseBindings {
void _bindingsUtils() { void _bindingsUtils() {
Get.lazyPut(() => EmailAddressDatabaseManager(Get.find<DatabaseClient>())); Get.lazyPut(() => EmailAddressDatabaseManager(Get.find<DatabaseClient>()));
Get.lazyPut(() => Uuid()); Get.lazyPut(() => const Uuid());
} }
@override @override
@@ -12,7 +12,7 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:html_editor_enhanced/html_editor.dart' as HtmlEditorBrowser; import 'package:html_editor_enhanced/html_editor.dart' as html_editor_browser;
import 'package:http_parser/http_parser.dart'; import 'package:http_parser/http_parser.dart';
import 'package:jmap_dart_client/jmap/core/id.dart'; import 'package:jmap_dart_client/jmap/core/id.dart';
import 'package:jmap_dart_client/jmap/mail/email/email.dart'; import 'package:jmap_dart_client/jmap/mail/email/email.dart';
@@ -86,7 +86,7 @@ class ComposerController extends BaseController {
List<EmailAddress> listBccEmailAddress = <EmailAddress>[]; List<EmailAddress> listBccEmailAddress = <EmailAddress>[];
ContactSuggestionSource _contactSuggestionSource = ContactSuggestionSource.localContact; ContactSuggestionSource _contactSuggestionSource = ContactSuggestionSource.localContact;
HtmlEditorApi? htmlEditorApi; HtmlEditorApi? htmlEditorApi;
final HtmlEditorBrowser.HtmlEditorController htmlControllerBrowser = HtmlEditorBrowser.HtmlEditorController(processNewLineAsBr: true); final html_editor_browser.HtmlEditorController htmlControllerBrowser = html_editor_browser.HtmlEditorController(processNewLineAsBr: true);
final subjectEmailInputController = TextEditingController(); final subjectEmailInputController = TextEditingController();
final toEmailAddressController = TextEditingController(); final toEmailAddressController = TextEditingController();
@@ -141,7 +141,7 @@ class ComposerController extends BaseController {
super.onReady(); super.onReady();
_initEmail(); _initEmail();
Future.delayed(Duration(milliseconds: 500), () => _checkContactPermission()); Future.delayed(const Duration(milliseconds: 500), () => _checkContactPermission());
} }
@override @override
@@ -485,8 +485,7 @@ class ComposerController extends BaseController {
if (!_validateAttachmentsSize()) { if (!_validateAttachmentsSize()) {
showConfirmDialogAction( showConfirmDialogAction(
context, context,
AppLocalizations.of(context).message_dialog_send_email_exceeds_maximum_size('${ AppLocalizations.of(context).message_dialog_send_email_exceeds_maximum_size(filesize(mailboxDashBoardController.maxSizeAttachmentsPerEmail?.value ?? 0, 0)),
filesize(mailboxDashBoardController.maxSizeAttachmentsPerEmail?.value ?? 0, 0)}'),
AppLocalizations.of(context).got_it, AppLocalizations.of(context).got_it,
() => {}, () => {},
title: AppLocalizations.of(context).sending_failed, title: AppLocalizations.of(context).sending_failed,
@@ -527,7 +526,7 @@ class ComposerController extends BaseController {
} }
void _saveEmailAddress() async { void _saveEmailAddress() async {
final listEmailAddressCanSave = Set<EmailAddress>(); final listEmailAddressCanSave = <EmailAddress>{};
listEmailAddressCanSave.addAll(listToEmailAddress + listCcEmailAddress + listBccEmailAddress); listEmailAddressCanSave.addAll(listToEmailAddress + listCcEmailAddress + listBccEmailAddress);
await _saveEmailAddressInteractor.execute(listEmailAddressCanSave.toList()); await _saveEmailAddressInteractor.execute(listEmailAddressCanSave.toList());
} }
@@ -561,7 +560,7 @@ class ComposerController extends BaseController {
clearFocusEditor(context); clearFocusEditor(context);
(ContextMenuBuilder(context) (ContextMenuBuilder(context)
..addHeader((ContextMenuHeaderBuilder(Key('attachment_picker_context_menu_header_builder')) ..addHeader((ContextMenuHeaderBuilder(const Key('attachment_picker_context_menu_header_builder'))
..addLabel(AppLocalizations.of(context).pick_attachments)) ..addLabel(AppLocalizations.of(context).pick_attachments))
.build()) .build())
..addTiles(actionTiles) ..addTiles(actionTiles)
@@ -592,8 +591,7 @@ class ComposerController extends BaseController {
if (currentContext != null) { if (currentContext != null) {
showConfirmDialogAction( showConfirmDialogAction(
currentContext!, currentContext!,
AppLocalizations.of(currentContext!).message_dialog_upload_attachments_exceeds_maximum_size('${ AppLocalizations.of(currentContext!).message_dialog_upload_attachments_exceeds_maximum_size(filesize(mailboxDashBoardController.maxSizeAttachmentsPerEmail?.value ?? 0, 0)),
filesize(mailboxDashBoardController.maxSizeAttachmentsPerEmail?.value ?? 0, 0)}'),
AppLocalizations.of(currentContext!).got_it, AppLocalizations.of(currentContext!).got_it,
() => {}, () => {},
title: AppLocalizations.of(currentContext!).maximum_files_size, title: AppLocalizations.of(currentContext!).maximum_files_size,
@@ -687,7 +685,7 @@ class ComposerController extends BaseController {
final recipients = arguments.presentationEmail final recipients = arguments.presentationEmail
?.generateRecipientsEmailAddressForComposer(arguments.emailActionType, arguments.mailboxRole) ?.generateRecipientsEmailAddressForComposer(arguments.emailActionType, arguments.mailboxRole)
?? Tuple3(<EmailAddress>[], <EmailAddress>[], <EmailAddress>[]); ?? const Tuple3(<EmailAddress>[], <EmailAddress>[], <EmailAddress>[]);
final newToEmailAddress = listToEmailAddress; final newToEmailAddress = listToEmailAddress;
final oldToEmailAddress = recipients.value1; final oldToEmailAddress = recipients.value1;
@@ -20,6 +20,8 @@ class ComposerView extends GetWidget<ComposerController> {
final imagePaths = Get.find<ImagePaths>(); final imagePaths = Get.find<ImagePaths>();
final keyboardUtils = Get.find<KeyboardUtils>(); final keyboardUtils = Get.find<KeyboardUtils>();
ComposerView({Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ResponsiveWidget( return ResponsiveWidget(
@@ -50,7 +52,7 @@ class ComposerView extends GetWidget<ComposerController> {
color: Colors.white, color: Colors.white,
child: Column(children: [ child: Column(children: [
Obx(() => _buildAppBar(context, controller.isEnableEmailSendButton.value)), Obx(() => _buildAppBar(context, controller.isEnableEmailSendButton.value)),
Divider(color: AppColor.colorDividerComposer, height: 1), const Divider(color: AppColor.colorDividerComposer, height: 1),
Expanded(child: _buildBodyMobile(context)) Expanded(child: _buildBodyMobile(context))
]) ])
) )
@@ -75,20 +77,20 @@ class ComposerView extends GetWidget<ComposerController> {
body: Align(alignment: Alignment.center, child: Card( body: Align(alignment: Alignment.center, child: Card(
color: Colors.transparent, color: Colors.transparent,
elevation: 20, elevation: 20,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(24))), shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(24))),
shadowColor: Colors.transparent, shadowColor: Colors.transparent,
child: Container( child: Container(
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(24))), decoration: const BoxDecoration(color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(24))),
width: responsiveUtils.getSizeScreenWidth(context) * 0.9, width: responsiveUtils.getSizeScreenWidth(context) * 0.9,
height: responsiveUtils.getSizeScreenHeight(context) * 0.9, height: responsiveUtils.getSizeScreenHeight(context) * 0.9,
child: ClipRRect( child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(24)), borderRadius: const BorderRadius.all(Radius.circular(24)),
child: SafeArea( child: SafeArea(
child: Column(children: [ child: Column(children: [
Padding(padding: EdgeInsets.symmetric(horizontal: 16), child: _buildAppBar(context, controller.isEnableEmailSendButton.value)), Padding(padding: const EdgeInsets.symmetric(horizontal: 16), child: _buildAppBar(context, controller.isEnableEmailSendButton.value)),
Padding(padding: EdgeInsets.only(top: 8), child: Divider(color: AppColor.colorDividerComposer, height: 1)), const Padding(padding: EdgeInsets.only(top: 8), child: Divider(color: AppColor.colorDividerComposer, height: 1)),
Expanded(child: _buildBodyTablet(context)), Expanded(child: _buildBodyTablet(context)),
Divider(color: AppColor.colorDividerComposer, height: 1), const Divider(color: AppColor.colorDividerComposer, height: 1),
Obx(() => _buildBottomBar(context, controller.isEnableEmailSendButton.value)), Obx(() => _buildBottomBar(context, controller.isEnableEmailSendButton.value)),
]), ]),
) )
@@ -102,7 +104,7 @@ class ComposerView extends GetWidget<ComposerController> {
Widget _buildAppBar(BuildContext context, bool isEnableSendButton) { Widget _buildAppBar(BuildContext context, bool isEnableSendButton) {
return Container( return Container(
padding: responsiveUtils.isMobile(context) ? EdgeInsets.all(8) : EdgeInsets.zero, padding: responsiveUtils.isMobile(context) ? const EdgeInsets.all(8) : EdgeInsets.zero,
color: Colors.white, color: Colors.white,
child: Row( child: Row(
children: [ children: [
@@ -128,22 +130,22 @@ class ComposerView extends GetWidget<ComposerController> {
Widget _buildBottomBar(BuildContext context, bool isEnableSendButton) { Widget _buildBottomBar(BuildContext context, bool isEnableSendButton) {
return Container( return Container(
padding: EdgeInsets.symmetric(vertical: 16), padding: const EdgeInsets.symmetric(vertical: 16),
color: Colors.white, color: Colors.white,
child: Row(mainAxisAlignment: MainAxisAlignment.center, child: Row(mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
buildTextButton( buildTextButton(
AppLocalizations.of(context).cancel, AppLocalizations.of(context).cancel,
textStyle: TextStyle(fontWeight: FontWeight.w500, fontSize: 17, color: AppColor.lineItemListColor), textStyle: const TextStyle(fontWeight: FontWeight.w500, fontSize: 17, color: AppColor.lineItemListColor),
backgroundColor: AppColor.emailAddressChipColor, backgroundColor: AppColor.emailAddressChipColor,
width: 150, width: 150,
height: 44, height: 44,
radius: 10, radius: 10,
onTap: () => controller.closeComposer()), onTap: () => controller.closeComposer()),
SizedBox(width: 12), const SizedBox(width: 12),
buildTextButton( buildTextButton(
AppLocalizations.of(context).save_to_drafts, AppLocalizations.of(context).save_to_drafts,
textStyle: TextStyle(fontWeight: FontWeight.w500, fontSize: 17, color: AppColor.colorTextButton), textStyle: const TextStyle(fontWeight: FontWeight.w500, fontSize: 17, color: AppColor.colorTextButton),
backgroundColor: AppColor.emailAddressChipColor, backgroundColor: AppColor.emailAddressChipColor,
width: 150, width: 150,
height: 44, height: 44,
@@ -152,7 +154,7 @@ class ComposerView extends GetWidget<ComposerController> {
controller.saveEmailAsDrafts(context); controller.saveEmailAsDrafts(context);
controller.closeComposer(); controller.closeComposer();
}), }),
SizedBox(width: 12), const SizedBox(width: 12),
buildTextButton( buildTextButton(
AppLocalizations.of(context).send, AppLocalizations.of(context).send,
width: 150, width: 150,
@@ -180,13 +182,13 @@ class ComposerView extends GetWidget<ComposerController> {
return [ return [
_pickPhotoAndVideoAction(context), _pickPhotoAndVideoAction(context),
_browseFileAction(context), _browseFileAction(context),
SizedBox(height: kIsWeb ? 16 : 30), const SizedBox(height: kIsWeb ? 16 : 30),
]; ];
} }
Widget _pickPhotoAndVideoAction(BuildContext context) { Widget _pickPhotoAndVideoAction(BuildContext context) {
return (SimpleContextMenuActionBuilder( return (SimpleContextMenuActionBuilder(
Key('pick_photo_and_video_context_menu_action'), const Key('pick_photo_and_video_context_menu_action'),
SvgPicture.asset(imagePaths.icPhotoLibrary, width: 24, height: 24, fit: BoxFit.fill), SvgPicture.asset(imagePaths.icPhotoLibrary, width: 24, height: 24, fit: BoxFit.fill),
AppLocalizations.of(context).photos_and_videos) AppLocalizations.of(context).photos_and_videos)
..onActionClick((_) => controller.openFilePickerByType(context, FileType.media))) ..onActionClick((_) => controller.openFilePickerByType(context, FileType.media)))
@@ -195,7 +197,7 @@ class ComposerView extends GetWidget<ComposerController> {
Widget _browseFileAction(BuildContext context) { Widget _browseFileAction(BuildContext context) {
return (SimpleContextMenuActionBuilder( return (SimpleContextMenuActionBuilder(
Key('browse_file_context_menu_action'), const Key('browse_file_context_menu_action'),
SvgPicture.asset(imagePaths.icMore, width: 24, height: 24, fit: BoxFit.fill), SvgPicture.asset(imagePaths.icMore, width: 24, height: 24, fit: BoxFit.fill),
AppLocalizations.of(context).browse) AppLocalizations.of(context).browse)
..onActionClick((_) => controller.openFilePickerByType(context, FileType.any))) ..onActionClick((_) => controller.openFilePickerByType(context, FileType.any)))
@@ -223,8 +225,8 @@ class ComposerView extends GetWidget<ComposerController> {
.build() .build()
)), )),
Obx(() => controller.listEmailAddressType.contains(PrefixEmailAddress.cc) == true Obx(() => controller.listEmailAddressType.contains(PrefixEmailAddress.cc) == true
? Divider(color: AppColor.colorDividerComposer, height: 1) ? const Divider(color: AppColor.colorDividerComposer, height: 1)
: SizedBox.shrink()), : const SizedBox.shrink()),
Obx(() => controller.listEmailAddressType.contains(PrefixEmailAddress.cc) == true Obx(() => controller.listEmailAddressType.contains(PrefixEmailAddress.cc) == true
? Padding( ? Padding(
padding: EdgeInsets.only(left: responsiveUtils.isMobile(context) ? 16 : 0), padding: EdgeInsets.only(left: responsiveUtils.isMobile(context) ? 16 : 0),
@@ -242,11 +244,11 @@ class ComposerView extends GetWidget<ComposerController> {
..addOnOpenSuggestionBoxEmailAddress(() => controller.getAutoCompleteSuggestion(isAll: true)) ..addOnOpenSuggestionBoxEmailAddress(() => controller.getAutoCompleteSuggestion(isAll: true))
..addOnSuggestionEmailAddress((word) => controller.getAutoCompleteSuggestion(word: word))) ..addOnSuggestionEmailAddress((word) => controller.getAutoCompleteSuggestion(word: word)))
.build()) .build())
: SizedBox.shrink() : const SizedBox.shrink()
), ),
Obx(() => controller.listEmailAddressType.contains(PrefixEmailAddress.bcc) == true Obx(() => controller.listEmailAddressType.contains(PrefixEmailAddress.bcc) == true
? Divider(color: AppColor.colorDividerComposer, height: 1) ? const Divider(color: AppColor.colorDividerComposer, height: 1)
: SizedBox.shrink()), : const SizedBox.shrink()),
Obx(() => controller.listEmailAddressType.contains(PrefixEmailAddress.bcc) == true Obx(() => controller.listEmailAddressType.contains(PrefixEmailAddress.bcc) == true
? Padding( ? Padding(
padding: EdgeInsets.only(left: responsiveUtils.isMobile(context) ? 16 : 0), padding: EdgeInsets.only(left: responsiveUtils.isMobile(context) ? 16 : 0),
@@ -264,7 +266,7 @@ class ComposerView extends GetWidget<ComposerController> {
..addOnOpenSuggestionBoxEmailAddress(() => controller.getAutoCompleteSuggestion(isAll: true)) ..addOnOpenSuggestionBoxEmailAddress(() => controller.getAutoCompleteSuggestion(isAll: true))
..addOnSuggestionEmailAddress((word) => controller.getAutoCompleteSuggestion(word: word))) ..addOnSuggestionEmailAddress((word) => controller.getAutoCompleteSuggestion(word: word)))
.build()) .build())
: SizedBox.shrink() : const SizedBox.shrink()
), ),
], ],
); );
@@ -274,20 +276,20 @@ class ComposerView extends GetWidget<ComposerController> {
return Row( return Row(
children: [ children: [
Padding( Padding(
padding: EdgeInsets.only(right: 8), padding: const EdgeInsets.only(right: 8),
child: Text( child: Text(
'${AppLocalizations.of(context).subject_email}:', '${AppLocalizations.of(context).subject_email}:',
style: TextStyle(fontSize: 15, color: AppColor.colorHintEmailAddressInput))), style: const TextStyle(fontSize: 15, color: AppColor.colorHintEmailAddressInput))),
Expanded( Expanded(
child: FocusScope(child: Focus( child: FocusScope(child: Focus(
onFocusChange: (focus) => controller.onSubjectEmailFocusChange(focus), onFocusChange: (focus) => controller.onSubjectEmailFocusChange(focus),
child: (TextFieldBuilder() child: (TextFieldBuilder()
..key(Key('subject_email_input')) ..key(const Key('subject_email_input'))
..cursorColor(AppColor.colorTextButton) ..cursorColor(AppColor.colorTextButton)
..maxLines(responsiveUtils.isMobile(context) ? null : 1) ..maxLines(responsiveUtils.isMobile(context) ? null : 1)
..onChange((value) => controller.setSubjectEmail(value)) ..onChange((value) => controller.setSubjectEmail(value))
..textStyle(TextStyle(color: Colors.black, fontSize: 15, fontWeight: FontWeight.normal)) ..textStyle(const TextStyle(color: Colors.black, fontSize: 15, fontWeight: FontWeight.normal))
..textDecoration(InputDecoration(contentPadding: EdgeInsets.zero, border: InputBorder.none)) ..textDecoration(const InputDecoration(contentPadding: EdgeInsets.zero, border: InputBorder.none))
..addController(controller.subjectEmailInputController)) ..addController(controller.subjectEmailInputController))
.build(), .build(),
)) ))
@@ -300,7 +302,7 @@ class ComposerView extends GetWidget<ComposerController> {
return Transform( return Transform(
transform: Matrix4.translationValues(-10.0, 0.0, 0.0), transform: Matrix4.translationValues(-10.0, 0.0, 0.0),
child: Padding( child: Padding(
padding: EdgeInsets.symmetric(vertical: 5), padding: const EdgeInsets.symmetric(vertical: 5),
child: Row(children: [ child: Row(children: [
buildIconWeb( buildIconWeb(
icon: SvgPicture.asset(imagePaths.icAttachmentsComposer, color: AppColor.colorTextButton, fit: BoxFit.fill), icon: SvgPicture.asset(imagePaths.icAttachmentsComposer, color: AppColor.colorTextButton, fit: BoxFit.fill),
@@ -313,29 +315,29 @@ class ComposerView extends GetWidget<ComposerController> {
Widget _buildBodyMobile(BuildContext context) { Widget _buildBodyMobile(BuildContext context) {
return SingleChildScrollView( return SingleChildScrollView(
physics: ClampingScrollPhysics(), physics: const ClampingScrollPhysics(),
child: Column(children: [ child: Column(children: [
_buildEmailAddress(context), _buildEmailAddress(context),
Divider(color: AppColor.colorDividerComposer, height: 1), const Divider(color: AppColor.colorDividerComposer, height: 1),
Padding(padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8), child: _buildSubjectEmail(context)), Padding(padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), child: _buildSubjectEmail(context)),
Divider(color: AppColor.colorDividerComposer, height: 1), const Divider(color: AppColor.colorDividerComposer, height: 1),
Padding(padding: EdgeInsets.symmetric(horizontal: 16), child: _buildListButton(context)), Padding(padding: const EdgeInsets.symmetric(horizontal: 16), child: _buildListButton(context)),
Divider(color: AppColor.colorDividerComposer, height: 1), const Divider(color: AppColor.colorDividerComposer, height: 1),
Obx(() => controller.attachments.isNotEmpty Obx(() => controller.attachments.isNotEmpty
? Padding( ? Padding(
padding: EdgeInsets.symmetric(horizontal: 16), padding: const EdgeInsets.symmetric(horizontal: 16),
child: _buildAttachmentsTitle(context, controller.attachments, controller.expandModeAttachments.value)) child: _buildAttachmentsTitle(context, controller.attachments, controller.expandModeAttachments.value))
: SizedBox.shrink()), : const SizedBox.shrink()),
Obx(() => controller.attachments.isEmpty Obx(() => controller.attachments.isEmpty
? _buildAttachmentsLoadingView() ? _buildAttachmentsLoadingView()
: SizedBox.shrink()), : const SizedBox.shrink()),
Obx(() => controller.attachments.isNotEmpty Obx(() => controller.attachments.isNotEmpty
? Padding( ? Padding(
padding: EdgeInsets.only(bottom: 8, left: 16, right: 16), padding: const EdgeInsets.only(bottom: 8, left: 16, right: 16),
child: _buildAttachmentsList(context, controller.attachments, controller.expandModeAttachments.value)) child: _buildAttachmentsList(context, controller.attachments, controller.expandModeAttachments.value))
: SizedBox.shrink()), : const SizedBox.shrink()),
Padding( Padding(
padding: EdgeInsets.only(left: 16, right: 16, bottom: 20), padding: const EdgeInsets.only(left: 16, right: 16, bottom: 20),
child: _buildComposerEditor(context)), child: _buildComposerEditor(context)),
]) ])
); );
@@ -343,48 +345,48 @@ class ComposerView extends GetWidget<ComposerController> {
Widget _buildBodyTablet(BuildContext context) { Widget _buildBodyTablet(BuildContext context) {
return SingleChildScrollView( return SingleChildScrollView(
physics: ClampingScrollPhysics(), physics: const ClampingScrollPhysics(),
child: Column(children: [ child: Column(children: [
Padding( Padding(
padding: EdgeInsets.only(left: 16), padding: const EdgeInsets.only(left: 16),
child: Row(crossAxisAlignment: CrossAxisAlignment.start, children: [ child: Row(crossAxisAlignment: CrossAxisAlignment.start, children: [
Padding(padding: EdgeInsets.only(top: 20), Padding(padding: const EdgeInsets.only(top: 20),
child: (AvatarBuilder() child: (AvatarBuilder()
..text('${controller.mailboxDashBoardController.userProfile.value?.getAvatarText() ?? ''}') ..text(controller.mailboxDashBoardController.userProfile.value?.getAvatarText() ?? '')
..size(56) ..size(56)
..addTextStyle(TextStyle(fontWeight: FontWeight.w600, fontSize: 28, color: Colors.white)) ..addTextStyle(const TextStyle(fontWeight: FontWeight.w600, fontSize: 28, color: Colors.white))
..backgroundColor(AppColor.colorAvatar)) ..backgroundColor(AppColor.colorAvatar))
.build()), .build()),
Expanded(child: Padding( Expanded(child: Padding(
padding: EdgeInsets.only(left: 16), padding: const EdgeInsets.only(left: 16),
child: Column(children: [ child: Column(children: [
_buildEmailAddress(context), _buildEmailAddress(context),
Divider(color: AppColor.colorDividerComposer, height: 1), const Divider(color: AppColor.colorDividerComposer, height: 1),
Padding(padding: EdgeInsets.only(right: 16), child: _buildSubjectEmail(context)), Padding(padding: const EdgeInsets.only(right: 16), child: _buildSubjectEmail(context)),
Divider(color: AppColor.colorDividerComposer, height: 1), const Divider(color: AppColor.colorDividerComposer, height: 1),
_buildListButton(context), _buildListButton(context),
]), ]),
)) ))
])), ])),
Divider(color: AppColor.colorDividerComposer, height: 1), const Divider(color: AppColor.colorDividerComposer, height: 1),
Padding( Padding(
padding: EdgeInsets.only(left: 60, right: 25), padding: const EdgeInsets.only(left: 60, right: 25),
child: Column(children: [ child: Column(children: [
Obx(() => controller.attachments.isNotEmpty Obx(() => controller.attachments.isNotEmpty
? Padding( ? Padding(
padding: EdgeInsets.symmetric(horizontal: 16), padding: const EdgeInsets.symmetric(horizontal: 16),
child: _buildAttachmentsTitle(context, controller.attachments, controller.expandModeAttachments.value)) child: _buildAttachmentsTitle(context, controller.attachments, controller.expandModeAttachments.value))
: SizedBox.shrink()), : const SizedBox.shrink()),
Obx(() => controller.attachments.isEmpty Obx(() => controller.attachments.isEmpty
? _buildAttachmentsLoadingView() ? _buildAttachmentsLoadingView()
: SizedBox.shrink()), : const SizedBox.shrink()),
Obx(() => controller.attachments.isNotEmpty Obx(() => controller.attachments.isNotEmpty
? Padding( ? Padding(
padding: EdgeInsets.only(bottom: 8, left: 16, right: 16), padding: const EdgeInsets.only(bottom: 8, left: 16, right: 16),
child: _buildAttachmentsList(context, controller.attachments, controller.expandModeAttachments.value)) child: _buildAttachmentsList(context, controller.attachments, controller.expandModeAttachments.value))
: SizedBox.shrink()), : const SizedBox.shrink()),
Padding( Padding(
padding: EdgeInsets.only(left: 16, right: 16, bottom: 20, top: 10), padding: const EdgeInsets.only(left: 16, right: 16, bottom: 20, top: 10),
child: _buildComposerEditor(context)), child: _buildComposerEditor(context)),
]) ])
) )
@@ -396,33 +398,33 @@ class ComposerView extends GetWidget<ComposerController> {
return Obx(() { return Obx(() {
if (controller.composerArguments.value?.emailActionType == EmailActionType.compose) { if (controller.composerArguments.value?.emailActionType == EmailActionType.compose) {
return HtmlEditor( return HtmlEditor(
key: Key('composer_editor'), key: const Key('composer_editor'),
minHeight: 550, minHeight: 550,
onCreated: (editorApi) => controller.htmlEditorApi = editorApi); onCreated: (editorApi) => controller.htmlEditorApi = editorApi);
} else { } else {
final message = controller.getContentEmail(context); final message = controller.getContentEmail(context);
return message != null && message.isNotEmpty return message != null && message.isNotEmpty
? HtmlEditor( ? HtmlEditor(
key: Key('composer_editor'), key: const Key('composer_editor'),
minHeight: 550, minHeight: 550,
onCreated: (editorApi) => controller.htmlEditorApi = editorApi, onCreated: (editorApi) => controller.htmlEditorApi = editorApi,
initialContent: message) initialContent: message)
: SizedBox.shrink(); : const SizedBox.shrink();
} }
}); });
} }
Widget _buildAttachmentsLoadingView({EdgeInsets? padding, double? size}) { Widget _buildAttachmentsLoadingView({EdgeInsets? padding, double? size}) {
return Obx(() => controller.viewState.value.fold( return Obx(() => controller.viewState.value.fold(
(failure) => SizedBox.shrink(), (failure) => const SizedBox.shrink(),
(success) => success is UploadingAttachmentState (success) => success is UploadingAttachmentState
? Center(child: Padding( ? Center(child: Padding(
padding: padding ?? EdgeInsets.all(10), padding: padding ?? const EdgeInsets.all(10),
child: SizedBox( child: SizedBox(
width: size ?? 20, width: size ?? 20,
height: size ?? 20, height: size ?? 20,
child: CupertinoActivityIndicator(color: AppColor.colorTextButton)))) child: const CupertinoActivityIndicator(color: AppColor.colorTextButton))))
: SizedBox.shrink())); : const SizedBox.shrink()));
} }
Widget _buildAttachmentsTitle(BuildContext context, List<Attachment> attachments, ExpandMode expandModeAttachment) { Widget _buildAttachmentsTitle(BuildContext context, List<Attachment> attachments, ExpandMode expandModeAttachment) {
@@ -430,9 +432,9 @@ class ComposerView extends GetWidget<ComposerController> {
children: [ children: [
Text( Text(
'${AppLocalizations.of(context).attachments} (${filesize(attachments.totalSize(), 0)}):', '${AppLocalizations.of(context).attachments} (${filesize(attachments.totalSize(), 0)}):',
style: TextStyle(fontSize: 12, color: AppColor.colorHintEmailAddressInput, fontWeight: FontWeight.normal)), style: const TextStyle(fontSize: 12, color: AppColor.colorHintEmailAddressInput, fontWeight: FontWeight.normal)),
_buildAttachmentsLoadingView(padding: EdgeInsets.only(left: 16), size: 16), _buildAttachmentsLoadingView(padding: const EdgeInsets.only(left: 16), size: 16),
Spacer(), const Spacer(),
Material( Material(
type: MaterialType.circle, type: MaterialType.circle,
color: Colors.transparent, color: Colors.transparent,
@@ -441,7 +443,7 @@ class ComposerView extends GetWidget<ComposerController> {
expandModeAttachment == ExpandMode.EXPAND expandModeAttachment == ExpandMode.EXPAND
? AppLocalizations.of(context).hide ? AppLocalizations.of(context).hide
: '${AppLocalizations.of(context).show_all} (${attachments.length})', : '${AppLocalizations.of(context).show_all} (${attachments.length})',
style: TextStyle(fontWeight: FontWeight.w500, fontSize: 12, color: AppColor.colorTextButton)), style: const TextStyle(fontWeight: FontWeight.w500, fontSize: 12, color: AppColor.colorTextButton)),
onPressed: () => controller.toggleDisplayAttachments() onPressed: () => controller.toggleDisplayAttachments()
) )
) )
@@ -453,7 +455,7 @@ class ComposerView extends GetWidget<ComposerController> {
if (expandMode == ExpandMode.EXPAND) { if (expandMode == ExpandMode.EXPAND) {
return LayoutBuilder(builder: (context, constraints) { return LayoutBuilder(builder: (context, constraints) {
return GridView.builder( return GridView.builder(
key: Key('list_attachment_full'), key: const Key('list_attachment_full'),
primary: false, primary: false,
shrinkWrap: true, shrinkWrap: true,
itemCount: attachments.length, itemCount: attachments.length,
@@ -475,14 +477,14 @@ class ComposerView extends GetWidget<ComposerController> {
child: SizedBox( child: SizedBox(
height: 60, height: 60,
child: ListView.builder( child: ListView.builder(
key: Key('list_attachment_minimize'), key: const Key('list_attachment_minimize'),
shrinkWrap: true, shrinkWrap: true,
physics: ClampingScrollPhysics(), physics: const ClampingScrollPhysics(),
scrollDirection: Axis.horizontal, scrollDirection: Axis.horizontal,
itemCount: attachments.length, itemCount: attachments.length,
itemBuilder: (context, index) => itemBuilder: (context, index) =>
(AttachmentFileComposerBuilder(context, imagePaths, attachments[index], (AttachmentFileComposerBuilder(context, imagePaths, attachments[index],
itemMargin: EdgeInsets.only(right: 8), itemMargin: const EdgeInsets.only(right: 8),
maxWidth: _getMaxWidthItemListAttachment(context, constraints), maxWidth: _getMaxWidthItemListAttachment(context, constraints),
maxHeight: 60) maxHeight: 60)
..addOnDeleteAttachmentAction((attachment) => controller.removeAttachmentAction(attachment))) ..addOnDeleteAttachmentAction((attachment) => controller.removeAttachmentAction(attachment)))
@@ -5,7 +5,7 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:html_editor_enhanced/html_editor.dart' as HtmlEditorBrowser; import 'package:html_editor_enhanced/html_editor.dart' as html_editor_browser;
import 'package:model/model.dart'; import 'package:model/model.dart';
import 'package:pointer_interceptor/pointer_interceptor.dart'; import 'package:pointer_interceptor/pointer_interceptor.dart';
import 'package:tmail_ui_user/features/composer/domain/state/upload_attachment_state.dart'; import 'package:tmail_ui_user/features/composer/domain/state/upload_attachment_state.dart';
@@ -22,6 +22,8 @@ class ComposerView extends GetWidget<ComposerController> {
final appToast = Get.find<AppToast>(); final appToast = Get.find<AppToast>();
final keyboardUtils = Get.find<KeyboardUtils>(); final keyboardUtils = Get.find<KeyboardUtils>();
ComposerView({Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ResponsiveWidget( return ResponsiveWidget(
@@ -34,13 +36,13 @@ class ComposerView extends GetWidget<ComposerController> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Obx(() => _buildAppBarForMobile(context, controller.isEnableEmailSendButton.value)), Obx(() => _buildAppBarForMobile(context, controller.isEnableEmailSendButton.value)),
Divider(color: AppColor.colorDividerComposer, height: 1), const Divider(color: AppColor.colorDividerComposer, height: 1),
_buildEmailAddress(context, constraints), _buildEmailAddress(context, constraints),
Divider(color: AppColor.colorDividerComposer, height: 1), const Divider(color: AppColor.colorDividerComposer, height: 1),
Padding(padding: EdgeInsets.symmetric(horizontal: 16), child: _buildSubjectEmail(context)), Padding(padding: const EdgeInsets.symmetric(horizontal: 16), child: _buildSubjectEmail(context)),
Divider(color: AppColor.colorDividerComposer, height: 1), const Divider(color: AppColor.colorDividerComposer, height: 1),
Padding(padding: EdgeInsets.symmetric(horizontal: 16), child: _buildListButton(context)), Padding(padding: const EdgeInsets.symmetric(horizontal: 16), child: _buildListButton(context)),
Divider(color: AppColor.colorDividerComposer, height: 1), const Divider(color: AppColor.colorDividerComposer, height: 1),
Expanded(child: _buildEditorAndAttachments(context)), Expanded(child: _buildEditorAndAttachments(context)),
] ]
))) )))
@@ -48,36 +50,36 @@ class ComposerView extends GetWidget<ComposerController> {
), ),
desktop: Obx(() { desktop: Obx(() {
return Stack(children: [ return Stack(children: [
if (controller.screenDisplayMode == ScreenDisplayMode.normal) if (controller.screenDisplayMode.value == ScreenDisplayMode.normal)
Positioned(right: 5, bottom: 5, child: Card( Positioned(right: 5, bottom: 5, child: Card(
elevation: 20, elevation: 20,
color: Colors.transparent, color: Colors.transparent,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(24))), shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(24))),
child: Container( child: Container(
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(24))), decoration: const BoxDecoration(color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(24))),
width: responsiveUtils.getSizeScreenWidth(context) * 0.5, width: responsiveUtils.getSizeScreenWidth(context) * 0.5,
height: responsiveUtils.getSizeScreenHeight(context) * 0.75, height: responsiveUtils.getSizeScreenHeight(context) * 0.75,
child: ClipRRect( child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(24)), borderRadius: const BorderRadius.all(Radius.circular(24)),
child: LayoutBuilder(builder: (context, constraints) => child: LayoutBuilder(builder: (context, constraints) =>
PointerInterceptor(child: _buildBodyForDesktop(context, constraints))) PointerInterceptor(child: _buildBodyForDesktop(context, constraints)))
) )
) )
)), )),
if (controller.screenDisplayMode == ScreenDisplayMode.minimize) if (controller.screenDisplayMode.value == ScreenDisplayMode.minimize)
Positioned(right: 5, bottom: 5, child: Card( Positioned(right: 5, bottom: 5, child: Card(
elevation: 20, elevation: 20,
color: Colors.transparent, color: Colors.transparent,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(16))), shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(16))),
child: Container( child: Container(
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(16))), decoration: const BoxDecoration(color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(16))),
width: 500, width: 500,
height: 50, height: 50,
child: ClipRRect( child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(16)), borderRadius: const BorderRadius.all(Radius.circular(16)),
child: PointerInterceptor(child: Row(children: [ child: PointerInterceptor(child: Row(children: [
Padding( Padding(
padding: EdgeInsets.only(left: 10), padding: const EdgeInsets.only(left: 10),
child: buildIconWeb( child: buildIconWeb(
icon: SvgPicture.asset(imagePaths.icCloseMailbox, fit: BoxFit.fill), icon: SvgPicture.asset(imagePaths.icCloseMailbox, fit: BoxFit.fill),
tooltip: AppLocalizations.of(context).close, tooltip: AppLocalizations.of(context).close,
@@ -95,25 +97,25 @@ class ComposerView extends GetWidget<ComposerController> {
tooltip: AppLocalizations.of(context).show, tooltip: AppLocalizations.of(context).show,
onTap: () => controller.displayScreenTypeComposerAction(ScreenDisplayMode.normal)), onTap: () => controller.displayScreenTypeComposerAction(ScreenDisplayMode.normal)),
Expanded(child: Padding( Expanded(child: Padding(
padding: EdgeInsets.only(left: 16, right: 80), padding: const EdgeInsets.only(left: 16, right: 80),
child: _buildTitleComposer(context), child: _buildTitleComposer(context),
)), )),
])) ]))
) )
) )
)), )),
if (controller.screenDisplayMode == ScreenDisplayMode.fullScreen) if (controller.screenDisplayMode.value == ScreenDisplayMode.fullScreen)
Scaffold( Scaffold(
backgroundColor: Colors.black38, backgroundColor: Colors.black38,
body: Align(alignment: Alignment.center, child: Card( body: Align(alignment: Alignment.center, child: Card(
color: Colors.transparent, color: Colors.transparent,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(24))), shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(24))),
child: Container( child: Container(
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(24))), decoration: const BoxDecoration(color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(24))),
width: responsiveUtils.getSizeScreenWidth(context) * 0.85, width: responsiveUtils.getSizeScreenWidth(context) * 0.85,
height: responsiveUtils.getSizeScreenHeight(context) * 0.9, height: responsiveUtils.getSizeScreenHeight(context) * 0.9,
child: ClipRRect( child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(24)), borderRadius: const BorderRadius.all(Radius.circular(24)),
child: LayoutBuilder(builder: (context, constraints) => child: LayoutBuilder(builder: (context, constraints) =>
PointerInterceptor(child: _buildBodyForDesktop(context, constraints))) PointerInterceptor(child: _buildBodyForDesktop(context, constraints)))
) )
@@ -129,10 +131,10 @@ class ComposerView extends GetWidget<ComposerController> {
color: Colors.transparent, color: Colors.transparent,
shadowColor: Colors.transparent, shadowColor: Colors.transparent,
child: Container( child: Container(
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(24))), decoration: const BoxDecoration(color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(24))),
margin: EdgeInsets.symmetric(horizontal: 16, vertical: 20), margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 20),
child: ClipRRect( child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(24)), borderRadius: const BorderRadius.all(Radius.circular(24)),
child: LayoutBuilder(builder: (context, constraints) => child: LayoutBuilder(builder: (context, constraints) =>
PointerInterceptor(child: _buildBodyForDesktop(context, constraints))) PointerInterceptor(child: _buildBodyForDesktop(context, constraints)))
) )
@@ -145,10 +147,10 @@ class ComposerView extends GetWidget<ComposerController> {
color: Colors.transparent, color: Colors.transparent,
shadowColor: Colors.transparent, shadowColor: Colors.transparent,
child: Container( child: Container(
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(24))), decoration: const BoxDecoration(color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(24))),
margin: EdgeInsets.symmetric(horizontal: 16, vertical: 20), margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 20),
child: ClipRRect( child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(24)), borderRadius: const BorderRadius.all(Radius.circular(24)),
child: LayoutBuilder(builder: (context, constraints) => child: LayoutBuilder(builder: (context, constraints) =>
PointerInterceptor(child: _buildBodyForDesktop(context, constraints))) PointerInterceptor(child: _buildBodyForDesktop(context, constraints)))
) )
@@ -171,12 +173,12 @@ class ComposerView extends GetWidget<ComposerController> {
if (responsiveUtils.isDesktop(context)) if (responsiveUtils.isDesktop(context))
Obx(() => buildIconWeb( Obx(() => buildIconWeb(
icon: SvgPicture.asset( icon: SvgPicture.asset(
controller.screenDisplayMode == ScreenDisplayMode.fullScreen controller.screenDisplayMode.value == ScreenDisplayMode.fullScreen
? imagePaths.icFullScreenExit ? imagePaths.icFullScreenExit
: imagePaths.icFullScreenComposer, : imagePaths.icFullScreenComposer,
fit: BoxFit.fill), fit: BoxFit.fill),
tooltip: AppLocalizations.of(context).fullscreen, tooltip: AppLocalizations.of(context).fullscreen,
onTap: () => controller.displayScreenTypeComposerAction(controller.screenDisplayMode == ScreenDisplayMode.fullScreen onTap: () => controller.displayScreenTypeComposerAction(controller.screenDisplayMode.value == ScreenDisplayMode.fullScreen
? ScreenDisplayMode.normal ? ScreenDisplayMode.normal
: ScreenDisplayMode.fullScreen))), : ScreenDisplayMode.fullScreen))),
if (responsiveUtils.isDesktop(context)) if (responsiveUtils.isDesktop(context))
@@ -185,14 +187,14 @@ class ComposerView extends GetWidget<ComposerController> {
tooltip: AppLocalizations.of(context).minimize, tooltip: AppLocalizations.of(context).minimize,
onTap: () => controller.displayScreenTypeComposerAction(ScreenDisplayMode.minimize)), onTap: () => controller.displayScreenTypeComposerAction(ScreenDisplayMode.minimize)),
Expanded(child: _buildTitleComposer(context)), Expanded(child: _buildTitleComposer(context)),
SizedBox(width: 100), const SizedBox(width: 100),
] ]
); );
} }
Widget _buildAppBarForMobile(BuildContext context, bool isEnableSendButton) { Widget _buildAppBarForMobile(BuildContext context, bool isEnableSendButton) {
return Container( return Container(
padding: EdgeInsets.only(left: 10, right: 10, top: 10, bottom: 10), padding: const EdgeInsets.only(left: 10, right: 10, top: 10, bottom: 10),
color: Colors.white, color: Colors.white,
child: Row( child: Row(
children: [ children: [
@@ -218,22 +220,22 @@ class ComposerView extends GetWidget<ComposerController> {
Widget _buildBottomBar(BuildContext context, bool isEnableSendButton) { Widget _buildBottomBar(BuildContext context, bool isEnableSendButton) {
return Container( return Container(
padding: EdgeInsets.symmetric(vertical: 16), padding: const EdgeInsets.symmetric(vertical: 16),
color: Colors.white, color: Colors.white,
child: Row(mainAxisAlignment: MainAxisAlignment.center, child: Row(mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
buildTextButton( buildTextButton(
AppLocalizations.of(context).cancel, AppLocalizations.of(context).cancel,
textStyle: TextStyle(fontWeight: FontWeight.w500, fontSize: 17, color: AppColor.lineItemListColor), textStyle: const TextStyle(fontWeight: FontWeight.w500, fontSize: 17, color: AppColor.lineItemListColor),
backgroundColor: AppColor.emailAddressChipColor, backgroundColor: AppColor.emailAddressChipColor,
width: 150, width: 150,
height: 44, height: 44,
radius: 10, radius: 10,
onTap: () => controller.closeComposerWeb()), onTap: () => controller.closeComposerWeb()),
SizedBox(width: 12), const SizedBox(width: 12),
buildTextButton( buildTextButton(
AppLocalizations.of(context).save_to_drafts, AppLocalizations.of(context).save_to_drafts,
textStyle: TextStyle(fontWeight: FontWeight.w500, fontSize: 17, color: AppColor.colorTextButton), textStyle: const TextStyle(fontWeight: FontWeight.w500, fontSize: 17, color: AppColor.colorTextButton),
backgroundColor: AppColor.emailAddressChipColor, backgroundColor: AppColor.emailAddressChipColor,
width: 150, width: 150,
height: 44, height: 44,
@@ -242,7 +244,7 @@ class ComposerView extends GetWidget<ComposerController> {
controller.saveEmailAsDrafts(context); controller.saveEmailAsDrafts(context);
controller.closeComposerWeb(); controller.closeComposerWeb();
}), }),
SizedBox(width: 12), const SizedBox(width: 12),
buildTextButton( buildTextButton(
AppLocalizations.of(context).send, AppLocalizations.of(context).send,
width: 150, width: 150,
@@ -256,34 +258,34 @@ class ComposerView extends GetWidget<ComposerController> {
Widget _buildBodyForDesktop(BuildContext context, BoxConstraints constraints) { Widget _buildBodyForDesktop(BuildContext context, BoxConstraints constraints) {
return Column(children: [ return Column(children: [
Padding(padding: EdgeInsets.only(left: 20, right: 20, top: 8), child: _buildAppBar(context)), Padding(padding: const EdgeInsets.only(left: 20, right: 20, top: 8), child: _buildAppBar(context)),
Padding(padding: EdgeInsets.only(top: 8), child: Divider(color: AppColor.colorDividerComposer, height: 1)), const Padding(padding: EdgeInsets.only(top: 8), child: Divider(color: AppColor.colorDividerComposer, height: 1)),
Padding( Padding(
padding: EdgeInsets.only(left: 16), padding: const EdgeInsets.only(left: 16),
child: Row(crossAxisAlignment: CrossAxisAlignment.start, children: [ child: Row(crossAxisAlignment: CrossAxisAlignment.start, children: [
Padding(padding: EdgeInsets.only(top: 20), Padding(padding: const EdgeInsets.only(top: 20),
child: (AvatarBuilder() child: (AvatarBuilder()
..text('${controller.mailboxDashBoardController.userProfile.value?.getAvatarText() ?? ''}') ..text(controller.mailboxDashBoardController.userProfile.value?.getAvatarText() ?? '')
..size(56) ..size(56)
..addTextStyle(TextStyle(fontWeight: FontWeight.w600, fontSize: 28, color: Colors.white)) ..addTextStyle(const TextStyle(fontWeight: FontWeight.w600, fontSize: 28, color: Colors.white))
..backgroundColor(AppColor.colorAvatar)) ..backgroundColor(AppColor.colorAvatar))
.build()), .build()),
Expanded(child: Padding( Expanded(child: Padding(
padding: EdgeInsets.only(left: 12), padding: const EdgeInsets.only(left: 12),
child: Column(children: [ child: Column(children: [
_buildEmailAddress(context, constraints), _buildEmailAddress(context, constraints),
Divider(color: AppColor.colorDividerComposer, height: 1), const Divider(color: AppColor.colorDividerComposer, height: 1),
Padding(padding: EdgeInsets.only(right: 16), child: _buildSubjectEmail(context)), Padding(padding: const EdgeInsets.only(right: 16), child: _buildSubjectEmail(context)),
Divider(color: AppColor.colorDividerComposer, height: 1), const Divider(color: AppColor.colorDividerComposer, height: 1),
_buildListButton(context), _buildListButton(context),
]), ]),
)) ))
])), ])),
Divider(color: AppColor.colorDividerComposer, height: 1), const Divider(color: AppColor.colorDividerComposer, height: 1),
Expanded(child: Padding( Expanded(child: Padding(
padding: EdgeInsets.only(left: responsiveUtils.isMobile(context) ? 16 : 60, right: responsiveUtils.isMobile(context) ? 16 : 25), padding: EdgeInsets.only(left: responsiveUtils.isMobile(context) ? 16 : 60, right: responsiveUtils.isMobile(context) ? 16 : 25),
child: _buildEditorAndAttachments(context))), child: _buildEditorAndAttachments(context))),
Divider(color: AppColor.colorDividerComposer, height: 1), const Divider(color: AppColor.colorDividerComposer, height: 1),
Obx(() => _buildBottomBar(context, controller.isEnableEmailSendButton.value)), Obx(() => _buildBottomBar(context, controller.isEnableEmailSendButton.value)),
]); ]);
} }
@@ -295,7 +297,7 @@ class ComposerView extends GetWidget<ComposerController> {
: AppLocalizations.of(context).new_message.capitalizeFirstEach, : AppLocalizations.of(context).new_message.capitalizeFirstEach,
maxLines: 1, maxLines: 1,
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold, color: Colors.black), style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold, color: Colors.black),
)); ));
} }
@@ -324,8 +326,8 @@ class ComposerView extends GetWidget<ComposerController> {
.build() .build()
)), )),
Obx(() => controller.listEmailAddressType.contains(PrefixEmailAddress.cc) == true Obx(() => controller.listEmailAddressType.contains(PrefixEmailAddress.cc) == true
? Divider(color: AppColor.colorDividerComposer, height: 1) ? const Divider(color: AppColor.colorDividerComposer, height: 1)
: SizedBox.shrink()), : const SizedBox.shrink()),
Obx(() => controller.listEmailAddressType.contains(PrefixEmailAddress.cc) == true Obx(() => controller.listEmailAddressType.contains(PrefixEmailAddress.cc) == true
? Padding( ? Padding(
padding: EdgeInsets.only(left: responsiveUtils.isMobile(context) ? 16 : 0), padding: EdgeInsets.only(left: responsiveUtils.isMobile(context) ? 16 : 0),
@@ -343,11 +345,11 @@ class ComposerView extends GetWidget<ComposerController> {
..addOnOpenSuggestionBoxEmailAddress(() => controller.getAutoCompleteSuggestion(isAll: true)) ..addOnOpenSuggestionBoxEmailAddress(() => controller.getAutoCompleteSuggestion(isAll: true))
..addOnSuggestionEmailAddress((word) => controller.getAutoCompleteSuggestion(word: word))) ..addOnSuggestionEmailAddress((word) => controller.getAutoCompleteSuggestion(word: word)))
.build()) .build())
: SizedBox.shrink() : const SizedBox.shrink()
), ),
Obx(() => controller.listEmailAddressType.contains(PrefixEmailAddress.bcc) == true Obx(() => controller.listEmailAddressType.contains(PrefixEmailAddress.bcc) == true
? Divider(color: AppColor.colorDividerComposer, height: 1) ? const Divider(color: AppColor.colorDividerComposer, height: 1)
: SizedBox.shrink()), : const SizedBox.shrink()),
Obx(() => controller.listEmailAddressType.contains(PrefixEmailAddress.bcc) == true Obx(() => controller.listEmailAddressType.contains(PrefixEmailAddress.bcc) == true
? Padding( ? Padding(
padding: EdgeInsets.only(left: responsiveUtils.isMobile(context) ? 16 : 0), padding: EdgeInsets.only(left: responsiveUtils.isMobile(context) ? 16 : 0),
@@ -365,7 +367,7 @@ class ComposerView extends GetWidget<ComposerController> {
..addOnOpenSuggestionBoxEmailAddress(() => controller.getAutoCompleteSuggestion(isAll: true)) ..addOnOpenSuggestionBoxEmailAddress(() => controller.getAutoCompleteSuggestion(isAll: true))
..addOnSuggestionEmailAddress((word) => controller.getAutoCompleteSuggestion(word: word))) ..addOnSuggestionEmailAddress((word) => controller.getAutoCompleteSuggestion(word: word)))
.build()) .build())
: SizedBox.shrink() : const SizedBox.shrink()
), ),
], ],
), ),
@@ -378,19 +380,19 @@ class ComposerView extends GetWidget<ComposerController> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Padding( Padding(
padding: EdgeInsets.only(right: 8, top: 16), padding: const EdgeInsets.only(right: 8, top: 16),
child: Text( child: Text(
'${AppLocalizations.of(context).subject_email}:', '${AppLocalizations.of(context).subject_email}:',
style: TextStyle(fontSize: 15, color: AppColor.colorHintEmailAddressInput))), style: const TextStyle(fontSize: 15, color: AppColor.colorHintEmailAddressInput))),
Expanded( Expanded(
child: FocusScope(child: Focus( child: FocusScope(child: Focus(
onFocusChange: (focus) => controller.onSubjectEmailFocusChange(focus), onFocusChange: (focus) => controller.onSubjectEmailFocusChange(focus),
child: (TextFieldBuilder() child: (TextFieldBuilder()
..key(Key('subject_email_input')) ..key(const Key('subject_email_input'))
..cursorColor(AppColor.colorTextButton) ..cursorColor(AppColor.colorTextButton)
..onChange((value) => controller.setSubjectEmail(value)) ..onChange((value) => controller.setSubjectEmail(value))
..textStyle(TextStyle(color: Colors.black, fontSize: 15, fontWeight: FontWeight.normal)) ..textStyle(const TextStyle(color: Colors.black, fontSize: 15, fontWeight: FontWeight.normal))
..textDecoration(InputDecoration(contentPadding: EdgeInsets.zero, border: InputBorder.none)) ..textDecoration(const InputDecoration(contentPadding: EdgeInsets.zero, border: InputBorder.none))
..addController(controller.subjectEmailInputController)) ..addController(controller.subjectEmailInputController))
.build(), .build(),
)) ))
@@ -403,7 +405,7 @@ class ComposerView extends GetWidget<ComposerController> {
return Transform( return Transform(
transform: Matrix4.translationValues(-10.0, 0.0, 0.0), transform: Matrix4.translationValues(-10.0, 0.0, 0.0),
child: Padding( child: Padding(
padding: EdgeInsets.symmetric(vertical: 5), padding: const EdgeInsets.symmetric(vertical: 5),
child: Row(children: [ child: Row(children: [
buildIconWeb( buildIconWeb(
icon: SvgPicture.asset(imagePaths.icAttachmentsComposer, color: AppColor.colorTextButton, fit: BoxFit.fill), icon: SvgPicture.asset(imagePaths.icAttachmentsComposer, color: AppColor.colorTextButton, fit: BoxFit.fill),
@@ -421,15 +423,15 @@ class ComposerView extends GetWidget<ComposerController> {
? Padding( ? Padding(
padding: EdgeInsets.only(top: 4, bottom: 4, left: responsiveUtils.isMobile(context) ? 16 : 20, right: responsiveUtils.isMobile(context) ? 16: 0), padding: EdgeInsets.only(top: 4, bottom: 4, left: responsiveUtils.isMobile(context) ? 16 : 20, right: responsiveUtils.isMobile(context) ? 16: 0),
child: _buildAttachmentsTitle(context, controller.attachments, controller.expandModeAttachments.value)) child: _buildAttachmentsTitle(context, controller.attachments, controller.expandModeAttachments.value))
: SizedBox.shrink()), : const SizedBox.shrink()),
Obx(() => controller.attachments.isEmpty Obx(() => controller.attachments.isEmpty
? _buildAttachmentsLoadingView() ? _buildAttachmentsLoadingView()
: SizedBox.shrink()), : const SizedBox.shrink()),
Obx(() => controller.attachments.isNotEmpty Obx(() => controller.attachments.isNotEmpty
? Padding( ? Padding(
padding: EdgeInsets.only(bottom: 8, left: responsiveUtils.isMobile(context) ? 16 : 10, right: responsiveUtils.isMobile(context) ? 16 : 10), padding: EdgeInsets.only(bottom: 8, left: responsiveUtils.isMobile(context) ? 16 : 10, right: responsiveUtils.isMobile(context) ? 16 : 10),
child: _buildAttachmentsList(context, controller.attachments, controller.expandModeAttachments.value)) child: _buildAttachmentsList(context, controller.attachments, controller.expandModeAttachments.value))
: SizedBox.shrink()), : const SizedBox.shrink()),
Obx(() { Obx(() {
if (controller.composerArguments.value != null) { if (controller.composerArguments.value != null) {
if (controller.composerArguments.value?.emailActionType == EmailActionType.compose) { if (controller.composerArguments.value?.emailActionType == EmailActionType.compose) {
@@ -444,7 +446,7 @@ class ComposerView extends GetWidget<ComposerController> {
padding: EdgeInsets.symmetric(horizontal: responsiveUtils.isMobile(context) ? 8 : 10), padding: EdgeInsets.symmetric(horizontal: responsiveUtils.isMobile(context) ? 8 : 10),
child: _buildEditor(context, initContent))); child: _buildEditor(context, initContent)));
} else { } else {
return Padding( return const Padding(
padding: EdgeInsets.all(16), padding: EdgeInsets.all(16),
child: SizedBox( child: SizedBox(
width: 30, width: 30,
@@ -458,7 +460,7 @@ class ComposerView extends GetWidget<ComposerController> {
child: _buildEditor(context, initContent))); child: _buildEditor(context, initContent)));
} }
} else { } else {
return SizedBox.shrink(); return const SizedBox.shrink();
} }
}), }),
] ]
@@ -468,19 +470,19 @@ class ComposerView extends GetWidget<ComposerController> {
Widget _buildEditor(BuildContext context, String initContent) { Widget _buildEditor(BuildContext context, String initContent) {
log('ComposerView::_buildEditor(): initContent: $initContent'); log('ComposerView::_buildEditor(): initContent: $initContent');
return HtmlEditorBrowser.HtmlEditor( return html_editor_browser.HtmlEditor(
key: Key('composer_editor_web'), key: const Key('composer_editor_web'),
controller: controller.htmlControllerBrowser, controller: controller.htmlControllerBrowser,
htmlEditorOptions: HtmlEditorBrowser.HtmlEditorOptions( htmlEditorOptions: html_editor_browser.HtmlEditorOptions(
hint: '${AppLocalizations.of(context).hint_compose_email}', hint: AppLocalizations.of(context).hint_compose_email,
darkMode: false, darkMode: false,
), ),
blockQuotedContent: initContent, blockQuotedContent: initContent,
htmlToolbarOptions: HtmlEditorBrowser.HtmlToolbarOptions( htmlToolbarOptions: const html_editor_browser.HtmlToolbarOptions(
toolbarPosition: HtmlEditorBrowser.ToolbarPosition.custom toolbarPosition: html_editor_browser.ToolbarPosition.custom
), ),
otherOptions: HtmlEditorBrowser.OtherOptions(height: 550), otherOptions: const html_editor_browser.OtherOptions(height: 550),
callbacks: HtmlEditorBrowser.Callbacks( callbacks: html_editor_browser.Callbacks(
onBeforeCommand: (String? currentHtml) { onBeforeCommand: (String? currentHtml) {
log('ComposerView::_buildComposerEditor(): onBeforeCommand : $currentHtml'); log('ComposerView::_buildComposerEditor(): onBeforeCommand : $currentHtml');
controller.setTextEditorWeb(currentHtml); controller.setTextEditorWeb(currentHtml);
@@ -506,15 +508,15 @@ class ComposerView extends GetWidget<ComposerController> {
Widget _buildAttachmentsLoadingView({EdgeInsets? padding, double? size}) { Widget _buildAttachmentsLoadingView({EdgeInsets? padding, double? size}) {
return Obx(() => controller.viewState.value.fold( return Obx(() => controller.viewState.value.fold(
(failure) => SizedBox.shrink(), (failure) => const SizedBox.shrink(),
(success) => success is UploadingAttachmentState (success) => success is UploadingAttachmentState
? Center(child: Padding( ? Center(child: Padding(
padding: padding ?? EdgeInsets.all(10), padding: padding ?? const EdgeInsets.all(10),
child: SizedBox( child: SizedBox(
width: size ?? 20, width: size ?? 20,
height: size ?? 20, height: size ?? 20,
child: CupertinoActivityIndicator(color: AppColor.colorTextButton)))) child: const CupertinoActivityIndicator(color: AppColor.colorTextButton))))
: SizedBox.shrink())); : const SizedBox.shrink()));
} }
Widget _buildAttachmentsTitle(BuildContext context, List<Attachment> attachments, ExpandMode expandModeAttachment) { Widget _buildAttachmentsTitle(BuildContext context, List<Attachment> attachments, ExpandMode expandModeAttachment) {
@@ -522,9 +524,9 @@ class ComposerView extends GetWidget<ComposerController> {
children: [ children: [
Text( Text(
'${AppLocalizations.of(context).attachments} (${filesize(attachments.totalSize(), 0)}):', '${AppLocalizations.of(context).attachments} (${filesize(attachments.totalSize(), 0)}):',
style: TextStyle(fontSize: 12, color: AppColor.colorHintEmailAddressInput, fontWeight: FontWeight.normal)), style: const TextStyle(fontSize: 12, color: AppColor.colorHintEmailAddressInput, fontWeight: FontWeight.normal)),
_buildAttachmentsLoadingView(padding: EdgeInsets.only(left: 16), size: 16), _buildAttachmentsLoadingView(padding: const EdgeInsets.only(left: 16), size: 16),
Spacer(), const Spacer(),
Material( Material(
type: MaterialType.circle, type: MaterialType.circle,
color: Colors.transparent, color: Colors.transparent,
@@ -533,7 +535,7 @@ class ComposerView extends GetWidget<ComposerController> {
expandModeAttachment == ExpandMode.EXPAND expandModeAttachment == ExpandMode.EXPAND
? AppLocalizations.of(context).hide ? AppLocalizations.of(context).hide
: '${AppLocalizations.of(context).show_all} (${attachments.length})', : '${AppLocalizations.of(context).show_all} (${attachments.length})',
style: TextStyle(fontWeight: FontWeight.w500, fontSize: 12, color: AppColor.colorTextButton)), style: const TextStyle(fontWeight: FontWeight.w500, fontSize: 12, color: AppColor.colorTextButton)),
onPressed: () => controller.toggleDisplayAttachments() onPressed: () => controller.toggleDisplayAttachments()
) )
) )
@@ -543,7 +545,7 @@ class ComposerView extends GetWidget<ComposerController> {
Widget _buildAttachmentsList(BuildContext context, List<Attachment> attachments, ExpandMode expandMode) { Widget _buildAttachmentsList(BuildContext context, List<Attachment> attachments, ExpandMode expandMode) {
if (expandMode == ExpandMode.COLLAPSE) { if (expandMode == ExpandMode.COLLAPSE) {
return SizedBox.shrink(); return const SizedBox.shrink();
} else { } else {
return LayoutBuilder(builder: (context, constraints) { return LayoutBuilder(builder: (context, constraints) {
return Align( return Align(
@@ -551,14 +553,14 @@ class ComposerView extends GetWidget<ComposerController> {
child: SizedBox( child: SizedBox(
height: 60, height: 60,
child: ListView.builder( child: ListView.builder(
key: Key('list_attachment_minimize'), key: const Key('list_attachment_minimize'),
shrinkWrap: true, shrinkWrap: true,
physics: ClampingScrollPhysics(), physics: const ClampingScrollPhysics(),
scrollDirection: Axis.horizontal, scrollDirection: Axis.horizontal,
itemCount: attachments.length, itemCount: attachments.length,
itemBuilder: (context, index) => itemBuilder: (context, index) =>
(AttachmentFileComposerBuilder(context, imagePaths, attachments[index], (AttachmentFileComposerBuilder(context, imagePaths, attachments[index],
itemMargin: EdgeInsets.only(right: 8), itemMargin: const EdgeInsets.only(right: 8),
maxWidth: _getMaxWidthItemListAttachment(context, constraints), maxWidth: _getMaxWidthItemListAttachment(context, constraints),
maxHeight: 60) maxHeight: 60)
..addOnDeleteAttachmentAction((attachment) => controller.removeAttachmentAction(attachment))) ..addOnDeleteAttachmentAction((attachment) => controller.removeAttachmentAction(attachment)))
@@ -54,7 +54,7 @@ class AttachmentFileComposerBuilder {
color: Colors.white), color: Colors.white),
child: Stack(children: [ child: Stack(children: [
ListTile( ListTile(
contentPadding: EdgeInsets.only(right: kIsWeb ? 16 : 18), contentPadding: const EdgeInsets.only(right: kIsWeb ? 16 : 18),
onTap: () {}, onTap: () {},
leading: Transform( leading: Transform(
transform: Matrix4.translationValues(8.0, kIsWeb ? -3.0 : -5.0, 0.0), transform: Matrix4.translationValues(8.0, kIsWeb ? -3.0 : -5.0, 0.0),
@@ -65,7 +65,7 @@ class AttachmentFileComposerBuilder {
attachment.name ?? '', attachment.name ?? '',
maxLines: 2, maxLines: 2,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: TextStyle(fontSize: 12, color: AppColor.colorNameEmail, fontWeight: FontWeight.w500), style: const TextStyle(fontSize: 12, color: AppColor.colorNameEmail, fontWeight: FontWeight.w500),
)), )),
subtitle: attachment.size != null && attachment.size?.value != 0 subtitle: attachment.size != null && attachment.size?.value != 0
? Transform( ? Transform(
@@ -74,7 +74,7 @@ class AttachmentFileComposerBuilder {
filesize(attachment.size?.value, 0), filesize(attachment.size?.value, 0),
maxLines: 1, maxLines: 1,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: TextStyle(fontSize: 10, color: AppColor.colorContentEmail, fontWeight: FontWeight.normal))) style: const TextStyle(fontSize: 10, color: AppColor.colorContentEmail, fontWeight: FontWeight.normal)))
: null, : null,
), ),
Positioned(right: kIsWeb ? -5 : -12, top: kIsWeb ? -5 : -12, child: buildIconWeb( Positioned(right: kIsWeb ? -5 : -12, top: kIsWeb ? -5 : -12, child: buildIconWeb(
@@ -30,7 +30,7 @@ class EmailAddressInputBuilder {
final TextEditingController? controller; final TextEditingController? controller;
final bool? isInitial; final bool? isInitial;
List<EmailAddress> _listEmailAddress = <EmailAddress>[]; List<EmailAddress> listEmailAddress = <EmailAddress>[];
OnUpdateListEmailAddressAction? _onUpdateListEmailAddressAction; OnUpdateListEmailAddressAction? _onUpdateListEmailAddressAction;
OnSuggestionEmailAddress? _onSuggestionEmailAddress; OnSuggestionEmailAddress? _onSuggestionEmailAddress;
@@ -72,7 +72,7 @@ class EmailAddressInputBuilder {
this._context, this._context,
this._imagePaths, this._imagePaths,
this._prefixEmailAddress, this._prefixEmailAddress,
this._listEmailAddress, this.listEmailAddress,
this._listEmailAddressType, this._listEmailAddressType,
{ {
this.isInitial, this.isInitial,
@@ -85,7 +85,7 @@ class EmailAddressInputBuilder {
return Row( return Row(
children: [ children: [
Text('${_prefixEmailAddress.asName(_context)}:', Text('${_prefixEmailAddress.asName(_context)}:',
style: TextStyle(fontSize: 15, color: AppColor.colorHintEmailAddressInput)), style: const TextStyle(fontSize: 15, color: AppColor.colorHintEmailAddressInput)),
Expanded(child: Padding( Expanded(child: Padding(
padding: EdgeInsets.only(right: _listEmailAddressType.length == 2 ? 8 : 8), padding: EdgeInsets.only(right: _listEmailAddressType.length == 2 ? 8 : 8),
child: _buildTagEditor())), child: _buildTagEditor())),
@@ -93,8 +93,8 @@ class EmailAddressInputBuilder {
Row(children: [ Row(children: [
if (!_listEmailAddressType.contains(PrefixEmailAddress.cc)) if (!_listEmailAddressType.contains(PrefixEmailAddress.cc))
buildTextIcon(AppLocalizations.of(_context).cc_email_address_prefix, buildTextIcon(AppLocalizations.of(_context).cc_email_address_prefix,
padding: EdgeInsets.all(5), padding: const EdgeInsets.all(5),
textStyle: TextStyle( textStyle: const TextStyle(
fontSize: 15, fontSize: 15,
fontWeight: FontWeight.normal, fontWeight: FontWeight.normal,
decoration: TextDecoration.underline, decoration: TextDecoration.underline,
@@ -102,14 +102,14 @@ class EmailAddressInputBuilder {
onTap: () => _onAddEmailAddressTypeAction?.call(PrefixEmailAddress.cc)), onTap: () => _onAddEmailAddressTypeAction?.call(PrefixEmailAddress.cc)),
if (!_listEmailAddressType.contains(PrefixEmailAddress.bcc)) if (!_listEmailAddressType.contains(PrefixEmailAddress.bcc))
buildTextIcon(AppLocalizations.of(_context).bcc_email_address_prefix, buildTextIcon(AppLocalizations.of(_context).bcc_email_address_prefix,
padding: EdgeInsets.all(5), padding: const EdgeInsets.all(5),
textStyle: TextStyle( textStyle: const TextStyle(
fontSize: 15, fontSize: 15,
fontWeight: FontWeight.normal, fontWeight: FontWeight.normal,
decoration: TextDecoration.underline, decoration: TextDecoration.underline,
color: AppColor.lineItemListColor), color: AppColor.lineItemListColor),
onTap: () => _onAddEmailAddressTypeAction?.call(PrefixEmailAddress.bcc)), onTap: () => _onAddEmailAddressTypeAction?.call(PrefixEmailAddress.bcc)),
SizedBox(width: 10), const SizedBox(width: 10),
]), ]),
if (_prefixEmailAddress != PrefixEmailAddress.to) if (_prefixEmailAddress != PrefixEmailAddress.to)
buildIconWeb( buildIconWeb(
@@ -121,7 +121,7 @@ class EmailAddressInputBuilder {
Widget _buildTagEditor() { Widget _buildTagEditor() {
return StatefulBuilder(builder: (BuildContext context, StateSetter setState) { return StatefulBuilder(builder: (BuildContext context, StateSetter setState) {
final newListEmailAddress = _isCollapse ? _listEmailAddress.sublist(0, 1) : _listEmailAddress; final newListEmailAddress = _isCollapse ? listEmailAddress.sublist(0, 1) : listEmailAddress;
return FocusScope(child: Focus( return FocusScope(child: Focus(
onFocusChange: (focus) => _onFocusEmailAddressChangeAction?.call(_prefixEmailAddress, focus), onFocusChange: (focus) => _onFocusEmailAddressChangeAction?.call(_prefixEmailAddress, focus),
child: TagEditor<EmailAddress>( child: TagEditor<EmailAddress>(
@@ -131,7 +131,7 @@ class EmailAddressInputBuilder {
textInputAction: TextInputAction.done, textInputAction: TextInputAction.done,
hasAddButton: false, hasAddButton: false,
tagSpacing: 8, tagSpacing: 8,
delimiters: [' '], delimiters: const [' '],
autofocus: _prefixEmailAddress != PrefixEmailAddress.to, autofocus: _prefixEmailAddress != PrefixEmailAddress.to,
minTextFieldWidth: 20, minTextFieldWidth: 20,
resetTextOnSubmitted: true, resetTextOnSubmitted: true,
@@ -139,48 +139,48 @@ class EmailAddressInputBuilder {
suggestionsBoxBackgroundColor: Colors.white, suggestionsBoxBackgroundColor: Colors.white,
suggestionsBoxRadius: 20, suggestionsBoxRadius: 20,
iconSuggestionBox: SvgPicture.asset(_imagePaths.icAddEmailAddress, fit: BoxFit.fill), iconSuggestionBox: SvgPicture.asset(_imagePaths.icAddEmailAddress, fit: BoxFit.fill),
textStyle: TextStyle(color: AppColor.colorEmailAddress, fontSize: 14, fontWeight: FontWeight.w500), textStyle: const TextStyle(color: AppColor.colorEmailAddress, fontSize: 14, fontWeight: FontWeight.w500),
onSubmitted: (value) { onSubmitted: (value) {
setState(() => _listEmailAddress.add(EmailAddress(null, value))); setState(() => listEmailAddress.add(EmailAddress(null, value)));
_onUpdateListEmailAddressAction?.call(_prefixEmailAddress, _listEmailAddress); _onUpdateListEmailAddressAction?.call(_prefixEmailAddress, listEmailAddress);
}, },
inputDecoration: InputDecoration(border: InputBorder.none), inputDecoration: const InputDecoration(border: InputBorder.none),
tagBuilder: (context, index) => Stack(alignment: Alignment.centerRight, children: [ tagBuilder: (context, index) => Stack(alignment: Alignment.centerRight, children: [
Padding( Padding(
padding: EdgeInsets.only(top: kIsWeb ? 8 : 0, right: _isCollapse ? 50 : 0), padding: EdgeInsets.only(top: kIsWeb ? 8 : 0, right: _isCollapse ? 50 : 0),
child: InkWell( child: InkWell(
onTap: () => _isCollapse ? _onShowFullListEmailAddressAction?.call(_prefixEmailAddress) : null, onTap: () => _isCollapse ? _onShowFullListEmailAddressAction?.call(_prefixEmailAddress) : null,
child: Chip( child: Chip(
labelPadding: EdgeInsets.only(left: 12, right: 12, bottom: 2), labelPadding: const EdgeInsets.only(left: 12, right: 12, bottom: 2),
label: Text(newListEmailAddress[index].asString(), maxLines: 1, overflow: kIsWeb ? null : TextOverflow.ellipsis), label: Text(newListEmailAddress[index].asString(), maxLines: 1, overflow: kIsWeb ? null : TextOverflow.ellipsis),
deleteIcon: SvgPicture.asset(_imagePaths.icClose, fit: BoxFit.fill), deleteIcon: SvgPicture.asset(_imagePaths.icClose, fit: BoxFit.fill),
labelStyle: TextStyle(color: Colors.black, fontSize: 17, fontWeight: FontWeight.normal), labelStyle: const TextStyle(color: Colors.black, fontSize: 17, fontWeight: FontWeight.normal),
backgroundColor: _isEmailAddressValid(_listEmailAddress[index].emailAddress) ? AppColor.colorEmailAddressTag : Colors.white, backgroundColor: _isEmailAddressValid(listEmailAddress[index].emailAddress) ? AppColor.colorEmailAddressTag : Colors.white,
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
side: BorderSide( side: BorderSide(
width: _isEmailAddressValid(_listEmailAddress[index].emailAddress) ? 0 : 1, width: _isEmailAddressValid(listEmailAddress[index].emailAddress) ? 0 : 1,
color: _isEmailAddressValid(_listEmailAddress[index].emailAddress) ? AppColor.colorEmailAddressTag : AppColor.colorBorderEmailAddressInvalid), color: _isEmailAddressValid(listEmailAddress[index].emailAddress) ? AppColor.colorEmailAddressTag : AppColor.colorBorderEmailAddressInvalid),
), ),
avatar: newListEmailAddress[index].displayName.isNotEmpty avatar: newListEmailAddress[index].displayName.isNotEmpty
? CircleAvatar( ? CircleAvatar(
backgroundColor: AppColor.colorTextButton, backgroundColor: AppColor.colorTextButton,
child: Text( child: Text(
_listEmailAddress[index].displayName[0].toUpperCase(), listEmailAddress[index].displayName[0].toUpperCase(),
style: TextStyle(color: Colors.white, fontSize: 12, fontWeight: FontWeight.w500))) style: const TextStyle(color: Colors.white, fontSize: 12, fontWeight: FontWeight.w500)))
: null, : null,
onDeleted: () { onDeleted: () {
setState(() => _listEmailAddress.removeAt(index)); setState(() => listEmailAddress.removeAt(index));
_onUpdateListEmailAddressAction?.call(_prefixEmailAddress, _listEmailAddress); _onUpdateListEmailAddressAction?.call(_prefixEmailAddress, listEmailAddress);
}, },
) )
) )
), ),
if (_isCollapse) _buildCounter(context, _listEmailAddress.length - newListEmailAddress.length), if (_isCollapse) _buildCounter(context, listEmailAddress.length - newListEmailAddress.length),
]), ]),
onTagChanged: (String value) { onTagChanged: (String value) {
setState(() => _listEmailAddress.add(EmailAddress(null, value))); setState(() => listEmailAddress.add(EmailAddress(null, value)));
_onUpdateListEmailAddressAction?.call(_prefixEmailAddress, _listEmailAddress); _onUpdateListEmailAddressAction?.call(_prefixEmailAddress, listEmailAddress);
}, },
findSuggestions: (String query) { findSuggestions: (String query) {
if (query.trim().isNotEmpty && _onSuggestionEmailAddress != null) { if (query.trim().isNotEmpty && _onSuggestionEmailAddress != null) {
@@ -204,17 +204,17 @@ class EmailAddressInputBuilder {
Widget _buildCounter(BuildContext context, int count) { Widget _buildCounter(BuildContext context, int count) {
return Padding( return Padding(
padding: EdgeInsets.only(left: 8, top: kIsWeb ? 8 : 0), padding: const EdgeInsets.only(left: 8, top: kIsWeb ? 8 : 0),
child: InkWell( child: InkWell(
onTap: () => _onShowFullListEmailAddressAction?.call(_prefixEmailAddress), onTap: () => _onShowFullListEmailAddressAction?.call(_prefixEmailAddress),
child: Chip( child: Chip(
labelPadding: EdgeInsets.symmetric(horizontal: 8), labelPadding: const EdgeInsets.symmetric(horizontal: 8),
label: Text('+$count', maxLines: 1, overflow: kIsWeb ? null : TextOverflow.ellipsis), label: Text('+$count', maxLines: 1, overflow: kIsWeb ? null : TextOverflow.ellipsis),
labelStyle: TextStyle(color: Colors.black, fontSize: 17, fontWeight: FontWeight.normal), labelStyle: const TextStyle(color: Colors.black, fontSize: 17, fontWeight: FontWeight.normal),
backgroundColor: AppColor.colorEmailAddressTag, backgroundColor: AppColor.colorEmailAddressTag,
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
side: BorderSide(width: 0, color: AppColor.colorEmailAddressTag), side: const BorderSide(width: 0, color: AppColor.colorEmailAddressTag),
), ),
), ),
), ),
@@ -222,7 +222,7 @@ class EmailAddressInputBuilder {
} }
bool get _isCollapse { bool get _isCollapse {
return _listEmailAddress.length > 1 && expandMode == ExpandMode.COLLAPSE; return listEmailAddress.length > 1 && expandMode == ExpandMode.COLLAPSE;
} }
Widget _buildSuggestionItem(StateSetter setState, BuildContext context, TagsEditorState<EmailAddress> tagEditorState, EmailAddress emailAddress) { Widget _buildSuggestionItem(StateSetter setState, BuildContext context, TagsEditorState<EmailAddress> tagEditorState, EmailAddress emailAddress) {
@@ -237,22 +237,22 @@ class EmailAddressInputBuilder {
border: Border.all(color: AppColor.colorShadowBgContentEmail, width: 1.0)), border: Border.all(color: AppColor.colorShadowBgContentEmail, width: 1.0)),
child: Text( child: Text(
emailAddress.asString().isNotEmpty ? emailAddress.asString()[0].toUpperCase() : '', emailAddress.asString().isNotEmpty ? emailAddress.asString()[0].toUpperCase() : '',
style: TextStyle(color: Colors.black, fontSize: 16, fontWeight: FontWeight.w600))), style: const TextStyle(color: Colors.black, fontSize: 16, fontWeight: FontWeight.w600))),
title: Text( title: Text(
emailAddress.asString(), emailAddress.asString(),
maxLines: 1, maxLines: 1,
overflow: kIsWeb ? null : TextOverflow.ellipsis, overflow: kIsWeb ? null : TextOverflow.ellipsis,
style: TextStyle(color: Colors.black, fontSize: 16, fontWeight: FontWeight.normal)), style: const TextStyle(color: Colors.black, fontSize: 16, fontWeight: FontWeight.normal)),
subtitle: emailAddress.displayName.isNotEmpty && emailAddress.emailAddress.isNotEmpty subtitle: emailAddress.displayName.isNotEmpty && emailAddress.emailAddress.isNotEmpty
? Text( ? Text(
emailAddress.emailAddress, emailAddress.emailAddress,
maxLines: 1, maxLines: 1,
overflow: kIsWeb ? null : TextOverflow.ellipsis, overflow: kIsWeb ? null : TextOverflow.ellipsis,
style: TextStyle(color: AppColor.colorHintSearchBar, fontSize: 13, fontWeight: FontWeight.normal)) style: const TextStyle(color: AppColor.colorHintSearchBar, fontSize: 13, fontWeight: FontWeight.normal))
: null, : null,
onTap: () { onTap: () {
setState(() => _listEmailAddress.add(emailAddress)); setState(() => listEmailAddress.add(emailAddress));
_onUpdateListEmailAddressAction?.call(_prefixEmailAddress, _listEmailAddress); _onUpdateListEmailAddressAction?.call(_prefixEmailAddress, listEmailAddress);
tagEditorState.selectSuggestion(emailAddress); tagEditorState.selectSuggestion(emailAddress);
}, },
); );
@@ -37,11 +37,11 @@ class TopBarComposerWidgetBuilder {
Widget build() { Widget build() {
return Container( return Container(
key: Key('top_bar_composer_widget'), key: const Key('top_bar_composer_widget'),
alignment: Alignment.center, alignment: Alignment.center,
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
child: MediaQuery( child: MediaQuery(
data: MediaQueryData(padding: EdgeInsets.zero), data: const MediaQueryData(padding: EdgeInsets.zero),
child: Row( child: Row(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end,
@@ -83,7 +83,7 @@ class TopBarComposerWidgetBuilder {
} }
}, },
child: Padding( child: Padding(
padding: EdgeInsets.only(right: kIsWeb ? 16 : 0), padding: const EdgeInsets.only(right: kIsWeb ? 16 : 0),
child: SvgPicture.asset(_imagePaths.icShare, fit: BoxFit.fill), child: SvgPicture.asset(_imagePaths.icShare, fit: BoxFit.fill),
), ),
onTapDown: (detail) { onTapDown: (detail) {
@@ -102,7 +102,7 @@ class TopBarComposerWidgetBuilder {
), ),
), ),
IconButton( IconButton(
key: Key('button_send_email'), key: const Key('button_send_email'),
color: _isEnableEmailSendButton ? AppColor.enableSendEmailButtonColor : AppColor.disableSendEmailButtonColor, color: _isEnableEmailSendButton ? AppColor.enableSendEmailButtonColor : AppColor.disableSendEmailButtonColor,
icon: SvgPicture.asset( icon: SvgPicture.asset(
_imagePaths.icComposerSend, _imagePaths.icComposerSend,
@@ -114,7 +114,7 @@ class TopBarComposerWidgetBuilder {
} }
} }
), ),
SizedBox(width: 8) const SizedBox(width: 8)
] ]
); );
} }