TF-2584 Remove toolbox buttons in keyboard header and move to app bar of composer in mobile

This commit is contained in:
dab246
2024-06-13 15:09:12 +07:00
committed by Dat H. Pham
parent 1c3ca5485a
commit 4ccebb8a55
7 changed files with 78 additions and 61 deletions
@@ -36,18 +36,8 @@ class ComposerView extends GetWidget<ComposerController> {
return ResponsiveWidget( return ResponsiveWidget(
responsiveUtils: controller.responsiveUtils, responsiveUtils: controller.responsiveUtils,
mobile: MobileContainerView( mobile: MobileContainerView(
keyboardRichTextController: controller.richTextMobileTabletController!.richTextController,
onCloseViewAction: () => controller.handleClickCloseComposer(context), onCloseViewAction: () => controller.handleClickCloseComposer(context),
onClearFocusAction: () => controller.clearFocus(context), onClearFocusAction: () => controller.clearFocus(context),
onAttachFileAction: () => controller.isNetworkConnectionAvailable
? controller.openPickAttachmentMenu(
context,
_pickAttachmentsActionTiles(context)
)
: null,
onInsertImageAction: (constraints) => controller.isNetworkConnectionAvailable
? controller.insertImage(context, constraints.maxWidth)
: null,
backgroundColor: MobileAppBarComposerWidgetStyle.backgroundColor, backgroundColor: MobileAppBarComposerWidgetStyle.backgroundColor,
childBuilder: (context, constraints) => SafeArea( childBuilder: (context, constraints) => SafeArea(
left: !controller.responsiveUtils.isLandscapeMobile(context), left: !controller.responsiveUtils.isLandscapeMobile(context),
@@ -75,6 +65,11 @@ class ComposerView extends GetWidget<ComposerController> {
_pickAttachmentsActionTiles(context) _pickAttachmentsActionTiles(context)
), ),
insertImageAction: () => controller.insertImage(context, constraints.maxWidth), insertImageAction: () => controller.insertImage(context, constraints.maxWidth),
openRichToolbarAction: () =>
controller.richTextMobileTabletController?.showFormatStyleBottomSheet(
context: context,
richTextController: controller.richTextMobileTabletController?.richTextController
),
)) ))
else else
Obx(() => AppBarComposerWidget( Obx(() => AppBarComposerWidget(
@@ -95,6 +90,11 @@ class ComposerView extends GetWidget<ComposerController> {
_pickAttachmentsActionTiles(context) _pickAttachmentsActionTiles(context)
), ),
insertImageAction: () => controller.insertImage(context, constraints.maxWidth), insertImageAction: () => controller.insertImage(context, constraints.maxWidth),
openRichToolbarAction: () =>
controller.richTextMobileTabletController?.showFormatStyleBottomSheet(
context: context,
richTextController: controller.richTextMobileTabletController?.richTextController
),
)), )),
Expanded( Expanded(
child: SafeArea( child: SafeArea(
@@ -1,12 +1,15 @@
import 'dart:io'; import 'dart:io';
import 'package:core/presentation/utils/keyboard_utils.dart';
import 'package:core/utils/app_logger.dart'; import 'package:core/utils/app_logger.dart';
import 'package:core/utils/html/html_utils.dart'; import 'package:core/utils/html/html_utils.dart';
import 'package:file_picker/file_picker.dart'; import 'package:file_picker/file_picker.dart';
import 'package:flutter/cupertino.dart';
import 'package:rich_text_composer/rich_text_composer.dart'; import 'package:rich_text_composer/rich_text_composer.dart';
import 'package:tmail_ui_user/features/composer/presentation/controller/base_rich_text_controller.dart'; import 'package:tmail_ui_user/features/composer/presentation/controller/base_rich_text_controller.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/inline_image.dart'; import 'package:tmail_ui_user/features/composer/presentation/model/inline_image.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
class RichTextMobileTabletController extends BaseRichTextController { class RichTextMobileTabletController extends BaseRichTextController {
HtmlEditorApi? htmlEditorApi; HtmlEditorApi? htmlEditorApi;
@@ -46,6 +49,28 @@ class RichTextMobileTabletController extends BaseRichTextController {
} }
} }
Future<void> showFormatStyleBottomSheet({
required BuildContext context,
required RichTextController? richTextController
}) async {
if (Platform.isAndroid) {
await htmlEditorApi?.storeSelectionRange();
KeyboardUtils.hideSystemKeyboardMobile();
} else {
await htmlEditorApi?.unfocus();
}
if (context.mounted) {
richTextController?.showRichTextBottomSheet(
context: context,
titleFormatBottomSheet: AppLocalizations.of(context).titleFormat,
titleQuickStyleBottomSheet: AppLocalizations.of(context).titleQuickStyles,
titleForegroundBottomSheet: AppLocalizations.of(context).titleForeground,
titleBackgroundBottomSheet: AppLocalizations.of(context).titleBackground,
);
}
}
@override @override
void onClose() { void onClose() {
richTextController.dispose(); richTextController.dispose();
@@ -7,7 +7,7 @@ class MobileAppBarComposerWidgetStyle {
static const double iconSize = 24; static const double iconSize = 24;
static const double space = 12; static const double space = 12;
static const double iconRadius = 8; static const double iconRadius = 8;
static const double sendButtonIconSize = 28; static const double sendButtonIconSize = 30;
static const double richTextIconSize = 28; static const double richTextIconSize = 28;
static const Color backgroundColor = AppColor.colorComposerAppBar; static const Color backgroundColor = AppColor.colorComposerAppBar;
@@ -17,5 +17,5 @@ class MobileAppBarComposerWidgetStyle {
static const EdgeInsetsGeometry padding = EdgeInsetsDirectional.symmetric(horizontal: 12); static const EdgeInsetsGeometry padding = EdgeInsetsDirectional.symmetric(horizontal: 12);
static const EdgeInsetsGeometry iconPadding = EdgeInsetsDirectional.all(3); static const EdgeInsetsGeometry iconPadding = EdgeInsetsDirectional.all(3);
static const EdgeInsetsGeometry richTextIconPadding = EdgeInsetsDirectional.all(2); static const EdgeInsetsGeometry richTextIconPadding = EdgeInsetsDirectional.all(5);
} }
@@ -1,33 +1,18 @@
import 'package:core/presentation/utils/responsive_utils.dart';
import 'package:core/utils/app_logger.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:core/utils/app_logger.dart';
import 'package:rich_text_composer/rich_text_composer.dart' as rich_composer;
import 'package:rich_text_composer/views/widgets/rich_text_keyboard_toolbar.dart';
import 'package:tmail_ui_user/features/composer/presentation/styles/mobile/mobile_container_view_style.dart'; import 'package:tmail_ui_user/features/composer/presentation/styles/mobile/mobile_container_view_style.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
typedef OnInsertImageAction = Function(BoxConstraints constraints);
class MobileContainerView extends StatelessWidget { class MobileContainerView extends StatelessWidget {
final Widget Function(BuildContext context, BoxConstraints constraints) childBuilder; final Widget Function(BuildContext context, BoxConstraints constraints) childBuilder;
final rich_composer.RichTextController keyboardRichTextController;
final VoidCallback onCloseViewAction; final VoidCallback onCloseViewAction;
final VoidCallback? onAttachFileAction;
final OnInsertImageAction? onInsertImageAction;
final VoidCallback? onClearFocusAction; final VoidCallback? onClearFocusAction;
final Color? backgroundColor; final Color? backgroundColor;
final _responsiveUtils = Get.find<ResponsiveUtils>(); const MobileContainerView({
MobileContainerView({
super.key, super.key,
required this.childBuilder, required this.childBuilder,
required this.keyboardRichTextController,
required this.onCloseViewAction, required this.onCloseViewAction,
this.onAttachFileAction,
this.onInsertImageAction,
this.onClearFocusAction, this.onClearFocusAction,
this.backgroundColor, this.backgroundColor,
}); });
@@ -48,25 +33,7 @@ class MobileContainerView extends StatelessWidget {
backgroundColor: backgroundColor ?? MobileContainerViewStyle.outSideBackgroundColor, backgroundColor: backgroundColor ?? MobileContainerViewStyle.outSideBackgroundColor,
resizeToAvoidBottomInset: false, resizeToAvoidBottomInset: false,
body: LayoutBuilder(builder: (context, constraints) { body: LayoutBuilder(builder: (context, constraints) {
return rich_composer.KeyboardRichText( return childBuilder(context, constraints);
richTextController: keyboardRichTextController,
keyBroadToolbar: RichTextKeyboardToolBar(
backgroundKeyboardToolBarColor: MobileContainerViewStyle.keyboardToolbarBackgroundColor,
isLandScapeMode: _responsiveUtils.isLandscapeMobile(context),
insertAttachment: onAttachFileAction,
insertImage: () => onInsertImageAction != null
? onInsertImageAction!(constraints)
: null,
richTextController: keyboardRichTextController,
titleQuickStyleBottomSheet: AppLocalizations.of(context).titleQuickStyles,
titleBackgroundBottomSheet: AppLocalizations.of(context).titleBackground,
titleForegroundBottomSheet: AppLocalizations.of(context).titleForeground,
titleFormatBottomSheet: AppLocalizations.of(context).titleFormat,
titleBack: AppLocalizations.of(context).format,
),
paddingChild: EdgeInsets.zero,
child: childBuilder(context, constraints),
);
}) })
), ),
) )
@@ -5,9 +5,10 @@ import 'package:get/get.dart';
import 'package:rich_text_composer/rich_text_composer.dart'; import 'package:rich_text_composer/rich_text_composer.dart';
import 'package:rich_text_composer/views/widgets/rich_text_keyboard_toolbar.dart'; import 'package:rich_text_composer/views/widgets/rich_text_keyboard_toolbar.dart';
import 'package:tmail_ui_user/features/composer/presentation/styles/mobile/tablet_container_view_style.dart'; import 'package:tmail_ui_user/features/composer/presentation/styles/mobile/tablet_container_view_style.dart';
import 'package:tmail_ui_user/features/composer/presentation/view/mobile/mobile_container_view.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
typedef OnInsertImageAction = Function(BoxConstraints constraints);
class TabletContainerView extends StatelessWidget { class TabletContainerView extends StatelessWidget {
final Widget Function(BuildContext context, BoxConstraints constraints) childBuilder; final Widget Function(BuildContext context, BoxConstraints constraints) childBuilder;
@@ -12,8 +12,9 @@ class AppBarComposerWidget extends StatelessWidget {
final bool isNetworkConnectionAvailable; final bool isNetworkConnectionAvailable;
final VoidCallback onCloseViewAction; final VoidCallback onCloseViewAction;
final VoidCallback sendMessageAction; final VoidCallback sendMessageAction;
final VoidCallback attachFileAction; final VoidCallback? attachFileAction;
final VoidCallback insertImageAction; final VoidCallback? insertImageAction;
final VoidCallback openRichToolbarAction;
final OnOpenContextMenuAction openContextMenuAction; final OnOpenContextMenuAction openContextMenuAction;
final _imagePaths = Get.find<ImagePaths>(); final _imagePaths = Get.find<ImagePaths>();
@@ -24,9 +25,10 @@ class AppBarComposerWidget extends StatelessWidget {
required this.onCloseViewAction, required this.onCloseViewAction,
required this.sendMessageAction, required this.sendMessageAction,
required this.openContextMenuAction, required this.openContextMenuAction,
required this.attachFileAction, required this.openRichToolbarAction,
required this.insertImageAction,
this.isNetworkConnectionAvailable = false, this.isNetworkConnectionAvailable = false,
this.attachFileAction,
this.insertImageAction,
}); });
@override @override
@@ -47,8 +49,18 @@ class AppBarComposerWidget extends StatelessWidget {
onTapActionCallback: onCloseViewAction onTapActionCallback: onCloseViewAction
), ),
const Spacer(), const Spacer(),
TMailButtonWidget.fromIcon(
icon: _imagePaths.icRichToolbar,
iconColor: MobileAppBarComposerWidgetStyle.iconColor,
backgroundColor: Colors.transparent,
iconSize: MobileAppBarComposerWidgetStyle.richTextIconSize,
padding: MobileAppBarComposerWidgetStyle.richTextIconPadding,
tooltipMessage: AppLocalizations.of(context).formattingOptions,
onTapActionCallback: openRichToolbarAction,
),
if (isNetworkConnectionAvailable) if (isNetworkConnectionAvailable)
...[ ...[
const SizedBox(width: 4),
TMailButtonWidget.fromIcon( TMailButtonWidget.fromIcon(
icon: _imagePaths.icAttachFile, icon: _imagePaths.icAttachFile,
iconColor: MobileAppBarComposerWidgetStyle.iconColor, iconColor: MobileAppBarComposerWidgetStyle.iconColor,
@@ -57,7 +69,7 @@ class AppBarComposerWidget extends StatelessWidget {
tooltipMessage: AppLocalizations.of(context).attach_file, tooltipMessage: AppLocalizations.of(context).attach_file,
onTapActionCallback: attachFileAction, onTapActionCallback: attachFileAction,
), ),
const SizedBox(width: 8), const SizedBox(width: 4),
TMailButtonWidget.fromIcon( TMailButtonWidget.fromIcon(
icon: _imagePaths.icInsertImage, icon: _imagePaths.icInsertImage,
iconColor: MobileAppBarComposerWidgetStyle.iconColor, iconColor: MobileAppBarComposerWidgetStyle.iconColor,
@@ -66,7 +78,7 @@ class AppBarComposerWidget extends StatelessWidget {
tooltipMessage: AppLocalizations.of(context).insertImage, tooltipMessage: AppLocalizations.of(context).insertImage,
onTapActionCallback: insertImageAction, onTapActionCallback: insertImageAction,
), ),
const SizedBox(width: 8), const SizedBox(width: 4),
], ],
TMailButtonWidget.fromIcon( TMailButtonWidget.fromIcon(
icon: isSendButtonEnabled icon: isSendButtonEnabled
@@ -12,8 +12,9 @@ class LandscapeAppBarComposerWidget extends StatelessWidget {
final bool isNetworkConnectionAvailable; final bool isNetworkConnectionAvailable;
final VoidCallback onCloseViewAction; final VoidCallback onCloseViewAction;
final VoidCallback sendMessageAction; final VoidCallback sendMessageAction;
final VoidCallback attachFileAction; final VoidCallback? attachFileAction;
final VoidCallback insertImageAction; final VoidCallback? insertImageAction;
final VoidCallback openRichToolbarAction;
final OnOpenContextMenuAction openContextMenuAction; final OnOpenContextMenuAction openContextMenuAction;
final _imagePaths = Get.find<ImagePaths>(); final _imagePaths = Get.find<ImagePaths>();
@@ -24,9 +25,10 @@ class LandscapeAppBarComposerWidget extends StatelessWidget {
required this.onCloseViewAction, required this.onCloseViewAction,
required this.sendMessageAction, required this.sendMessageAction,
required this.openContextMenuAction, required this.openContextMenuAction,
required this.attachFileAction, required this.openRichToolbarAction,
required this.insertImageAction,
this.isNetworkConnectionAvailable = false, this.isNetworkConnectionAvailable = false,
this.attachFileAction,
this.insertImageAction,
}); });
@override @override
@@ -50,8 +52,18 @@ class LandscapeAppBarComposerWidget extends StatelessWidget {
onTapActionCallback: onCloseViewAction onTapActionCallback: onCloseViewAction
), ),
const Spacer(), const Spacer(),
TMailButtonWidget.fromIcon(
icon: _imagePaths.icRichToolbar,
iconColor: MobileAppBarComposerWidgetStyle.iconColor,
backgroundColor: Colors.transparent,
iconSize: MobileAppBarComposerWidgetStyle.richTextIconSize,
padding: MobileAppBarComposerWidgetStyle.richTextIconPadding,
tooltipMessage: AppLocalizations.of(context).formattingOptions,
onTapActionCallback: openRichToolbarAction,
),
if (isNetworkConnectionAvailable) if (isNetworkConnectionAvailable)
...[ ...[
const SizedBox(width: 4),
TMailButtonWidget.fromIcon( TMailButtonWidget.fromIcon(
icon: _imagePaths.icAttachFile, icon: _imagePaths.icAttachFile,
iconColor: MobileAppBarComposerWidgetStyle.iconColor, iconColor: MobileAppBarComposerWidgetStyle.iconColor,
@@ -60,7 +72,7 @@ class LandscapeAppBarComposerWidget extends StatelessWidget {
tooltipMessage: AppLocalizations.of(context).attach_file, tooltipMessage: AppLocalizations.of(context).attach_file,
onTapActionCallback: attachFileAction, onTapActionCallback: attachFileAction,
), ),
const SizedBox(width: 8), const SizedBox(width: 4),
TMailButtonWidget.fromIcon( TMailButtonWidget.fromIcon(
icon: _imagePaths.icInsertImage, icon: _imagePaths.icInsertImage,
iconColor: MobileAppBarComposerWidgetStyle.iconColor, iconColor: MobileAppBarComposerWidgetStyle.iconColor,
@@ -69,7 +81,7 @@ class LandscapeAppBarComposerWidget extends StatelessWidget {
tooltipMessage: AppLocalizations.of(context).insertImage, tooltipMessage: AppLocalizations.of(context).insertImage,
onTapActionCallback: insertImageAction, onTapActionCallback: insertImageAction,
), ),
const SizedBox(width: 8), const SizedBox(width: 4),
], ],
TMailButtonWidget.fromIcon( TMailButtonWidget.fromIcon(
icon: isSendButtonEnabled icon: isSendButtonEnabled