diff --git a/lib/features/identity_creator/presentation/identity_creator_controller.dart b/lib/features/identity_creator/presentation/identity_creator_controller.dart index ceb623b05..6d76a6219 100644 --- a/lib/features/identity_creator/presentation/identity_creator_controller.dart +++ b/lib/features/identity_creator/presentation/identity_creator_controller.dart @@ -65,7 +65,6 @@ class IdentityCreatorController extends BaseController { final actionType = IdentityActionType.create.obs; final isDefaultIdentity = RxBool(false); final isDefaultIdentitySupported = RxBool(false); - final isMobileEditorFocus = RxBool(false); final isCompressingInlineImage = RxBool(false); final TextEditingController inputNameIdentityController = TextEditingController(); @@ -296,11 +295,21 @@ class IdentityCreatorController extends BaseController { return defaultIdentityIds?.length != allIdentities?.length; } - void updateEmailOfIdentity(EmailAddress? newEmailAddress) { + void updateEmailOfIdentity(BuildContext context, EmailAddress? newEmailAddress) { + if (PlatformInfo.isMobile) { + richTextMobileTabletController?.richTextController.htmlEditorApi?.unfocus(); + } + FocusScope.of(context).unfocus(); + emailOfIdentity.value = newEmailAddress; } - void updaterReplyToOfIdentity(EmailAddress? newEmailAddress) { + void updaterReplyToOfIdentity(BuildContext context, EmailAddress? newEmailAddress) { + if (PlatformInfo.isMobile) { + richTextMobileTabletController?.richTextController.htmlEditorApi?.unfocus(); + } + FocusScope.of(context).unfocus(); + replyToOfIdentity.value = newEmailAddress; } @@ -432,8 +441,7 @@ class IdentityCreatorController extends BaseController { void clearFocusEditor(BuildContext context) { if (PlatformInfo.isMobile) { - richTextMobileTabletController?.htmlEditorApi?.unfocus(); - KeyboardUtils.hideSystemKeyboardMobile(); + richTextMobileTabletController?.richTextController.htmlEditorApi?.unfocus(); } KeyboardUtils.hideKeyboard(context); } @@ -449,18 +457,20 @@ class IdentityCreatorController extends BaseController { richTextMobileTabletController?.richTextController.onCreateHTMLEditor( editorApi, onEnterKeyDown: _onEnterKeyDownOnMobile, - onFocus: _onFocusHTMLEditorOnMobile, + onFocus: () => _onFocusHTMLEditorOnMobile(context) ); - richTextMobileTabletController?.htmlEditorApi?.onFocusOut = () { - richTextMobileTabletController?.richTextController.hideRichTextView(); - isMobileEditorFocus.value = false; - }; } - void _onFocusHTMLEditorOnMobile() async { + void _onFocusHTMLEditorOnMobile(BuildContext context) async { + if (PlatformInfo.isAndroid) { + FocusScope.of(context).unfocus(); + await Future.delayed( + const Duration(milliseconds: 300), + richTextMobileTabletController?.richTextController.showDeviceKeyboard); + } + inputBccIdentityFocusNode.unfocus(); inputNameIdentityFocusNode.unfocus(); - isMobileEditorFocus.value = true; if (htmlKey.currentContext != null) { await Scrollable.ensureVisible(htmlKey.currentContext!); } diff --git a/lib/features/identity_creator/presentation/identity_creator_view.dart b/lib/features/identity_creator/presentation/identity_creator_view.dart index 31e1761f6..d16b922b5 100644 --- a/lib/features/identity_creator/presentation/identity_creator_view.dart +++ b/lib/features/identity_creator/presentation/identity_creator_view.dart @@ -8,6 +8,7 @@ import 'package:core/presentation/views/responsive/responsive_widget.dart'; import 'package:core/utils/html/html_utils.dart'; import 'package:core/utils/platform_info.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_portal/flutter_portal.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:get/get.dart'; import 'package:html_editor_enhanced/html_editor.dart' as html_editor_browser; @@ -39,129 +40,7 @@ class IdentityCreatorView extends GetWidget @override Widget build(BuildContext context) { - final responsiveWidget = ResponsiveWidget( - responsiveUtils: controller.responsiveUtils, - 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) - ), - ), - child: _buildBodyView(context), - ), - ), - ), - ), - ), - ), - landscapeMobile: Scaffold( - backgroundColor: Colors.white, - body: GestureDetector( - onTap: () => controller.clearFocusEditor(context), - child: SafeArea( - child: _buildBodyView(context), - ), - ) - ), - tablet: Scaffold( - backgroundColor: Colors.black38, - body: GestureDetector( - onTap: () => controller.clearFocusEditor(context), - child: Center( - child: Padding( - padding: const EdgeInsetsDirectional.symmetric(horizontal: 24), - child: Card( - color: Colors.transparent, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.all(Radius.circular(16)) - ), - child: Container( - decoration: const BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.all(Radius.circular(16)) - ), - width: math.max(controller.responsiveUtils.getSizeScreenWidth(context) * 0.4, 700), - height: controller.responsiveUtils.getSizeScreenHeight(context) * 0.8, - child: ClipRRect( - borderRadius: const BorderRadius.all(Radius.circular(16)), - child: _buildBodyView(context) - ) - ) - ), - ) - ) - ), - ), - desktop: Scaffold( - backgroundColor: Colors.black38, - body: GestureDetector( - onTap: () => controller.clearFocusEditor(context), - child: Center(child: Card( - color: Colors.transparent, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.all(Radius.circular(16)) - ), - child: Container( - decoration: const BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.all(Radius.circular(16)) - ), - width: math.max(controller.responsiveUtils.getSizeScreenWidth(context) * 0.4, 800), - height: controller.responsiveUtils.getSizeScreenHeight(context) * 0.8, - child: ClipRRect( - borderRadius: const BorderRadius.all(Radius.circular(16)), - child: _buildBodyView(context) - ) - ) - )), - ) - ) - ); - - if (PlatformInfo.isWeb) { - return responsiveWidget; - } else { - return KeyboardRichText( - keyBroadToolbar: RichTextKeyboardToolBar( - titleBack: AppLocalizations.of(context).titleFormat, - backgroundKeyboardToolBarColor: PlatformInfo.isIOS - ? AppColor.colorBackgroundKeyboard - : AppColor.colorBackgroundKeyboardAndroid, - richTextController: controller.richTextMobileTabletController!.richTextController, - quickStyleLabel: AppLocalizations.of(context).titleQuickStyles, - backgroundLabel: AppLocalizations.of(context).titleBackground, - foregroundLabel: AppLocalizations.of(context).titleForeground, - formatLabel: AppLocalizations.of(context).titleFormat, - insertImage: () => controller.pickImage(context), - rootContext: context, - ), - richTextController: controller.richTextMobileTabletController!.richTextController, - child: responsiveWidget - ); - } - } - - Widget _buildBodyView(BuildContext context) { - final bodyCreatorView = SingleChildScrollView( + Widget bodyCreatorView = SingleChildScrollView( controller: controller.scrollController, physics: const ClampingScrollPhysics(), child: Padding( @@ -184,11 +63,13 @@ class IdentityCreatorView extends GetWidget AppLocalizations.of(context).email.inCaps, controller.emailOfIdentity.value, controller.listEmailAddressDefault, - onSelectItemDropList: controller.updateEmailOfIdentity); + onSelectItemDropList: (emailAddress) => controller.updateEmailOfIdentity(context, emailAddress) + ); } else { return IdentityFieldNoEditableBuilder( AppLocalizations.of(context).email.inCaps, - controller.emailOfIdentity.value); + controller.emailOfIdentity.value + ); } }), const SizedBox(height: 24), @@ -197,7 +78,7 @@ class IdentityCreatorView extends GetWidget AppLocalizations.of(context).reply_to, controller.replyToOfIdentity.value, controller.listEmailAddressOfReplyTo, - onSelectItemDropList: controller.updaterReplyToOfIdentity + onSelectItemDropList: (emailAddress) => controller.updaterReplyToOfIdentity(context, emailAddress) )), const SizedBox(height: 24), Obx(() => IdentityInputWithDropListFieldBuilder( @@ -238,33 +119,244 @@ class IdentityCreatorView extends GetWidget ), const SizedBox(height: 12), if (controller.isMobile(context)) - _buildActionButtonMobile(context), - if (PlatformInfo.isMobile) - Obx(() { - if (controller.isMobileEditorFocus.isTrue) { - return const SizedBox(height: 48); - } else { - return const SizedBox.shrink(); - } - }) + _buildActionButtonMobile(context) + else + _buildActionButtonDesktop(context) ]), ), ); - return GestureDetector( - onTap: () => controller.clearFocusEditor(context), - child: Column(children: [ - _buildHeaderView(context), - Expanded(child: PointerInterceptor(child: bodyCreatorView)), - if (!controller.isMobile(context)) ...[ - Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: _buildActionButtonDesktop(context), + if (PlatformInfo.isWeb) { + return GestureDetector( + onTap: () => controller.clearFocusEditor(context), + child: ResponsiveWidget( + responsiveUtils: controller.responsiveUtils, + mobile: Scaffold( + backgroundColor: Colors.black38, + body: Card( + margin: EdgeInsets.zero, + borderOnForeground: false, + color: Colors.transparent, + 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) + ), + ), + child: Column(children: [ + _buildHeaderView(context), + Expanded(child: PointerInterceptor(child: bodyCreatorView)) + ]), + ), + ), + ), ), - const SizedBox(height: 12), - ], - ]), - ); + landscapeMobile: Scaffold( + backgroundColor: Colors.white, + body: Column(children: [ + _buildHeaderView(context), + Expanded(child: PointerInterceptor(child: bodyCreatorView)) + ]) + ), + tablet: Scaffold( + backgroundColor: Colors.black38, + body: Center( + child: Padding( + padding: const EdgeInsetsDirectional.symmetric(horizontal: 24), + child: Card( + color: Colors.transparent, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(16)) + ), + child: Container( + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(16)) + ), + width: math.max(controller.responsiveUtils.getSizeScreenWidth(context) * 0.4, 700), + height: controller.responsiveUtils.getSizeScreenHeight(context) * 0.8, + child: ClipRRect( + borderRadius: const BorderRadius.all(Radius.circular(16)), + child: Column(children: [ + _buildHeaderView(context), + Expanded(child: PointerInterceptor(child: bodyCreatorView)) + ]) + ) + ) + ), + ) + ), + ), + desktop: Scaffold( + backgroundColor: Colors.black38, + body: Center( + child: Card( + color: Colors.transparent, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(16)) + ), + child: Container( + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(16)) + ), + width: math.max(controller.responsiveUtils.getSizeScreenWidth(context) * 0.4, 800), + height: controller.responsiveUtils.getSizeScreenHeight(context) * 0.8, + child: ClipRRect( + borderRadius: const BorderRadius.all(Radius.circular(16)), + child: Column(children: [ + _buildHeaderView(context), + Expanded(child: PointerInterceptor(child: bodyCreatorView)) + ]) + ) + ) + ) + ) + ) + ), + ); + } else { + return ResponsiveWidget( + responsiveUtils: controller.responsiveUtils, + mobile: GestureDetector( + onTap: () => controller.clearFocusEditor(context), + child: Scaffold( + backgroundColor: Colors.black38, + body: SafeArea( + bottom: false, + child: KeyboardRichText( + keyBroadToolbar: RichTextKeyboardToolBar( + rootContext: context, + titleBack: AppLocalizations.of(context).titleFormat, + backgroundKeyboardToolBarColor: PlatformInfo.isIOS + ? AppColor.colorBackgroundKeyboard + : AppColor.colorBackgroundKeyboardAndroid, + richTextController: controller.richTextMobileTabletController!.richTextController, + quickStyleLabel: AppLocalizations.of(context).titleQuickStyles, + backgroundLabel: AppLocalizations.of(context).titleBackground, + foregroundLabel: AppLocalizations.of(context).titleForeground, + formatLabel: AppLocalizations.of(context).titleFormat, + insertImage: () => controller.pickImage(context), + ), + richTextController: controller.richTextMobileTabletController!.richTextController, + child: Card( + margin: EdgeInsets.zero, + elevation: 16, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.only( + topRight: Radius.circular(16), + topLeft: Radius.circular(16) + ), + ), + clipBehavior: Clip.antiAlias, + child: Container( + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.only( + topRight: Radius.circular(16), + topLeft: Radius.circular(16) + ), + ), + child: Column(children: [ + _buildHeaderView(context), + Expanded(child: bodyCreatorView) + ]), + ), + ), + ), + ), + ), + ), + landscapeMobile: GestureDetector( + onTap: () => controller.clearFocusEditor(context), + child: Scaffold( + backgroundColor: Colors.white, + body: SafeArea( + left: false, + right: false, + child: KeyboardRichText( + keyBroadToolbar: RichTextKeyboardToolBar( + rootContext: context, + titleBack: AppLocalizations.of(context).titleFormat, + backgroundKeyboardToolBarColor: PlatformInfo.isIOS + ? AppColor.colorBackgroundKeyboard + : AppColor.colorBackgroundKeyboardAndroid, + richTextController: controller.richTextMobileTabletController!.richTextController, + quickStyleLabel: AppLocalizations.of(context).titleQuickStyles, + backgroundLabel: AppLocalizations.of(context).titleBackground, + foregroundLabel: AppLocalizations.of(context).titleForeground, + formatLabel: AppLocalizations.of(context).titleFormat, + insertImage: () => controller.pickImage(context), + ), + richTextController: controller.richTextMobileTabletController!.richTextController, + child: SafeArea( + child: Column(children: [ + _buildHeaderView(context), + Expanded(child: bodyCreatorView) + ]), + ), + ), + ) + ), + ), + tablet: Portal( + child: GestureDetector( + onTap: () => controller.clearFocusEditor(context), + child: Scaffold( + backgroundColor: Colors.black38, + body: SafeArea( + child: KeyboardRichText( + keyBroadToolbar: RichTextKeyboardToolBar( + rootContext: context, + titleBack: AppLocalizations.of(context).titleFormat, + backgroundKeyboardToolBarColor: PlatformInfo.isIOS + ? AppColor.colorBackgroundKeyboard + : AppColor.colorBackgroundKeyboardAndroid, + richTextController: controller.richTextMobileTabletController!.richTextController, + quickStyleLabel: AppLocalizations.of(context).titleQuickStyles, + backgroundLabel: AppLocalizations.of(context).titleBackground, + foregroundLabel: AppLocalizations.of(context).titleForeground, + formatLabel: AppLocalizations.of(context).titleFormat, + insertImage: () => controller.pickImage(context), + ), + richTextController: controller.richTextMobileTabletController!.richTextController, + child: Center( + child: Padding( + padding: const EdgeInsetsDirectional.symmetric(horizontal: 24), + child: Card( + color: Colors.transparent, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(16)) + ), + clipBehavior: Clip.antiAlias, + child: Container( + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(16)) + ), + width: math.max(controller.responsiveUtils.getSizeScreenWidth(context) * 0.4, 700), + height: controller.responsiveUtils.getSizeScreenHeight(context) * 0.8, + child: Column(children: [ + _buildHeaderView(context), + Expanded(child: bodyCreatorView) + ]) + ) + ), + ) + ), + ), + ), + ), + ), + ) + ); + } } Widget _buildHeaderView(BuildContext context) {