TF-1194 create new default identity: add presentation layer

This commit is contained in:
sherlockvn
2023-01-16 17:05:20 +07:00
committed by Dat Vu
parent ce46de9e73
commit 8587b9e8bd
9 changed files with 728 additions and 586 deletions
@@ -10,21 +10,13 @@ import 'package:jmap_dart_client/jmap/identities/identity.dart';
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/base/mixin/app_loader_mixin.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/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/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/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/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/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/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/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/upload/presentation/model/upload_file_state.dart';
import 'package:tmail_ui_user/features/email/domain/state/get_email_content_state.dart'; import 'package:tmail_ui_user/features/email/domain/state/get_email_content_state.dart';
@@ -72,7 +64,7 @@ class ComposerView extends GetWidget<ComposerController>
Expanded(child: Column( Expanded(child: Column(
children: [ children: [
_buildAttachmentsWidget(context), _buildAttachmentsWidget(context),
_buildToolbarRichTextWidget(context), ToolbarRichTextWebBuilder(richTextWebController: controller.richTextWebController),
buildInlineLoadingView(controller), buildInlineLoadingView(controller),
_buildEditorForm(context) _buildEditorForm(context)
] ]
@@ -368,7 +360,7 @@ class ComposerView extends GetWidget<ComposerController>
child: Column( child: Column(
children: [ children: [
_buildAttachmentsWidget(context), _buildAttachmentsWidget(context),
_buildToolbarRichTextWidget(context), ToolbarRichTextWebBuilder(richTextWebController: controller.richTextWebController),
buildInlineLoadingView(controller), buildInlineLoadingView(controller),
_buildEditorForm(context) _buildEditorForm(context)
] ]
@@ -846,193 +838,4 @@ class ComposerView extends GetWidget<ComposerController>
return constraints.maxHeight > 0 ? constraints.maxHeight * 0.4 : 150.0; 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<FontNameType>(
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))),
),
),
)
]
),
);
});
}
} }
@@ -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<ImagePaths>();
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<FontNameType>(
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))),
),
),
)
]
),
);
});
}
}
@@ -1,12 +1,16 @@
import 'dart:math';
import 'package:core/core.dart'; import 'package:core/core.dart';
import 'package:enough_html_editor/enough_html_editor.dart' as html_editor_mobile; import 'package:enough_html_editor/enough_html_editor.dart' as html_editor_mobile;
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 html_editor_browser; 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:jmap_dart_client/jmap/mail/email/email_address.dart';
import 'package:rich_text_composer/views/keyboard_richtext.dart'; import 'package:rich_text_composer/views/keyboard_richtext.dart';
import 'package:rich_text_composer/views/widgets/rich_text_keyboard_toolbar.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/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/identity_creator_arguments.dart';
import 'package:tmail_ui_user/features/identity_creator/presentation/model/signature_type.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_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_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/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/features/manage_account/presentation/model/identity_action_type.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
@@ -44,15 +50,12 @@ class IdentityCreatorView extends GetWidget<IdentityCreatorController> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ResponsiveWidget( return ResponsiveWidget(
responsiveUtils: _responsiveUtils, responsiveUtils: _responsiveUtils,
mobile: Scaffold( mobile: GestureDetector(
backgroundColor: Colors.white, onTap: () => controller.clearFocusEditor(context),
body: GestureDetector( child: SizedBox(
onTap: () => controller.clearFocusEditor(context), height: MediaQuery.of(context).size.height * 0.95,
child: SafeArea( child: SafeArea(
child: ClipRRect( child: BuildUtils.isWeb ? Scaffold(body: _buildBodyMobile(context)) : _buildBodyMobile(context),
borderRadius: const BorderRadius.only(topRight: Radius.circular(14), topLeft: Radius.circular(14)),
child: _buildBodyMobile(context)
),
), ),
) )
), ),
@@ -90,11 +93,11 @@ class IdentityCreatorView extends GetWidget<IdentityCreatorController> {
decoration: const BoxDecoration( decoration: const BoxDecoration(
color: Colors.white, color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(16))), borderRadius: BorderRadius.all(Radius.circular(16))),
width: _responsiveUtils.getSizeScreenWidth(context) * 0.9, width: _responsiveUtils.getSizeScreenWidth(context) * 0.85,
height: _responsiveUtils.getSizeScreenHeight(context) * 0.9, height: _responsiveUtils.getSizeScreenHeight(context) * 0.6,
child: ClipRRect( child: ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(16)), borderRadius: const BorderRadius.all(Radius.circular(16)),
child: _buildBodyDesktop(context) child: _buildBodyMobile(context)
) )
) )
)), )),
@@ -123,11 +126,44 @@ class IdentityCreatorView extends GetWidget<IdentityCreatorController> {
decoration: const BoxDecoration( decoration: const BoxDecoration(
color: Colors.white, color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(16))), borderRadius: BorderRadius.all(Radius.circular(16))),
width: _responsiveUtils.getSizeScreenWidth(context) * 0.9, width: _responsiveUtils.getSizeScreenWidth(context) * 0.85,
height: _responsiveUtils.getSizeScreenHeight(context) * 0.9, height: _responsiveUtils.getSizeScreenHeight(context) * 0.6,
child: ClipRRect( child: ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(16)), 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<IdentityCreatorController> {
desktop: Scaffold( desktop: Scaffold(
backgroundColor: Colors.black.withAlpha(24), backgroundColor: Colors.black.withAlpha(24),
body: GestureDetector( body: GestureDetector(
onTap: () => controller.clearFocusEditor(context), onTap: () {
controller.clearFocusEditor(context);
debugPrint('${MediaQuery.of(context).size.width}');
},
child: Center(child: Card( child: Center(child: Card(
color: Colors.transparent, color: Colors.transparent,
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(16))), shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(16))),
@@ -145,11 +184,11 @@ class IdentityCreatorView extends GetWidget<IdentityCreatorController> {
decoration: const BoxDecoration( decoration: const BoxDecoration(
color: Colors.white, color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(16))), borderRadius: BorderRadius.all(Radius.circular(16))),
width: _responsiveUtils.getSizeScreenWidth(context) * 0.4, width: max(_responsiveUtils.getSizeScreenWidth(context) * 0.4, 600),
height: _responsiveUtils.getSizeScreenHeight(context) * 0.9, height: _responsiveUtils.getSizeScreenHeight(context) * 0.75,
child: ClipRRect( child: ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(16)), borderRadius: const BorderRadius.all(Radius.circular(16)),
child: _buildBodyDesktop(context) child: _buildBodyMobile(context)
) )
) )
)), )),
@@ -158,319 +197,209 @@ class IdentityCreatorView extends GetWidget<IdentityCreatorController> {
); );
} }
Widget _buildBodyDesktop(BuildContext context) { Widget _buildBodyMobile(BuildContext context) {
return Stack( return GestureDetector(
children: [ onTap: () => controller.clearFocusEditor(context),
Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ child: Stack(
Padding( children: [
padding: const EdgeInsets.only(left: 24, top: 24), Column(children: [
child: Obx(() => Text(controller.actionType.value == IdentityActionType.create Padding(
? AppLocalizations.of(context).new_identity.inCaps padding: const EdgeInsets.only(top: 14),
: AppLocalizations.of(context).edit_identity.inCaps, child: Text(controller.actionType.value == IdentityActionType.create
style: const TextStyle( ? AppLocalizations.of(context).createNewIdentity.inCaps
fontWeight: FontWeight.bold, : AppLocalizations.of(context).edit_identity.inCaps,
fontSize: 24, style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 20, color: Colors.black))),
color: Colors.black)))), const SizedBox(height: 8),
const SizedBox(height: 8), Expanded(
Expanded(child: SingleChildScrollView( child: KeyboardRichText(
controller: controller.scrollController, keyBroadToolbar: RichTextKeyboardToolBar(
physics: const ClampingScrollPhysics(), titleBack: AppLocalizations.of(context).titleFormat,
child: Padding( backgroundKeyboardToolBarColor: AppColor.colorBackgroundKeyboard,
padding: const EdgeInsets.all(24.0), isLandScapeMode: _responsiveUtils.isLandscapeMobile(context),
child: Column(children: [ richTextController: controller.keyboardRichTextController,
Row(crossAxisAlignment: CrossAxisAlignment.start, children: [ titleQuickStyleBottomSheet: AppLocalizations.of(context).titleQuickStyles,
Expanded(child: Obx(() => (IdentityInputFieldBuilder( 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, AppLocalizations.of(context).name,
controller.errorNameIdentity.value, controller.errorNameIdentity.value,
AppLocalizations.of(context).required,
editingController: controller.inputNameIdentityController, editingController: controller.inputNameIdentityController,
focusNode: controller.inputNameIdentityFocusNode, focusNode: controller.inputNameIdentityFocusNode,
isMandatory: true) isMandatory: true)
..addOnChangeInputNameAction((value) => controller.updateNameIdentity(context, value))) ..addOnChangeInputNameAction((value) => controller.updateNameIdentity(context, value)))
.build())), .build()),
const SizedBox(width: 24), const SizedBox(height: 24),
Expanded(child: Obx(() { Obx(() {
if (controller.actionType.value == IdentityActionType.create) { if (controller.actionType.value == IdentityActionType.create) {
return (IdentityDropListFieldBuilder( 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, _imagePaths,
AppLocalizations.of(context).email.inCaps, AppLocalizations.of(context).reply_to,
controller.emailOfIdentity.value, controller.replyToOfIdentity.value,
controller.listEmailAddressDefault) controller.listEmailAddressOfReplyTo)
..addOnSelectEmailAddressDropListAction((emailAddress) => ..addOnSelectEmailAddressDropListAction((newEmailAddress) =>
controller.updateEmailOfIdentity(emailAddress)) controller.updaterReplyToOfIdentity(newEmailAddress)))
).build(); .build()),
} else { const SizedBox(height: 24),
return IdentityFieldNoEditableBuilder( Obx(() => (IdentityInputWithDropListFieldBuilder(
AppLocalizations.of(context).email.inCaps, AppLocalizations.of(context).bcc_to,
controller.emailOfIdentity.value controller.errorBccIdentity.value,
).build(); controller.inputBccIdentityController)
} ..addOnSelectedSuggestionAction((newEmailAddress) {
})), controller.inputBccIdentityController?.text = newEmailAddress?.email ?? '';
]), controller.updateBccOfIdentity(newEmailAddress);
const SizedBox(height: 24), })
Row(crossAxisAlignment: CrossAxisAlignment.start, children: [ ..addOnChangeInputSuggestionAction((pattern) {
Expanded(child: Obx(() => (IdentityDropListFieldBuilder( controller.validateInputBccAddress(context, pattern);
_imagePaths, if (pattern == null || pattern.trim().isEmpty) {
AppLocalizations.of(context).reply_to_address, controller.updateBccOfIdentity(null);
controller.replyToOfIdentity.value, } else {
controller.listEmailAddressOfReplyTo) controller.updateBccOfIdentity(EmailAddress(null, pattern));
..addOnSelectEmailAddressDropListAction((emailAddress) => }
controller.updaterReplyToOfIdentity(emailAddress))) })
.build())), ..addOnSuggestionCallbackAction((pattern) =>
const SizedBox(width: 24), controller.getSuggestionEmailAddress(pattern)))
Expanded(child: Obx(() => (IdentityInputWithDropListFieldBuilder( .build()
AppLocalizations.of(context).bcc_to_address, ),
controller.errorBccIdentity.value, const SizedBox(height: 32),
controller.inputBccIdentityController) Row(
..addOnSelectedSuggestionAction((newEmailAddress) { children: [
controller.inputBccIdentityController?.text = newEmailAddress?.email ?? ''; Text(AppLocalizations.of(context).signature,
controller.updateBccOfIdentity(newEmailAddress); style: const TextStyle(
}) fontWeight: FontWeight.normal,
..addOnChangeInputSuggestionAction((pattern) { fontSize: 14,
controller.validateInputBccAddress(context, pattern); color: AppColor.colorContentEmail,
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,
), ),
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), padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 16),
Expanded( child: Stack(
child: Obx(() => buildTextButton( children: [
controller.actionType.value == IdentityActionType.create if (controller.signatureType.value == SignatureType.plainText)
? AppLocalizations.of(context).create _buildSignaturePlainTextTemplate(context)
: AppLocalizations.of(context).save, else
width: 128, _buildSignatureHtmlTemplate(context)
height: 44, ]
radius: 10,
onTap: () => controller.createNewIdentity(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( Positioned(top: 2, right: 8,
titleBack: AppLocalizations.of(context).titleFormat, child: buildIconWeb(
backgroundKeyboardToolBarColor: AppColor.colorBackgroundKeyboard, iconSize: 24,
isLandScapeMode: _responsiveUtils.isLandscapeMobile(context), icon: SvgPicture.asset(_imagePaths.icComposerClose, fit: BoxFit.fill, color: AppColor.colorDeleteContactIcon),
richTextController: controller.keyboardRichTextController, tooltip: AppLocalizations.of(context).close,
titleQuickStyleBottomSheet: AppLocalizations.of(context).titleQuickStyles, onTap: () => controller.closeView(context)))
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)))
]
); );
} }
@@ -522,45 +451,134 @@ class IdentityCreatorView extends GetWidget<IdentityCreatorController> {
} }
Widget _buildSignatureHtmlTemplate(BuildContext context) { Widget _buildSignatureHtmlTemplate(BuildContext context) {
if (BuildUtils.isWeb) { final htmlEditor = BuildUtils.isWeb
return html_editor_browser.HtmlEditor( ? _buildHtmlEditorWeb(context, controller.contentHtmlEditor ?? '')
key: const Key('signature_html_editor_web'), : _buildHtmlEditor(context, initialContent: controller.contentHtmlEditor ?? '');
controller: controller.signatureHtmlEditorController,
htmlEditorOptions: const html_editor_browser.HtmlEditorOptions( return SizedBox(
hint: '', height: 160,
darkMode: false, child: Column(
), children: [
blockQuotedContent: controller.contentHtmlEditor ?? '<p></p>', if(BuildUtils.isWeb)
htmlToolbarOptions: const html_editor_browser.HtmlToolbarOptions( ToolbarRichTextWebBuilder(richTextWebController: controller.richTextWebController),
toolbarPosition: html_editor_browser.ToolbarPosition.custom, htmlEditor,
), ],
otherOptions: const html_editor_browser.OtherOptions(height: 230), ),
callbacks: html_editor_browser.Callbacks(onInit: () { );
controller.signatureHtmlEditorController.setFullScreen(); }
}, onChangeContent: (String? changed) {
controller.updateContentHtmlEditor(changed); Widget _buildHtmlEditorWeb(BuildContext context, String initContent) {
}, onFocus: () { log('IdentityCreatorView::_buildHtmlEditorWeb(): initContent: $initContent');
FocusManager.instance.primaryFocus?.unfocus(); return Expanded(
Future.delayed(const Duration(milliseconds: 500), () { child: Padding(
controller.signatureHtmlEditorController.setFocus(); padding: EdgeInsets.symmetric(
}); horizontal: _responsiveUtils.isMobile(context) ? 8 : 10),
}), child: html_editor_browser.HtmlEditor(
); key: const Key('identity_create_editor_web'),
} else { controller: controller.richTextWebController.editorController,
return html_editor_mobile.HtmlEditor( htmlEditorOptions: const HtmlEditorOptions(
key: controller.htmlKey, hint: '',
minHeight: 230, darkMode: false,
onCreated: (htmlEditorController) { customBodyCssStyle: bodyCssStyleForEditor),
controller.keyboardRichTextController.onCreateHTMLEditor( blockQuotedContent: initContent,
htmlEditorController, htmlToolbarOptions: const HtmlToolbarOptions(
onFocus: controller.onFocusHTMLEditor, toolbarType: ToolbarType.hide,
onEnterKeyDown: controller.onEnterKeyDown, defaultToolbarButtons: []),
context: context, otherOptions: const OtherOptions(height: 550),
); callbacks: Callbacks(onBeforeCommand: (currentHtml) {
controller.signatureHtmlEditorMobileController = htmlEditorController; 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)),
],
),
),
)
],
);
} }
} }
@@ -14,7 +14,7 @@ extension SignatureTypeExtension on SignatureType {
case SignatureType.plainText: case SignatureType.plainText:
return AppLocalizations.of(context).plain_text; return AppLocalizations.of(context).plain_text;
case SignatureType.htmlTemplate: case SignatureType.htmlTemplate:
return AppLocalizations.of(context).html_template; return AppLocalizations.of(context).html;
} }
} }
} }
@@ -9,6 +9,7 @@ class IdentityInputFieldBuilder {
final String _label; final String _label;
final String? _error; final String? _error;
final String? requiredIndicator;
final TextEditingController? editingController; final TextEditingController? editingController;
final FocusNode? focusNode; final FocusNode? focusNode;
final TextInputType? inputType; final TextInputType? inputType;
@@ -18,7 +19,8 @@ class IdentityInputFieldBuilder {
IdentityInputFieldBuilder( IdentityInputFieldBuilder(
this._label, this._label,
this._error, { this._error,
this.requiredIndicator, {
this.isMandatory = false, this.isMandatory = false,
this.editingController, this.editingController,
this.focusNode, this.focusNode,
@@ -31,10 +33,13 @@ class IdentityInputFieldBuilder {
Widget build() { Widget build() {
return Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ return Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
Text(isMandatory ? '$_label*' : _label, style: const TextStyle( Text(
fontSize: 14, isMandatory
fontWeight: FontWeight.normal, ? '$_label ($requiredIndicator)'
color: AppColor.colorContentEmail)), : _label, style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
color: AppColor.colorContentEmail)),
const SizedBox(height: 8), const SizedBox(height: 8),
(TextFieldBuilder() (TextFieldBuilder()
..onChange((value) => onChangeInputNameAction?.call(value)) ..onChange((value) => onChangeInputNameAction?.call(value))
@@ -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,
),
),
),
],
);
}
}
+29 -6
View File
@@ -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": "Initializing data...",
"@initializing_data": { "@initializing_data": {
"type": "text", "type": "text",
@@ -1178,6 +1178,12 @@
"placeholders_order": [], "placeholders_order": [],
"placeholders": {} "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": "Select the identity or email address you want to use to send an emails",
"@identitiesSettingExplanation": { "@identitiesSettingExplanation": {
"type": "text", "type": "text",
@@ -1202,14 +1208,14 @@
"placeholders_order": [], "placeholders_order": [],
"placeholders": {} "placeholders": {}
}, },
"reply_to_address": "Reply to address", "reply_to": "Reply to",
"@reply_to_address": { "@reply_to": {
"type": "text", "type": "text",
"placeholders_order": [], "placeholders_order": [],
"placeholders": {} "placeholders": {}
}, },
"bcc_to_address": "Bcc to address", "bcc_to": "Bcc to",
"@bcc_to_address": { "@bcc_to": {
"type": "text", "type": "text",
"placeholders_order": [], "placeholders_order": [],
"placeholders": {} "placeholders": {}
@@ -1232,6 +1238,12 @@
"placeholders_order": [], "placeholders_order": [],
"placeholders": {} "placeholders": {}
}, },
"html": "Html",
"@html": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"create": "Create", "create": "Create",
"@create": { "@create": {
"type": "text", "type": "text",
@@ -1244,6 +1256,12 @@
"placeholders_order": [], "placeholders_order": [],
"placeholders": {} "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": "All identities",
"@all_identities": { "@all_identities": {
"type": "text", "type": "text",
@@ -2552,7 +2570,6 @@
"placeholders_order": [], "placeholders_order": [],
"placeholders": {} "placeholders": {}
}, },
<<<<<<< HEAD
"youHaveNewMessages": "You have new messages", "youHaveNewMessages": "You have new messages",
"@youHaveNewMessages": { "@youHaveNewMessages": {
"type": "text", "type": "text",
@@ -2580,5 +2597,11 @@
"type": "text", "type": "text",
"placeholders_order": [], "placeholders_order": [],
"placeholders": {} "placeholders": {}
},
"required": "required",
"@required": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
} }
} }
+31 -6
View File
@@ -1212,6 +1212,13 @@ class AppLocalizations {
name: 'identities'); name: 'identities');
} }
String get setDefaultIdentity {
return Intl.message(
'Set as default identity',
name: 'setDefaultIdentity'
);
}
String get identitiesSettingExplanation { String get identitiesSettingExplanation {
return Intl.message( return Intl.message(
'Select the identity or email address you want to use to send an emails', 'Select the identity or email address you want to use to send an emails',
@@ -1235,16 +1242,16 @@ class AppLocalizations {
name: 'name'); name: 'name');
} }
String get reply_to_address { String get reply_to {
return Intl.message( return Intl.message(
'Reply to address', 'Reply to',
name: 'reply_to_address'); name: 'reply_to');
} }
String get bcc_to_address { String get bcc_to {
return Intl.message( return Intl.message(
'Bcc to address', 'Bcc to',
name: 'bcc_to_address'); name: 'bcc_to');
} }
String get signature { String get signature {
@@ -1265,6 +1272,12 @@ class AppLocalizations {
name: 'html_template'); name: 'html_template');
} }
String get html {
return Intl.message(
'Html',
name: 'html');
}
String get create { String get create {
return Intl.message( return Intl.message(
'Create', 'Create',
@@ -1277,6 +1290,12 @@ class AppLocalizations {
name: 'you_have_created_a_new_identity'); 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 { String get all_identities {
return Intl.message( return Intl.message(
'All identities', 'All identities',
@@ -2683,4 +2702,10 @@ class AppLocalizations {
name: 'enableSpamReport', name: 'enableSpamReport',
); );
} }
String get required {
return Intl.message(
'required',
name: 'required');
}
} }
-9
View File
@@ -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/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_bindings.dart';
import 'package:tmail_ui_user/features/home/presentation/home_view.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/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_bindings.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/rules_filter_creator_view.dart' deferred as rules_filter_creator; 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.loadLibrary,
() => contact_view.ContactView()), () => contact_view.ContactView()),
binding: ContactBindings()), binding: ContactBindings()),
GetPage(
name: AppRoutes.identityCreator,
opaque: false,
page: () => DeferredWidget(
identity_creator.loadLibrary,
() => identity_creator.IdentityCreatorView()),
binding: IdentityCreatorBindings()),
GetPage( GetPage(
name: AppRoutes.rulesFilterCreator, name: AppRoutes.rulesFilterCreator,
opaque: false, opaque: false,