TF-1512 Show keyboard below editor while type text

This commit is contained in:
dab246
2023-03-01 17:36:40 +07:00
committed by Dat Vu
parent b9ea97baa5
commit 9609e7ee9c
4 changed files with 98 additions and 80 deletions
@@ -18,7 +18,6 @@ import 'package:model/model.dart';
import 'package:rich_text_composer/richtext_controller.dart'; import 'package:rich_text_composer/richtext_controller.dart';
import 'package:tmail_ui_user/features/base/base_controller.dart'; import 'package:tmail_ui_user/features/base/base_controller.dart';
import 'package:tmail_ui_user/features/composer/presentation/controller/rich_text_web_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/identity_creator_bindings.dart';
import 'package:tmail_ui_user/features/identity_creator/presentation/model/identity_creator_arguments.dart'; import 'package:tmail_ui_user/features/identity_creator/presentation/model/identity_creator_arguments.dart';
import 'package:tmail_ui_user/features/mailbox_creator/domain/model/verification/email_address_validator.dart'; import 'package:tmail_ui_user/features/mailbox_creator/domain/model/verification/email_address_validator.dart';
import 'package:tmail_ui_user/features/mailbox_creator/domain/model/verification/empty_name_validator.dart'; import 'package:tmail_ui_user/features/mailbox_creator/domain/model/verification/empty_name_validator.dart';
@@ -56,8 +55,6 @@ class IdentityCreatorController extends BaseController {
final bccOfIdentity = Rxn<EmailAddress>(); final bccOfIdentity = Rxn<EmailAddress>();
final actionType = IdentityActionType.create.obs; final actionType = IdentityActionType.create.obs;
final isDefaultIdentity = RxBool(false); final isDefaultIdentity = RxBool(false);
final htmlEditorNode = FocusNode(debugLabel: 'html_editor');
final identityCreatorBinding = IdentityCreatorBindings();
late RichTextController keyboardRichTextController; late RichTextController keyboardRichTextController;
late RichTextWebController richTextWebController; late RichTextWebController richTextWebController;
@@ -75,8 +72,8 @@ class IdentityCreatorController extends BaseController {
IdentityCreatorArguments? arguments; IdentityCreatorArguments? arguments;
OnCreatedIdentityCallback? onCreatedIdentityCallback; OnCreatedIdentityCallback? onCreatedIdentityCallback;
VoidCallback? onDismissIdentityCreator; VoidCallback? onDismissIdentityCreator;
ScrollController? scrollController;
final ScrollController scrollController = ScrollController();
final GlobalKey htmlKey = GlobalKey(); final GlobalKey htmlKey = GlobalKey();
final htmlEditorMinHeight = 160; final htmlEditorMinHeight = 160;
@@ -110,6 +107,7 @@ class IdentityCreatorController extends BaseController {
inputNameIdentityController = TextEditingController(); inputNameIdentityController = TextEditingController();
inputBccIdentityController = TextEditingController(); inputBccIdentityController = TextEditingController();
inputNameIdentityFocusNode = FocusNode(); inputNameIdentityFocusNode = FocusNode();
scrollController = ScrollController();
} }
@override @override
@@ -128,7 +126,6 @@ class IdentityCreatorController extends BaseController {
@override @override
void onClose() { void onClose() {
keyboardRichTextController.dispose();
_disposeWidget(); _disposeWidget();
super.onClose(); super.onClose();
} }
@@ -153,9 +150,11 @@ class IdentityCreatorController extends BaseController {
_nameIdentity = identity?.name ?? ''; _nameIdentity = identity?.name ?? '';
inputNameIdentityController?.text = identity?.name ?? ''; inputNameIdentityController?.text = identity?.name ?? '';
if (identity?.htmlSignature?.value.isNotEmpty == true) { if (identity?.signatureAsString.isNotEmpty == true) {
updateContentHtmlEditor(arguments?.identity?.htmlSignature?.value ?? ''); updateContentHtmlEditor(arguments?.identity?.signatureAsString ?? '');
signatureHtmlEditorController.setText(arguments?.identity?.htmlSignature?.value ?? ''); if (BuildUtils.isWeb) {
signatureHtmlEditorController.setText(arguments?.identity?.signatureAsString ?? '');
}
} }
} }
@@ -339,14 +338,13 @@ class IdentityCreatorController extends BaseController {
newIdentity, newIdentity,
isDefaultIdentity: isDefaultIdentity.value isDefaultIdentity: isDefaultIdentity.value
); );
_disposeWidget();
if (BuildUtils.isWeb) { if (BuildUtils.isWeb) {
_disposeWidget();
onCreatedIdentityCallback?.call(identityRequest); onCreatedIdentityCallback?.call(identityRequest);
} else { } else {
popBack(result: identityRequest); popBack(result: identityRequest);
} }
} else { } else {
final identityRequest = EditIdentityRequest( final identityRequest = EditIdentityRequest(
identityId: identity!.id!, identityId: identity!.id!,
@@ -360,7 +358,6 @@ class IdentityCreatorController extends BaseController {
popBack(result: identityRequest); popBack(result: identityRequest);
} }
} }
identityCreatorBinding.dispose();
} }
void onCheckboxChanged() { void onCheckboxChanged() {
@@ -433,40 +430,42 @@ class IdentityCreatorController extends BaseController {
onDismissIdentityCreator?.call(); onDismissIdentityCreator?.call();
} else { } else {
popBack(); popBack();
identityCreatorBinding.dispose();
} }
} }
void _disposeWidget() { void _disposeWidget() {
keyboardRichTextController.dispose();
inputNameIdentityFocusNode?.dispose(); inputNameIdentityFocusNode?.dispose();
inputNameIdentityFocusNode = null; inputNameIdentityFocusNode = null;
inputNameIdentityController?.dispose(); inputNameIdentityController?.dispose();
inputNameIdentityController = null; inputNameIdentityController = null;
inputBccIdentityController?.dispose(); inputBccIdentityController?.dispose();
inputBccIdentityController = null; inputBccIdentityController = null;
scrollController.dispose(); scrollController?.dispose();
} }
void onFocusHTMLEditorOnMobile() async { void onFocusHTMLEditorOnMobile() async {
if (htmlKey.currentContext != null) { if (scrollController != null) {
await Scrollable.ensureVisible(htmlKey.currentContext!); if (htmlKey.currentContext != null) {
await Scrollable.ensureVisible(htmlKey.currentContext!);
}
await Future.delayed(const Duration(milliseconds: 500), () {
final offset = scrollController!.position.pixels +
defaultKeyboardToolbarHeight +
htmlEditorMinHeight;
scrollController!.animateTo(
offset,
duration: const Duration(milliseconds: 1),
curve: Curves.linear,
);
});
} }
await Future.delayed(const Duration(milliseconds: 500), () {
final offset = scrollController.position.pixels +
defaultKeyboardToolbarHeight +
htmlEditorMinHeight;
scrollController.animateTo(
offset,
duration: const Duration(milliseconds: 1),
curve: Curves.linear,
);
});
} }
void onEnterKeyDownOnMobile() { void onEnterKeyDownOnMobile() {
if(scrollController.position.pixels < scrollController.position.maxScrollExtent) { if (scrollController != null && scrollController!.position.pixels < scrollController!.position.maxScrollExtent) {
scrollController.animateTo( scrollController!.animateTo(
scrollController.position.pixels + 20, scrollController!.position.pixels + 20,
duration: const Duration(milliseconds: 1), duration: const Duration(milliseconds: 1),
curve: Curves.linear, curve: Curves.linear,
); );
@@ -50,14 +50,47 @@ class IdentityCreatorView extends GetWidget<IdentityCreatorController> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ResponsiveWidget( return ResponsiveWidget(
responsiveUtils: _responsiveUtils, responsiveUtils: _responsiveUtils,
mobile: GestureDetector( mobile: Card(
onTap: () => controller.clearFocusEditor(context), margin: EdgeInsets.zero,
child: SizedBox( borderOnForeground: false,
height: MediaQuery.of(context).size.height * 0.95, color: Colors.transparent,
child: BuildUtils.isWeb child: SafeArea(
? Scaffold(body: _buildBodyMobile(context)) top: !BuildUtils.isWeb,
: _buildBodyMobile(context) 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(
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),
]),
child: _buildBodyMobile(context),
),
),
),
),
),
), ),
landscapeMobile: Scaffold( landscapeMobile: Scaffold(
backgroundColor: Colors.white, backgroundColor: Colors.white,
@@ -163,7 +196,7 @@ class IdentityCreatorView extends GetWidget<IdentityCreatorController> {
controller: controller.scrollController, controller: controller.scrollController,
physics: const ClampingScrollPhysics(), physics: const ClampingScrollPhysics(),
child: Padding( child: Padding(
padding: const EdgeInsets.all(24.0), padding: const EdgeInsets.all(24.0),
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
Obx(() => (IdentityInputFieldBuilder( Obx(() => (IdentityInputFieldBuilder(
AppLocalizations.of(context).name, AppLocalizations.of(context).name,
@@ -223,27 +256,21 @@ class IdentityCreatorView extends GetWidget<IdentityCreatorController> {
.build() .build()
), ),
const SizedBox(height: 32), const SizedBox(height: 32),
Row( Text(AppLocalizations.of(context).signature,
children: [ style: const TextStyle(
Text(AppLocalizations.of(context).signature, fontWeight: FontWeight.normal,
style: const TextStyle( fontSize: 14,
fontWeight: FontWeight.normal, color: AppColor.colorContentEmail,
fontSize: 14, ),
color: AppColor.colorContentEmail,
),
),
],
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
PointerInterceptor( Container(
child: Container( decoration: BoxDecoration(
decoration: BoxDecoration( borderRadius: BorderRadius.circular(12),
borderRadius: BorderRadius.circular(12), border: Border.all(color: AppColor.colorInputBorderCreateMailbox),
border: Border.all(color: AppColor.colorInputBorderCreateMailbox), color: Colors.white,
color: Colors.white,
),
child: _buildSignatureHtmlTemplate(context),
), ),
child: _buildSignatureHtmlTemplate(context),
), ),
if (_responsiveUtils.isTablet(context) || _responsiveUtils.isMobile(context))...[ if (_responsiveUtils.isTablet(context) || _responsiveUtils.isMobile(context))...[
Obx(() => Padding( Obx(() => Padding(
@@ -11,8 +11,6 @@ import 'package:get/get.dart';
import 'package:jmap_dart_client/jmap/account_id.dart'; import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/identities/identity.dart'; import 'package:jmap_dart_client/jmap/identities/identity.dart';
import 'package:tmail_ui_user/features/base/base_controller.dart'; import 'package:tmail_ui_user/features/base/base_controller.dart';
import 'package:tmail_ui_user/features/identity_creator/presentation/identity_creator_bindings.dart';
import 'package:tmail_ui_user/features/identity_creator/presentation/identity_creator_view.dart';
import 'package:tmail_ui_user/features/identity_creator/presentation/model/identity_creator_arguments.dart'; import 'package:tmail_ui_user/features/identity_creator/presentation/model/identity_creator_arguments.dart';
import 'package:tmail_ui_user/features/manage_account/domain/model/create_new_identity_request.dart'; import 'package:tmail_ui_user/features/manage_account/domain/model/create_new_identity_request.dart';
import 'package:tmail_ui_user/features/manage_account/domain/model/edit_identity_request.dart'; import 'package:tmail_ui_user/features/manage_account/domain/model/edit_identity_request.dart';
@@ -32,6 +30,7 @@ import 'package:tmail_ui_user/features/manage_account/presentation/model/identit
import 'package:tmail_ui_user/features/manage_account/presentation/model/settings_page_level.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/model/settings_page_level.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/profiles/identities/widgets/delete_identity_dialog_builder.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/profiles/identities/widgets/delete_identity_dialog_builder.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
import 'package:tmail_ui_user/main/routes/app_routes.dart';
import 'package:tmail_ui_user/main/routes/route_navigation.dart'; import 'package:tmail_ui_user/main/routes/route_navigation.dart';
class IdentitiesController extends BaseController { class IdentitiesController extends BaseController {
@@ -40,7 +39,6 @@ class IdentitiesController extends BaseController {
final _appToast = Get.find<AppToast>(); final _appToast = Get.find<AppToast>();
final _imagePaths = Get.find<ImagePaths>(); final _imagePaths = Get.find<ImagePaths>();
final _responsiveUtils = Get.find<ResponsiveUtils>(); final _responsiveUtils = Get.find<ResponsiveUtils>();
final _identityCreatorBindings = IdentityCreatorBindings();
final GetAllIdentitiesInteractor _getAllIdentitiesInteractor; final GetAllIdentitiesInteractor _getAllIdentitiesInteractor;
final CreateNewIdentityInteractor _createNewIdentityInteractor; final CreateNewIdentityInteractor _createNewIdentityInteractor;
@@ -165,8 +163,9 @@ class IdentitiesController extends BaseController {
} }
}); });
} else { } else {
final newIdentityArguments = final newIdentityArguments = await push(
await _getIdentityRequest(context, arguments); AppRoutes.identityCreator,
arguments: arguments);
if (newIdentityArguments is CreateNewIdentityRequest) { if (newIdentityArguments is CreateNewIdentityRequest) {
_createNewIdentityAction(accountId, newIdentityArguments); _createNewIdentityAction(accountId, newIdentityArguments);
@@ -177,25 +176,6 @@ class IdentitiesController extends BaseController {
} }
} }
Future<dynamic> _getIdentityRequest(
BuildContext context,
dynamic arguments
) async {
return await showModalBottomSheet(
enableDrag: false,
context: context,
isScrollControlled: true,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(16.0),
topRight: Radius.circular(16.0)),
),
builder: (context) {
_identityCreatorBindings.dependencies();
return IdentityCreatorView.fromArguments(arguments);
});
}
void _createNewIdentityAction( void _createNewIdentityAction(
AccountId accountId, AccountId accountId,
CreateNewIdentityRequest identityRequest CreateNewIdentityRequest identityRequest
@@ -308,7 +288,9 @@ class IdentitiesController extends BaseController {
} }
}); });
} else { } else {
final newIdentityArguments = await _getIdentityRequest(context, arguments); final newIdentityArguments = await push(
AppRoutes.identityCreator,
arguments: arguments);
if (newIdentityArguments is CreateNewIdentityRequest) { if (newIdentityArguments is CreateNewIdentityRequest) {
_createNewIdentityAction(accountId, newIdentityArguments); _createNewIdentityAction(accountId, newIdentityArguments);
+10
View File
@@ -9,6 +9,7 @@ import 'package:tmail_ui_user/features/destination_picker/presentation/destinati
import 'package:tmail_ui_user/features/home/presentation/home_bindings.dart'; import 'package:tmail_ui_user/features/home/presentation/home_bindings.dart';
import 'package:tmail_ui_user/features/home/presentation/home_view.dart'; import 'package:tmail_ui_user/features/home/presentation/home_view.dart';
import 'package:tmail_ui_user/features/contact/presentation/contact_view.dart' deferred as contact_view; import 'package:tmail_ui_user/features/contact/presentation/contact_view.dart' deferred as contact_view;
import 'package:tmail_ui_user/features/identity_creator/presentation/identity_creator_bindings.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/rules_filter_creator_bindings.dart'; import 'package:tmail_ui_user/features/rules_filter_creator/presentation/rules_filter_creator_bindings.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/rules_filter_creator_view.dart' deferred as rules_filter_creator; import 'package:tmail_ui_user/features/rules_filter_creator/presentation/rules_filter_creator_view.dart' deferred as rules_filter_creator;
import 'package:tmail_ui_user/features/login/presentation/login_bindings.dart'; import 'package:tmail_ui_user/features/login/presentation/login_bindings.dart';
@@ -16,6 +17,7 @@ import 'package:tmail_ui_user/features/login/presentation/login_view.dart'
if (dart.library.html) 'package:tmail_ui_user/features/login/presentation/login_view_web.dart' deferred as login; if (dart.library.html) 'package:tmail_ui_user/features/login/presentation/login_view_web.dart' deferred as login;
import 'package:tmail_ui_user/features/mailbox_creator/presentation/mailbox_creator_bindings.dart'; import 'package:tmail_ui_user/features/mailbox_creator/presentation/mailbox_creator_bindings.dart';
import 'package:tmail_ui_user/features/mailbox_creator/presentation/mailbox_creator_view.dart' deferred as mailbox_creator; import 'package:tmail_ui_user/features/mailbox_creator/presentation/mailbox_creator_view.dart' deferred as mailbox_creator;
import 'package:tmail_ui_user/features/identity_creator/presentation/identity_creator_view.dart' deferred as identity_creator;
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/bindings/mailbox_dashboard_bindings.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/bindings/mailbox_dashboard_bindings.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mailbox_dashboard_view.dart' import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mailbox_dashboard_view.dart'
if (dart.library.html) 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mailbox_dashboard_view_web.dart' deferred as mailbox_dashboard; if (dart.library.html) 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mailbox_dashboard_view_web.dart' deferred as mailbox_dashboard;
@@ -107,6 +109,14 @@ class AppPages {
() => search_mailbox_view.SearchMailboxView() () => search_mailbox_view.SearchMailboxView()
), ),
binding: SearchMailboxBindings()), binding: SearchMailboxBindings()),
GetPage(
name: AppRoutes.identityCreator,
opaque: false,
page: () => DeferredWidget(
identity_creator.loadLibrary,
() => identity_creator.IdentityCreatorView()
),
binding: IdentityCreatorBindings()),
] ]
]; ];