TF-2118 Handle drop n drop file as attachment

(cherry picked from commit cb1f15dcba46a15dbd5c5a8493593854855be331)
This commit is contained in:
dab246
2023-09-28 11:12:34 +07:00
committed by Dat H. Pham
parent 25b26acc42
commit 8b20e9e1d4
6 changed files with 105 additions and 8 deletions
@@ -49,6 +49,7 @@ import 'package:tmail_ui_user/features/composer/domain/usecases/update_email_dra
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_mobile_tablet_controller.dart';
import 'package:tmail_ui_user/features/composer/presentation/extensions/email_action_type_extension.dart';
import 'package:tmail_ui_user/features/composer/presentation/extensions/file_upload_extension.dart';
import 'package:tmail_ui_user/features/composer/presentation/extensions/list_identities_extension.dart';
import 'package:tmail_ui_user/features/composer/presentation/model/draggable_email_address.dart';
import 'package:tmail_ui_user/features/composer/presentation/model/image_source.dart';
@@ -1839,10 +1840,10 @@ class ComposerController extends BaseController {
onEditorFocusChange(true);
}
void handleImageUploadSuccess(
void handleImageUploadSuccess (
BuildContext context,
web_html_editor.FileUpload fileUpload
) {
) async {
log('ComposerController::handleImageUploadSuccess:NAME: ${fileUpload.name} | TYPE: ${fileUpload.type} | SIZE: ${fileUpload.size}');
if (fileUpload.base64 == null) {
_appToast.showToastErrorMessage(
@@ -1853,6 +1854,15 @@ class ComposerController extends BaseController {
}
if (fileUpload.type == null) {
final fileInfo = await fileUpload.toFileInfo();
if (fileInfo != null) {
_addAttachmentFromDragAndDrop(fileInfo: fileInfo);
} else if (context.mounted) {
_appToast.showToastErrorMessage(
context,
AppLocalizations.of(context).can_not_upload_this_file_as_attachments
);
}
return;
}
@@ -1864,6 +1874,16 @@ class ComposerController extends BaseController {
type: mediaType,
size: fileUpload.size,
);
} else {
final fileInfo = await fileUpload.toFileInfo();
if (fileInfo != null) {
_addAttachmentFromDragAndDrop(fileInfo: fileInfo);
} else if (context.mounted) {
_appToast.showToastErrorMessage(
context,
AppLocalizations.of(context).can_not_upload_this_file_as_attachments
);
}
}
}
@@ -1895,6 +1915,23 @@ class ComposerController extends BaseController {
);
}
void _addAttachmentFromDragAndDrop({required FileInfo fileInfo}) {
if (uploadController.hasEnoughMaxAttachmentSize(listFiles: [fileInfo])) {
_uploadAttachmentsAction([fileInfo]);
} else {
if (currentContext != null) {
showConfirmDialogAction(
currentContext!,
AppLocalizations.of(currentContext!).message_dialog_upload_attachments_exceeds_maximum_size(
filesize(mailboxDashBoardController.maxSizeAttachmentsPerEmail?.value ?? 0, 0)),
AppLocalizations.of(currentContext!).got_it,
title: AppLocalizations.of(currentContext!).maximum_files_size,
hasCancelButton: false,
);
}
}
}
FocusNode? getNextFocusOfToEmailAddress() {
if (ccRecipientState.value == PrefixRecipientState.enabled) {
return ccAddressFocusNode;
@@ -0,0 +1,45 @@
import 'dart:convert' as convert;
import 'dart:typed_data' as type_data;
import 'package:flutter/foundation.dart';
import 'package:get/get_connect/http/src/request/request.dart';
import 'package:html_editor_enhanced/utils/file_upload_model.dart';
import 'package:model/upload/file_info.dart';
extension FileUploadExtension on FileUpload {
String? get base64Data {
if (base64 != null) {
if (!base64!.contains(',')) {
return base64;
}
final listData = base64!.split(',');
if (listData.length < 2) {
return base64;
}
final base64Origin = listData[1];
return base64Origin;
}
return base64;
}
Future<FileInfo?> toFileInfo() async {
if (base64Data != null) {
final bytesStream = await compute(convertBytesToStream, base64Data!);
return FileInfo.fromStream(
stream: bytesStream,
name: name,
size: size
);
} else {
return null;
}
}
static Stream<List<int>> convertBytesToStream(String base64) {
type_data.Uint8List decodeBytes = convert.base64Decode(base64);
final bytesStream = BodyBytesStream.fromBytes(decodeBytes);
return bytesStream;
}
}
@@ -57,11 +57,15 @@ class UploadAttachment with EquatableMixin {
if (attachment != null) {
_updateEvent(Right(SuccessAttachmentUploadState(uploadTaskId, attachment, fileInfo)));
} else {
_updateEvent(Left(ErrorAttachmentUploadState(uploadTaskId)));
_updateEvent(Left(ErrorAttachmentUploadState(uploadId: uploadTaskId)));
}
} catch (e) {
logError('UploadAttachment::upload():ERROR: $e');
_updateEvent(Left(ErrorAttachmentUploadState(uploadTaskId)));
if (e is DioError && e.type == DioErrorType.cancel) {
_updateEvent(Left(CancelAttachmentUploadState(uploadTaskId)));
} else {
_updateEvent(Left(ErrorAttachmentUploadState(uploadId: uploadTaskId, exception: e)));
}
} finally {
await _progressStateController.close();
}
@@ -51,13 +51,16 @@ class SuccessAttachmentUploadState extends Success {
];
}
class ErrorAttachmentUploadState extends Failure {
class ErrorAttachmentUploadState extends FeatureFailure {
final UploadTaskId uploadId;
ErrorAttachmentUploadState(this.uploadId);
ErrorAttachmentUploadState({
required this.uploadId,
dynamic exception
}) : super(exception: exception);
@override
List<Object?> get props => [uploadId];
List<Object?> get props => [uploadId, ...super.props];
}
class CancelAttachmentUploadState extends Failure {
@@ -258,7 +258,7 @@ class UploadController extends BaseController {
if (currentContext != null && currentOverlayContext != null) {
_appToast.showToastErrorMessage(
currentOverlayContext!,
AppLocalizations.of(currentContext!).can_not_upload_this_file_as_attachments,
'${AppLocalizations.of(currentContext!).can_not_upload_this_file_as_attachments}. ${failure.exception ?? ''}',
leadingSVGIconColor: Colors.white,
leadingSVGIcon: _imagePaths.icAttachment);
}
+8
View File
@@ -16,6 +16,14 @@ class FileInfo with EquatableMixin {
return FileInfo('', '', 0);
}
factory FileInfo.fromStream({
required Stream<List<int>> stream,
String? name,
int? size
}) {
return FileInfo(name ?? '', '', size ?? 0, readStream: stream);
}
String get fileExtension => fileName.split('.').last;
String get mimeType => lookupMimeType(kIsWeb ? fileName : filePath) ?? 'application/json; charset=UTF-8';