TF-3427 Fix subject was not in print & click outside context menu can not close

Signed-off-by: dab246 <tdvu@linagora.com>
This commit is contained in:
dab246
2025-01-17 18:30:29 +07:00
committed by Dat H. Pham
parent 778c138a10
commit 395b24e58f
18 changed files with 356 additions and 261 deletions
@@ -4,6 +4,7 @@ import 'dart:math';
import 'package:collection/collection.dart';
import 'package:core/core.dart';
import 'package:custom_pop_up_menu/custom_pop_up_menu.dart';
import 'package:dartz/dartz.dart';
import 'package:desktop_drop/desktop_drop.dart';
import 'package:dio/dio.dart';
@@ -184,6 +185,7 @@ class ComposerController extends BaseController
RichTextMobileTabletController? richTextMobileTabletController;
RichTextWebController? richTextWebController;
CustomPopupMenuController? menuMoreOptionController;
final ScrollController scrollController = ScrollController();
final ScrollController scrollControllerEmailAddress = ScrollController();
@@ -237,6 +239,7 @@ class ComposerController extends BaseController
if (PlatformInfo.isWeb) {
richTextWebController = getBinding<RichTextWebController>();
responsiveContainerKey = GlobalKey();
menuMoreOptionController = CustomPopupMenuController();
} else {
richTextMobileTabletController = getBinding<RichTextMobileTabletController>();
}
@@ -277,6 +280,8 @@ class ComposerController extends BaseController
if (PlatformInfo.isWeb) {
richTextWebController = null;
responsiveContainerKey = null;
menuMoreOptionController?.dispose();
menuMoreOptionController = null;
} else {
richTextMobileTabletController = null;
}
@@ -476,7 +481,7 @@ class ComposerController extends BaseController
outboxMailboxId: mailboxDashBoardController.outboxMailbox?.mailboxId,
sentMailboxId: mailboxDashBoardController.mapDefaultMailboxIdByRole[PresentationMailbox.roleSent],
draftsMailboxId: mailboxDashBoardController.mapDefaultMailboxIdByRole[PresentationMailbox.roleDrafts],
draftsEmailId: _getDraftEmailId(),
draftsEmailId: getDraftEmailId(),
answerForwardEmailId: composerArguments.value!.presentationEmail?.id,
unsubscribeEmailId: composerArguments.value!.previousEmailId,
messageId: composerArguments.value!.messageId,
@@ -1046,7 +1051,7 @@ class ComposerController extends BaseController
inlineAttachments: uploadController.mapInlineAttachments,
outboxMailboxId: mailboxDashBoardController.outboxMailbox?.mailboxId,
sentMailboxId: mailboxDashBoardController.mapDefaultMailboxIdByRole[PresentationMailbox.roleSent],
draftsEmailId: _getDraftEmailId(),
draftsEmailId: getDraftEmailId(),
answerForwardEmailId: composerArguments.value!.presentationEmail?.id,
unsubscribeEmailId: composerArguments.value!.previousEmailId,
messageId: composerArguments.value!.messageId,
@@ -2000,6 +2005,9 @@ class ComposerController extends BaseController
FocusManager.instance.primaryFocus?.unfocus();
richTextWebController?.editorController.setFocus();
richTextWebController?.closeAllMenuPopup();
if (menuMoreOptionController?.menuIsShowing == true) {
menuMoreOptionController?.hideMenu();
}
}
void handleOnMouseDownHtmlEditorWeb() {
@@ -2277,7 +2285,7 @@ class ComposerController extends BaseController
popBack();
final emailContent = await getContentInEditor();
final draftEmailId = _getDraftEmailId();
final draftEmailId = getDraftEmailId();
log('ComposerController::_handleSaveMessageToDraft: draftEmailId = $draftEmailId');
final cancelToken = CancelToken();
final resultState = await _showSavingMessageToDraftsDialog(
@@ -2306,7 +2314,7 @@ class ComposerController extends BaseController
}
}
EmailId? _getDraftEmailId() {
EmailId? getDraftEmailId() {
if (_emailIdEditing != null &&
_emailIdEditing != composerArguments.value!.presentationEmail?.id) {
return _emailIdEditing;
@@ -48,6 +48,7 @@ class ComposerView extends GetWidget<ComposerController> {
children: [
if (controller.responsiveUtils.isLandscapeMobile(context))
Obx(() => LandscapeAppBarComposerWidget(
imagePaths: controller.imagePaths,
isSendButtonEnabled: controller.isEnableEmailSendButton.value,
onCloseViewAction: () => controller.handleClickCloseComposer(context),
sendMessageAction: () => controller.handleClickSendButton(context),
@@ -73,6 +74,7 @@ class ComposerView extends GetWidget<ComposerController> {
))
else
Obx(() => AppBarComposerWidget(
imagePaths: controller.imagePaths,
isSendButtonEnabled: controller.isEnableEmailSendButton.value,
onCloseViewAction: () => controller.handleClickCloseComposer(context),
sendMessageAction: () => controller.handleClickSendButton(context),
@@ -1,11 +1,9 @@
import 'package:core/presentation/extensions/color_extension.dart';
import 'package:core/presentation/views/responsive/responsive_widget.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:model/email/prefix_email_address.dart';
import 'package:pointer_interceptor/pointer_interceptor.dart';
import 'package:tmail_ui_user/features/base/widget/popup_item_widget.dart';
import 'package:tmail_ui_user/features/composer/presentation/composer_controller.dart';
import 'package:tmail_ui_user/features/composer/presentation/extensions/composer_print_draft_extension.dart';
import 'package:tmail_ui_user/features/composer/presentation/model/prefix_recipient_state.dart';
@@ -26,8 +24,6 @@ import 'package:tmail_ui_user/features/composer/presentation/widgets/web/from_co
import 'package:tmail_ui_user/features/composer/presentation/widgets/web/local_file_drop_zone_widget.dart';
import 'package:tmail_ui_user/features/composer/presentation/widgets/web/mobile_responsive_app_bar_composer_widget.dart';
import 'package:tmail_ui_user/features/composer/presentation/widgets/web/toolbar_rich_text_builder.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
class ComposerView extends GetWidget<ComposerController> {
@@ -50,18 +46,18 @@ class ComposerView extends GetWidget<ComposerController> {
isFormattingOptionsEnabled: controller.richTextWebController!.isFormattingOptionsEnabled,
openRichToolbarAction: controller.richTextWebController!.toggleFormattingOptions,
isSendButtonEnabled: controller.isEnableEmailSendButton.value,
hasRequestReadReceipt: controller.hasRequestReadReceipt.value,
isPrintDraftEnabled: controller.isEmailChanged.value,
menuMoreOptionController: controller.menuMoreOptionController!,
onCloseViewAction: () => controller.handleClickCloseComposer(context),
attachFileAction: () => controller.openFilePickerByType(context, FileType.any),
insertImageAction: () => controller.insertImage(context, constraints.maxWidth),
sendMessageAction: () => controller.handleClickSendButton(context),
openContextMenuAction: (position) {
controller.openPopupMenuAction(
context,
position,
_createMoreOptionPopupItems(context),
radius: ComposerStyle.popupMenuRadius
);
},
toggleCodeViewAction: controller.richTextWebController!.toggleCodeView,
printDraftAction: () => controller.printDraft(context),
toggleRequestReadReceiptAction: () => controller.toggleRequestReadReceipt(context),
saveToDraftsAction: () => controller.handleClickSaveAsDraftsButton(context),
deleteComposerAction: () => controller.handleClickDeleteComposer(context),
)),
ConstrainedBox(
constraints: BoxConstraints(
@@ -523,14 +519,10 @@ class ComposerView extends GetWidget<ComposerController> {
saveToDraftAction: () => controller.handleClickSaveAsDraftsButton(context),
sendMessageAction: () => controller.handleClickSendButton(context),
isPrintDraftEnabled: controller.isEmailChanged.isTrue,
openContextMenuAction: (position) {
controller.openPopupMenuAction(
context,
position,
_createMoreOptionPopupItemsOnDesktop(context),
radius: ComposerStyle.popupMenuRadius,
);
},
toggleCodeViewAction: controller.richTextWebController!.toggleCodeView,
menuMoreOptionController: controller.menuMoreOptionController!,
printDraftAction: () => controller.printDraft(context),
toggleRequestReadReceiptAction: () => controller.toggleRequestReadReceipt(context),
)),
],
),
@@ -810,14 +802,10 @@ class ComposerView extends GetWidget<ComposerController> {
saveToDraftAction: () => controller.handleClickSaveAsDraftsButton(context),
sendMessageAction: () => controller.handleClickSendButton(context),
isPrintDraftEnabled: controller.isEmailChanged.isTrue,
openContextMenuAction: (position) {
controller.openPopupMenuAction(
context,
position,
_createMoreOptionPopupItemsOnDesktop(context),
radius: ComposerStyle.popupMenuRadius,
);
},
toggleCodeViewAction: controller.richTextWebController!.toggleCodeView,
menuMoreOptionController: controller.menuMoreOptionController!,
printDraftAction: () => controller.printDraft(context),
toggleRequestReadReceiptAction: () => controller.toggleRequestReadReceipt(context),
)),
],
),
@@ -877,136 +865,4 @@ class ComposerView extends GetWidget<ComposerController> {
)
);
}
List<PopupMenuEntry> _createMoreOptionPopupItems(BuildContext context) {
return [
PopupMenuItem(
padding: EdgeInsets.zero,
child: PopupItemWidget(
controller.imagePaths.icStyleCodeView,
AppLocalizations.of(context).embedCode,
styleName: ComposerStyle.popupItemTextStyle,
colorIcon: ComposerStyle.popupItemIconColor,
padding: ComposerStyle.popupItemPadding,
selectedIcon: controller.imagePaths.icFilterSelected,
isSelected: controller.richTextWebController?.codeViewEnabled,
onCallbackAction: () {
popBack();
controller.richTextWebController?.toggleCodeView();
}
)
),
PopupMenuItem(
padding: EdgeInsets.zero,
child: PopupItemWidget(
controller.imagePaths.icReadReceipt,
AppLocalizations.of(context).requestReadReceipt,
styleName: ComposerStyle.popupItemTextStyle,
padding: ComposerStyle.popupItemPadding,
colorIcon: ComposerStyle.popupItemIconColor,
selectedIcon: controller.imagePaths.icFilterSelected,
isSelected: controller.hasRequestReadReceipt.value,
onCallbackAction: () {
popBack();
controller.toggleRequestReadReceipt(context);
}
)
),
if (controller.isEmailChanged.isTrue)
PopupMenuItem(
padding: EdgeInsets.zero,
child: PopupItemWidget(
controller.imagePaths.icPrinter,
AppLocalizations.of(context).print,
colorIcon: AppColor.steelGrayA540,
styleName: ComposerStyle.popupItemTextStyle,
padding: ComposerStyle.popupItemPadding,
onCallbackAction: () {
popBack();
controller.printDraft(context);
},
),
),
PopupMenuItem(
padding: EdgeInsets.zero,
child: PopupItemWidget(
controller.imagePaths.icSaveToDraft,
AppLocalizations.of(context).saveAsDraft,
colorIcon: ComposerStyle.popupItemIconColor,
styleName: ComposerStyle.popupItemTextStyle,
padding: ComposerStyle.popupItemPadding,
onCallbackAction: () {
popBack();
controller.handleClickSaveAsDraftsButton(context);
}
)
),
PopupMenuItem(
padding: EdgeInsets.zero,
child: PopupItemWidget(
controller.imagePaths.icDeleteMailbox,
AppLocalizations.of(context).delete,
colorIcon: ComposerStyle.popupItemIconColor,
styleName: ComposerStyle.popupItemTextStyle,
padding: ComposerStyle.popupItemPadding,
onCallbackAction: () {
popBack();
controller.handleClickDeleteComposer(context);
},
)
),
];
}
List<PopupMenuEntry> _createMoreOptionPopupItemsOnDesktop(BuildContext context) {
return [
PopupMenuItem(
padding: EdgeInsets.zero,
child: PopupItemWidget(
controller.imagePaths.icStyleCodeView,
AppLocalizations.of(context).embedCode,
styleName: ComposerStyle.popupItemTextStyle,
colorIcon: ComposerStyle.popupItemIconColor,
padding: ComposerStyle.popupItemPadding,
selectedIcon: controller.imagePaths.icFilterSelected,
isSelected: controller.richTextWebController?.codeViewEnabled,
onCallbackAction: () {
popBack();
controller.richTextWebController?.toggleCodeView();
},
),
),
PopupMenuItem(
padding: EdgeInsets.zero,
child: PopupItemWidget(
controller.imagePaths.icReadReceipt,
AppLocalizations.of(context).requestReadReceipt,
styleName: ComposerStyle.popupItemTextStyle,
padding: ComposerStyle.popupItemPadding,
colorIcon: ComposerStyle.popupItemIconColor,
selectedIcon: controller.imagePaths.icFilterSelected,
isSelected: controller.hasRequestReadReceipt.value,
onCallbackAction: () {
popBack();
controller.toggleRequestReadReceipt(context);
},
),
),
if (controller.isEmailChanged.isTrue)
PopupMenuItem(
padding: EdgeInsets.zero,
child: PopupItemWidget(
controller.imagePaths.icPrinter,
AppLocalizations.of(context).print,
colorIcon: ComposerStyle.popupItemIconColor,
styleName: ComposerStyle.popupItemTextStyle,
padding: ComposerStyle.popupItemPadding,
onCallbackAction: () {
popBack();
controller.printDraft(context);
},
),
),
];
}
}
@@ -4,6 +4,7 @@ import 'package:core/presentation/extensions/color_extension.dart';
import 'package:core/utils/app_logger.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:model/email/email_action_type.dart';
import 'package:model/extensions/identity_extension.dart';
import 'package:model/extensions/list_email_address_extension.dart';
import 'package:model/extensions/presentation_email_extension.dart';
@@ -13,6 +14,7 @@ import 'package:tmail_ui_user/features/composer/presentation/composer_controller
import 'package:tmail_ui_user/features/composer/presentation/model/draft_email_print.dart';
import 'package:tmail_ui_user/features/composer/presentation/widgets/web/print_draft_dialog_view.dart';
import 'package:tmail_ui_user/features/email/domain/state/print_email_state.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/extensions/datetime_extension.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
extension ComposerPrintDraftExtension on ComposerController {
@@ -59,8 +61,26 @@ extension ComposerPrintDraftExtension on ComposerController {
required Locale locale,
required String emailContent,
}) {
final presentationEmail = composerArguments.value!.presentationEmail;
final presentationEmail = composerArguments.value?.presentationEmail;
final emailActionType = composerArguments.value?.emailActionType;
String receiveTime = '';
if (emailActionType == EmailActionType.editDraft) {
receiveTime = presentationEmail?.getReceivedAt(
locale.toLanguageTag(),
pattern: presentationEmail.receivedAt
?.value
.toLocal()
.toPatternForPrinting(locale.toLanguageTag()),
) ?? '';
} else {
final currentTime = DateTime.now();
receiveTime = currentTime.formatDate(
locale: locale.toLanguageTag(),
pattern: currentTime.toPatternForPrinting(locale.toLanguageTag()),
);
}
log('ComposerPrintDraftExtension::_showPrintDraftsDialog:receiveTime = $receiveTime | emailActionType = $emailActionType');
final childWidget = PointerInterceptor(
child: PrintDraftDialogView(
emailPrint: DraftEmailPrint(
@@ -68,7 +88,6 @@ extension ComposerPrintDraftExtension on ComposerController {
userName: mailboxDashBoardController.userEmail,
attachments: uploadController.allAttachmentsUploaded,
emailContent: emailContent,
locale: locale.toLanguageTag(),
fromPrefix: appLocalizations.from_email_address_prefix,
toPrefix: appLocalizations.to_email_address_prefix,
ccPrefix: appLocalizations.cc_email_address_prefix,
@@ -79,14 +98,8 @@ extension ComposerPrintDraftExtension on ComposerController {
ccAddress: listCcEmailAddress.toSet().toEscapeHtmlStringUseCommaSeparator(),
bccAddress: listBccEmailAddress.toSet().toEscapeHtmlStringUseCommaSeparator(),
sender: identitySelected.value?.toEmailAddress(),
receiveTime: presentationEmail?.getReceivedAt(
locale.toLanguageTag(),
pattern: presentationEmail.receivedAt
?.value
.toLocal()
.toPatternForPrinting(locale.toLanguageTag()),
) ?? '',
subject: presentationEmail?.subject,
receiveTime: receiveTime,
subject: subjectEmail.value ?? '',
),
printEmailInteractor: printEmailInteractor,
),
@@ -324,6 +324,7 @@ mixin RichTextButtonMixin {
_imagePaths,
(paragraph) => richTextController.applyParagraphType(paragraph)))
.toList(),
padding: const EdgeInsets.symmetric(horizontal: 5),
iconButton: buildWrapIconStyleText(
padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 5),
spacing: 3,
@@ -344,6 +345,7 @@ mixin RichTextButtonMixin {
_imagePaths,
(orderType) => richTextController.applyOrderListType(orderType)))
.toList(),
padding: const EdgeInsets.symmetric(horizontal: 5),
iconButton: buildWrapIconStyleText(
padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 5),
spacing: 3,
@@ -6,7 +6,6 @@ class DraftEmailPrint extends EmailPrint {
required super.appName,
required super.userName,
required super.emailContent,
required super.locale,
required super.fromPrefix,
required super.toPrefix,
required super.ccPrefix,
@@ -10,11 +10,19 @@ class MobileAppBarComposerWidgetStyle {
static const double richTextIconSize = 28;
static const Color backgroundColor = AppColor.colorComposerAppBar;
static const Color iconColor = AppColor.colorMobileRichButtonComposer;
static const Color iconColor = AppColor.steelGrayA540;
static const Color popupItemIconColor = AppColor.steelGrayA540;
static const Color selectedBackgroundColor = AppColor.colorSelected;
static const Color selectedIconColor = AppColor.primaryColor;
static const Color selectedIconColor = AppColor.blue700;
static const EdgeInsetsGeometry padding = EdgeInsetsDirectional.symmetric(horizontal: 12);
static const EdgeInsetsGeometry iconPadding = EdgeInsetsDirectional.all(3);
static const EdgeInsetsGeometry richTextIconPadding = EdgeInsetsDirectional.all(5);
static const EdgeInsetsGeometry popupItemPadding = EdgeInsetsDirectional.symmetric(horizontal: 12);
static const TextStyle popupItemTextStyle = TextStyle(
color: Colors.black,
fontSize: 16,
fontWeight: FontWeight.w500,
);
}
@@ -22,9 +22,16 @@ class BottomBarComposerWidgetStyle {
static const EdgeInsetsGeometry iconPadding = EdgeInsetsDirectional.all(5);
static const EdgeInsetsGeometry sendButtonPadding = EdgeInsetsDirectional.symmetric(vertical: 8, horizontal: 24);
static const EdgeInsetsGeometry richTextIconPadding = EdgeInsetsDirectional.all(2);
static const EdgeInsetsGeometry popupItemPadding = EdgeInsetsDirectional.symmetric(horizontal: 12);
static const TextStyle sendButtonTextStyle = TextStyle(
fontWeight: FontWeight.w500,
fontSize: 15,
color: Colors.white,
);
static const TextStyle popupItemTextStyle = TextStyle(
color: Colors.black,
fontSize: 16,
fontWeight: FontWeight.w500,
);
}
@@ -1,13 +1,14 @@
import 'package:core/presentation/resources/image_paths.dart';
import 'package:core/presentation/views/button/tmail_button_widget.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:tmail_ui_user/features/composer/presentation/styles/mobile_app_bar_composer_widget_style.dart';
import 'package:tmail_ui_user/features/composer/presentation/widgets/web/mobile_responsive_app_bar_composer_widget.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
typedef OnOpenContextMenuAction = Function(RelativeRect position);
class AppBarComposerWidget extends StatelessWidget {
final ImagePaths imagePaths;
final bool isSendButtonEnabled;
final bool isNetworkConnectionAvailable;
final VoidCallback onCloseViewAction;
@@ -17,10 +18,9 @@ class AppBarComposerWidget extends StatelessWidget {
final VoidCallback openRichToolbarAction;
final OnOpenContextMenuAction openContextMenuAction;
final _imagePaths = Get.find<ImagePaths>();
AppBarComposerWidget({
const AppBarComposerWidget({
super.key,
required this.imagePaths,
required this.isSendButtonEnabled,
required this.onCloseViewAction,
required this.sendMessageAction,
@@ -40,7 +40,7 @@ class AppBarComposerWidget extends StatelessWidget {
child: Row(
children: [
TMailButtonWidget.fromIcon(
icon: _imagePaths.icCancel,
icon: imagePaths.icCancel,
backgroundColor: Colors.transparent,
tooltipMessage: AppLocalizations.of(context).saveAndClose,
iconSize: MobileAppBarComposerWidgetStyle.iconSize,
@@ -49,7 +49,7 @@ class AppBarComposerWidget extends StatelessWidget {
),
const Spacer(),
TMailButtonWidget.fromIcon(
icon: _imagePaths.icRichToolbar,
icon: imagePaths.icRichToolbar,
iconColor: MobileAppBarComposerWidgetStyle.iconColor,
backgroundColor: Colors.transparent,
iconSize: MobileAppBarComposerWidgetStyle.richTextIconSize,
@@ -61,7 +61,7 @@ class AppBarComposerWidget extends StatelessWidget {
...[
const SizedBox(width: MobileAppBarComposerWidgetStyle.space),
TMailButtonWidget.fromIcon(
icon: _imagePaths.icAttachFile,
icon: imagePaths.icAttachFile,
iconColor: MobileAppBarComposerWidgetStyle.iconColor,
backgroundColor: Colors.transparent,
iconSize: MobileAppBarComposerWidgetStyle.iconSize,
@@ -70,7 +70,7 @@ class AppBarComposerWidget extends StatelessWidget {
),
const SizedBox(width: MobileAppBarComposerWidgetStyle.space),
TMailButtonWidget.fromIcon(
icon: _imagePaths.icInsertImage,
icon: imagePaths.icInsertImage,
iconColor: MobileAppBarComposerWidgetStyle.iconColor,
backgroundColor: Colors.transparent,
iconSize: MobileAppBarComposerWidgetStyle.iconSize,
@@ -81,8 +81,8 @@ class AppBarComposerWidget extends StatelessWidget {
],
TMailButtonWidget.fromIcon(
icon: isSendButtonEnabled
? _imagePaths.icSendMobile
: _imagePaths.icSendDisable,
? imagePaths.icSendMobile
: imagePaths.icSendDisable,
backgroundColor: Colors.transparent,
padding: MobileAppBarComposerWidgetStyle.iconPadding,
iconSize: MobileAppBarComposerWidgetStyle.sendButtonIconSize,
@@ -91,7 +91,7 @@ class AppBarComposerWidget extends StatelessWidget {
),
const SizedBox(width: MobileAppBarComposerWidgetStyle.space),
TMailButtonWidget.fromIcon(
icon: _imagePaths.icMore,
icon: imagePaths.icMore,
iconColor: MobileAppBarComposerWidgetStyle.iconColor,
backgroundColor: Colors.transparent,
padding: MobileAppBarComposerWidgetStyle.iconPadding,
@@ -1,13 +1,13 @@
import 'package:core/presentation/resources/image_paths.dart';
import 'package:core/presentation/views/button/tmail_button_widget.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:tmail_ui_user/features/composer/presentation/styles/mobile_app_bar_composer_widget_style.dart';
import 'package:tmail_ui_user/features/composer/presentation/widgets/web/mobile_responsive_app_bar_composer_widget.dart';
import 'package:tmail_ui_user/features/composer/presentation/widgets/mobile/app_bar_composer_widget.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
class LandscapeAppBarComposerWidget extends StatelessWidget {
final ImagePaths imagePaths;
final bool isSendButtonEnabled;
final bool isNetworkConnectionAvailable;
final VoidCallback onCloseViewAction;
@@ -17,10 +17,9 @@ class LandscapeAppBarComposerWidget extends StatelessWidget {
final VoidCallback openRichToolbarAction;
final OnOpenContextMenuAction openContextMenuAction;
final _imagePaths = Get.find<ImagePaths>();
LandscapeAppBarComposerWidget({
const LandscapeAppBarComposerWidget({
super.key,
required this.imagePaths,
required this.isSendButtonEnabled,
required this.onCloseViewAction,
required this.sendMessageAction,
@@ -43,7 +42,7 @@ class LandscapeAppBarComposerWidget extends StatelessWidget {
child: Row(
children: [
TMailButtonWidget.fromIcon(
icon: _imagePaths.icCancel,
icon: imagePaths.icCancel,
backgroundColor: Colors.transparent,
tooltipMessage: AppLocalizations.of(context).saveAndClose,
iconSize: MobileAppBarComposerWidgetStyle.iconSize,
@@ -52,7 +51,7 @@ class LandscapeAppBarComposerWidget extends StatelessWidget {
),
const Spacer(),
TMailButtonWidget.fromIcon(
icon: _imagePaths.icRichToolbar,
icon: imagePaths.icRichToolbar,
iconColor: MobileAppBarComposerWidgetStyle.iconColor,
backgroundColor: Colors.transparent,
iconSize: MobileAppBarComposerWidgetStyle.richTextIconSize,
@@ -64,7 +63,7 @@ class LandscapeAppBarComposerWidget extends StatelessWidget {
...[
const SizedBox(width: MobileAppBarComposerWidgetStyle.space),
TMailButtonWidget.fromIcon(
icon: _imagePaths.icAttachFile,
icon: imagePaths.icAttachFile,
iconColor: MobileAppBarComposerWidgetStyle.iconColor,
backgroundColor: Colors.transparent,
iconSize: MobileAppBarComposerWidgetStyle.iconSize,
@@ -73,7 +72,7 @@ class LandscapeAppBarComposerWidget extends StatelessWidget {
),
const SizedBox(width: MobileAppBarComposerWidgetStyle.space),
TMailButtonWidget.fromIcon(
icon: _imagePaths.icInsertImage,
icon: imagePaths.icInsertImage,
iconColor: MobileAppBarComposerWidgetStyle.iconColor,
backgroundColor: Colors.transparent,
iconSize: MobileAppBarComposerWidgetStyle.iconSize,
@@ -84,8 +83,8 @@ class LandscapeAppBarComposerWidget extends StatelessWidget {
],
TMailButtonWidget.fromIcon(
icon: isSendButtonEnabled
? _imagePaths.icSendMobile
: _imagePaths.icSendDisable,
? imagePaths.icSendMobile
: imagePaths.icSendDisable,
backgroundColor: Colors.transparent,
padding: MobileAppBarComposerWidgetStyle.iconPadding,
iconSize: MobileAppBarComposerWidgetStyle.sendButtonIconSize,
@@ -94,7 +93,7 @@ class LandscapeAppBarComposerWidget extends StatelessWidget {
),
const SizedBox(width: MobileAppBarComposerWidgetStyle.space),
TMailButtonWidget.fromIcon(
icon: _imagePaths.icMore,
icon: imagePaths.icMore,
iconColor: MobileAppBarComposerWidgetStyle.iconColor,
backgroundColor: Colors.transparent,
padding: MobileAppBarComposerWidgetStyle.iconPadding,
@@ -1,8 +1,11 @@
import 'package:core/presentation/resources/image_paths.dart';
import 'package:core/presentation/views/button/tmail_button_widget.dart';
import 'package:custom_pop_up_menu/custom_pop_up_menu.dart';
import 'package:flutter/material.dart';
import 'package:tmail_ui_user/features/base/widget/highlight_svg_icon_on_hover.dart';
import 'package:tmail_ui_user/features/base/widget/popup_item_widget.dart';
import 'package:tmail_ui_user/features/base/widget/popup_menu_overlay_widget.dart';
import 'package:tmail_ui_user/features/composer/presentation/styles/web/bottom_bar_composer_widget_style.dart';
import 'package:tmail_ui_user/features/composer/presentation/widgets/web/mobile_responsive_app_bar_composer_widget.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
class BottomBarComposerWidget extends StatelessWidget {
@@ -12,13 +15,16 @@ class BottomBarComposerWidget extends StatelessWidget {
final bool isPrintDraftEnabled;
final bool isFormattingOptionsEnabled;
final bool hasReadReceipt;
final CustomPopupMenuController menuMoreOptionController;
final VoidCallback openRichToolbarAction;
final VoidCallback attachFileAction;
final VoidCallback insertImageAction;
final VoidCallback deleteComposerAction;
final VoidCallback saveToDraftAction;
final VoidCallback sendMessageAction;
final OnOpenContextMenuAction openContextMenuAction;
final VoidCallback toggleCodeViewAction;
final VoidCallback toggleRequestReadReceiptAction;
final VoidCallback printDraftAction;
const BottomBarComposerWidget({
super.key,
@@ -27,13 +33,16 @@ class BottomBarComposerWidget extends StatelessWidget {
required this.isPrintDraftEnabled,
required this.isFormattingOptionsEnabled,
required this.hasReadReceipt,
required this.menuMoreOptionController,
required this.openRichToolbarAction,
required this.attachFileAction,
required this.insertImageAction,
required this.deleteComposerAction,
required this.saveToDraftAction,
required this.sendMessageAction,
required this.openContextMenuAction,
required this.toggleCodeViewAction,
required this.toggleRequestReadReceiptAction,
required this.printDraftAction,
});
@override
@@ -84,13 +93,56 @@ class BottomBarComposerWidget extends StatelessWidget {
),
),
const SizedBox(width: BottomBarComposerWidgetStyle.space),
TMailButtonWidget.fromIcon(
icon: imagePaths.icMore,
iconColor: BottomBarComposerWidgetStyle.iconColor,
backgroundColor: Colors.transparent,
iconSize: BottomBarComposerWidgetStyle.iconSize,
tooltipMessage: AppLocalizations.of(context).more,
onTapActionAtPositionCallback: openContextMenuAction,
PopupMenuOverlayWidget(
controller: menuMoreOptionController,
iconButton: HighlightSVGIconOnHover(
icon: imagePaths.icMore,
size: BottomBarComposerWidgetStyle.iconSize,
iconColor: BottomBarComposerWidgetStyle.iconColor,
tooltipMessage: AppLocalizations.of(context).more,
),
listButtonAction: [
PopupItemWidget(
imagePaths.icStyleCodeView,
AppLocalizations.of(context).embedCode,
styleName: BottomBarComposerWidgetStyle.popupItemTextStyle,
colorIcon: BottomBarComposerWidgetStyle.iconColor,
padding: BottomBarComposerWidgetStyle.popupItemPadding,
selectedIcon: imagePaths.icFilterSelected,
isSelected: isCodeViewEnabled,
onCallbackAction: () {
menuMoreOptionController.hideMenu();
toggleCodeViewAction();
},
),
PopupItemWidget(
imagePaths.icReadReceipt,
AppLocalizations.of(context).requestReadReceipt,
styleName: BottomBarComposerWidgetStyle.popupItemTextStyle,
padding: BottomBarComposerWidgetStyle.popupItemPadding,
colorIcon: BottomBarComposerWidgetStyle.iconColor,
selectedIcon: imagePaths.icFilterSelected,
isSelected: hasReadReceipt,
onCallbackAction: () {
menuMoreOptionController.hideMenu();
toggleRequestReadReceiptAction();
},
),
if (isPrintDraftEnabled)
PopupItemWidget(
imagePaths.icPrinter,
AppLocalizations.of(context).print,
colorIcon: BottomBarComposerWidgetStyle.iconColor,
styleName: BottomBarComposerWidgetStyle.popupItemTextStyle,
padding: BottomBarComposerWidgetStyle.popupItemPadding,
onCallbackAction: () {
menuMoreOptionController.hideMenu();
printDraftAction();
},
),
],
arrangeAsList: true,
position: null,
),
const Spacer(),
TMailButtonWidget.fromIcon(
@@ -1,23 +1,32 @@
import 'package:core/presentation/resources/image_paths.dart';
import 'package:core/presentation/views/button/tmail_button_widget.dart';
import 'package:custom_pop_up_menu/custom_pop_up_menu.dart';
import 'package:flutter/material.dart';
import 'package:tmail_ui_user/features/base/widget/highlight_svg_icon_on_hover.dart';
import 'package:tmail_ui_user/features/base/widget/popup_item_widget.dart';
import 'package:tmail_ui_user/features/base/widget/popup_menu_overlay_widget.dart';
import 'package:tmail_ui_user/features/composer/presentation/styles/mobile_app_bar_composer_widget_style.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
typedef OnOpenContextMenuAction = Function(RelativeRect position);
class MobileResponsiveAppBarComposerWidget extends StatelessWidget {
final ImagePaths imagePaths;
final bool isCodeViewEnabled;
final bool isSendButtonEnabled;
final bool isFormattingOptionsEnabled;
final bool hasRequestReadReceipt;
final bool isPrintDraftEnabled;
final CustomPopupMenuController menuMoreOptionController;
final VoidCallback onCloseViewAction;
final VoidCallback attachFileAction;
final VoidCallback insertImageAction;
final VoidCallback sendMessageAction;
final OnOpenContextMenuAction openContextMenuAction;
final VoidCallback openRichToolbarAction;
final VoidCallback toggleCodeViewAction;
final VoidCallback toggleRequestReadReceiptAction;
final VoidCallback printDraftAction;
final VoidCallback saveToDraftsAction;
final VoidCallback deleteComposerAction;
const MobileResponsiveAppBarComposerWidget({
super.key,
@@ -25,12 +34,19 @@ class MobileResponsiveAppBarComposerWidget extends StatelessWidget {
required this.isCodeViewEnabled,
required this.isFormattingOptionsEnabled,
required this.isSendButtonEnabled,
required this.hasRequestReadReceipt,
required this.isPrintDraftEnabled,
required this.menuMoreOptionController,
required this.openRichToolbarAction,
required this.onCloseViewAction,
required this.attachFileAction,
required this.insertImageAction,
required this.sendMessageAction,
required this.openContextMenuAction,
required this.toggleCodeViewAction,
required this.toggleRequestReadReceiptAction,
required this.printDraftAction,
required this.saveToDraftsAction,
required this.deleteComposerAction,
});
@override
@@ -94,13 +110,78 @@ class MobileResponsiveAppBarComposerWidget extends StatelessWidget {
onTapActionCallback: sendMessageAction,
),
const SizedBox(width: MobileAppBarComposerWidgetStyle.space),
TMailButtonWidget.fromIcon(
icon: imagePaths.icMore,
iconColor: MobileAppBarComposerWidgetStyle.iconColor,
backgroundColor: Colors.transparent,
iconSize: MobileAppBarComposerWidgetStyle.iconSize,
tooltipMessage: AppLocalizations.of(context).more,
onTapActionAtPositionCallback: openContextMenuAction,
PopupMenuOverlayWidget(
controller: menuMoreOptionController,
iconButton: HighlightSVGIconOnHover(
icon: imagePaths.icMore,
size: MobileAppBarComposerWidgetStyle.iconSize,
iconColor: MobileAppBarComposerWidgetStyle.iconColor,
tooltipMessage: AppLocalizations.of(context).more,
),
listButtonAction: [
PopupItemWidget(
imagePaths.icStyleCodeView,
AppLocalizations.of(context).embedCode,
styleName: MobileAppBarComposerWidgetStyle.popupItemTextStyle,
colorIcon: MobileAppBarComposerWidgetStyle.iconColor,
padding: MobileAppBarComposerWidgetStyle.popupItemPadding,
selectedIcon: imagePaths.icFilterSelected,
isSelected: isCodeViewEnabled,
onCallbackAction: () {
menuMoreOptionController.hideMenu();
toggleCodeViewAction();
},
),
PopupItemWidget(
imagePaths.icReadReceipt,
AppLocalizations.of(context).requestReadReceipt,
styleName: MobileAppBarComposerWidgetStyle.popupItemTextStyle,
padding: MobileAppBarComposerWidgetStyle.popupItemPadding,
colorIcon: MobileAppBarComposerWidgetStyle.popupItemIconColor,
selectedIcon: imagePaths.icFilterSelected,
isSelected: hasRequestReadReceipt,
onCallbackAction: () {
menuMoreOptionController.hideMenu();
toggleRequestReadReceiptAction();
},
),
if (isPrintDraftEnabled)
PopupItemWidget(
imagePaths.icPrinter,
AppLocalizations.of(context).print,
colorIcon: MobileAppBarComposerWidgetStyle.popupItemIconColor,
styleName: MobileAppBarComposerWidgetStyle.popupItemTextStyle,
padding: MobileAppBarComposerWidgetStyle.popupItemPadding,
onCallbackAction: () {
menuMoreOptionController.hideMenu();
printDraftAction();
},
),
PopupItemWidget(
imagePaths.icSaveToDraft,
AppLocalizations.of(context).saveAsDraft,
colorIcon: MobileAppBarComposerWidgetStyle.popupItemIconColor,
styleName: MobileAppBarComposerWidgetStyle.popupItemTextStyle,
padding: MobileAppBarComposerWidgetStyle.popupItemPadding,
onCallbackAction: () {
menuMoreOptionController.hideMenu();
saveToDraftsAction();
},
),
PopupItemWidget(
imagePaths.icDeleteMailbox,
AppLocalizations.of(context).delete,
colorIcon: MobileAppBarComposerWidgetStyle.popupItemIconColor,
styleName: MobileAppBarComposerWidgetStyle.popupItemTextStyle,
padding: MobileAppBarComposerWidgetStyle.popupItemPadding,
onCallbackAction: () {
menuMoreOptionController.hideMenu();
deleteComposerAction();
},
),
],
arrangeAsList: true,
position: null,
),
],
),
@@ -212,6 +212,7 @@ class ToolbarRichTextWebBuilder extends StatelessWidget with RichTextButtonMixin
_imagePaths,
(paragraph) => richTextWebController.applyParagraphType(paragraph)))
.toList(),
padding: const EdgeInsets.symmetric(horizontal: 5),
iconButton: buildWrapIconStyleText(
padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 5),
spacing: 3,
@@ -235,6 +236,7 @@ class ToolbarRichTextWebBuilder extends StatelessWidget with RichTextButtonMixin
_imagePaths,
(orderType) => richTextWebController.applyOrderListType(orderType)))
.toList(),
padding: const EdgeInsets.symmetric(horizontal: 5),
iconButton: buildWrapIconStyleText(
padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 5),
spacing: 3,