TF-2116 Add RequestReadReceipt and more option

(cherry picked from commit 5f9eb6b9c78239ffb586eea98feaf3e6c30981f9)
This commit is contained in:
dab246
2023-09-07 19:10:23 +07:00
committed by Dat H. Pham
parent 3809a05a35
commit 655446133c
17 changed files with 354 additions and 44 deletions
@@ -8,6 +8,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
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/model/prefix_recipient_state.dart';
import 'package:tmail_ui_user/features/composer/presentation/styles/composer_style.dart';
@@ -22,6 +23,7 @@ import 'package:tmail_ui_user/features/composer/presentation/widgets/recipient_c
import 'package:tmail_ui_user/features/composer/presentation/widgets/subject_composer_widget.dart';
import 'package:tmail_ui_user/features/composer/presentation/widgets/web/desktop_app_bar_composer_widget.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> {
@@ -59,14 +61,28 @@ class ComposerView extends GetWidget<ComposerController> {
isSendButtonEnabled: controller.isEnableEmailSendButton.value,
onCloseViewAction: () => controller.saveToDraftAndClose(context),
sendMessageAction: () => controller.sendEmailAction(context),
openContextMenuAction: () => {},
openContextMenuAction: (position) {
controller.openPopupMenuAction(
context,
position,
_createMoreOptionPopupItems(context),
radius: ComposerStyle.popupMenuRadius
);
},
))
else
Obx(() => AppBarComposerWidget(
isSendButtonEnabled: controller.isEnableEmailSendButton.value,
onCloseViewAction: () => controller.saveToDraftAndClose(context),
sendMessageAction: () => controller.sendEmailAction(context),
openContextMenuAction: () => {},
openContextMenuAction: (position) {
controller.openPopupMenuAction(
context,
position,
_createMoreOptionPopupItems(context),
radius: ComposerStyle.popupMenuRadius
);
},
)),
Expanded(
child: SafeArea(
@@ -317,6 +333,14 @@ class ComposerView extends GetWidget<ComposerController> {
deleteComposerAction: () => controller.closeComposer(context),
saveToDraftAction: () => controller.saveToDraftAction(context),
sendMessageAction: () => controller.sendEmailAction(context),
requestReadReceiptAction: (position) {
controller.openPopupMenuAction(
context,
position,
_createReadReceiptPopupItems(context),
radius: ComposerStyle.popupMenuRadius
);
},
),
]
)
@@ -350,4 +374,72 @@ class ComposerView extends GetWidget<ComposerController> {
..onActionClick((_) => controller.openFilePickerByType(context, FileType.any)))
.build();
}
List<PopupMenuEntry> _createReadReceiptPopupItems(BuildContext context) {
return [
PopupMenuItem(
padding: EdgeInsets.zero,
child: PopupItemWidget(
_imagePaths.icReadReceipt,
AppLocalizations.of(context).requestReadReceipt,
styleName: ComposerStyle.popupItemTextStyle,
padding: ComposerStyle.popupItemPadding,
selectedIcon: _imagePaths.icFilterSelected,
isSelected: controller.hasRequestReadReceipt.value,
onCallbackAction: () {
popBack();
controller.toggleRequestReadReceipt();
}
)
),
];
}
List<PopupMenuEntry> _createMoreOptionPopupItems(BuildContext context) {
return [
PopupMenuItem(
padding: EdgeInsets.zero,
child: PopupItemWidget(
_imagePaths.icReadReceipt,
AppLocalizations.of(context).requestReadReceipt,
styleName: ComposerStyle.popupItemTextStyle,
padding: ComposerStyle.popupItemPadding,
colorIcon: ComposerStyle.popupItemIconColor,
selectedIcon: _imagePaths.icFilterSelected,
isSelected: controller.hasRequestReadReceipt.value,
onCallbackAction: () {
popBack();
controller.toggleRequestReadReceipt();
}
)
),
PopupMenuItem(
padding: EdgeInsets.zero,
child: PopupItemWidget(
_imagePaths.icSaveToDraft,
AppLocalizations.of(context).saveAsDraft,
colorIcon: ComposerStyle.popupItemIconColor,
styleName: ComposerStyle.popupItemTextStyle,
padding: ComposerStyle.popupItemPadding,
onCallbackAction: () {
popBack();
controller.saveToDraftAction(context);
}
)
),
PopupMenuItem(
padding: EdgeInsets.zero,
child: PopupItemWidget(
_imagePaths.icDeleteMailbox,
AppLocalizations.of(context).delete,
styleName: ComposerStyle.popupItemTextStyle,
padding: ComposerStyle.popupItemPadding,
onCallbackAction: () {
popBack();
controller.closeComposer(context);
},
)
),
];
}
}
@@ -1,9 +1,11 @@
import 'package:core/presentation/resources/image_paths.dart';
import 'package:core/presentation/utils/responsive_utils.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: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/model/prefix_recipient_state.dart';
import 'package:tmail_ui_user/features/composer/presentation/styles/composer_style.dart';
@@ -18,10 +20,13 @@ import 'package:tmail_ui_user/features/composer/presentation/widgets/web/mobile_
import 'package:tmail_ui_user/features/composer/presentation/widgets/recipient_composer_widget.dart';
import 'package:tmail_ui_user/features/composer/presentation/widgets/subject_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> {
final _responsiveUtils = Get.find<ResponsiveUtils>();
final _imagePaths = Get.find<ImagePaths>();
ComposerView({Key? key}) : super(key: key);
@@ -43,7 +48,14 @@ class ComposerView extends GetWidget<ComposerController> {
attachFileAction: () => controller.openFilePickerByType(context, FileType.any),
insertImageAction: () => controller.insertImage(context, constraints.maxWidth),
sendMessageAction: () => controller.sendEmailAction(context),
openContextMenuAction: () => {},
openContextMenuAction: (position) {
controller.openPopupMenuAction(
context,
position,
_createMoreOptionPopupItems(context),
radius: ComposerStyle.popupMenuRadius
);
},
)),
ConstrainedBox(
constraints: BoxConstraints(
@@ -340,6 +352,14 @@ class ComposerView extends GetWidget<ComposerController> {
deleteComposerAction: () => controller.closeComposer(context),
saveToDraftAction: () => controller.saveToDraftAction(context),
sendMessageAction: () => controller.sendEmailAction(context),
requestReadReceiptAction: (position) {
controller.openPopupMenuAction(
context,
position,
_createReadReceiptPopupItems(context),
radius: ComposerStyle.popupMenuRadius
);
},
)),
]);
},
@@ -510,10 +530,102 @@ class ComposerView extends GetWidget<ComposerController> {
deleteComposerAction: () => controller.closeComposer(context),
saveToDraftAction: () => controller.saveToDraftAction(context),
sendMessageAction: () => controller.sendEmailAction(context),
requestReadReceiptAction: (position) {
controller.openPopupMenuAction(
context,
position,
_createReadReceiptPopupItems(context),
radius: ComposerStyle.popupMenuRadius
);
},
)),
]);
},
)
);
}
List<PopupMenuEntry> _createReadReceiptPopupItems(BuildContext context) {
return [
PopupMenuItem(
padding: EdgeInsets.zero,
child: PopupItemWidget(
_imagePaths.icReadReceipt,
AppLocalizations.of(context).requestReadReceipt,
styleName: ComposerStyle.popupItemTextStyle,
padding: ComposerStyle.popupItemPadding,
selectedIcon: _imagePaths.icFilterSelected,
isSelected: controller.hasRequestReadReceipt.value,
onCallbackAction: () {
popBack();
controller.toggleRequestReadReceipt();
}
)
),
];
}
List<PopupMenuEntry> _createMoreOptionPopupItems(BuildContext context) {
return [
PopupMenuItem(
padding: EdgeInsets.zero,
child: PopupItemWidget(
_imagePaths.icStyleCodeView,
AppLocalizations.of(context).embedCode,
styleName: ComposerStyle.popupItemTextStyle,
colorIcon: ComposerStyle.popupItemIconColor,
padding: ComposerStyle.popupItemPadding,
selectedIcon: _imagePaths.icFilterSelected,
isSelected: controller.richTextWebController.codeViewEnabled,
onCallbackAction: () {
popBack();
controller.richTextWebController.toggleCodeView();
}
)
),
PopupMenuItem(
padding: EdgeInsets.zero,
child: PopupItemWidget(
_imagePaths.icReadReceipt,
AppLocalizations.of(context).requestReadReceipt,
styleName: ComposerStyle.popupItemTextStyle,
padding: ComposerStyle.popupItemPadding,
colorIcon: ComposerStyle.popupItemIconColor,
selectedIcon: _imagePaths.icFilterSelected,
isSelected: controller.hasRequestReadReceipt.value,
onCallbackAction: () {
popBack();
controller.toggleRequestReadReceipt();
}
)
),
PopupMenuItem(
padding: EdgeInsets.zero,
child: PopupItemWidget(
_imagePaths.icSaveToDraft,
AppLocalizations.of(context).saveAsDraft,
colorIcon: ComposerStyle.popupItemIconColor,
styleName: ComposerStyle.popupItemTextStyle,
padding: ComposerStyle.popupItemPadding,
onCallbackAction: () {
popBack();
controller.saveToDraftAction(context);
}
)
),
PopupMenuItem(
padding: EdgeInsets.zero,
child: PopupItemWidget(
_imagePaths.icDeleteMailbox,
AppLocalizations.of(context).delete,
styleName: ComposerStyle.popupItemTextStyle,
padding: ComposerStyle.popupItemPadding,
onCallbackAction: () {
popBack();
controller.closeComposer(context);
},
)
),
];
}
}
@@ -8,11 +8,13 @@ class ComposerStyle {
static const double radius = 28;
static const double keyboardMaxHeight = 500;
static const double keyboardToolBarHeight = 200;
static const double popupMenuRadius = 8;
static const Color borderColor = AppColor.colorLineComposer;
static const Color backgroundEditorColor = Colors.white;
static const Color richToolbarColor = Colors.white;
static const Color mobileBackgroundColor = Colors.white;
static const Color popupItemIconColor = AppColor.primaryColor;
static const EdgeInsetsGeometry richToolbarPadding = EdgeInsetsDirectional.symmetric(horizontal: 24, vertical: 8);
static const EdgeInsetsGeometry desktopRecipientPadding = EdgeInsetsDirectional.only(end: 24);
@@ -30,6 +32,13 @@ class ComposerStyle {
static const EdgeInsetsGeometry mobileSubjectMargin = EdgeInsetsDirectional.only(start: 16);
static const EdgeInsetsGeometry mobileSubjectPadding = EdgeInsetsDirectional.only(end: 16, top: 12, bottom: 12);
static const EdgeInsetsGeometry mobileEditorPadding = EdgeInsetsDirectional.symmetric(horizontal: 12);
static const EdgeInsetsGeometry popupItemPadding = EdgeInsetsDirectional.symmetric(horizontal: 12);
static const TextStyle popupItemTextStyle = TextStyle(
color: Colors.black,
fontSize: 16,
fontWeight: FontWeight.w500
);
static const List<BoxShadow> richToolbarShadow = [
BoxShadow(
@@ -3,6 +3,7 @@ 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';
class AppBarComposerWidget extends StatelessWidget {
@@ -10,7 +11,7 @@ class AppBarComposerWidget extends StatelessWidget {
final bool isSendButtonEnabled;
final VoidCallback onCloseViewAction;
final VoidCallback sendMessageAction;
final VoidCallback openContextMenuAction;
final OnOpenContextMenuAction openContextMenuAction;
final _imagePaths = Get.find<ImagePaths>();
@@ -59,7 +60,7 @@ class AppBarComposerWidget extends StatelessWidget {
padding: MobileAppBarComposerWidgetStyle.iconPadding,
iconSize: MobileAppBarComposerWidgetStyle.iconSize,
tooltipMessage: AppLocalizations.of(context).more,
onTapActionCallback: openContextMenuAction,
onTapActionAtPositionCallback: openContextMenuAction,
),
],
),
@@ -3,6 +3,7 @@ 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';
class LandscapeAppBarComposerWidget extends StatelessWidget {
@@ -10,7 +11,7 @@ class LandscapeAppBarComposerWidget extends StatelessWidget {
final bool isSendButtonEnabled;
final VoidCallback onCloseViewAction;
final VoidCallback sendMessageAction;
final VoidCallback openContextMenuAction;
final OnOpenContextMenuAction openContextMenuAction;
final _imagePaths = Get.find<ImagePaths>();
@@ -62,7 +63,7 @@ class LandscapeAppBarComposerWidget extends StatelessWidget {
padding: MobileAppBarComposerWidgetStyle.iconPadding,
iconSize: MobileAppBarComposerWidgetStyle.iconSize,
tooltipMessage: AppLocalizations.of(context).more,
onTapActionCallback: openContextMenuAction,
onTapActionAtPositionCallback: openContextMenuAction,
),
],
),
@@ -3,6 +3,7 @@ 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/features/composer/presentation/widgets/web/bottom_bar_composer_widget.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
class TabletBottomBarComposerWidget extends StatelessWidget {
@@ -10,6 +11,7 @@ class TabletBottomBarComposerWidget extends StatelessWidget {
final VoidCallback deleteComposerAction;
final VoidCallback saveToDraftAction;
final VoidCallback sendMessageAction;
final OnRequestReadReceiptAction? requestReadReceiptAction;
final _imagePaths = Get.find<ImagePaths>();
@@ -18,6 +20,7 @@ class TabletBottomBarComposerWidget extends StatelessWidget {
required this.deleteComposerAction,
required this.saveToDraftAction,
required this.sendMessageAction,
this.requestReadReceiptAction,
});
@override
@@ -37,12 +40,21 @@ class TabletBottomBarComposerWidget extends StatelessWidget {
onTapActionCallback: deleteComposerAction,
),
const SizedBox(width: TabletBottomBarComposerWidgetStyle.space),
TMailButtonWidget.fromIcon(
icon: _imagePaths.icReadReceipt,
borderRadius: TabletBottomBarComposerWidgetStyle.iconRadius,
padding: TabletBottomBarComposerWidgetStyle.iconPadding,
iconSize: TabletBottomBarComposerWidgetStyle.iconSize,
tooltipMessage: AppLocalizations.of(context).requestReadReceipt,
onTapActionAtPositionCallback: requestReadReceiptAction,
),
const SizedBox(width: TabletBottomBarComposerWidgetStyle.space),
TMailButtonWidget.fromIcon(
icon: _imagePaths.icSaveToDraft,
borderRadius: TabletBottomBarComposerWidgetStyle.iconRadius,
padding: TabletBottomBarComposerWidgetStyle.iconPadding,
iconSize: TabletBottomBarComposerWidgetStyle.iconSize,
tooltipMessage: AppLocalizations.of(context).save_to_drafts,
tooltipMessage: AppLocalizations.of(context).saveAsDraft,
onTapActionCallback: saveToDraftAction,
),
const SizedBox(width: TabletBottomBarComposerWidgetStyle.sendButtonSpace),
@@ -5,6 +5,8 @@ import 'package:get/get.dart';
import 'package:tmail_ui_user/features/composer/presentation/styles/web/bottom_bar_composer_widget_style.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
typedef OnRequestReadReceiptAction = Function(RelativeRect position);
class BottomBarComposerWidget extends StatelessWidget {
final bool isCodeViewEnabled;
@@ -16,6 +18,7 @@ class BottomBarComposerWidget extends StatelessWidget {
final VoidCallback deleteComposerAction;
final VoidCallback saveToDraftAction;
final VoidCallback sendMessageAction;
final OnRequestReadReceiptAction? requestReadReceiptAction;
final _imagePaths = Get.find<ImagePaths>();
@@ -30,6 +33,7 @@ class BottomBarComposerWidget extends StatelessWidget {
required this.deleteComposerAction,
required this.saveToDraftAction,
required this.sendMessageAction,
this.requestReadReceiptAction,
});
@override
@@ -103,12 +107,21 @@ class BottomBarComposerWidget extends StatelessWidget {
onTapActionCallback: deleteComposerAction,
),
const SizedBox(width: BottomBarComposerWidgetStyle.space),
TMailButtonWidget.fromIcon(
icon: _imagePaths.icReadReceipt,
borderRadius: BottomBarComposerWidgetStyle.iconRadius,
padding: BottomBarComposerWidgetStyle.iconPadding,
iconSize: BottomBarComposerWidgetStyle.iconSize,
tooltipMessage: AppLocalizations.of(context).requestReadReceipt,
onTapActionAtPositionCallback: requestReadReceiptAction,
),
const SizedBox(width: BottomBarComposerWidgetStyle.space),
TMailButtonWidget.fromIcon(
icon: _imagePaths.icSaveToDraft,
borderRadius: BottomBarComposerWidgetStyle.iconRadius,
padding: BottomBarComposerWidgetStyle.iconPadding,
iconSize: BottomBarComposerWidgetStyle.iconSize,
tooltipMessage: AppLocalizations.of(context).save_to_drafts,
tooltipMessage: AppLocalizations.of(context).saveAsDraft,
onTapActionCallback: saveToDraftAction,
),
const SizedBox(width: BottomBarComposerWidgetStyle.sendButtonSpace),
@@ -5,6 +5,8 @@ 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/main/localizations/app_localizations.dart';
typedef OnOpenContextMenuAction = Function(RelativeRect position);
class MobileResponsiveAppBarComposerWidget extends StatelessWidget {
final bool isCodeViewEnabled;
@@ -14,7 +16,7 @@ class MobileResponsiveAppBarComposerWidget extends StatelessWidget {
final VoidCallback attachFileAction;
final VoidCallback insertImageAction;
final VoidCallback sendMessageAction;
final VoidCallback openContextMenuAction;
final OnOpenContextMenuAction openContextMenuAction;
final VoidCallback openRichToolbarAction;
final _imagePaths = Get.find<ImagePaths>();
@@ -109,7 +111,7 @@ class MobileResponsiveAppBarComposerWidget extends StatelessWidget {
padding: MobileAppBarComposerWidgetStyle.iconPadding,
iconSize: MobileAppBarComposerWidgetStyle.iconSize,
tooltipMessage: AppLocalizations.of(context).more,
onTapActionCallback: openContextMenuAction,
onTapActionAtPositionCallback: openContextMenuAction,
),
],
),