add bullets and align composer tablet
This commit is contained in:
@@ -27,6 +27,7 @@ class DropDownButtonWidget<T> extends StatelessWidget {
|
|||||||
final Widget? iconArrowDown;
|
final Widget? iconArrowDown;
|
||||||
final Color? colorButton;
|
final Color? colorButton;
|
||||||
final String tooltip;
|
final String tooltip;
|
||||||
|
final double? dropdownWidth;
|
||||||
|
|
||||||
const DropDownButtonWidget({
|
const DropDownButtonWidget({
|
||||||
Key? key,
|
Key? key,
|
||||||
@@ -41,6 +42,7 @@ class DropDownButtonWidget<T> extends StatelessWidget {
|
|||||||
this.radiusButton = 10,
|
this.radiusButton = 10,
|
||||||
this.opacity = 1.0,
|
this.opacity = 1.0,
|
||||||
this.iconArrowDown,
|
this.iconArrowDown,
|
||||||
|
this.dropdownWidth,
|
||||||
this.colorButton = Colors.white,
|
this.colorButton = Colors.white,
|
||||||
this.tooltip = '',
|
this.tooltip = '',
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
@@ -147,6 +149,7 @@ class DropDownButtonWidget<T> extends StatelessWidget {
|
|||||||
scrollbarRadius: const Radius.circular(40),
|
scrollbarRadius: const Radius.circular(40),
|
||||||
scrollbarThickness: 6,
|
scrollbarThickness: 6,
|
||||||
onMenuStateChange: onMenuStateChange,
|
onMenuStateChange: onMenuStateChange,
|
||||||
|
dropdownWidth: dropdownWidth,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -11,10 +11,13 @@ import 'package:jmap_dart_client/jmap/identities/identity.dart';
|
|||||||
import 'package:model/model.dart';
|
import 'package:model/model.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/drop_down_button_widget.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/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/header_style_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/rich_text_style_type.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/drop_down_menu_header_style_widget.dart';
|
||||||
@@ -494,6 +497,7 @@ class ComposerView extends GetWidget<ComposerController>
|
|||||||
Widget _buildToolbarRichTextWidget(BuildContext context) {
|
Widget _buildToolbarRichTextWidget(BuildContext context) {
|
||||||
return Obx(() {
|
return Obx(() {
|
||||||
final richTextMobileTabletController = controller.richTextMobileTabletController;
|
final richTextMobileTabletController = controller.richTextMobileTabletController;
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.only(left: 20, top: 8, bottom: 8),
|
padding: const EdgeInsets.only(left: 20, top: 8, bottom: 8),
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
@@ -503,16 +507,16 @@ class ComposerView extends GetWidget<ComposerController>
|
|||||||
children: [
|
children: [
|
||||||
DropDownMenuHeaderStyleWidget(
|
DropDownMenuHeaderStyleWidget(
|
||||||
icon: buildWrapIconStyleText(
|
icon: buildWrapIconStyleText(
|
||||||
isSelected: richTextMobileTabletController.isMenuHeaderStyleOpen,
|
isSelected: richTextMobileTabletController.isMenuHeaderStyleOpen,
|
||||||
icon: SvgPicture.asset(RichTextStyleType.headerStyle.getIcon(imagePaths),
|
icon: SvgPicture.asset(RichTextStyleType.headerStyle.getIcon(imagePaths),
|
||||||
color: AppColor.colorDefaultRichTextButton,
|
color: AppColor.colorDefaultRichTextButton,
|
||||||
fit: BoxFit.fill),
|
fit: BoxFit.fill),
|
||||||
padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 5),
|
padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 5),
|
||||||
),
|
),
|
||||||
items: HeaderStyleType.values,
|
items: HeaderStyleType.values,
|
||||||
onChanged: (newStyle) => richTextMobileTabletController.applyHeaderStyle(newStyle)),
|
onChanged: (newStyle) => richTextMobileTabletController.applyHeaderStyle(newStyle)),
|
||||||
Container(
|
Container(
|
||||||
width: 200,
|
width: 120,
|
||||||
padding: const EdgeInsets.only(right: 2, left: 8),
|
padding: const EdgeInsets.only(right: 2, left: 8),
|
||||||
child: DropDownButtonWidget<SafeFont>(
|
child: DropDownButtonWidget<SafeFont>(
|
||||||
items: SafeFont.values,
|
items: SafeFont.values,
|
||||||
@@ -520,6 +524,7 @@ class ComposerView extends GetWidget<ComposerController>
|
|||||||
onChanged: (newFont) => richTextMobileTabletController.applyNewFontStyle(newFont),
|
onChanged: (newFont) => richTextMobileTabletController.applyNewFontStyle(newFont),
|
||||||
heightItem: 38,
|
heightItem: 38,
|
||||||
sizeIconChecked: 16,
|
sizeIconChecked: 16,
|
||||||
|
dropdownWidth: 200,
|
||||||
radiusButton: 5,
|
radiusButton: 5,
|
||||||
colorButton: Colors.white,
|
colorButton: Colors.white,
|
||||||
supportSelectionIcon: true)),
|
supportSelectionIcon: true)),
|
||||||
@@ -564,6 +569,46 @@ class ComposerView extends GetWidget<ComposerController>
|
|||||||
isSelected: richTextMobileTabletController.isTextStyleTypeSelected(RichTextStyleType.strikeThrough),
|
isSelected: richTextMobileTabletController.isTextStyleTypeSelected(RichTextStyleType.strikeThrough),
|
||||||
onTap: () => richTextMobileTabletController.applyRichTextStyle(context, RichTextStyleType.strikeThrough))
|
onTap: () => richTextMobileTabletController.applyRichTextStyle(context, RichTextStyleType.strikeThrough))
|
||||||
])),
|
])),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 8),
|
||||||
|
child: PopupMenuOverlayWidget(
|
||||||
|
controller: richTextMobileTabletController.menuParagraphController,
|
||||||
|
listButtonAction: ParagraphType.values
|
||||||
|
.map((paragraph) => paragraph.buildButtonWidget(
|
||||||
|
context,
|
||||||
|
imagePaths,
|
||||||
|
(paragraph) => richTextMobileTabletController.applyParagraphType(paragraph)))
|
||||||
|
.toList(),
|
||||||
|
iconButton: buildWrapIconStyleText(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 5),
|
||||||
|
spacing: 3,
|
||||||
|
isSelected: richTextMobileTabletController.focusMenuParagraph.value,
|
||||||
|
icon: buildIcon(
|
||||||
|
path: richTextMobileTabletController.selectedParagraph.value.getIcon(imagePaths),
|
||||||
|
color: AppColor.colorDefaultRichTextButton,
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 8),
|
||||||
|
child: PopupMenuOverlayWidget(
|
||||||
|
controller: richTextMobileTabletController.menuOrderListController,
|
||||||
|
listButtonAction: OrderListType.values
|
||||||
|
.map((orderType) => orderType.buildButtonWidget(
|
||||||
|
context,
|
||||||
|
imagePaths,
|
||||||
|
(orderType) => richTextMobileTabletController.applyOrderListType(orderType)))
|
||||||
|
.toList(),
|
||||||
|
iconButton: buildWrapIconStyleText(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 5),
|
||||||
|
spacing: 3,
|
||||||
|
isSelected: richTextMobileTabletController.focusMenuOrderList.value,
|
||||||
|
icon: buildIcon(
|
||||||
|
path: richTextMobileTabletController.selectedOrderList.value.getIcon(imagePaths),
|
||||||
|
color: AppColor.colorDefaultRichTextButton,
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
+48
-4
@@ -1,5 +1,6 @@
|
|||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:core/core.dart';
|
import 'package:core/core.dart';
|
||||||
|
import 'package:custom_pop_up_menu/custom_pop_up_menu.dart';
|
||||||
import 'package:dartz/dartz.dart';
|
import 'package:dartz/dartz.dart';
|
||||||
import 'package:enough_html_editor/enough_html_editor.dart';
|
import 'package:enough_html_editor/enough_html_editor.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@@ -11,6 +12,8 @@ import 'package:tmail_ui_user/features/composer/presentation/model/dropdown_menu
|
|||||||
import 'package:tmail_ui_user/features/composer/presentation/model/header_style_type.dart';
|
import 'package:tmail_ui_user/features/composer/presentation/model/header_style_type.dart';
|
||||||
import 'package:tmail_ui_user/features/composer/presentation/model/image_source.dart';
|
import 'package:tmail_ui_user/features/composer/presentation/model/image_source.dart';
|
||||||
import 'package:tmail_ui_user/features/composer/presentation/model/inline_image.dart';
|
import 'package:tmail_ui_user/features/composer/presentation/model/inline_image.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/rich_text_style_type.dart';
|
||||||
|
|
||||||
class RichTextMobileTabletController extends BaseRichTextController {
|
class RichTextMobileTabletController extends BaseRichTextController {
|
||||||
@@ -24,6 +27,26 @@ class RichTextMobileTabletController extends BaseRichTextController {
|
|||||||
|
|
||||||
bool get isMenuHeaderStyleOpen => menuHeaderStyleStatus.value == DropdownMenuFontStatus.open;
|
bool get isMenuHeaderStyleOpen => menuHeaderStyleStatus.value == DropdownMenuFontStatus.open;
|
||||||
|
|
||||||
|
final selectedParagraph = ParagraphType.alignLeft.obs;
|
||||||
|
final selectedOrderList = OrderListType.bulletedList.obs;
|
||||||
|
|
||||||
|
final focusMenuOrderList = RxBool(false);
|
||||||
|
final focusMenuParagraph = RxBool(false);
|
||||||
|
|
||||||
|
final menuParagraphController = CustomPopupMenuController();
|
||||||
|
final menuOrderListController = CustomPopupMenuController();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onReady() {
|
||||||
|
super.onReady();
|
||||||
|
menuParagraphController.addListener(() {
|
||||||
|
focusMenuParagraph.value = menuParagraphController.menuIsShowing;
|
||||||
|
});
|
||||||
|
menuOrderListController.addListener(() {
|
||||||
|
focusMenuOrderList.value = menuOrderListController.menuIsShowing;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void listenHtmlEditorApi() {
|
void listenHtmlEditorApi() {
|
||||||
htmlEditorApi?.onFormatSettingsChanged = (formatSettings) {
|
htmlEditorApi?.onFormatSettingsChanged = (formatSettings) {
|
||||||
listTextStyleApply.clear();
|
listTextStyleApply.clear();
|
||||||
@@ -63,11 +86,13 @@ class RichTextMobileTabletController extends BaseRichTextController {
|
|||||||
openMenuSelectColor(context, selectedTextBackgroundColor.value,
|
openMenuSelectColor(context, selectedTextBackgroundColor.value,
|
||||||
onResetToDefault: () {
|
onResetToDefault: () {
|
||||||
selectedTextBackgroundColor.value = Colors.white;
|
selectedTextBackgroundColor.value = Colors.white;
|
||||||
htmlEditorApi?.setColorTextBackground(selectedTextBackgroundColor.value);
|
htmlEditorApi
|
||||||
|
?.setColorTextBackground(selectedTextBackgroundColor.value);
|
||||||
}, onSelectColor: (selectedColor) {
|
}, onSelectColor: (selectedColor) {
|
||||||
final newColor = selectedColor ?? Colors.white;
|
final newColor = selectedColor ?? Colors.white;
|
||||||
selectedTextBackgroundColor.value = newColor;
|
selectedTextBackgroundColor.value = newColor;
|
||||||
htmlEditorApi?.setColorTextBackground(selectedTextBackgroundColor.value);
|
htmlEditorApi
|
||||||
|
?.setColorTextBackground(selectedTextBackgroundColor.value);
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case RichTextStyleType.bold:
|
case RichTextStyleType.bold:
|
||||||
@@ -105,11 +130,12 @@ class RichTextMobileTabletController extends BaseRichTextController {
|
|||||||
|
|
||||||
Future<Tuple2<String, List<Attachment>>> refactorContentHasInlineImage(
|
Future<Tuple2<String, List<Attachment>>> refactorContentHasInlineImage(
|
||||||
String emailContent,
|
String emailContent,
|
||||||
Map<String, Attachment> mapInlineAttachments
|
Map<String, Attachment> mapInlineAttachments,
|
||||||
) async {
|
) async {
|
||||||
final document = parse(emailContent);
|
final document = parse(emailContent);
|
||||||
final listImgTag = document.querySelectorAll('img[src^="data:image/"]');
|
final listImgTag = document.querySelectorAll('img[src^="data:image/"]');
|
||||||
final listInlineAttachment = await Future.wait(listImgTag.map((imgTag) async {
|
final listInlineAttachment =
|
||||||
|
await Future.wait(listImgTag.map((imgTag) async {
|
||||||
final cid = imgTag.attributes['id'];
|
final cid = imgTag.attributes['id'];
|
||||||
log('RichTextMobileTabletController::refactorContentHasInlineImage(): cid: $cid');
|
log('RichTextMobileTabletController::refactorContentHasInlineImage(): cid: $cid');
|
||||||
imgTag.attributes['src'] = 'cid:$cid';
|
imgTag.attributes['src'] = 'cid:$cid';
|
||||||
@@ -154,4 +180,22 @@ class RichTextMobileTabletController extends BaseRichTextController {
|
|||||||
htmlEditorApi?.formatHeader(styleSelected.styleValue);
|
htmlEditorApi?.formatHeader(styleSelected.styleValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void applyParagraphType(ParagraphType newParagraph) {
|
||||||
|
selectedParagraph.value = newParagraph;
|
||||||
|
htmlEditorApi?.execCommand(newParagraph.commandAction);
|
||||||
|
menuParagraphController.hideMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
void applyOrderListType(OrderListType newOrderList) {
|
||||||
|
selectedOrderList.value = newOrderList;
|
||||||
|
htmlEditorApi?.execCommand(newOrderList.commandAction);
|
||||||
|
menuOrderListController.hideMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onClose() {
|
||||||
|
menuParagraphController.dispose();
|
||||||
|
menuOrderListController.dispose();
|
||||||
|
super.onClose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user