TF-3449 Add Mark as important option in context menu

Signed-off-by: dab246 <tdvu@linagora.com>
This commit is contained in:
dab246
2025-02-07 14:54:44 +07:00
committed by Dat H. Pham
parent a91381da9e
commit 621756dca1
11 changed files with 175 additions and 8 deletions
+5
View File
@@ -0,0 +1,5 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M12.0001 1.71436C17.6807 1.71436 22.2858 6.31943 22.2858 12.0001C22.2858 17.6807 17.6807 22.2858 12.0001 22.2858C6.31943 22.2858 1.71436 17.6807 1.71436 12.0001C1.71436 6.31943 6.31943 1.71436 12.0001 1.71436ZM12.0001 3.42864C7.2662 3.42864 3.42864 7.2662 3.42864 12.0001C3.42864 16.7339 7.2662 20.5715 12.0001 20.5715C16.7339 20.5715 20.5715 16.7339 20.5715 12.0001C20.5715 7.2662 16.7339 3.42864 12.0001 3.42864ZM12.0001 15.0858C12.6628 15.0858 13.2001 15.623 13.2001 16.2858C13.2001 16.9485 12.6628 17.4858 12.0001 17.4858C11.3373 17.4858 10.8001 16.9485 10.8001 16.2858C10.8001 15.623 11.3373 15.0858 12.0001 15.0858ZM12.0632 6.85721C12.2668 6.85721 12.3947 6.88904 12.5064 6.9488C12.6182 7.00856 12.7059 7.09626 12.7656 7.20801C12.8254 7.31975 12.8572 7.4476 12.8572 7.65125V12.9203C12.8572 13.124 12.8254 13.2518 12.7656 13.3636C12.7059 13.4753 12.6182 13.563 12.5064 13.6228C12.3947 13.6825 12.2668 13.7144 12.0632 13.7144H11.937C11.7333 13.7144 11.6055 13.6825 11.4937 13.6228C11.382 13.563 11.2943 13.4753 11.2345 13.3636C11.1748 13.2518 11.1429 13.124 11.1429 12.9203V7.65125C11.1429 7.4476 11.1748 7.31975 11.2345 7.20801C11.2943 7.09626 11.382 7.00856 11.4937 6.9488C11.6055 6.88904 11.7333 6.85721 11.937 6.85721H12.0632Z"
fill="#55687D" />
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

