TF-3911 Support keyboard shortcut actions ESC to close composer on web

This commit is contained in:
dab246
2025-07-29 10:28:42 +07:00
committed by Dat H. Pham
parent f169ff5feb
commit 6c86682111
10 changed files with 151 additions and 50 deletions
@@ -7,10 +7,12 @@ import 'package:model/email/prefix_email_address.dart';
import 'package:pointer_interceptor/pointer_interceptor.dart';
import 'package:tmail_ui_user/features/base/mixin/message_dialog_action_manager.dart';
import 'package:tmail_ui_user/features/base/widget/dialog_picker/color_dialog_picker.dart';
import 'package:tmail_ui_user/features/base/widget/keyboard/keyboard_handler_wrapper.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/handle_edit_recipient_extension.dart';
import 'package:tmail_ui_user/features/composer/presentation/extensions/handle_recipients_collapsed_extensions.dart';
import 'package:tmail_ui_user/features/composer/presentation/extensions/handle_keyboard_shortcut_actions_extension.dart';
import 'package:tmail_ui_user/features/composer/presentation/extensions/mark_as_important_extension.dart';
import 'package:tmail_ui_user/features/composer/presentation/extensions/remove_draggable_email_address_between_recipient_fields_extension.dart';
import 'package:tmail_ui_user/features/composer/presentation/model/prefix_recipient_state.dart';
@@ -67,12 +69,12 @@ class ComposerView extends GetWidget<ComposerController> {
}
});
return ResponsiveWidget(
final bodyWidget = ResponsiveWidget(
responsiveUtils: controller.responsiveUtils,
mobile: MobileResponsiveContainerView(
childBuilder: (_, constraints) {
return GestureDetector(
onTap: () => controller.clickOutsideComposer(context),
onTap: controller.clickOutsideComposer,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@@ -96,7 +98,7 @@ class ComposerView extends GetWidget<ComposerController> {
toggleMarkAsImportantAction: () => controller.toggleMarkAsImportant(context),
saveToDraftsAction: () => controller.handleClickSaveAsDraftsButton(context),
saveToTemplateAction: () => controller.handleClickSaveAsTemplateButton(context),
deleteComposerAction: () => controller.handleClickDeleteComposer(context),
deleteComposerAction: controller.handleClickDeleteComposer,
)),
ConstrainedBox(
constraints: BoxConstraints(
@@ -231,6 +233,7 @@ class ComposerView extends GetWidget<ComposerController> {
uploadError: uploadError
),
onInitialContentLoadComplete: controller.onInitialContentLoadCompleteWeb,
onKeyDownEditorAction: controller.onKeyDownEditorAction,
));
}
),
@@ -318,7 +321,7 @@ class ComposerView extends GetWidget<ComposerController> {
desktop: Obx(() => DesktopResponsiveContainerView(
childBuilder: (_, constraints) {
return GestureDetector(
onTap: () => controller.clickOutsideComposer(context),
onTap: controller.clickOutsideComposer,
child: Column(children: [
Obx(() => DesktopAppBarComposerWidget(
imagePaths: controller.imagePaths,
@@ -468,6 +471,7 @@ class ComposerView extends GetWidget<ComposerController> {
uploadError: uploadError
),
onInitialContentLoadComplete: controller.onInitialContentLoadCompleteWeb,
onKeyDownEditorAction: controller.onKeyDownEditorAction,
);
});
}
@@ -514,7 +518,7 @@ class ComposerView extends GetWidget<ComposerController> {
openRichToolbarAction: controller.richTextWebController!.toggleFormattingOptions,
attachFileAction: () => controller.openFilePickerByType(context, FileType.any),
insertImageAction: () => controller.insertImage(context, constraints.maxWidth),
deleteComposerAction: () => controller.handleClickDeleteComposer(context),
deleteComposerAction: controller.handleClickDeleteComposer,
saveToDraftAction: () => controller.handleClickSaveAsDraftsButton(context),
sendMessageAction: () => controller.handleClickSendButton(context),
isEmailChanged: controller.isEmailChanged.isTrue,
@@ -588,7 +592,7 @@ class ComposerView extends GetWidget<ComposerController> {
tablet: TabletResponsiveContainerView(
childBuilder: (_, constraints) {
return GestureDetector(
onTap: () => controller.clickOutsideComposer(context),
onTap: controller.clickOutsideComposer,
child: Column(children: [
Obx(() => DesktopAppBarComposerWidget(
imagePaths: controller.imagePaths,
@@ -735,6 +739,7 @@ class ComposerView extends GetWidget<ComposerController> {
uploadError: uploadError
),
onInitialContentLoadComplete: controller.onInitialContentLoadCompleteWeb,
onKeyDownEditorAction: controller.onKeyDownEditorAction,
));
}
),
@@ -780,7 +785,7 @@ class ComposerView extends GetWidget<ComposerController> {
openRichToolbarAction: controller.richTextWebController!.toggleFormattingOptions,
attachFileAction: () => controller.openFilePickerByType(context, FileType.any),
insertImageAction: () => controller.insertImage(context, constraints.maxWidth),
deleteComposerAction: () => controller.handleClickDeleteComposer(context),
deleteComposerAction: controller.handleClickDeleteComposer,
saveToDraftAction: () => controller.handleClickSaveAsDraftsButton(context),
sendMessageAction: () => controller.handleClickSendButton(context),
isEmailChanged: controller.isEmailChanged.isTrue,
@@ -844,6 +849,16 @@ class ComposerView extends GetWidget<ComposerController> {
},
)
);
if (controller.keyboardShortcutFocusNode != null) {
return KeyboardHandlerWrapper(
focusNode: controller.keyboardShortcutFocusNode!,
onKeyDownEventAction: controller.onKeyDownEventAction,
child: bodyWidget,
);
} else {
return bodyWidget;
}
}
Widget _buildRecipientComposerWidget({