TF-2118 Handle drop n drop image as inline
(cherry picked from commit 2eb6ad6a05224b3caafc59565fd5fa6bdd819870)
This commit is contained in:
@@ -9,6 +9,8 @@ extension MediaTypeExtension on MediaType {
|
||||
|
||||
bool isImageFile() => SupportedPreviewFileTypes.imageMimeTypes.contains(mimeType);
|
||||
|
||||
bool isImageValid() => type == 'image';
|
||||
|
||||
bool isDocFile() => SupportedPreviewFileTypes.docMimeTypes.contains(mimeType);
|
||||
|
||||
bool isPowerPointFile() => SupportedPreviewFileTypes.pptMimeTypes.contains(mimeType);
|
||||
|
||||
@@ -15,6 +15,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:html_editor_enhanced/html_editor.dart' as web_html_editor;
|
||||
import 'package:http_parser/http_parser.dart';
|
||||
import 'package:jmap_dart_client/jmap/account_id.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/id.dart';
|
||||
@@ -1838,6 +1839,62 @@ class ComposerController extends BaseController {
|
||||
onEditorFocusChange(true);
|
||||
}
|
||||
|
||||
void handleImageUploadSuccess(
|
||||
BuildContext context,
|
||||
web_html_editor.FileUpload fileUpload
|
||||
) {
|
||||
log('ComposerController::handleImageUploadSuccess:NAME: ${fileUpload.name} | TYPE: ${fileUpload.type} | SIZE: ${fileUpload.size}');
|
||||
if (fileUpload.base64 == null) {
|
||||
_appToast.showToastErrorMessage(
|
||||
context,
|
||||
AppLocalizations.of(context).can_not_upload_this_file_as_attachments
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fileUpload.type == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final mediaType = MediaType.parse(fileUpload.type!);
|
||||
if (mediaType.isImageValid()) {
|
||||
_addInlineImageFromDragAndDrop(
|
||||
base64Data: fileUpload.base64!,
|
||||
name: fileUpload.name,
|
||||
type: mediaType,
|
||||
size: fileUpload.size,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void _addInlineImageFromDragAndDrop({
|
||||
required String base64Data,
|
||||
String? name,
|
||||
MediaType? type,
|
||||
int? size
|
||||
}) {
|
||||
log('ComposerController::_addInlineImageFromDragAndDrop:name: $name');
|
||||
richTextWebController.insertInlineImage(
|
||||
base64Data: base64Data,
|
||||
name: name,
|
||||
type: type,
|
||||
size: size,
|
||||
);
|
||||
}
|
||||
|
||||
void handleImageUploadFailure({
|
||||
required BuildContext context,
|
||||
required web_html_editor.UploadError uploadError,
|
||||
web_html_editor.FileUpload? fileUpload,
|
||||
String? base64Str,
|
||||
}) {
|
||||
logError('ComposerController::handleImageUploadFailure:fileUpload: $fileUpload | uploadError: $uploadError');
|
||||
_appToast.showToastErrorMessage(
|
||||
context,
|
||||
'${AppLocalizations.of(context).can_not_upload_this_file_as_attachments}. (${uploadError.name})'
|
||||
);
|
||||
}
|
||||
|
||||
FocusNode? getNextFocusOfToEmailAddress() {
|
||||
if (ccRecipientState.value == PrefixRecipientState.enabled) {
|
||||
return ccAddressFocusNode;
|
||||
|
||||
@@ -161,6 +161,15 @@ class ComposerView extends GetWidget<ComposerController> {
|
||||
onUnFocus: controller.handleOnUnFocusHtmlEditorWeb,
|
||||
onMouseDown: controller.handleOnMouseDownHtmlEditorWeb,
|
||||
onEditorSettings: controller.richTextWebController.onEditorSettingsChange,
|
||||
onImageUploadSuccessAction: (fileUpload) => controller.handleImageUploadSuccess(context, fileUpload),
|
||||
onImageUploadFailureAction: (fileUpload, base64Str, uploadError) {
|
||||
return controller.handleImageUploadFailure(
|
||||
context: context,
|
||||
uploadError: uploadError,
|
||||
fileUpload: fileUpload,
|
||||
base64Str: base64Str,
|
||||
);
|
||||
}
|
||||
),
|
||||
),
|
||||
Obx(() => Align(
|
||||
@@ -330,6 +339,15 @@ class ComposerView extends GetWidget<ComposerController> {
|
||||
onUnFocus: controller.handleOnUnFocusHtmlEditorWeb,
|
||||
onMouseDown: controller.handleOnMouseDownHtmlEditorWeb,
|
||||
onEditorSettings: controller.richTextWebController.onEditorSettingsChange,
|
||||
onImageUploadSuccessAction: (fileUpload) => controller.handleImageUploadSuccess(context, fileUpload),
|
||||
onImageUploadFailureAction: (fileUpload, base64Str, uploadError) {
|
||||
return controller.handleImageUploadFailure(
|
||||
context: context,
|
||||
uploadError: uploadError,
|
||||
fileUpload: fileUpload,
|
||||
base64Str: base64Str,
|
||||
);
|
||||
}
|
||||
),
|
||||
),
|
||||
)),
|
||||
@@ -523,6 +541,15 @@ class ComposerView extends GetWidget<ComposerController> {
|
||||
onUnFocus: controller.handleOnUnFocusHtmlEditorWeb,
|
||||
onMouseDown: controller.handleOnMouseDownHtmlEditorWeb,
|
||||
onEditorSettings: controller.richTextWebController.onEditorSettingsChange,
|
||||
onImageUploadSuccessAction: (fileUpload) => controller.handleImageUploadSuccess(context, fileUpload),
|
||||
onImageUploadFailureAction: (fileUpload, base64Str, uploadError) {
|
||||
return controller.handleImageUploadFailure(
|
||||
context: context,
|
||||
uploadError: uploadError,
|
||||
fileUpload: fileUpload,
|
||||
base64Str: base64Str,
|
||||
);
|
||||
}
|
||||
),
|
||||
),
|
||||
)),
|
||||
|
||||
@@ -8,6 +8,7 @@ import 'package:file_picker/file_picker.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:html_editor_enhanced/html_editor.dart';
|
||||
import 'package:http_parser/http_parser.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/model/code_view_state.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/model/dropdown_menu_font_status.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/model/formatting_options_state.dart';
|
||||
@@ -185,6 +186,17 @@ class RichTextWebController extends BaseRichTextController {
|
||||
}
|
||||
}
|
||||
|
||||
void insertInlineImage({
|
||||
required String base64Data,
|
||||
String? name,
|
||||
MediaType? type,
|
||||
int? size,
|
||||
}) async {
|
||||
log('RichTextWebController::insertInlineImage():name: $name | type: $type');
|
||||
final base64Uri = '<img src="$base64Data" data-filename="$name" alt="Inline Image TeamMail" style="max-width: 100%" />';
|
||||
editorController.insertHtml(base64Uri);
|
||||
}
|
||||
|
||||
void applyNewFontStyle(FontNameType? newFont) {
|
||||
final fontSelected = newFont ?? FontNameType.sansSerif;
|
||||
selectedFontName.value = fontSelected;
|
||||
|
||||
@@ -26,6 +26,8 @@ class WebEditorView extends StatelessWidget with EditorViewMixin {
|
||||
final VoidCallback? onUnFocus;
|
||||
final OnMouseDownEditorAction? onMouseDown;
|
||||
final OnEditorSettingsChange? onEditorSettings;
|
||||
final OnImageUploadSuccessAction? onImageUploadSuccessAction;
|
||||
final OnImageUploadFailureAction? onImageUploadFailureAction;
|
||||
|
||||
const WebEditorView({
|
||||
super.key,
|
||||
@@ -39,6 +41,8 @@ class WebEditorView extends StatelessWidget with EditorViewMixin {
|
||||
this.onUnFocus,
|
||||
this.onMouseDown,
|
||||
this.onEditorSettings,
|
||||
this.onImageUploadSuccessAction,
|
||||
this.onImageUploadFailureAction,
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -61,6 +65,8 @@ class WebEditorView extends StatelessWidget with EditorViewMixin {
|
||||
onUnFocus: onUnFocus,
|
||||
onMouseDown: onMouseDown,
|
||||
onEditorSettings: onEditorSettings,
|
||||
onImageUploadSuccessAction: onImageUploadSuccessAction,
|
||||
onImageUploadFailureAction: onImageUploadFailureAction,
|
||||
);
|
||||
case EmailActionType.editDraft:
|
||||
case EmailActionType.editSendingEmail:
|
||||
@@ -80,6 +86,8 @@ class WebEditorView extends StatelessWidget with EditorViewMixin {
|
||||
onUnFocus: onUnFocus,
|
||||
onMouseDown: onMouseDown,
|
||||
onEditorSettings: onEditorSettings,
|
||||
onImageUploadSuccessAction: onImageUploadSuccessAction,
|
||||
onImageUploadFailureAction: onImageUploadFailureAction,
|
||||
),
|
||||
(success) {
|
||||
if (success is GetEmailContentLoading) {
|
||||
@@ -101,6 +109,8 @@ class WebEditorView extends StatelessWidget with EditorViewMixin {
|
||||
onUnFocus: onUnFocus,
|
||||
onMouseDown: onMouseDown,
|
||||
onEditorSettings: onEditorSettings,
|
||||
onImageUploadSuccessAction: onImageUploadSuccessAction,
|
||||
onImageUploadFailureAction: onImageUploadFailureAction,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -129,6 +139,8 @@ class WebEditorView extends StatelessWidget with EditorViewMixin {
|
||||
onUnFocus: onUnFocus,
|
||||
onMouseDown: onMouseDown,
|
||||
onEditorSettings: onEditorSettings,
|
||||
onImageUploadSuccessAction: onImageUploadSuccessAction,
|
||||
onImageUploadFailureAction: onImageUploadFailureAction,
|
||||
);
|
||||
},
|
||||
(success) {
|
||||
@@ -153,6 +165,8 @@ class WebEditorView extends StatelessWidget with EditorViewMixin {
|
||||
onUnFocus: onUnFocus,
|
||||
onMouseDown: onMouseDown,
|
||||
onEditorSettings: onEditorSettings,
|
||||
onImageUploadSuccessAction: onImageUploadSuccessAction,
|
||||
onImageUploadFailureAction: onImageUploadFailureAction,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -168,6 +182,8 @@ class WebEditorView extends StatelessWidget with EditorViewMixin {
|
||||
onUnFocus: onUnFocus,
|
||||
onMouseDown: onMouseDown,
|
||||
onEditorSettings: onEditorSettings,
|
||||
onImageUploadSuccessAction: onImageUploadSuccessAction,
|
||||
onImageUploadFailureAction: onImageUploadFailureAction,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@ typedef OnChangeContentEditorAction = Function(String? text);
|
||||
typedef OnInitialContentEditorAction = Function(String text);
|
||||
typedef OnMouseDownEditorAction = Function(BuildContext context);
|
||||
typedef OnEditorSettingsChange = Function(EditorSettings settings);
|
||||
typedef OnImageUploadSuccessAction = Function(FileUpload fileUpload);
|
||||
typedef OnImageUploadFailureAction = Function(FileUpload? fileUpload, String? base64Str, UploadError error);
|
||||
|
||||
class WebEditorWidget extends StatefulWidget {
|
||||
|
||||
@@ -20,6 +22,8 @@ class WebEditorWidget extends StatefulWidget {
|
||||
final VoidCallback? onUnFocus;
|
||||
final OnMouseDownEditorAction? onMouseDown;
|
||||
final OnEditorSettingsChange? onEditorSettings;
|
||||
final OnImageUploadSuccessAction? onImageUploadSuccessAction;
|
||||
final OnImageUploadFailureAction? onImageUploadFailureAction;
|
||||
|
||||
const WebEditorWidget({
|
||||
super.key,
|
||||
@@ -32,6 +36,8 @@ class WebEditorWidget extends StatefulWidget {
|
||||
this.onUnFocus,
|
||||
this.onMouseDown,
|
||||
this.onEditorSettings,
|
||||
this.onImageUploadSuccessAction,
|
||||
this.onImageUploadFailureAction,
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -82,7 +88,9 @@ class _WebEditorState extends State<WebEditorWidget> {
|
||||
onBlur: widget.onUnFocus,
|
||||
onMouseDown: () => widget.onMouseDown?.call(context),
|
||||
onChangeSelection: widget.onEditorSettings,
|
||||
onChangeCodeview: widget.onChangeContent
|
||||
onChangeCodeview: widget.onChangeContent,
|
||||
onImageUpload: widget.onImageUploadSuccessAction,
|
||||
onImageUploadError: widget.onImageUploadFailureAction,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user