From b27d2818768e8c6ec5b677f05ecb80c05cd4dcda Mon Sep 17 00:00:00 2001 From: ManhNTX Date: Tue, 26 Jul 2022 13:56:19 +0700 Subject: [PATCH] add insert inline image function --- .../presentation/composer_controller.dart | 77 ++++++++--- .../composer/presentation/composer_view.dart | 130 ++++++++++-------- .../rich_text_mobile_tablet_controller.dart | 14 ++ 3 files changed, 147 insertions(+), 74 deletions(-) diff --git a/lib/features/composer/presentation/composer_controller.dart b/lib/features/composer/presentation/composer_controller.dart index 1181eb8fc..726c2c5a6 100644 --- a/lib/features/composer/presentation/composer_controller.dart +++ b/lib/features/composer/presentation/composer_controller.dart @@ -139,7 +139,7 @@ class ComposerController extends BaseController { log('ComposerController::_getEmailBodyText():WEB: newContentHtml: $newContentHtml'); return newContentHtml; } else { - final contentHtml = await htmlEditorApi?.getText() ?? ''; + final contentHtml = (await htmlEditorApi?.getText() ?? '').replaceAll('"', '"'); log('ComposerController::_getEmailBodyText():MOBILE: $contentHtml'); final newContentHtml = contentHtml.removeEditorStartTag(); if (changedEmail) { @@ -247,13 +247,23 @@ class ComposerController extends BaseController { selectIdentity(listIdentities.first); } } else if (success is DownloadImageAsBase64Success) { - richTextWebController.insertImage( - InlineImage( - ImageSource.local, - fileInfo: success.fileInfo, - cid: success.cid, - base64: success.imageAsBase64), - maxWithEditor: maxWithEditor); + if(kIsWeb) { + richTextWebController.insertImage( + InlineImage( + ImageSource.local, + fileInfo: success.fileInfo, + cid: success.cid, + base64: success.imageAsBase64), + maxWithEditor: maxWithEditor); + } else { + richTextMobileTabletController.insertImage( + InlineImage( + ImageSource.local, + fileInfo: success.fileInfo, + cid: success.cid, + base64: success.imageAsBase64), + maxWithEditor: maxWithEditor); + } maxWithEditor = null; } }); @@ -1111,16 +1121,41 @@ class ComposerController extends BaseController { } void insertImage(BuildContext context, {double? maxWithEditor}) async { - await InsertImageDialogBuilder( - context, - insertActionCallback: (inlineImage) { - log('ComposerController::insertImage(): ${inlineImage.source}|$maxWithEditor'); - if (BuildUtils.isWeb) { - this.maxWithEditor = maxWithEditor; - _insertImageOnWeb(inlineImage); + if(kIsWeb) { + await InsertImageDialogBuilder( + context, + insertActionCallback: (inlineImage) { + log('ComposerController::insertImage(): ${inlineImage.source}|$maxWithEditor'); + if (BuildUtils.isWeb) { + this.maxWithEditor = maxWithEditor; + _insertImageOnWeb(inlineImage); + } } - } - ).show(); + ).show(); + } else { + final inlineImage = await _selectFromFile(); + if(inlineImage != null) { + this.maxWithEditor = maxWithEditor; + _insertImageOnMobileAndTablet(inlineImage); + } + } + } + + Future _selectFromFile() async { + final filePickerResult = await FilePicker.platform.pickFiles( + type: FileType.image, + withReadStream: true); + final platformFile = filePickerResult?.files.single; + if (platformFile != null) { + final fileSelected = FileInfo( + platformFile.name, + BuildUtils.isWeb ? '' : platformFile.path ?? '', + platformFile.size, + readStream: platformFile.readStream); + return InlineImage(ImageSource.local, fileInfo: fileSelected); + } + + return null; } void _insertImageOnWeb(InlineImage inlineImage) { @@ -1131,6 +1166,14 @@ class ComposerController extends BaseController { } } + void _insertImageOnMobileAndTablet(InlineImage inlineImage) { + if (inlineImage.source == ImageSource.local) { + _uploadInlineAttachmentsAction(inlineImage.fileInfo!); + } else { + richTextMobileTabletController.insertImage(inlineImage); + } + } + void _uploadInlineAttachmentsAction(FileInfo pickedFile) async { if (uploadController.hasEnoughMaxAttachmentSize(listFiles: [pickedFile])) { final session = mailboxDashBoardController.sessionCurrent; diff --git a/lib/features/composer/presentation/composer_view.dart b/lib/features/composer/presentation/composer_view.dart index b367c7420..817b9bfe9 100644 --- a/lib/features/composer/presentation/composer_view.dart +++ b/lib/features/composer/presentation/composer_view.dart @@ -5,6 +5,7 @@ import 'package:file_picker/file_picker.dart'; import 'package:filesize/filesize.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:get/get.dart'; import 'package:jmap_dart_client/jmap/identities/identity.dart'; @@ -372,8 +373,8 @@ class ComposerView extends GetWidget with AppLoaderMixin, Ri ); } - Widget _buildListButton(BuildContext context) { - return Transform( + Widget _buildListButton(BuildContext context, BoxConstraints constraints) { + return Transform( transform: Matrix4.translationValues(-10.0, 0.0, 0.0), child: Padding( padding: const EdgeInsets.symmetric(vertical: 5), @@ -382,6 +383,16 @@ class ComposerView extends GetWidget with AppLoaderMixin, Ri icon: SvgPicture.asset(imagePaths.icAttachmentsComposer, color: AppColor.colorTextButton, fit: BoxFit.fill), tooltip: AppLocalizations.of(context).attach_file, onTap: () => controller.openPickAttachmentMenu(context, _pickAttachmentsActionTiles(context))), + buildIconWeb( + minSize: 40, + iconPadding: EdgeInsets.zero, + icon: SvgPicture.asset(imagePaths.icInsertImage, + color: AppColor.colorTextButton, + fit: BoxFit.fill), + tooltip: AppLocalizations.of(context).insertImage, + onTap: () => controller.insertImage( + context, + maxWithEditor: constraints.maxWidth - 120)) ]) ) ); @@ -390,67 +401,72 @@ class ComposerView extends GetWidget with AppLoaderMixin, Ri Widget _buildBodyMobile(BuildContext context) { return SingleChildScrollView( physics: const ClampingScrollPhysics(), - child: Column(children: [ - Obx(() => controller.identitySelected.value != null - ? _buildFromEmailAddress(context) - : const SizedBox.shrink()), - Obx(() => controller.identitySelected.value != null - ? const Divider(color: AppColor.colorDividerComposer, height: 1) - : const SizedBox.shrink()), - _buildEmailAddress(context), - const Divider(color: AppColor.colorDividerComposer, height: 1), - Padding(padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), child: _buildSubjectEmail(context)), - const Divider(color: AppColor.colorDividerComposer, height: 1), - Padding(padding: const EdgeInsets.symmetric(horizontal: 16), child: _buildListButton(context)), - const Divider(color: AppColor.colorDividerComposer, height: 1), - _buildAttachmentsWidget(context), - _buildComposerEditor(context), - ]) + child: LayoutBuilder( + builder: (context, constraints) => Column(children: [ + Obx(() => controller.identitySelected.value != null + ? _buildFromEmailAddress(context) + : const SizedBox.shrink()), + Obx(() => controller.identitySelected.value != null + ? const Divider(color: AppColor.colorDividerComposer, height: 1) + : const SizedBox.shrink()), + _buildEmailAddress(context), + const Divider(color: AppColor.colorDividerComposer, height: 1), + Padding(padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), child: _buildSubjectEmail(context)), + const Divider(color: AppColor.colorDividerComposer, height: 1), + Padding(padding: const EdgeInsets.symmetric(horizontal: 16), child: _buildListButton(context, constraints)), + const Divider(color: AppColor.colorDividerComposer, height: 1), + _buildAttachmentsWidget(context), + _buildInlineLoadingView(), + _buildComposerEditor(context), + ]), + ) ); } Widget _buildBodyTablet(BuildContext context) { return SingleChildScrollView( physics: const ClampingScrollPhysics(), - child: Column(children: [ - Padding( - padding: const EdgeInsets.only(left: 16), - child: Row(crossAxisAlignment: CrossAxisAlignment.start, children: [ - Padding(padding: const EdgeInsets.only(top: 20), - child: (AvatarBuilder() - ..text(controller.mailboxDashBoardController.userProfile.value?.getAvatarText() ?? '') - ..size(56) - ..addTextStyle(const TextStyle(fontWeight: FontWeight.w600, fontSize: 28, color: Colors.white)) - ..backgroundColor(AppColor.colorAvatar)) - .build()), - Expanded(child: Padding( - padding: const EdgeInsets.only(left: 16), - child: Column(children: [ - Obx(() => controller.identitySelected.value != null - ? _buildFromEmailAddress(context) - : const SizedBox.shrink()), - Obx(() => controller.identitySelected.value != null - ? const Divider(color: AppColor.colorDividerComposer, height: 1) - : const SizedBox.shrink()), - _buildEmailAddress(context), - const Divider(color: AppColor.colorDividerComposer, height: 1), - Padding(padding: const EdgeInsets.only(right: 16), child: _buildSubjectEmail(context)), - const Divider(color: AppColor.colorDividerComposer, height: 1), - _buildListButton(context), - ]), - )) - ])), - const Divider(color: AppColor.colorDividerComposer, height: 1), - Padding( - padding: const EdgeInsets.only(left: 60, right: 25), - child: Column(children: [ - _buildToolbarRichTextWidget(context), - _buildAttachmentsWidget(context), - _buildInlineLoadingView(), - _buildComposerEditor(context), - ]) - ) - ]) + child: LayoutBuilder( + builder: (context, constraints) => Column(children: [ + Padding( + padding: const EdgeInsets.only(left: 16), + child: Row(crossAxisAlignment: CrossAxisAlignment.start, children: [ + Padding(padding: const EdgeInsets.only(top: 20), + child: (AvatarBuilder() + ..text(controller.mailboxDashBoardController.userProfile.value?.getAvatarText() ?? '') + ..size(56) + ..addTextStyle(const TextStyle(fontWeight: FontWeight.w600, fontSize: 28, color: Colors.white)) + ..backgroundColor(AppColor.colorAvatar)) + .build()), + Expanded(child: Padding( + padding: const EdgeInsets.only(left: 16), + child: Column(children: [ + Obx(() => controller.identitySelected.value != null + ? _buildFromEmailAddress(context) + : const SizedBox.shrink()), + Obx(() => controller.identitySelected.value != null + ? const Divider(color: AppColor.colorDividerComposer, height: 1) + : const SizedBox.shrink()), + _buildEmailAddress(context), + const Divider(color: AppColor.colorDividerComposer, height: 1), + Padding(padding: const EdgeInsets.only(right: 16), child: _buildSubjectEmail(context)), + const Divider(color: AppColor.colorDividerComposer, height: 1), + _buildListButton(context, constraints), + ]), + )) + ])), + const Divider(color: AppColor.colorDividerComposer, height: 1), + Padding( + padding: const EdgeInsets.only(left: 60, right: 25), + child: Column(children: [ + _buildToolbarRichTextWidget(context), + _buildAttachmentsWidget(context), + _buildInlineLoadingView(), + _buildComposerEditor(context), + ]) + ) + ]), + ) ); } diff --git a/lib/features/composer/presentation/controller/rich_text_mobile_tablet_controller.dart b/lib/features/composer/presentation/controller/rich_text_mobile_tablet_controller.dart index 1b9e732cf..0ce31659e 100644 --- a/lib/features/composer/presentation/controller/rich_text_mobile_tablet_controller.dart +++ b/lib/features/composer/presentation/controller/rich_text_mobile_tablet_controller.dart @@ -1,8 +1,11 @@ +import 'package:core/core.dart'; import 'package:enough_html_editor/enough_html_editor.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:tmail_ui_user/features/composer/presentation/controller/base_rich_text_controller.dart'; import 'package:tmail_ui_user/features/composer/presentation/model/dropdown_menu_font_status.dart'; +import 'package:tmail_ui_user/features/composer/presentation/model/image_source.dart'; +import 'package:tmail_ui_user/features/composer/presentation/model/inline_image.dart'; import 'package:tmail_ui_user/features/composer/presentation/model/rich_text_style_type.dart'; import 'package:tmail_ui_user/main/routes/route_navigation.dart'; @@ -109,4 +112,15 @@ class RichTextMobileTabletController extends BaseRichTextController { void closeDropdownMenuFont() { popBack(); } + + void insertImage(InlineImage image, {double? maxWithEditor}) async { + log('RichTextMobileTabletController::insertImage(): $image | maxWithEditor: $maxWithEditor'); + if (image.source == ImageSource.network) { + htmlEditorApi?.insertImageLink(image.link!); + } else { + final htmlContent = await image.generateImgTagHtml(maxWithEditor: maxWithEditor); + log('RichTextMobileTabletController::insertImage(): $htmlContent'); + htmlEditorApi?.insertHtml(htmlContent); + } + } }