TF-1512 Show keyboard below editor while type text
This commit is contained in:
@@ -18,7 +18,6 @@ import 'package:model/model.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/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/mailbox_creator/domain/model/verification/email_address_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 actionType = IdentityActionType.create.obs;
|
||||
final isDefaultIdentity = RxBool(false);
|
||||
final htmlEditorNode = FocusNode(debugLabel: 'html_editor');
|
||||
final identityCreatorBinding = IdentityCreatorBindings();
|
||||
|
||||
late RichTextController keyboardRichTextController;
|
||||
late RichTextWebController richTextWebController;
|
||||
@@ -75,8 +72,8 @@ class IdentityCreatorController extends BaseController {
|
||||
IdentityCreatorArguments? arguments;
|
||||
OnCreatedIdentityCallback? onCreatedIdentityCallback;
|
||||
VoidCallback? onDismissIdentityCreator;
|
||||
ScrollController? scrollController;
|
||||
|
||||
final ScrollController scrollController = ScrollController();
|
||||
final GlobalKey htmlKey = GlobalKey();
|
||||
final htmlEditorMinHeight = 160;
|
||||
|
||||
@@ -110,6 +107,7 @@ class IdentityCreatorController extends BaseController {
|
||||
inputNameIdentityController = TextEditingController();
|
||||
inputBccIdentityController = TextEditingController();
|
||||
inputNameIdentityFocusNode = FocusNode();
|
||||
scrollController = ScrollController();
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -128,7 +126,6 @@ class IdentityCreatorController extends BaseController {
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
keyboardRichTextController.dispose();
|
||||
_disposeWidget();
|
||||
super.onClose();
|
||||
}
|
||||
@@ -153,9 +150,11 @@ class IdentityCreatorController extends BaseController {
|
||||
_nameIdentity = identity?.name ?? '';
|
||||
inputNameIdentityController?.text = identity?.name ?? '';
|
||||
|
||||
if (identity?.htmlSignature?.value.isNotEmpty == true) {
|
||||
updateContentHtmlEditor(arguments?.identity?.htmlSignature?.value ?? '');
|
||||
signatureHtmlEditorController.setText(arguments?.identity?.htmlSignature?.value ?? '');
|
||||
if (identity?.signatureAsString.isNotEmpty == true) {
|
||||
updateContentHtmlEditor(arguments?.identity?.signatureAsString ?? '');
|
||||
if (BuildUtils.isWeb) {
|
||||
signatureHtmlEditorController.setText(arguments?.identity?.signatureAsString ?? '');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -339,14 +338,13 @@ class IdentityCreatorController extends BaseController {
|
||||
newIdentity,
|
||||
isDefaultIdentity: isDefaultIdentity.value
|
||||
);
|
||||
_disposeWidget();
|
||||
|
||||
if (BuildUtils.isWeb) {
|
||||
_disposeWidget();
|
||||
onCreatedIdentityCallback?.call(identityRequest);
|
||||
} else {
|
||||
popBack(result: identityRequest);
|
||||
}
|
||||
|
||||
} else {
|
||||
final identityRequest = EditIdentityRequest(
|
||||
identityId: identity!.id!,
|
||||
@@ -360,7 +358,6 @@ class IdentityCreatorController extends BaseController {
|
||||
popBack(result: identityRequest);
|
||||
}
|
||||
}
|
||||
identityCreatorBinding.dispose();
|
||||
}
|
||||
|
||||
void onCheckboxChanged() {
|
||||
@@ -433,40 +430,42 @@ class IdentityCreatorController extends BaseController {
|
||||
onDismissIdentityCreator?.call();
|
||||
} else {
|
||||
popBack();
|
||||
identityCreatorBinding.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
void _disposeWidget() {
|
||||
keyboardRichTextController.dispose();
|
||||
inputNameIdentityFocusNode?.dispose();
|
||||
inputNameIdentityFocusNode = null;
|
||||
inputNameIdentityController?.dispose();
|
||||
inputNameIdentityController = null;
|
||||
inputBccIdentityController?.dispose();
|
||||
inputBccIdentityController = null;
|
||||
scrollController.dispose();
|
||||
scrollController?.dispose();
|
||||
}
|
||||
|
||||
void onFocusHTMLEditorOnMobile() async {
|
||||
if (htmlKey.currentContext != null) {
|
||||
await Scrollable.ensureVisible(htmlKey.currentContext!);
|
||||
if (scrollController != null) {
|
||||
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() {
|
||||
if(scrollController.position.pixels < scrollController.position.maxScrollExtent) {
|
||||
scrollController.animateTo(
|
||||
scrollController.position.pixels + 20,
|
||||
if (scrollController != null && scrollController!.position.pixels < scrollController!.position.maxScrollExtent) {
|
||||
scrollController!.animateTo(
|
||||
scrollController!.position.pixels + 20,
|
||||
duration: const Duration(milliseconds: 1),
|
||||
curve: Curves.linear,
|
||||
);
|
||||
|
||||
@@ -50,14 +50,47 @@ class IdentityCreatorView extends GetWidget<IdentityCreatorController> {
|
||||
Widget build(BuildContext context) {
|
||||
return ResponsiveWidget(
|
||||
responsiveUtils: _responsiveUtils,
|
||||
mobile: GestureDetector(
|
||||
onTap: () => controller.clearFocusEditor(context),
|
||||
child: SizedBox(
|
||||
height: MediaQuery.of(context).size.height * 0.95,
|
||||
child: BuildUtils.isWeb
|
||||
? Scaffold(body: _buildBodyMobile(context))
|
||||
: _buildBodyMobile(context)
|
||||
)
|
||||
mobile: Card(
|
||||
margin: EdgeInsets.zero,
|
||||
borderOnForeground: false,
|
||||
color: Colors.transparent,
|
||||
child: SafeArea(
|
||||
top: !BuildUtils.isWeb,
|
||||
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(
|
||||
backgroundColor: Colors.white,
|
||||
@@ -163,7 +196,7 @@ class IdentityCreatorView extends GetWidget<IdentityCreatorController> {
|
||||
controller: controller.scrollController,
|
||||
physics: const ClampingScrollPhysics(),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(24.0),
|
||||
padding: const EdgeInsets.all(24.0),
|
||||
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||
Obx(() => (IdentityInputFieldBuilder(
|
||||
AppLocalizations.of(context).name,
|
||||
@@ -223,27 +256,21 @@ class IdentityCreatorView extends GetWidget<IdentityCreatorController> {
|
||||
.build()
|
||||
),
|
||||
const SizedBox(height: 32),
|
||||
Row(
|
||||
children: [
|
||||
Text(AppLocalizations.of(context).signature,
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.normal,
|
||||
fontSize: 14,
|
||||
color: AppColor.colorContentEmail,
|
||||
),
|
||||
),
|
||||
],
|
||||
Text(AppLocalizations.of(context).signature,
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.normal,
|
||||
fontSize: 14,
|
||||
color: AppColor.colorContentEmail,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
PointerInterceptor(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
border: Border.all(color: AppColor.colorInputBorderCreateMailbox),
|
||||
color: Colors.white,
|
||||
),
|
||||
child: _buildSignatureHtmlTemplate(context),
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
border: Border.all(color: AppColor.colorInputBorderCreateMailbox),
|
||||
color: Colors.white,
|
||||
),
|
||||
child: _buildSignatureHtmlTemplate(context),
|
||||
),
|
||||
if (_responsiveUtils.isTablet(context) || _responsiveUtils.isMobile(context))...[
|
||||
Obx(() => Padding(
|
||||
|
||||
+7
-25
@@ -11,8 +11,6 @@ import 'package:get/get.dart';
|
||||
import 'package:jmap_dart_client/jmap/account_id.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/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/manage_account/domain/model/create_new_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/profiles/identities/widgets/delete_identity_dialog_builder.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';
|
||||
|
||||
class IdentitiesController extends BaseController {
|
||||
@@ -40,7 +39,6 @@ class IdentitiesController extends BaseController {
|
||||
final _appToast = Get.find<AppToast>();
|
||||
final _imagePaths = Get.find<ImagePaths>();
|
||||
final _responsiveUtils = Get.find<ResponsiveUtils>();
|
||||
final _identityCreatorBindings = IdentityCreatorBindings();
|
||||
|
||||
final GetAllIdentitiesInteractor _getAllIdentitiesInteractor;
|
||||
final CreateNewIdentityInteractor _createNewIdentityInteractor;
|
||||
@@ -165,8 +163,9 @@ class IdentitiesController extends BaseController {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
final newIdentityArguments =
|
||||
await _getIdentityRequest(context, arguments);
|
||||
final newIdentityArguments = await push(
|
||||
AppRoutes.identityCreator,
|
||||
arguments: arguments);
|
||||
|
||||
if (newIdentityArguments is CreateNewIdentityRequest) {
|
||||
_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(
|
||||
AccountId accountId,
|
||||
CreateNewIdentityRequest identityRequest
|
||||
@@ -308,7 +288,9 @@ class IdentitiesController extends BaseController {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
final newIdentityArguments = await _getIdentityRequest(context, arguments);
|
||||
final newIdentityArguments = await push(
|
||||
AppRoutes.identityCreator,
|
||||
arguments: arguments);
|
||||
|
||||
if (newIdentityArguments is CreateNewIdentityRequest) {
|
||||
_createNewIdentityAction(accountId, newIdentityArguments);
|
||||
|
||||
@@ -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_view.dart';
|
||||
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_view.dart' deferred as rules_filter_creator;
|
||||
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;
|
||||
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/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/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;
|
||||
@@ -107,6 +109,14 @@ class AppPages {
|
||||
() => search_mailbox_view.SearchMailboxView()
|
||||
),
|
||||
binding: SearchMailboxBindings()),
|
||||
GetPage(
|
||||
name: AppRoutes.identityCreator,
|
||||
opaque: false,
|
||||
page: () => DeferredWidget(
|
||||
identity_creator.loadLibrary,
|
||||
() => identity_creator.IdentityCreatorView()
|
||||
),
|
||||
binding: IdentityCreatorBindings()),
|
||||
]
|
||||
];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user