diff --git a/core/lib/presentation/extensions/color_extension.dart b/core/lib/presentation/extensions/color_extension.dart index ba69f2ff4..7bb309437 100644 --- a/core/lib/presentation/extensions/color_extension.dart +++ b/core/lib/presentation/extensions/color_extension.dart @@ -147,6 +147,7 @@ extension AppColor on Color { static const colorCloseButton = Color(0xFF818C99); static const colorDropShadow = Color(0x0F000000); static const colorBackgroundKeyboard = Color(0xFFD2D5DC); + static const colorBackgroundKeyboardAndroid = Color(0xFFF2F0F4); static const colorShadowLayerBottom = Color(0x29000000); static const colorShadowLayerTop = Color(0x1F000000); static const colorDividerHorizontal = Color(0x1F000000); diff --git a/core/lib/presentation/views/text/type_ahead_form_field_builder.dart b/core/lib/presentation/views/text/type_ahead_form_field_builder.dart index 7fa7363a5..01e64d93c 100644 --- a/core/lib/presentation/views/text/type_ahead_form_field_builder.dart +++ b/core/lib/presentation/views/text/type_ahead_form_field_builder.dart @@ -74,6 +74,7 @@ class _TypeAheadFormFieldBuilderState extends State this * 1024; + int get toBytes => this * 1024; } \ No newline at end of file diff --git a/lib/features/identity_creator/presentation/identity_creator_controller.dart b/lib/features/identity_creator/presentation/identity_creator_controller.dart index 2af63fcd4..61483c8ca 100644 --- a/lib/features/identity_creator/presentation/identity_creator_controller.dart +++ b/lib/features/identity_creator/presentation/identity_creator_controller.dart @@ -20,6 +20,7 @@ import 'package:model/extensions/identity_extension.dart'; import 'package:model/user/user_profile.dart'; import 'package:rich_text_composer/rich_text_composer.dart'; import 'package:tmail_ui_user/features/base/base_controller.dart'; +import 'package:tmail_ui_user/features/composer/presentation/controller/rich_text_mobile_tablet_controller.dart'; import 'package:tmail_ui_user/features/composer/presentation/controller/rich_text_web_controller.dart'; import 'package:tmail_ui_user/features/identity_creator/presentation/extesions/size_extension.dart'; import 'package:tmail_ui_user/features/identity_creator/presentation/model/identity_creator_arguments.dart'; @@ -61,8 +62,10 @@ class IdentityCreatorController extends BaseController { final actionType = IdentityActionType.create.obs; final isDefaultIdentity = RxBool(false); final isDefaultIdentitySupported = RxBool(false); + final isMobileEditorFocus = RxBool(false); final RichTextController keyboardRichTextController = RichTextController(); + final RichTextMobileTabletController richTextMobileTabletController = RichTextMobileTabletController(); final RichTextWebController richTextWebController = RichTextWebController(); final TextEditingController inputNameIdentityController = TextEditingController(); final TextEditingController inputBccIdentityController = TextEditingController(); @@ -79,7 +82,7 @@ class IdentityCreatorController extends BaseController { IdentityCreatorArguments? arguments; final GlobalKey htmlKey = GlobalKey(); - final htmlEditorMinHeight = 160; + final htmlEditorMinHeight = 150; void updateNameIdentity(BuildContext context, String? value) { _nameIdentity = value; @@ -428,17 +431,23 @@ class IdentityCreatorController extends BaseController { } void initRichTextForMobile(BuildContext context, HtmlEditorApi editorApi) { + richTextMobileTabletController.htmlEditorApi = editorApi; keyboardRichTextController.onCreateHTMLEditor( editorApi, onEnterKeyDown: _onEnterKeyDownOnMobile, onFocus: _onFocusHTMLEditorOnMobile, context: context ); + keyboardRichTextController.htmlEditorApi?.onFocusOut = () { + keyboardRichTextController.hideRichTextView(); + isMobileEditorFocus.value = false; + }; } void _onFocusHTMLEditorOnMobile() async { inputBccIdentityFocusNode.unfocus(); inputNameIdentityFocusNode.unfocus(); + isMobileEditorFocus.value = true; if (htmlKey.currentContext != null) { await Scrollable.ensureVisible(htmlKey.currentContext!); } @@ -464,7 +473,9 @@ class IdentityCreatorController extends BaseController { } } - void pickImage(BuildContext context) async { + void pickImage(BuildContext context, {int? maxWidth}) async { + clearFocusEditor(context); + final filePickerResult = await FilePicker.platform.pickFiles( type: FileType.image, withData: true @@ -473,7 +484,7 @@ class IdentityCreatorController extends BaseController { if (context.mounted) { final platformFile = filePickerResult?.files.single; if (platformFile != null) { - _insertInlineImage(context, platformFile); + _insertInlineImage(context, platformFile, maxWidth: maxWidth); } else { _appToast.showToastErrorMessage( context, @@ -486,18 +497,28 @@ class IdentityCreatorController extends BaseController { } bool _isExceedMaxSizeInlineImage(int fileSize) => - fileSize > IdentityCreatorConstants.maxSizeIdentityInlineImage.kiloByteToBytes; + fileSize > IdentityCreatorConstants.maxKBSizeIdentityInlineImage.toBytes; - void _insertInlineImage(BuildContext context, PlatformFile platformFile) { + void _insertInlineImage( + BuildContext context, + PlatformFile platformFile, + {int? maxWidth} + ) { if (_isExceedMaxSizeInlineImage(platformFile.size)) { _appToast.showToastErrorMessage( context, AppLocalizations.of(context).pleaseChooseAnImageSizeCorrectly( - IdentityCreatorConstants.maxSizeIdentityInlineImage + IdentityCreatorConstants.maxKBSizeIdentityInlineImage ) ); } else { - richTextWebController.insertImageAsBase64(platformFile: platformFile); + if (PlatformInfo.isWeb) { + richTextWebController.insertImageAsBase64(platformFile: platformFile); + } else if (PlatformInfo.isMobile) { + richTextMobileTabletController.insertImageAsBase64(platformFile: platformFile, maxWidth: maxWidth); + } else { + logError("IdentityCreatorController::_insertInlineImage: Platform not supported"); + } } } } \ No newline at end of file diff --git a/lib/features/identity_creator/presentation/identity_creator_view.dart b/lib/features/identity_creator/presentation/identity_creator_view.dart index b0dda3957..f19504716 100644 --- a/lib/features/identity_creator/presentation/identity_creator_view.dart +++ b/lib/features/identity_creator/presentation/identity_creator_view.dart @@ -43,43 +43,33 @@ class IdentityCreatorView extends GetWidget @override Widget build(BuildContext context) { - return ResponsiveWidget( + final responsiveWidget = ResponsiveWidget( responsiveUtils: _responsiveUtils, - mobile: Card( - margin: EdgeInsets.zero, - borderOnForeground: false, - color: Colors.transparent, - child: SafeArea( - top: PlatformInfo.isMobile, - bottom: false, - left: false, - right: false, - child: ClipRRect( - borderRadius: const BorderRadius.only( - topRight: Radius.circular(16), - topLeft: Radius.circular(16)), - child: GestureDetector( - onTap: () => controller.clearFocusEditor(context), - child: Scaffold( - backgroundColor: Colors.white, - body: Container( + mobile: Scaffold( + backgroundColor: Colors.black38, + body: GestureDetector( + onTap: () => controller.clearFocusEditor(context), + child: Card( + margin: EdgeInsets.zero, + borderOnForeground: false, + color: Colors.transparent, + child: SafeArea( + top: PlatformInfo.isMobile, + bottom: false, + left: false, + right: false, + child: ClipRRect( + borderRadius: const BorderRadius.only( + topRight: Radius.circular(16), + topLeft: Radius.circular(16)), + child: Container( decoration: const BoxDecoration( color: Colors.white, borderRadius: BorderRadius.only( topRight: Radius.circular(16), - topLeft: Radius.circular(16)), - boxShadow: [ - BoxShadow( - color: AppColor.colorShadowLayerBottom, - blurRadius: 96, - spreadRadius: 96, - offset: Offset.zero), - BoxShadow( - color: AppColor.colorShadowLayerTop, - blurRadius: 2, - spreadRadius: 2, - offset: Offset.zero), - ]), + topLeft: Radius.circular(16) + ), + ), child: _buildBodyView(context), ), ), @@ -150,6 +140,29 @@ class IdentityCreatorView extends GetWidget ) ) ); + + if (PlatformInfo.isWeb) { + return responsiveWidget; + } else { + return KeyboardRichText( + keyBroadToolbar: RichTextKeyboardToolBar( + titleBack: AppLocalizations.of(context).titleFormat, + backgroundKeyboardToolBarColor: PlatformInfo.isIOS + ? AppColor.colorBackgroundKeyboard + : AppColor.colorBackgroundKeyboardAndroid, + isLandScapeMode: _responsiveUtils.isLandscapeMobile(context), + richTextController: controller.keyboardRichTextController, + titleQuickStyleBottomSheet: AppLocalizations.of(context).titleQuickStyles, + titleBackgroundBottomSheet: AppLocalizations.of(context).titleBackground, + titleForegroundBottomSheet: AppLocalizations.of(context).titleForeground, + titleFormatBottomSheet: AppLocalizations.of(context).titleFormat, + insertImage: () => controller.pickImage(context, maxWidth: _getMaxWidth(context).toInt()), + ), + richTextController: controller.keyboardRichTextController, + paddingChild: EdgeInsets.zero, + child: responsiveWidget + ); + } } Widget _buildBodyView(BuildContext context) { @@ -232,7 +245,15 @@ class IdentityCreatorView extends GetWidget if (_isMobile(context)) _buildActionButtonMobile(context) else - _buildActionButtonDesktop(context) + _buildActionButtonDesktop(context), + if (PlatformInfo.isMobile) + Obx(() { + if (controller.isMobileEditorFocus.isTrue) { + return const SizedBox(height: 48); + } else { + return const SizedBox.shrink(); + } + }) ]), ), ); @@ -241,24 +262,7 @@ class IdentityCreatorView extends GetWidget onTap: () => controller.clearFocusEditor(context), child: Column(children: [ _buildHeaderView(context), - Expanded( - child: PlatformInfo.isWeb - ? PointerInterceptor(child: bodyCreatorView) - : KeyboardRichText( - keyBroadToolbar: RichTextKeyboardToolBar( - titleBack: AppLocalizations.of(context).titleFormat, - backgroundKeyboardToolBarColor: AppColor.colorBackgroundKeyboard, - isLandScapeMode: _responsiveUtils.isLandscapeMobile(context), - richTextController: controller.keyboardRichTextController, - titleQuickStyleBottomSheet: AppLocalizations.of(context).titleQuickStyles, - titleBackgroundBottomSheet: AppLocalizations.of(context).titleBackground, - titleForegroundBottomSheet: AppLocalizations.of(context).titleForeground, - titleFormatBottomSheet: AppLocalizations.of(context).titleFormat, - ), - richTextController: controller.keyboardRichTextController, - paddingChild: EdgeInsets.zero, - child: bodyCreatorView), - ), + Expanded(child: PointerInterceptor(child: bodyCreatorView)) ]), ); } @@ -455,5 +459,17 @@ class IdentityCreatorView extends GetWidget )); } - bool _isMobile(BuildContext context) => _responsiveUtils.isPortraitMobile(context) || _responsiveUtils.isLandscapeMobile(context); + bool _isMobile(BuildContext context) => + _responsiveUtils.isPortraitMobile(context) || + _responsiveUtils.isLandscapeMobile(context); + + double _getMaxWidth(BuildContext context) { + if (_isMobile(context)) { + return _responsiveUtils.getSizeScreenWidth(context); + } else if (_responsiveUtils.isDesktop(context)) { + return math.max(_responsiveUtils.getSizeScreenWidth(context) * 0.4, 800); + } else { + return math.max(_responsiveUtils.getSizeScreenWidth(context) * 0.4, 700); + } + } } \ No newline at end of file diff --git a/lib/features/identity_creator/presentation/utils/identity_creator_constants.dart b/lib/features/identity_creator/presentation/utils/identity_creator_constants.dart index 8d7a6ccfb..e26a3b27a 100644 --- a/lib/features/identity_creator/presentation/utils/identity_creator_constants.dart +++ b/lib/features/identity_creator/presentation/utils/identity_creator_constants.dart @@ -1,4 +1,4 @@ class IdentityCreatorConstants { - static const int maxSizeIdentityInlineImage = 16; // Kilobyte + static const int maxKBSizeIdentityInlineImage = 16; // Kilobyte } \ No newline at end of file