From 8587b9e8bdfa790d68e1bb326580b1305d60c27f Mon Sep 17 00:00:00 2001 From: sherlockvn Date: Mon, 16 Jan 2023 17:05:20 +0700 Subject: [PATCH] TF-1194 create new default identity: add presentation layer --- .../presentation/composer_view_web.dart | 205 +---- .../widgets/toolbar_rich_text_builder.dart | 218 ++++++ .../presentation/identity_creator_view.dart | 734 +++++++++--------- .../presentation/model/signature_type.dart | 2 +- .../widgets/identity_input_field_builder.dart | 15 +- ...set_default_identity_checkbox_builder.dart | 59 ++ lib/l10n/intl_messages.arb | 35 +- lib/main/localizations/app_localizations.dart | 37 +- lib/main/pages/app_pages.dart | 9 - 9 files changed, 728 insertions(+), 586 deletions(-) create mode 100644 lib/features/composer/presentation/widgets/toolbar_rich_text_builder.dart create mode 100644 lib/features/identity_creator/presentation/widgets/set_default_identity_checkbox_builder.dart diff --git a/lib/features/composer/presentation/composer_view_web.dart b/lib/features/composer/presentation/composer_view_web.dart index 40b25fa70..46c02fdfa 100644 --- a/lib/features/composer/presentation/composer_view_web.dart +++ b/lib/features/composer/presentation/composer_view_web.dart @@ -10,21 +10,13 @@ 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/base/mixin/app_loader_mixin.dart'; -import 'package:tmail_ui_user/features/base/widget/popup_menu_overlay_widget.dart'; -import 'package:tmail_ui_user/features/base/widget/drop_down_button_widget.dart'; import 'package:tmail_ui_user/features/composer/presentation/composer_controller.dart'; import 'package:tmail_ui_user/features/composer/presentation/mixin/composer_loading_mixin.dart'; import 'package:tmail_ui_user/features/composer/presentation/mixin/rich_text_button_mixin.dart'; -import 'package:tmail_ui_user/features/composer/presentation/model/dropdown_menu_font_status.dart'; -import 'package:tmail_ui_user/features/composer/presentation/model/font_name_type.dart'; -import 'package:tmail_ui_user/features/composer/presentation/model/header_style_type.dart'; -import 'package:tmail_ui_user/features/composer/presentation/model/order_list_type.dart'; -import 'package:tmail_ui_user/features/composer/presentation/model/paragraph_type.dart'; -import 'package:tmail_ui_user/features/composer/presentation/model/rich_text_style_type.dart'; import 'package:tmail_ui_user/features/composer/presentation/model/screen_display_mode.dart'; import 'package:tmail_ui_user/features/composer/presentation/widgets/attachment_file_composer_builder.dart'; -import 'package:tmail_ui_user/features/composer/presentation/widgets/drop_down_menu_header_style_widget.dart'; import 'package:tmail_ui_user/features/composer/presentation/widgets/email_address_input_builder.dart'; +import 'package:tmail_ui_user/features/composer/presentation/widgets/toolbar_rich_text_builder.dart'; import 'package:tmail_ui_user/features/upload/presentation/extensions/list_upload_file_state_extension.dart'; import 'package:tmail_ui_user/features/upload/presentation/model/upload_file_state.dart'; import 'package:tmail_ui_user/features/email/domain/state/get_email_content_state.dart'; @@ -72,7 +64,7 @@ class ComposerView extends GetWidget Expanded(child: Column( children: [ _buildAttachmentsWidget(context), - _buildToolbarRichTextWidget(context), + ToolbarRichTextWebBuilder(richTextWebController: controller.richTextWebController), buildInlineLoadingView(controller), _buildEditorForm(context) ] @@ -368,7 +360,7 @@ class ComposerView extends GetWidget child: Column( children: [ _buildAttachmentsWidget(context), - _buildToolbarRichTextWidget(context), + ToolbarRichTextWebBuilder(richTextWebController: controller.richTextWebController), buildInlineLoadingView(controller), _buildEditorForm(context) ] @@ -739,7 +731,7 @@ class ComposerView extends GetWidget Widget _buildAttachmentsWidget(BuildContext context) { return Obx(() { final attachments = controller.uploadController.listUploadAttachments; - if (attachments.isNotEmpty) { + if (attachments.isNotEmpty) { return Column(children: [ Padding( padding: EdgeInsets.only( @@ -846,193 +838,4 @@ class ComposerView extends GetWidget return constraints.maxHeight > 0 ? constraints.maxHeight * 0.4 : 150.0; } } - - Widget _buildToolbarRichTextWidget(BuildContext context) { - return Obx(() { - final richTextController = controller.richTextWebController; - final codeViewEnabled = richTextController.codeViewEnabled; - final opacity = codeViewEnabled ? 0.5 : 1.0; - - return Container( - padding: const EdgeInsets.only(left: 20, top: 8, bottom: 8), - alignment: Alignment.centerLeft, - child: Wrap( - crossAxisAlignment: WrapCrossAlignment.center, - runSpacing: 8, - children: [ - AbsorbPointer( - absorbing: codeViewEnabled, - child: DropDownMenuHeaderStyleWidget( - icon: buildWrapIconStyleText( - isSelected: richTextController.isMenuHeaderStyleOpen, - icon: SvgPicture.asset(RichTextStyleType.headerStyle.getIcon(imagePaths), - color: AppColor.colorDefaultRichTextButton.withOpacity(opacity), - fit: BoxFit.fill), - padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 5), - tooltip: RichTextStyleType.headerStyle.getTooltipButton(context) - ), - items: HeaderStyleType.values, - onMenuStateChange: (isOpen) { - log('ComposerView::_buildToolbarRichTextWidget(): MenuHeaderStyleStatus: $isOpen'); - final newStatus = isOpen - ? DropdownMenuFontStatus.open - : DropdownMenuFontStatus.closed; - richTextController.menuHeaderStyleStatus.value = newStatus; - }, - onChanged: (newStyle) => richTextController.applyHeaderStyle(newStyle)), - ), - AbsorbPointer( - absorbing: codeViewEnabled, - child: Container( - width: 130, - padding: const EdgeInsets.only(left: 4.0, right: 4.0), - child: DropDownButtonWidget( - items: FontNameType.values, - itemSelected: richTextController.selectedFontName.value, - onChanged: (newFont) => richTextController.applyNewFontStyle(newFont), - onMenuStateChange: (isOpen) { - log('ComposerView::_buildToolbarRichTextWidget(): MenuFontStatus: $isOpen'); - final newStatus = isOpen - ? DropdownMenuFontStatus.open - : DropdownMenuFontStatus.closed; - richTextController.menuFontStatus.value = newStatus; - }, - heightItem: 40, - sizeIconChecked: 16, - radiusButton: 8, - opacity: opacity, - dropdownWidth: 200, - colorButton: richTextController.isMenuFontOpen - ? AppColor.colorBackgroundWrapIconStyleCode - : Colors.white, - iconArrowDown: SvgPicture.asset(imagePaths.icStyleArrowDown), - tooltip: RichTextStyleType.fontName.getTooltipButton(context), - supportSelectionIcon: true)), - ), - Padding( - padding: const EdgeInsets.only(right: 4.0), - child: AbsorbPointer( - absorbing: codeViewEnabled, - child: buildWrapIconStyleText( - icon: buildIconWithTooltip( - path: RichTextStyleType.textColor.getIcon(imagePaths), - color: richTextController.selectedTextColor.value, - tooltip: RichTextStyleType.textColor.getTooltipButton(context), - opacity: opacity), - onTap: () => richTextController.applyRichTextStyle(context, RichTextStyleType.textColor)), - ), - ), - Padding( - padding: const EdgeInsets.only(right: 4.0), - child: AbsorbPointer( - absorbing: codeViewEnabled, - child: buildWrapIconStyleText( - padding: const EdgeInsets.symmetric(vertical: 9, horizontal: 7), - spacing: 3, - icon: buildIconColorBackgroundText( - iconData: RichTextStyleType.textBackgroundColor.getIconData(), - colorSelected: richTextController.selectedTextBackgroundColor.value, - tooltip: RichTextStyleType.textBackgroundColor.getTooltipButton(context), - opacity: opacity), - onTap: () => richTextController.applyRichTextStyle(context, RichTextStyleType.textBackgroundColor)), - ), - ), - Padding( - padding: const EdgeInsets.only(right: 4.0), - child: buildWrapIconStyleText( - hasDropdown: false, - padding: const EdgeInsets.symmetric(vertical: 3, horizontal: 5), - icon: Wrap(children: [ - AbsorbPointer( - absorbing: codeViewEnabled, - child: buildIconStyleText( - path: RichTextStyleType.bold.getIcon(imagePaths), - isSelected: richTextController.isTextStyleTypeSelected(RichTextStyleType.bold), - tooltip: RichTextStyleType.bold.getTooltipButton(context), - opacity: opacity, - onTap: () => richTextController.applyRichTextStyle(context, RichTextStyleType.bold)), - ), - AbsorbPointer( - absorbing: codeViewEnabled, - child: buildIconStyleText( - path: RichTextStyleType.italic.getIcon(imagePaths), - isSelected: richTextController.isTextStyleTypeSelected(RichTextStyleType.italic), - tooltip: RichTextStyleType.italic.getTooltipButton(context), - opacity: opacity, - onTap: () => richTextController.applyRichTextStyle(context, RichTextStyleType.italic)), - ), - AbsorbPointer( - absorbing: codeViewEnabled, - child: buildIconStyleText( - path: RichTextStyleType.underline.getIcon(imagePaths), - isSelected: richTextController.isTextStyleTypeSelected(RichTextStyleType.underline), - tooltip: RichTextStyleType.underline.getTooltipButton(context), - opacity: opacity, - onTap: () => richTextController.applyRichTextStyle(context, RichTextStyleType.underline)), - ), - AbsorbPointer( - absorbing: codeViewEnabled, - child: buildIconStyleText( - path: RichTextStyleType.strikeThrough.getIcon(imagePaths), - isSelected: richTextController.isTextStyleTypeSelected( - RichTextStyleType.strikeThrough), - tooltip: RichTextStyleType.strikeThrough.getTooltipButton(context), - opacity: opacity, - onTap: () => richTextController.applyRichTextStyle(context, RichTextStyleType.strikeThrough)), - ) - ])), - ), - Padding( - padding: const EdgeInsets.only(right: 4.0), - child: AbsorbPointer( - absorbing: codeViewEnabled, - child: PopupMenuOverlayWidget( - controller: richTextController.menuParagraphController, - listButtonAction: ParagraphType.values - .map((paragraph) => paragraph.buildButtonWidget( - context, - imagePaths, - (paragraph) => richTextController.applyParagraphType(paragraph))) - .toList(), - iconButton: buildWrapIconStyleText( - padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 5), - spacing: 3, - isSelected: richTextController.focusMenuParagraph.value, - icon: buildIconWithTooltip( - path: richTextController.selectedParagraph.value.getIcon(imagePaths), - color: AppColor.colorDefaultRichTextButton, - opacity: opacity, - tooltip: RichTextStyleType.paragraph.getTooltipButton(context))), - ), - ), - ), - Padding( - padding: const EdgeInsets.only(right: 4.0), - child: AbsorbPointer( - absorbing: codeViewEnabled, - child: PopupMenuOverlayWidget( - controller: richTextController.menuOrderListController, - listButtonAction: OrderListType.values - .map((orderType) => orderType.buildButtonWidget( - context, - imagePaths, - (orderType) => richTextController.applyOrderListType(orderType))) - .toList(), - iconButton: buildWrapIconStyleText( - padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 5), - spacing: 3, - isSelected: richTextController.focusMenuOrderList.value, - icon: buildIconWithTooltip( - path: richTextController.selectedOrderList.value.getIcon(imagePaths), - color: AppColor.colorDefaultRichTextButton, - opacity: opacity, - tooltip: RichTextStyleType.orderList.getTooltipButton(context))), - ), - ), - ) - ] - ), - ); - }); - } } \ No newline at end of file diff --git a/lib/features/composer/presentation/widgets/toolbar_rich_text_builder.dart b/lib/features/composer/presentation/widgets/toolbar_rich_text_builder.dart new file mode 100644 index 000000000..5b4638224 --- /dev/null +++ b/lib/features/composer/presentation/widgets/toolbar_rich_text_builder.dart @@ -0,0 +1,218 @@ +import 'dart:developer'; + +import 'package:core/presentation/extensions/color_extension.dart'; +import 'package:core/presentation/resources/image_paths.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:tmail_ui_user/features/base/widget/drop_down_button_widget.dart'; +import 'package:tmail_ui_user/features/base/widget/popup_menu_overlay_widget.dart'; +import 'package:tmail_ui_user/features/composer/presentation/controller/rich_text_web_controller.dart'; +import 'package:tmail_ui_user/features/composer/presentation/mixin/rich_text_button_mixin.dart'; +import 'package:tmail_ui_user/features/composer/presentation/model/dropdown_menu_font_status.dart'; +import 'package:tmail_ui_user/features/composer/presentation/model/font_name_type.dart'; +import 'package:tmail_ui_user/features/composer/presentation/model/header_style_type.dart'; +import 'package:tmail_ui_user/features/composer/presentation/model/order_list_type.dart'; +import 'package:tmail_ui_user/features/composer/presentation/model/paragraph_type.dart'; +import 'package:tmail_ui_user/features/composer/presentation/model/rich_text_style_type.dart'; +import 'package:tmail_ui_user/features/composer/presentation/widgets/drop_down_menu_header_style_widget.dart'; + +class ToolbarRichTextWebBuilder extends StatelessWidget with RichTextButtonMixin { + + final RichTextWebController richTextWebController; + final ImagePaths _imagePaths = Get.find(); + + ToolbarRichTextWebBuilder({ + Key? key, + required this.richTextWebController + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Obx(() { + final codeViewEnabled = richTextWebController.codeViewEnabled; + final opacity = codeViewEnabled ? 0.5 : 1.0; + + return Container( + padding: const EdgeInsets.only(left: 20, top: 8, bottom: 8), + alignment: Alignment.centerLeft, + child: Wrap( + crossAxisAlignment: WrapCrossAlignment.center, + runSpacing: 8, + children: [ + AbsorbPointer( + absorbing: codeViewEnabled, + child: DropDownMenuHeaderStyleWidget( + icon: buildWrapIconStyleText( + isSelected: richTextWebController.isMenuHeaderStyleOpen, + icon: SvgPicture.asset(RichTextStyleType.headerStyle.getIcon(_imagePaths), + color: AppColor.colorDefaultRichTextButton.withOpacity(opacity), + fit: BoxFit.fill), + padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 5), + tooltip: RichTextStyleType.headerStyle.getTooltipButton(context) + ), + items: HeaderStyleType.values, + onMenuStateChange: (isOpen) { + log('ComposerView::_buildToolbarRichTextWidget(): MenuHeaderStyleStatus: $isOpen'); + final newStatus = isOpen + ? DropdownMenuFontStatus.open + : DropdownMenuFontStatus.closed; + richTextWebController.menuHeaderStyleStatus.value = newStatus; + }, + onChanged: (newStyle) => richTextWebController.applyHeaderStyle(newStyle)), + ), + AbsorbPointer( + absorbing: codeViewEnabled, + child: Container( + width: 130, + padding: const EdgeInsets.only(left: 4.0, right: 4.0), + child: DropDownButtonWidget( + items: FontNameType.values, + itemSelected: richTextWebController.selectedFontName.value, + onChanged: (newFont) => richTextWebController.applyNewFontStyle(newFont), + onMenuStateChange: (isOpen) { + log('ComposerView::_buildToolbarRichTextWidget(): MenuFontStatus: $isOpen'); + final newStatus = isOpen + ? DropdownMenuFontStatus.open + : DropdownMenuFontStatus.closed; + richTextWebController.menuFontStatus.value = newStatus; + }, + heightItem: 40, + sizeIconChecked: 16, + radiusButton: 8, + opacity: opacity, + dropdownWidth: 200, + colorButton: richTextWebController.isMenuFontOpen + ? AppColor.colorBackgroundWrapIconStyleCode + : Colors.white, + iconArrowDown: SvgPicture.asset(_imagePaths.icStyleArrowDown), + tooltip: RichTextStyleType.fontName.getTooltipButton(context), + supportSelectionIcon: true)), + ), + Padding( + padding: const EdgeInsets.only(right: 4.0), + child: AbsorbPointer( + absorbing: codeViewEnabled, + child: buildWrapIconStyleText( + icon: buildIconWithTooltip( + path: RichTextStyleType.textColor.getIcon(_imagePaths), + color: richTextWebController.selectedTextColor.value, + tooltip: RichTextStyleType.textColor.getTooltipButton(context), + opacity: opacity), + onTap: () => richTextWebController.applyRichTextStyle(context, RichTextStyleType.textColor)), + ), + ), + Padding( + padding: const EdgeInsets.only(right: 4.0), + child: AbsorbPointer( + absorbing: codeViewEnabled, + child: buildWrapIconStyleText( + padding: const EdgeInsets.symmetric(vertical: 9, horizontal: 7), + spacing: 3, + icon: buildIconColorBackgroundText( + iconData: RichTextStyleType.textBackgroundColor.getIconData(), + colorSelected: richTextWebController.selectedTextBackgroundColor.value, + tooltip: RichTextStyleType.textBackgroundColor.getTooltipButton(context), + opacity: opacity), + onTap: () => richTextWebController.applyRichTextStyle(context, RichTextStyleType.textBackgroundColor)), + ), + ), + Padding( + padding: const EdgeInsets.only(right: 4.0), + child: buildWrapIconStyleText( + hasDropdown: false, + padding: const EdgeInsets.symmetric(vertical: 3, horizontal: 5), + icon: Wrap(children: [ + AbsorbPointer( + absorbing: codeViewEnabled, + child: buildIconStyleText( + path: RichTextStyleType.bold.getIcon(_imagePaths), + isSelected: richTextWebController.isTextStyleTypeSelected(RichTextStyleType.bold), + tooltip: RichTextStyleType.bold.getTooltipButton(context), + opacity: opacity, + onTap: () => richTextWebController.applyRichTextStyle(context, RichTextStyleType.bold)), + ), + AbsorbPointer( + absorbing: codeViewEnabled, + child: buildIconStyleText( + path: RichTextStyleType.italic.getIcon(_imagePaths), + isSelected: richTextWebController.isTextStyleTypeSelected(RichTextStyleType.italic), + tooltip: RichTextStyleType.italic.getTooltipButton(context), + opacity: opacity, + onTap: () => richTextWebController.applyRichTextStyle(context, RichTextStyleType.italic)), + ), + AbsorbPointer( + absorbing: codeViewEnabled, + child: buildIconStyleText( + path: RichTextStyleType.underline.getIcon(_imagePaths), + isSelected: richTextWebController.isTextStyleTypeSelected(RichTextStyleType.underline), + tooltip: RichTextStyleType.underline.getTooltipButton(context), + opacity: opacity, + onTap: () => richTextWebController.applyRichTextStyle(context, RichTextStyleType.underline)), + ), + AbsorbPointer( + absorbing: codeViewEnabled, + child: buildIconStyleText( + path: RichTextStyleType.strikeThrough.getIcon(_imagePaths), + isSelected: richTextWebController.isTextStyleTypeSelected( + RichTextStyleType.strikeThrough), + tooltip: RichTextStyleType.strikeThrough.getTooltipButton(context), + opacity: opacity, + onTap: () => richTextWebController.applyRichTextStyle(context, RichTextStyleType.strikeThrough)), + ) + ])), + ), + Padding( + padding: const EdgeInsets.only(right: 4.0), + child: AbsorbPointer( + absorbing: codeViewEnabled, + child: PopupMenuOverlayWidget( + controller: richTextWebController.menuParagraphController, + listButtonAction: ParagraphType.values + .map((paragraph) => paragraph.buildButtonWidget( + context, + _imagePaths, + (paragraph) => richTextWebController.applyParagraphType(paragraph))) + .toList(), + iconButton: buildWrapIconStyleText( + padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 5), + spacing: 3, + isSelected: richTextWebController.focusMenuParagraph.value, + icon: buildIconWithTooltip( + path: richTextWebController.selectedParagraph.value.getIcon(_imagePaths), + color: AppColor.colorDefaultRichTextButton, + opacity: opacity, + tooltip: RichTextStyleType.paragraph.getTooltipButton(context))), + ), + ), + ), + Padding( + padding: const EdgeInsets.only(right: 4.0), + child: AbsorbPointer( + absorbing: codeViewEnabled, + child: PopupMenuOverlayWidget( + controller: richTextWebController.menuOrderListController, + listButtonAction: OrderListType.values + .map((orderType) => orderType.buildButtonWidget( + context, + _imagePaths, + (orderType) => richTextWebController.applyOrderListType(orderType))) + .toList(), + iconButton: buildWrapIconStyleText( + padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 5), + spacing: 3, + isSelected: richTextWebController.focusMenuOrderList.value, + icon: buildIconWithTooltip( + path: richTextWebController.selectedOrderList.value.getIcon(_imagePaths), + color: AppColor.colorDefaultRichTextButton, + opacity: opacity, + tooltip: RichTextStyleType.orderList.getTooltipButton(context))), + ), + ), + ) + ] + ), + ); + }); + } +} \ No newline at end of file diff --git a/lib/features/identity_creator/presentation/identity_creator_view.dart b/lib/features/identity_creator/presentation/identity_creator_view.dart index f110683a2..a0cc4e369 100644 --- a/lib/features/identity_creator/presentation/identity_creator_view.dart +++ b/lib/features/identity_creator/presentation/identity_creator_view.dart @@ -1,12 +1,16 @@ +import 'dart:math'; + import 'package:core/core.dart'; import 'package:enough_html_editor/enough_html_editor.dart' as html_editor_mobile; 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:html_editor_enhanced/html_editor.dart'; import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; import 'package:rich_text_composer/views/keyboard_richtext.dart'; import 'package:rich_text_composer/views/widgets/rich_text_keyboard_toolbar.dart'; +import 'package:tmail_ui_user/features/composer/presentation/widgets/toolbar_rich_text_builder.dart'; import 'package:tmail_ui_user/features/identity_creator/presentation/identity_creator_controller.dart'; import 'package:tmail_ui_user/features/identity_creator/presentation/model/identity_creator_arguments.dart'; import 'package:tmail_ui_user/features/identity_creator/presentation/model/signature_type.dart'; @@ -14,6 +18,8 @@ import 'package:tmail_ui_user/features/identity_creator/presentation/widgets/ide import 'package:tmail_ui_user/features/identity_creator/presentation/widgets/identity_field_no_editable_builder.dart'; import 'package:tmail_ui_user/features/identity_creator/presentation/widgets/identity_input_field_builder.dart'; import 'package:tmail_ui_user/features/identity_creator/presentation/widgets/identity_input_with_drop_list_field_builder.dart'; +import 'package:tmail_ui_user/features/identity_creator/presentation/widgets/set_default_identity_checkbox_builder.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/state/get_all_identities_state.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/model/identity_action_type.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; @@ -44,15 +50,12 @@ class IdentityCreatorView extends GetWidget { Widget build(BuildContext context) { return ResponsiveWidget( responsiveUtils: _responsiveUtils, - mobile: Scaffold( - backgroundColor: Colors.white, - body: GestureDetector( - onTap: () => controller.clearFocusEditor(context), - child: SafeArea( - child: ClipRRect( - borderRadius: const BorderRadius.only(topRight: Radius.circular(14), topLeft: Radius.circular(14)), - child: _buildBodyMobile(context) - ), + mobile: GestureDetector( + onTap: () => controller.clearFocusEditor(context), + child: SizedBox( + height: MediaQuery.of(context).size.height * 0.95, + child: SafeArea( + child: BuildUtils.isWeb ? Scaffold(body: _buildBodyMobile(context)) : _buildBodyMobile(context), ), ) ), @@ -90,11 +93,11 @@ class IdentityCreatorView extends GetWidget { decoration: const BoxDecoration( color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(16))), - width: _responsiveUtils.getSizeScreenWidth(context) * 0.9, - height: _responsiveUtils.getSizeScreenHeight(context) * 0.9, + width: _responsiveUtils.getSizeScreenWidth(context) * 0.85, + height: _responsiveUtils.getSizeScreenHeight(context) * 0.6, child: ClipRRect( borderRadius: const BorderRadius.all(Radius.circular(16)), - child: _buildBodyDesktop(context) + child: _buildBodyMobile(context) ) ) )), @@ -123,11 +126,44 @@ class IdentityCreatorView extends GetWidget { decoration: const BoxDecoration( color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(16))), - width: _responsiveUtils.getSizeScreenWidth(context) * 0.9, - height: _responsiveUtils.getSizeScreenHeight(context) * 0.9, + width: _responsiveUtils.getSizeScreenWidth(context) * 0.85, + height: _responsiveUtils.getSizeScreenHeight(context) * 0.6, child: ClipRRect( borderRadius: const BorderRadius.all(Radius.circular(16)), - child: _buildBodyDesktop(context) + child: _buildBodyMobile(context) + ) + ) + )), + ) + ) + ), + landscapeTablet: Scaffold( + backgroundColor: Colors.black.withAlpha(24), + body: GestureDetector( + onTap: () => controller.clearFocusEditor(context), + child: KeyboardRichText( + richTextController: controller.keyboardRichTextController, + keyBroadToolbar: RichTextKeyboardToolBar( + backgroundKeyboardToolBarColor: AppColor.colorBackgroundKeyboard, + richTextController: controller.keyboardRichTextController, + titleQuickStyleBottomSheet: AppLocalizations.of(context).titleQuickStyles, + titleBackgroundBottomSheet: AppLocalizations.of(context).titleBackground, + titleForegroundBottomSheet: AppLocalizations.of(context).titleForeground, + titleFormatBottomSheet: AppLocalizations.of(context).titleFormat, + titleBack: AppLocalizations.of(context).format, + ), + child: Center(child: Card( + color: Colors.transparent, + shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(16))), + child: Container( + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(16))), + width: _responsiveUtils.getSizeScreenWidth(context) * 0.65, + height: _responsiveUtils.getSizeScreenHeight(context) * 0.8, + child: ClipRRect( + borderRadius: const BorderRadius.all(Radius.circular(16)), + child: _buildBodyMobile(context) ) ) )), @@ -137,7 +173,10 @@ class IdentityCreatorView extends GetWidget { desktop: Scaffold( backgroundColor: Colors.black.withAlpha(24), body: GestureDetector( - onTap: () => controller.clearFocusEditor(context), + onTap: () { + controller.clearFocusEditor(context); + debugPrint('${MediaQuery.of(context).size.width}'); + }, child: Center(child: Card( color: Colors.transparent, shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(16))), @@ -145,11 +184,11 @@ class IdentityCreatorView extends GetWidget { decoration: const BoxDecoration( color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(16))), - width: _responsiveUtils.getSizeScreenWidth(context) * 0.4, - height: _responsiveUtils.getSizeScreenHeight(context) * 0.9, + width: max(_responsiveUtils.getSizeScreenWidth(context) * 0.4, 600), + height: _responsiveUtils.getSizeScreenHeight(context) * 0.75, child: ClipRRect( borderRadius: const BorderRadius.all(Radius.circular(16)), - child: _buildBodyDesktop(context) + child: _buildBodyMobile(context) ) ) )), @@ -158,319 +197,209 @@ class IdentityCreatorView extends GetWidget { ); } - Widget _buildBodyDesktop(BuildContext context) { - return Stack( - children: [ - Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ - Padding( - padding: const EdgeInsets.only(left: 24, top: 24), - child: Obx(() => Text(controller.actionType.value == IdentityActionType.create - ? AppLocalizations.of(context).new_identity.inCaps - : AppLocalizations.of(context).edit_identity.inCaps, - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 24, - color: Colors.black)))), - const SizedBox(height: 8), - Expanded(child: SingleChildScrollView( - controller: controller.scrollController, - physics: const ClampingScrollPhysics(), - child: Padding( - padding: const EdgeInsets.all(24.0), - child: Column(children: [ - Row(crossAxisAlignment: CrossAxisAlignment.start, children: [ - Expanded(child: Obx(() => (IdentityInputFieldBuilder( + Widget _buildBodyMobile(BuildContext context) { + return GestureDetector( + onTap: () => controller.clearFocusEditor(context), + child: Stack( + children: [ + Column(children: [ + Padding( + padding: const EdgeInsets.only(top: 14), + child: Text(controller.actionType.value == IdentityActionType.create + ? AppLocalizations.of(context).createNewIdentity.inCaps + : AppLocalizations.of(context).edit_identity.inCaps, + style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 20, color: Colors.black))), + const SizedBox(height: 8), + Expanded( + child: KeyboardRichText( + keyBroadToolbar: RichTextKeyboardToolBar( + titleBack: AppLocalizations.of(context).titleFormat, + backgroundKeyboardToolBarColor: AppColor.colorBackgroundKeyboard, + isLandScapeMode: _responsiveUtils.isLandscapeMobile(context), + richTextController: controller.keyboardRichTextController, + titleQuickStyleBottomSheet: AppLocalizations.of(context).titleQuickStyles, + titleBackgroundBottomSheet: AppLocalizations.of(context).titleBackground, + titleForegroundBottomSheet: AppLocalizations.of(context).titleForeground, + titleFormatBottomSheet: AppLocalizations.of(context).titleFormat, + ), + richTextController: controller.keyboardRichTextController, + child: SingleChildScrollView( + controller: controller.scrollController, + physics: const ClampingScrollPhysics(), + child: Padding( + padding: const EdgeInsets.all(24.0), + child: Column(children: [ + Obx(() => (IdentityInputFieldBuilder( AppLocalizations.of(context).name, controller.errorNameIdentity.value, + AppLocalizations.of(context).required, editingController: controller.inputNameIdentityController, focusNode: controller.inputNameIdentityFocusNode, isMandatory: true) - ..addOnChangeInputNameAction((value) => controller.updateNameIdentity(context, value))) - .build())), - const SizedBox(width: 24), - Expanded(child: Obx(() { - if (controller.actionType.value == IdentityActionType.create) { - return (IdentityDropListFieldBuilder( + ..addOnChangeInputNameAction((value) => controller.updateNameIdentity(context, value))) + .build()), + const SizedBox(height: 24), + Obx(() { + if (controller.actionType.value == IdentityActionType.create) { + return (IdentityDropListFieldBuilder( + _imagePaths, + AppLocalizations.of(context).email.inCaps, + controller.emailOfIdentity.value, + controller.listEmailAddressDefault) + ..addOnSelectEmailAddressDropListAction((emailAddress) => + controller.updateEmailOfIdentity(emailAddress)) + ).build(); + } else { + return IdentityFieldNoEditableBuilder( + AppLocalizations.of(context).email.inCaps, + controller.emailOfIdentity.value + ).build(); + } + }), + const SizedBox(height: 24), + Obx(() => (IdentityDropListFieldBuilder( _imagePaths, - AppLocalizations.of(context).email.inCaps, - controller.emailOfIdentity.value, - controller.listEmailAddressDefault) - ..addOnSelectEmailAddressDropListAction((emailAddress) => - controller.updateEmailOfIdentity(emailAddress)) - ).build(); - } else { - return IdentityFieldNoEditableBuilder( - AppLocalizations.of(context).email.inCaps, - controller.emailOfIdentity.value - ).build(); - } - })), - ]), - const SizedBox(height: 24), - Row(crossAxisAlignment: CrossAxisAlignment.start, children: [ - Expanded(child: Obx(() => (IdentityDropListFieldBuilder( - _imagePaths, - AppLocalizations.of(context).reply_to_address, - controller.replyToOfIdentity.value, - controller.listEmailAddressOfReplyTo) - ..addOnSelectEmailAddressDropListAction((emailAddress) => - controller.updaterReplyToOfIdentity(emailAddress))) - .build())), - const SizedBox(width: 24), - Expanded(child: Obx(() => (IdentityInputWithDropListFieldBuilder( - AppLocalizations.of(context).bcc_to_address, - controller.errorBccIdentity.value, - controller.inputBccIdentityController) - ..addOnSelectedSuggestionAction((newEmailAddress) { - controller.inputBccIdentityController?.text = newEmailAddress?.email ?? ''; - controller.updateBccOfIdentity(newEmailAddress); - }) - ..addOnChangeInputSuggestionAction((pattern) { - controller.validateInputBccAddress(context, pattern); - if (pattern == null || pattern.trim().isEmpty) { - controller.updateBccOfIdentity(null); - } else { - controller.updateBccOfIdentity(EmailAddress(null, pattern)); - } - }) - ..addOnSuggestionCallbackAction((pattern) => - controller.getSuggestionEmailAddress(pattern))) - .build() - )), - ]), - const SizedBox(height: 32), - Row(children: [ - Text(AppLocalizations.of(context).signature, - style: const TextStyle( - fontWeight: FontWeight.normal, - fontSize: 14, - color: AppColor.colorContentEmail)), - const Spacer(), - Obx(() => _buildSignatureButton(context, SignatureType.plainText)), - const SizedBox(width: 10), - Obx(() => _buildSignatureButton(context, SignatureType.htmlTemplate)), - ]), - const SizedBox(height: 8), - Obx(() => Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10), - border: Border.all(color: AppColor.colorInputBorderCreateMailbox), - color: Colors.white), - padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 16), - child: Stack( - children: [ - if (controller.signatureType.value == SignatureType.plainText) - _buildSignaturePlainTextTemplate(context) - else - _buildSignatureHtmlTemplate(context) - ] - ), - )) - ]), - ), - )), - Container( - padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 24), - alignment: Alignment.centerRight, - color: Colors.white, - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - buildTextButton( - AppLocalizations.of(context).cancel, - textStyle: const TextStyle( - fontWeight: FontWeight.w500, - fontSize: 17, - color: AppColor.colorTextButton), - backgroundColor: AppColor.emailAddressChipColor, - width: 128, - height: 44, - radius: 10, - onTap: () => controller.closeView(context)), - const SizedBox(width: 12), - Obx(() => buildTextButton( - controller.actionType.value == IdentityActionType.create - ? AppLocalizations.of(context).create - : AppLocalizations.of(context).save, - width: 128, - height: 44, - radius: 10, - onTap: () => controller.createNewIdentity(context))), - ] - ), - ) - ]), - Positioned(top: 8, right: 8, - child: buildIconWeb( - icon: SvgPicture.asset(_imagePaths.icCloseMailbox, fit: BoxFit.fill), - tooltip: AppLocalizations.of(context).close, - onTap: () => controller.closeView(context))) - ] - ); - } - - Widget _buildBodyMobile(BuildContext context) { - return Stack( - children: [ - Column(children: [ - Padding( - padding: const EdgeInsets.only(top: 16), - child: Text(controller.actionType.value == IdentityActionType.create - ? AppLocalizations.of(context).new_identity.inCaps - : AppLocalizations.of(context).edit_identity.inCaps, - style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 21, color: Colors.black))), - const SizedBox(height: 8), - Expanded(child: KeyboardRichText( - child: SingleChildScrollView( - controller: controller.scrollController, - physics: const ClampingScrollPhysics(), - child: Padding( - padding: const EdgeInsets.all(24.0), - child: Column(children: [ - Obx(() => (IdentityInputFieldBuilder( - AppLocalizations.of(context).name, - controller.errorNameIdentity.value, - editingController: controller.inputNameIdentityController, - focusNode: controller.inputNameIdentityFocusNode, - isMandatory: true) - ..addOnChangeInputNameAction((value) => controller.updateNameIdentity(context, value))) - .build()), - const SizedBox(height: 24), - Obx(() { - if (controller.actionType.value == IdentityActionType.create) { - return (IdentityDropListFieldBuilder( - _imagePaths, - AppLocalizations.of(context).email.inCaps, - controller.emailOfIdentity.value, - controller.listEmailAddressDefault) - ..addOnSelectEmailAddressDropListAction((emailAddress) => - controller.updateEmailOfIdentity(emailAddress)) - ).build(); - } else { - return IdentityFieldNoEditableBuilder( - AppLocalizations.of(context).email.inCaps, - controller.emailOfIdentity.value - ).build(); - } - }), - const SizedBox(height: 24), - Obx(() => (IdentityDropListFieldBuilder( - _imagePaths, - AppLocalizations.of(context).reply_to_address, - controller.replyToOfIdentity.value, - controller.listEmailAddressOfReplyTo) - ..addOnSelectEmailAddressDropListAction((newEmailAddress) => - controller.updaterReplyToOfIdentity(newEmailAddress))) - .build()), - const SizedBox(height: 24), - Obx(() => (IdentityInputWithDropListFieldBuilder( - AppLocalizations.of(context).bcc_to_address, - controller.errorBccIdentity.value, - controller.inputBccIdentityController) - ..addOnSelectedSuggestionAction((newEmailAddress) { - controller.inputBccIdentityController?.text = newEmailAddress?.email ?? ''; - controller.updateBccOfIdentity(newEmailAddress); - }) - ..addOnChangeInputSuggestionAction((pattern) { - controller.validateInputBccAddress(context, pattern); - if (pattern == null || pattern.trim().isEmpty) { - controller.updateBccOfIdentity(null); - } else { - controller.updateBccOfIdentity(EmailAddress(null, pattern)); - } - }) - ..addOnSuggestionCallbackAction((pattern) => - controller.getSuggestionEmailAddress(pattern))) - .build() - ), - const SizedBox(height: 32), - Text(AppLocalizations.of(context).signature, - style: const TextStyle( - fontWeight: FontWeight.normal, - fontSize: 14, - color: AppColor.colorContentEmail, - ), - ), - const SizedBox(height: 8), - Row(mainAxisAlignment: MainAxisAlignment.center, children: [ - Obx(() => _buildSignatureButton(context, SignatureType.plainText)), - const SizedBox(width: 10), - Obx(() => _buildSignatureButton(context, SignatureType.htmlTemplate)), - ]), - const SizedBox(height: 8), - Obx(() => Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10), - border: Border.all(color: AppColor.colorInputBorderCreateMailbox), - color: Colors.white, - ), - padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 16), - child: Stack( - children: [ - if (controller.signatureType.value == SignatureType.plainText) - _buildSignaturePlainTextTemplate(context) - else - _buildSignatureHtmlTemplate(context) - ] - ), - )), - const SizedBox(height: 24), - Container( - alignment: Alignment.center, - color: Colors.white, - child: Row( - children: [ - Expanded( - child: buildTextButton( - AppLocalizations.of(context).cancel, - textStyle: const TextStyle( - fontWeight: FontWeight.w500, - fontSize: 17, - color: AppColor.colorTextButton, + AppLocalizations.of(context).reply_to, + controller.replyToOfIdentity.value, + controller.listEmailAddressOfReplyTo) + ..addOnSelectEmailAddressDropListAction((newEmailAddress) => + controller.updaterReplyToOfIdentity(newEmailAddress))) + .build()), + const SizedBox(height: 24), + Obx(() => (IdentityInputWithDropListFieldBuilder( + AppLocalizations.of(context).bcc_to, + controller.errorBccIdentity.value, + controller.inputBccIdentityController) + ..addOnSelectedSuggestionAction((newEmailAddress) { + controller.inputBccIdentityController?.text = newEmailAddress?.email ?? ''; + controller.updateBccOfIdentity(newEmailAddress); + }) + ..addOnChangeInputSuggestionAction((pattern) { + controller.validateInputBccAddress(context, pattern); + if (pattern == null || pattern.trim().isEmpty) { + controller.updateBccOfIdentity(null); + } else { + controller.updateBccOfIdentity(EmailAddress(null, pattern)); + } + }) + ..addOnSuggestionCallbackAction((pattern) => + controller.getSuggestionEmailAddress(pattern))) + .build() + ), + const SizedBox(height: 32), + Row( + children: [ + Text(AppLocalizations.of(context).signature, + style: const TextStyle( + fontWeight: FontWeight.normal, + fontSize: 14, + color: AppColor.colorContentEmail, ), - backgroundColor: AppColor.emailAddressChipColor, - width: 128, - height: 44, - radius: 10, - onTap: () => controller.closeView(context), ), + Expanded( + child: Row(mainAxisAlignment: MainAxisAlignment.end, children: [ + Obx(() => _buildSignatureButton(context, SignatureType.plainText)), + const SizedBox(width: 10), + Obx(() => _buildSignatureButton(context, SignatureType.htmlTemplate)), + ]), + ) + ], + ), + const SizedBox(height: 8), + Obx(() => Container( + height: 160, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + border: Border.all(color: AppColor.colorInputBorderCreateMailbox), + color: Colors.white, ), - const SizedBox(width: 12), - Expanded( - child: Obx(() => buildTextButton( - controller.actionType.value == IdentityActionType.create - ? AppLocalizations.of(context).create - : AppLocalizations.of(context).save, - width: 128, - height: 44, - radius: 10, - onTap: () => controller.createNewIdentity(context))), + padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 16), + child: Stack( + children: [ + if (controller.signatureType.value == SignatureType.plainText) + _buildSignaturePlainTextTemplate(context) + else + _buildSignatureHtmlTemplate(context) + ] ), + )), + if (_responsiveUtils.isTablet(context) || _responsiveUtils.isMobile(context))...[ + Obx(() => Padding( + padding: const EdgeInsets.only(top: 27, bottom: 135), + child: SetDefaultIdentityCheckboxBuilder( + imagePaths: _imagePaths, + isCheck: controller.isDefaultIdentity.value, + onCheckboxChanged: controller.onCheckboxChanged), + )), + const SizedBox(height: 24), + Container( + alignment: Alignment.center, + color: Colors.white, + child: Row( + children: [ + Expanded( + child: buildTextButton( + AppLocalizations.of(context).cancel, + textStyle: const TextStyle( + fontWeight: FontWeight.w500, + fontSize: 17, + color: AppColor.colorTextButton, + ), + backgroundColor: AppColor.emailAddressChipColor, + width: 128, + height: 44, + radius: 10, + onTap: () => controller.closeView(context), + ), + ), + const SizedBox(width: 12), + Expanded( + child: Obx(() => controller.viewState.value.fold( + (failure) => buildTextButton( + controller.actionType.value == IdentityActionType.create + ? AppLocalizations.of(context).create + : AppLocalizations.of(context).save, + width: 128, + height: 44, + radius: 10, + onTap: () => controller.createNewIdentity(context)), + (success) { + if (success is GetAllIdentitiesLoading) { + return const Center( + key: Key('create_loading_icon'), + child: CircularProgressIndicator(color: AppColor.primaryColor)); + } else { + return buildTextButton( + controller.actionType.value == IdentityActionType.create + ? AppLocalizations.of(context).create + : AppLocalizations.of(context).save, + width: 128, + height: 44, + radius: 10, + onTap: () => controller.createNewIdentity(context)); + } + } + )), + ), + ] + ), + )] else ...[ + _buildActionBottomDesktop(context) ] - ), - ) - ]), + ]), + ), + ), ), ), - richTextController: controller.keyboardRichTextController, - keyBroadToolbar: RichTextKeyboardToolBar( - titleBack: AppLocalizations.of(context).titleFormat, - backgroundKeyboardToolBarColor: AppColor.colorBackgroundKeyboard, - isLandScapeMode: _responsiveUtils.isLandscapeMobile(context), - richTextController: controller.keyboardRichTextController, - titleQuickStyleBottomSheet: AppLocalizations.of(context).titleQuickStyles, - titleBackgroundBottomSheet: AppLocalizations.of(context).titleBackground, - titleForegroundBottomSheet: AppLocalizations.of(context).titleForeground, - titleFormatBottomSheet: AppLocalizations.of(context).titleFormat, - ), - )), - ]), - Positioned(top: 8, right: 8, - child: buildIconWeb( - icon: SvgPicture.asset(_imagePaths.icCloseMailbox, fit: BoxFit.fill), - tooltip: AppLocalizations.of(context).close, - onTap: () => controller.closeView(context))) - ] + ]), + Positioned(top: 2, right: 8, + child: buildIconWeb( + iconSize: 24, + icon: SvgPicture.asset(_imagePaths.icComposerClose, fit: BoxFit.fill, color: AppColor.colorDeleteContactIcon), + tooltip: AppLocalizations.of(context).close, + onTap: () => controller.closeView(context))) + ] + ), ); } @@ -522,45 +451,134 @@ class IdentityCreatorView extends GetWidget { } Widget _buildSignatureHtmlTemplate(BuildContext context) { - if (BuildUtils.isWeb) { - return html_editor_browser.HtmlEditor( - key: const Key('signature_html_editor_web'), - controller: controller.signatureHtmlEditorController, - htmlEditorOptions: const html_editor_browser.HtmlEditorOptions( - hint: '', - darkMode: false, - ), - blockQuotedContent: controller.contentHtmlEditor ?? '

', - htmlToolbarOptions: const html_editor_browser.HtmlToolbarOptions( - toolbarPosition: html_editor_browser.ToolbarPosition.custom, - ), - otherOptions: const html_editor_browser.OtherOptions(height: 230), - callbacks: html_editor_browser.Callbacks(onInit: () { - controller.signatureHtmlEditorController.setFullScreen(); - }, onChangeContent: (String? changed) { - controller.updateContentHtmlEditor(changed); - }, onFocus: () { - FocusManager.instance.primaryFocus?.unfocus(); - Future.delayed(const Duration(milliseconds: 500), () { - controller.signatureHtmlEditorController.setFocus(); - }); - }), - ); - } else { - return html_editor_mobile.HtmlEditor( - key: controller.htmlKey, - minHeight: 230, - onCreated: (htmlEditorController) { - controller.keyboardRichTextController.onCreateHTMLEditor( - htmlEditorController, - onFocus: controller.onFocusHTMLEditor, - onEnterKeyDown: controller.onEnterKeyDown, - context: context, - ); - controller.signatureHtmlEditorMobileController = htmlEditorController; + final htmlEditor = BuildUtils.isWeb + ? _buildHtmlEditorWeb(context, controller.contentHtmlEditor ?? '') + : _buildHtmlEditor(context, initialContent: controller.contentHtmlEditor ?? ''); + + return SizedBox( + height: 160, + child: Column( + children: [ + if(BuildUtils.isWeb) + ToolbarRichTextWebBuilder(richTextWebController: controller.richTextWebController), + htmlEditor, + ], + ), + ); + } + + Widget _buildHtmlEditorWeb(BuildContext context, String initContent) { + log('IdentityCreatorView::_buildHtmlEditorWeb(): initContent: $initContent'); + return Expanded( + child: Padding( + padding: EdgeInsets.symmetric( + horizontal: _responsiveUtils.isMobile(context) ? 8 : 10), + child: html_editor_browser.HtmlEditor( + key: const Key('identity_create_editor_web'), + controller: controller.richTextWebController.editorController, + htmlEditorOptions: const HtmlEditorOptions( + hint: '', + darkMode: false, + customBodyCssStyle: bodyCssStyleForEditor), + blockQuotedContent: initContent, + htmlToolbarOptions: const HtmlToolbarOptions( + toolbarType: ToolbarType.hide, + defaultToolbarButtons: []), + otherOptions: const OtherOptions(height: 550), + callbacks: Callbacks(onBeforeCommand: (currentHtml) { + log('IdentityCreatorView::_buildHtmlEditorWeb(): onBeforeCommand : $currentHtml'); + controller.updateContentHtmlEditor(currentHtml); + }, onChangeContent: (changed) { + log('IdentityCreatorView::_buildHtmlEditorWeb(): onChangeContent : $changed'); + controller.updateContentHtmlEditor(changed); + }, onInit: () { + log('IdentityCreatorView::_buildHtmlEditorWeb(): onInit'); + controller.updateContentHtmlEditor(initContent); + controller.richTextWebController.setFullScreenEditor(); + controller.richTextWebController.setEnableCodeView(); + }, onFocus: () { + log('IdentityCreatorView::_buildHtmlEditorWeb(): onFocus'); + FocusManager.instance.primaryFocus?.unfocus(); + Future.delayed(const Duration(milliseconds: 500), () { + controller.richTextWebController.editorController.setFocus(); + }); + controller.richTextWebController.closeAllMenuPopup(); + }, onChangeSelection: (settings) { + controller.richTextWebController.onEditorSettingsChange(settings); + }, onChangeCodeview: (contentChanged) { + log('IdentityCreatorView::_buildHtmlEditorWeb(): onChangeCodeView : $contentChanged'); + controller.updateContentHtmlEditor(contentChanged); + }), + ) + ) + ); + } + + Widget _buildHtmlEditor(BuildContext context, {String? initialContent}) { + final richTextMobileTabletController = controller.richTextMobileTabletController; + return Focus( + focusNode: controller.htmlEditorNode, + child: html_editor_mobile.HtmlEditor( + key: const Key('identity_create_editor'), + minHeight: 111, + addDefaultSelectionMenuItems: false, + initialContent: initialContent ?? '', + onCreated: (editorApi) { + richTextMobileTabletController.htmlEditorApi = editorApi; + controller.keyboardRichTextController.onCreateHTMLEditor( + editorApi, + onEnterKeyDown: controller.onEnterKeyDown, + context: context, + ); }, - initialContent: controller.contentHtmlEditor ?? '', - ); - } + ) + ); + } + + Widget _buildActionBottomDesktop(BuildContext context) { + return Row( + children: [ + Obx(() { + return SetDefaultIdentityCheckboxBuilder( + imagePaths: _imagePaths, + isCheck: controller.isDefaultIdentity.value, + onCheckboxChanged: controller.onCheckboxChanged); + }), + Expanded( + child: Padding( + padding: const EdgeInsets.only(top: 24.0, bottom: 12.0, left: 12.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Padding( + padding: const EdgeInsets.only(right: 12.0), + child: buildTextButton( + AppLocalizations.of(context).cancel, + textStyle: const TextStyle( + fontWeight: FontWeight.w500, + fontSize: 17, + color: AppColor.colorTextButton, + ), + backgroundColor: AppColor.emailAddressChipColor, + width: 156, + height: 44, + radius: 10, + onTap: () => controller.closeView(context), + ), + ), + buildTextButton( + controller.actionType.value == IdentityActionType.create + ? AppLocalizations.of(context).create + : AppLocalizations.of(context).save, + width: 156, + height: 44, + radius: 10, + onTap: () => controller.createNewIdentity(context)), + ], + ), + ), + ) + ], + ); } } \ No newline at end of file diff --git a/lib/features/identity_creator/presentation/model/signature_type.dart b/lib/features/identity_creator/presentation/model/signature_type.dart index c77491f2b..c56fb0aca 100644 --- a/lib/features/identity_creator/presentation/model/signature_type.dart +++ b/lib/features/identity_creator/presentation/model/signature_type.dart @@ -14,7 +14,7 @@ extension SignatureTypeExtension on SignatureType { case SignatureType.plainText: return AppLocalizations.of(context).plain_text; case SignatureType.htmlTemplate: - return AppLocalizations.of(context).html_template; + return AppLocalizations.of(context).html; } } } \ No newline at end of file diff --git a/lib/features/identity_creator/presentation/widgets/identity_input_field_builder.dart b/lib/features/identity_creator/presentation/widgets/identity_input_field_builder.dart index 5ba660f75..873045cf3 100644 --- a/lib/features/identity_creator/presentation/widgets/identity_input_field_builder.dart +++ b/lib/features/identity_creator/presentation/widgets/identity_input_field_builder.dart @@ -9,6 +9,7 @@ class IdentityInputFieldBuilder { final String _label; final String? _error; + final String? requiredIndicator; final TextEditingController? editingController; final FocusNode? focusNode; final TextInputType? inputType; @@ -18,7 +19,8 @@ class IdentityInputFieldBuilder { IdentityInputFieldBuilder( this._label, - this._error, { + this._error, + this.requiredIndicator, { this.isMandatory = false, this.editingController, this.focusNode, @@ -31,10 +33,13 @@ class IdentityInputFieldBuilder { Widget build() { return Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text(isMandatory ? '$_label*' : _label, style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.normal, - color: AppColor.colorContentEmail)), + Text( + isMandatory + ? '$_label ($requiredIndicator)' + : _label, style: const TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + color: AppColor.colorContentEmail)), const SizedBox(height: 8), (TextFieldBuilder() ..onChange((value) => onChangeInputNameAction?.call(value)) diff --git a/lib/features/identity_creator/presentation/widgets/set_default_identity_checkbox_builder.dart b/lib/features/identity_creator/presentation/widgets/set_default_identity_checkbox_builder.dart new file mode 100644 index 000000000..4254c94a7 --- /dev/null +++ b/lib/features/identity_creator/presentation/widgets/set_default_identity_checkbox_builder.dart @@ -0,0 +1,59 @@ +import 'package:core/presentation/extensions/color_extension.dart'; +import 'package:core/presentation/resources/image_paths.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; + +typedef OnCheckboxChanged = void Function(); + +class SetDefaultIdentityCheckboxBuilder extends StatelessWidget { + final ImagePaths imagePaths; + final OnCheckboxChanged onCheckboxChanged; + final bool isCheck; + + const SetDefaultIdentityCheckboxBuilder( + {Key? key, + required this.imagePaths, + required this.onCheckboxChanged, + required this.isCheck}) + : super(key: key); + + @override + Widget build(BuildContext context) { + return Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Material( + child: InkWell( + onTap: onCheckboxChanged, + child: Container( + width: 20, + height: 20, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(4.0), + border: Border.all(color: AppColor.primaryColor, width: 2.0), + color: isCheck ? AppColor.primaryColor : Colors.transparent, + ), + child: SvgPicture.asset( + imagePaths.icSelectedSB, + color: isCheck ? Colors.white : Colors.transparent, + width: 18, + height: 18, + )), + ), + ), + Padding( + padding: const EdgeInsets.only(left: 8.0), + child: Text( + AppLocalizations.of(context).setDefaultIdentity, + style: const TextStyle( + fontWeight: FontWeight.normal, + fontSize: 14, + color: AppColor.colorSettingExplanation, + ), + ), + ), + ], + ); + } +} diff --git a/lib/l10n/intl_messages.arb b/lib/l10n/intl_messages.arb index 25103c7aa..655226e28 100644 --- a/lib/l10n/intl_messages.arb +++ b/lib/l10n/intl_messages.arb @@ -1,5 +1,5 @@ { - "@@last_modified": "2023-01-12T18:44:51.610329", + "@@last_modified": "2023-01-16T10:06:45.070370", "initializing_data": "Initializing data...", "@initializing_data": { "type": "text", @@ -1178,6 +1178,12 @@ "placeholders_order": [], "placeholders": {} }, + "setDefaultIdentity": "Set as default identity", + "@setDefaultIdentity": { + "type": "text", + "placeholders_order": [], + "placeholders": {} + }, "identitiesSettingExplanation": "Select the identity or email address you want to use to send an emails", "@identitiesSettingExplanation": { "type": "text", @@ -1202,14 +1208,14 @@ "placeholders_order": [], "placeholders": {} }, - "reply_to_address": "Reply to address", - "@reply_to_address": { + "reply_to": "Reply to", + "@reply_to": { "type": "text", "placeholders_order": [], "placeholders": {} }, - "bcc_to_address": "Bcc to address", - "@bcc_to_address": { + "bcc_to": "Bcc to", + "@bcc_to": { "type": "text", "placeholders_order": [], "placeholders": {} @@ -1232,6 +1238,12 @@ "placeholders_order": [], "placeholders": {} }, + "html": "Html", + "@html": { + "type": "text", + "placeholders_order": [], + "placeholders": {} + }, "create": "Create", "@create": { "type": "text", @@ -1244,6 +1256,12 @@ "placeholders_order": [], "placeholders": {} }, + "you_have_created_a_new_default_identity": "You have created a new default identity", + "@you_have_created_a_new_default_identity": { + "type": "text", + "placeholders_order": [], + "placeholders": {} + }, "all_identities": "All identities", "@all_identities": { "type": "text", @@ -2552,7 +2570,6 @@ "placeholders_order": [], "placeholders": {} }, -<<<<<<< HEAD "youHaveNewMessages": "You have new messages", "@youHaveNewMessages": { "type": "text", @@ -2580,5 +2597,11 @@ "type": "text", "placeholders_order": [], "placeholders": {} + }, + "required": "required", + "@required": { + "type": "text", + "placeholders_order": [], + "placeholders": {} } } \ No newline at end of file diff --git a/lib/main/localizations/app_localizations.dart b/lib/main/localizations/app_localizations.dart index 7ed6f3713..98d80a791 100644 --- a/lib/main/localizations/app_localizations.dart +++ b/lib/main/localizations/app_localizations.dart @@ -1212,6 +1212,13 @@ class AppLocalizations { name: 'identities'); } + String get setDefaultIdentity { + return Intl.message( + 'Set as default identity', + name: 'setDefaultIdentity' + ); + } + String get identitiesSettingExplanation { return Intl.message( 'Select the identity or email address you want to use to send an emails', @@ -1235,16 +1242,16 @@ class AppLocalizations { name: 'name'); } - String get reply_to_address { + String get reply_to { return Intl.message( - 'Reply to address', - name: 'reply_to_address'); + 'Reply to', + name: 'reply_to'); } - String get bcc_to_address { + String get bcc_to { return Intl.message( - 'Bcc to address', - name: 'bcc_to_address'); + 'Bcc to', + name: 'bcc_to'); } String get signature { @@ -1265,6 +1272,12 @@ class AppLocalizations { name: 'html_template'); } + String get html { + return Intl.message( + 'Html', + name: 'html'); + } + String get create { return Intl.message( 'Create', @@ -1277,6 +1290,12 @@ class AppLocalizations { name: 'you_have_created_a_new_identity'); } + String get you_have_created_a_new_default_identity { + return Intl.message( + 'You have created a new default identity', + name: 'you_have_created_a_new_default_identity'); + } + String get all_identities { return Intl.message( 'All identities', @@ -2683,4 +2702,10 @@ class AppLocalizations { name: 'enableSpamReport', ); } + + String get required { + return Intl.message( + 'required', + name: 'required'); + } } \ No newline at end of file diff --git a/lib/main/pages/app_pages.dart b/lib/main/pages/app_pages.dart index 833e2657e..ee76d9a07 100644 --- a/lib/main/pages/app_pages.dart +++ b/lib/main/pages/app_pages.dart @@ -8,8 +8,6 @@ import 'package:tmail_ui_user/features/destination_picker/presentation/destinati import 'package:tmail_ui_user/features/destination_picker/presentation/destination_picker_view.dart' deferred as destination_picker; import 'package:tmail_ui_user/features/home/presentation/home_bindings.dart'; import 'package:tmail_ui_user/features/home/presentation/home_view.dart'; -import 'package:tmail_ui_user/features/identity_creator/presentation/identity_creator_bindings.dart'; -import 'package:tmail_ui_user/features/identity_creator/presentation/identity_creator_view.dart' deferred as identity_creator; import 'package:tmail_ui_user/features/contact/presentation/contact_view.dart' deferred as contact_view; import 'package:tmail_ui_user/features/rules_filter_creator/presentation/rules_filter_creator_bindings.dart'; import 'package:tmail_ui_user/features/rules_filter_creator/presentation/rules_filter_creator_view.dart' deferred as rules_filter_creator; @@ -92,13 +90,6 @@ class AppPages { contact_view.loadLibrary, () => contact_view.ContactView()), binding: ContactBindings()), - GetPage( - name: AppRoutes.identityCreator, - opaque: false, - page: () => DeferredWidget( - identity_creator.loadLibrary, - () => identity_creator.IdentityCreatorView()), - binding: IdentityCreatorBindings()), GetPage( name: AppRoutes.rulesFilterCreator, opaque: false,