@@ -226,6 +226,7 @@ class ImagePaths {
String get icCopy => _getImagePath('ic_copy.svg');
String get icSubaddressingAllow => _getImagePath('ic_subaddressing_allow.svg');
String get icSubaddressingDisallow => _getImagePath('ic_subaddressing_disallow.svg');
String get icMarkAsImportant => _getImagePath('ic_mark_as_important.svg');
String _getImagePath(String imageName) {
return AssetsPaths.images + imageName;
@@ -137,6 +137,7 @@ class ComposerController extends BaseController
final identitySelected = Rxn<Identity>();
final listFromIdentities = RxList<Identity>();
final isEmailChanged = Rx<bool>(false);
final isMarkAsImportant = Rx<bool>(false);
final LocalFilePickerInteractor _localFilePickerInteractor;
final LocalImagePickerInteractor _localImagePickerInteractor;
@@ -8,6 +8,7 @@ import 'package:get/get.dart';
import 'package:model/email/prefix_email_address.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/mark_as_important_extension.dart';
import 'package:tmail_ui_user/features/composer/presentation/model/prefix_recipient_state.dart';
import 'package:tmail_ui_user/features/composer/presentation/styles/composer_style.dart';
import 'package:tmail_ui_user/features/composer/presentation/styles/mobile_app_bar_composer_widget_style.dart';
@@ -452,11 +453,14 @@ class ComposerView extends GetWidget<ComposerController> {
)
),
Obx(() => TabletBottomBarComposerWidget(
imagePaths: controller.imagePaths,
hasReadReceipt: controller.hasRequestReadReceipt.value,
isMarkAsImportant: controller.isMarkAsImportant.value,
deleteComposerAction: () => controller.handleClickDeleteComposer(context),
saveToDraftAction: () => controller.handleClickSaveAsDraftsButton(context),
sendMessageAction: () => controller.handleClickSendButton(context),
requestReadReceiptAction: () => controller.toggleRequestReadReceipt(context),
toggleMarkAsImportantAction: () => controller.toggleMarkAsImportant(context),
)),
]
)
@@ -493,6 +497,22 @@ class ComposerView extends GetWidget<ComposerController> {
List<PopupMenuEntry> _createMoreOptionPopupItems(BuildContext context) {
return [
PopupMenuItem(
padding: EdgeInsets.zero,
child: PopupItemWidget(
iconAction: controller.imagePaths.icMarkAsImportant,
nameAction: AppLocalizations.of(context).markAsImportant,
styleName: ComposerStyle.popupItemTextStyle,
padding: ComposerStyle.popupItemPadding,
colorIcon: ComposerStyle.popupItemIconColor,
selectedIcon: controller.imagePaths.icFilterSelected,
isSelected: controller.isMarkAsImportant.value,
onCallbackAction: () {
popBack();
controller.toggleMarkAsImportant(context);
},
),
),
PopupMenuItem(
padding: EdgeInsets.zero,
child: PopupItemWidget(
@@ -6,6 +6,7 @@ import 'package:model/email/prefix_email_address.dart';
import 'package:pointer_interceptor/pointer_interceptor.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/extensions/mark_as_important_extension.dart';
import 'package:tmail_ui_user/features/composer/presentation/model/prefix_recipient_state.dart';
import 'package:tmail_ui_user/features/composer/presentation/styles/composer_style.dart';
import 'package:tmail_ui_user/features/composer/presentation/view/web/desktop_responsive_container_view.dart';
@@ -47,6 +48,7 @@ class ComposerView extends GetWidget<ComposerController> {
openRichToolbarAction: controller.richTextWebController!.toggleFormattingOptions,
isSendButtonEnabled: controller.isEnableEmailSendButton.value,
hasRequestReadReceipt: controller.hasRequestReadReceipt.value,
isMarkAsImportant: controller.isMarkAsImportant.value,
isEmailChanged: controller.isEmailChanged.value,
menuMoreOptionController: controller.menuMoreOptionController!,
onCloseViewAction: () => controller.handleClickCloseComposer(context),
@@ -56,6 +58,7 @@ class ComposerView extends GetWidget<ComposerController> {
toggleCodeViewAction: controller.richTextWebController!.toggleCodeView,
printDraftAction: () => controller.printDraft(context),
toggleRequestReadReceiptAction: () => controller.toggleRequestReadReceipt(context),
toggleMarkAsImportantAction: () => controller.toggleMarkAsImportant(context),
saveToDraftsAction: () => controller.handleClickSaveAsDraftsButton(context),
deleteComposerAction: () => controller.handleClickDeleteComposer(context),
)),
@@ -562,6 +565,7 @@ class ComposerView extends GetWidget<ComposerController> {
isCodeViewEnabled: controller.richTextWebController!.codeViewEnabled,
isFormattingOptionsEnabled: controller.richTextWebController!.isFormattingOptionsEnabled,
hasReadReceipt: controller.hasRequestReadReceipt.value,
isMarkAsImportant: controller.isMarkAsImportant.value,
openRichToolbarAction: controller.richTextWebController!.toggleFormattingOptions,
attachFileAction: () => controller.openFilePickerByType(context, FileType.any),
insertImageAction: () => controller.insertImage(context, constraints.maxWidth),
@@ -573,6 +577,7 @@ class ComposerView extends GetWidget<ComposerController> {
menuMoreOptionController: controller.menuMoreOptionController!,
printDraftAction: () => controller.printDraft(context),
toggleRequestReadReceiptAction: () => controller.toggleRequestReadReceipt(context),
toggleMarkAsImportantAction: () => controller.toggleMarkAsImportant(context),
)),
],
),
@@ -870,6 +875,7 @@ class ComposerView extends GetWidget<ComposerController> {
isCodeViewEnabled: controller.richTextWebController!.codeViewEnabled,
isFormattingOptionsEnabled: controller.richTextWebController!.isFormattingOptionsEnabled,
hasReadReceipt: controller.hasRequestReadReceipt.value,
isMarkAsImportant: controller.isMarkAsImportant.value,
openRichToolbarAction: controller.richTextWebController!.toggleFormattingOptions,
attachFileAction: () => controller.openFilePickerByType(context, FileType.any),
insertImageAction: () => controller.insertImage(context, constraints.maxWidth),
@@ -881,6 +887,7 @@ class ComposerView extends GetWidget<ComposerController> {
menuMoreOptionController: controller.menuMoreOptionController!,
printDraftAction: () => controller.printDraft(context),
toggleRequestReadReceiptAction: () => controller.toggleRequestReadReceipt(context),
toggleMarkAsImportantAction: () => controller.toggleMarkAsImportant(context),
)),
],
),
@@ -0,0 +1,17 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:tmail_ui_user/features/composer/presentation/composer_controller.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
extension MarkAsImportantExtension on ComposerController {
void toggleMarkAsImportant(BuildContext context) {
isMarkAsImportant.toggle();
appToast.showToastSuccessMessage(
context,
isMarkAsImportant.isTrue
? AppLocalizations.of(context).markAsImportantIsEnabled
: AppLocalizations.of(context).markAsImportantIsDisabled);
}
}
@@ -1,27 +1,30 @@
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/tablet_bottom_bar_composer_widget_style.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
class TabletBottomBarComposerWidget extends StatelessWidget {
final ImagePaths imagePaths;
final bool hasReadReceipt;
final bool isMarkAsImportant;
final VoidCallback deleteComposerAction;
final VoidCallback saveToDraftAction;
final VoidCallback sendMessageAction;
final VoidCallback requestReadReceiptAction;
final VoidCallback toggleMarkAsImportantAction;
final _imagePaths = Get.find<ImagePaths>();
TabletBottomBarComposerWidget({
const TabletBottomBarComposerWidget({
super.key,
required this.imagePaths,
required this.hasReadReceipt,
required this.isMarkAsImportant,
required this.deleteComposerAction,
required this.saveToDraftAction,
required this.sendMessageAction,
required this.requestReadReceiptAction,
required this.toggleMarkAsImportantAction,
});
@override
@@ -33,7 +36,7 @@ class TabletBottomBarComposerWidget extends StatelessWidget {
children: [
const Spacer(),
TMailButtonWidget.fromIcon(
icon: _imagePaths.icDeleteMailbox,
icon: imagePaths.icDeleteMailbox,
borderRadius: TabletBottomBarComposerWidgetStyle.iconRadius,
padding: TabletBottomBarComposerWidgetStyle.iconPadding,
iconSize: TabletBottomBarComposerWidgetStyle.iconSize,
@@ -42,7 +45,21 @@ class TabletBottomBarComposerWidget extends StatelessWidget {
),
const SizedBox(width: TabletBottomBarComposerWidgetStyle.space),
TMailButtonWidget.fromIcon(
icon: _imagePaths.icReadReceipt,
icon: imagePaths.icMarkAsImportant,
borderRadius: TabletBottomBarComposerWidgetStyle.iconRadius,
padding: TabletBottomBarComposerWidgetStyle.iconPadding,
iconSize: TabletBottomBarComposerWidgetStyle.iconSize,
iconColor: isMarkAsImportant
? TabletBottomBarComposerWidgetStyle.selectedIconColor
: TabletBottomBarComposerWidgetStyle.iconColor,
tooltipMessage: isMarkAsImportant
? AppLocalizations.of(context).turnOffMarkAsImportant
: AppLocalizations.of(context).turnOnMarkAsImportant,
onTapActionCallback: toggleMarkAsImportantAction,
),
const SizedBox(width: TabletBottomBarComposerWidgetStyle.space),
TMailButtonWidget.fromIcon(
icon: imagePaths.icReadReceipt,
borderRadius: TabletBottomBarComposerWidgetStyle.iconRadius,
padding: TabletBottomBarComposerWidgetStyle.iconPadding,
iconSize: TabletBottomBarComposerWidgetStyle.iconSize,
@@ -56,7 +73,7 @@ class TabletBottomBarComposerWidget extends StatelessWidget {
),
const SizedBox(width: TabletBottomBarComposerWidgetStyle.space),
TMailButtonWidget.fromIcon(
icon: _imagePaths.icSaveToDraft,
icon: imagePaths.icSaveToDraft,
borderRadius: TabletBottomBarComposerWidgetStyle.iconRadius,
padding: TabletBottomBarComposerWidgetStyle.iconPadding,
iconSize: TabletBottomBarComposerWidgetStyle.iconSize,
@@ -66,7 +83,7 @@ class TabletBottomBarComposerWidget extends StatelessWidget {
const SizedBox(width: TabletBottomBarComposerWidgetStyle.sendButtonSpace),
TMailButtonWidget(
text: AppLocalizations.of(context).send,
icon: _imagePaths.icSend,
icon: imagePaths.icSend,
iconAlignment: TextDirection.rtl,
padding: TabletBottomBarComposerWidgetStyle.sendButtonPadding,
iconSize: TabletBottomBarComposerWidgetStyle.iconSize,
@@ -16,6 +16,7 @@ class BottomBarComposerWidget extends StatelessWidget {
final bool isEmailChanged;
final bool isFormattingOptionsEnabled;
final bool hasReadReceipt;
final bool isMarkAsImportant;
final CustomPopupMenuController menuMoreOptionController;
final VoidCallback openRichToolbarAction;
final VoidCallback attachFileAction;
@@ -26,6 +27,7 @@ class BottomBarComposerWidget extends StatelessWidget {
final VoidCallback toggleCodeViewAction;
final VoidCallback toggleRequestReadReceiptAction;
final VoidCallback printDraftAction;
final VoidCallback toggleMarkAsImportantAction;
const BottomBarComposerWidget({
super.key,
@@ -34,6 +36,7 @@ class BottomBarComposerWidget extends StatelessWidget {
required this.isEmailChanged,
required this.isFormattingOptionsEnabled,
required this.hasReadReceipt,
required this.isMarkAsImportant,
required this.menuMoreOptionController,
required this.openRichToolbarAction,
required this.attachFileAction,
@@ -44,6 +47,7 @@ class BottomBarComposerWidget extends StatelessWidget {
required this.toggleCodeViewAction,
required this.toggleRequestReadReceiptAction,
required this.printDraftAction,
required this.toggleMarkAsImportantAction,
});
@override
@@ -103,6 +107,19 @@ class BottomBarComposerWidget extends StatelessWidget {
tooltipMessage: AppLocalizations.of(context).more,
),
listButtonAction: [
PopupItemWidget(
iconAction: imagePaths.icMarkAsImportant,
nameAction: AppLocalizations.of(context).markAsImportant,
styleName: BottomBarComposerWidgetStyle.popupItemTextStyle,
padding: BottomBarComposerWidgetStyle.popupItemPadding,
colorIcon: BottomBarComposerWidgetStyle.iconColor,
selectedIcon: imagePaths.icFilterSelected,
isSelected: isMarkAsImportant,
onCallbackAction: () {
menuMoreOptionController.hideMenu();
toggleMarkAsImportantAction();
},
),
PopupItemWidget(
iconAction: imagePaths.icStyleCodeView,
nameAction: AppLocalizations.of(context).embedCode,
@@ -16,6 +16,7 @@ class MobileResponsiveAppBarComposerWidget extends StatelessWidget {
final bool isSendButtonEnabled;
final bool isFormattingOptionsEnabled;
final bool hasRequestReadReceipt;
final bool isMarkAsImportant;
final bool isEmailChanged;
final CustomPopupMenuController menuMoreOptionController;
final VoidCallback onCloseViewAction;
@@ -28,6 +29,7 @@ class MobileResponsiveAppBarComposerWidget extends StatelessWidget {
final VoidCallback printDraftAction;
final VoidCallback saveToDraftsAction;
final VoidCallback deleteComposerAction;
final VoidCallback toggleMarkAsImportantAction;
const MobileResponsiveAppBarComposerWidget({
super.key,
@@ -36,6 +38,7 @@ class MobileResponsiveAppBarComposerWidget extends StatelessWidget {
required this.isFormattingOptionsEnabled,
required this.isSendButtonEnabled,
required this.hasRequestReadReceipt,
required this.isMarkAsImportant,
required this.isEmailChanged,
required this.menuMoreOptionController,
required this.openRichToolbarAction,
@@ -48,6 +51,7 @@ class MobileResponsiveAppBarComposerWidget extends StatelessWidget {
required this.printDraftAction,
required this.saveToDraftsAction,
required this.deleteComposerAction,
required this.toggleMarkAsImportantAction,
});
@override
@@ -120,6 +124,19 @@ class MobileResponsiveAppBarComposerWidget extends StatelessWidget {
tooltipMessage: AppLocalizations.of(context).more,
),
listButtonAction: [
PopupItemWidget(
iconAction: imagePaths.icMarkAsImportant,
nameAction: AppLocalizations.of(context).markAsImportant,
styleName: MobileAppBarComposerWidgetStyle.popupItemTextStyle,
padding: MobileAppBarComposerWidgetStyle.popupItemPadding,
colorIcon: MobileAppBarComposerWidgetStyle.popupItemIconColor,
selectedIcon: imagePaths.icFilterSelected,
isSelected: isMarkAsImportant,
onCallbackAction: () {
menuMoreOptionController.hideMenu();
toggleMarkAsImportantAction();
},
),
PopupItemWidget(
iconAction: imagePaths.icStyleCodeView,
nameAction: AppLocalizations.of(context).embedCode,
+30
View File
@@ -4309,5 +4309,35 @@
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"markAsImportant": "Mark as important",
"@markAsImportant": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"markAsImportantIsEnabled": "Mark as important is enabled",
"@markAsImportantIsEnabled": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"markAsImportantIsDisabled": "Mark as important is disabled",
"@markAsImportantIsDisabled": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"turnOnMarkAsImportant": "Turn on mark as important",
"@turnOnMarkAsImportant": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"turnOffMarkAsImportant": "Turn off mark as important",
"@turnOffMarkAsImportant": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
}
}
@@ -4520,4 +4520,39 @@ class AppLocalizations {
name: 'sizeAscending',
);
}
String get markAsImportant {
return Intl.message(
'Mark as important',
name: 'markAsImportant',
);
}
String get markAsImportantIsEnabled {
return Intl.message(
'Mark as important is enabled',
name: 'markAsImportantIsEnabled',
);
}
String get markAsImportantIsDisabled {
return Intl.message(
'Mark as important is disabled',
name: 'markAsImportantIsDisabled',
);
}
String get turnOnMarkAsImportant {
return Intl.message(
'Turn on mark as important',
name: 'turnOnMarkAsImportant',
);
}
String get turnOffMarkAsImportant {
return Intl.message(
'Turn off mark as important',
name: 'turnOffMarkAsImportant',
);
}
}