TF-3514 Detect base64 image to transfer it to cid attachment
Signed-off-by: dab246 <tdvu@linagora.com>
This commit is contained in:
@@ -2,8 +2,8 @@
|
||||
import 'package:core/data/network/dio_client.dart';
|
||||
import 'package:core/utils/file_utils.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:model/upload/file_info.dart';
|
||||
import 'package:tmail_ui_user/features/base/isolate/background_isolate_binary_messenger/background_isolate_binary_messenger.dart';
|
||||
import 'package:tmail_ui_user/features/upload/domain/model/mobile_file_upload.dart';
|
||||
import 'package:tmail_ui_user/features/upload/domain/model/upload_task_id.dart';
|
||||
|
||||
class UploadFileArguments with EquatableMixin {
|
||||
@@ -11,7 +11,7 @@ class UploadFileArguments with EquatableMixin {
|
||||
final DioClient dioClient;
|
||||
final FileUtils fileUtils;
|
||||
final UploadTaskId uploadId;
|
||||
final MobileFileUpload mobileFileUpload;
|
||||
final FileInfo fileInfo;
|
||||
final Uri uploadUri;
|
||||
final RootIsolateToken isolateToken;
|
||||
|
||||
@@ -19,7 +19,7 @@ class UploadFileArguments with EquatableMixin {
|
||||
this.dioClient,
|
||||
this.fileUtils,
|
||||
this.uploadId,
|
||||
this.mobileFileUpload,
|
||||
this.fileInfo,
|
||||
this.uploadUri,
|
||||
this.isolateToken,
|
||||
);
|
||||
@@ -29,7 +29,7 @@ class UploadFileArguments with EquatableMixin {
|
||||
dioClient,
|
||||
fileUtils,
|
||||
uploadId,
|
||||
mobileFileUpload,
|
||||
fileInfo,
|
||||
uploadUri,
|
||||
isolateToken,
|
||||
];
|
||||
|
||||
@@ -19,7 +19,6 @@ import 'package:tmail_ui_user/features/base/isolate/background_isolate_binary_me
|
||||
import 'package:tmail_ui_user/features/caching/config/hive_cache_config.dart';
|
||||
import 'package:tmail_ui_user/features/upload/data/model/upload_file_arguments.dart';
|
||||
import 'package:tmail_ui_user/features/upload/domain/exceptions/upload_exception.dart';
|
||||
import 'package:tmail_ui_user/features/upload/domain/extensions/file_info_extension.dart';
|
||||
import 'package:tmail_ui_user/features/upload/domain/model/upload_task_id.dart';
|
||||
import 'package:tmail_ui_user/features/upload/domain/state/attachment_upload_state.dart';
|
||||
import 'package:tmail_ui_user/main/exceptions/isolate_exception.dart';
|
||||
@@ -43,31 +42,33 @@ class FileUploader {
|
||||
|
||||
Future<Attachment> uploadAttachment(
|
||||
UploadTaskId uploadId,
|
||||
StreamController<Either<Failure, Success>> onSendController,
|
||||
FileInfo fileInfo,
|
||||
Uri uploadUri,
|
||||
{CancelToken? cancelToken}
|
||||
{
|
||||
CancelToken? cancelToken,
|
||||
StreamController<Either<Failure, Success>>? onSendController,
|
||||
}
|
||||
) async {
|
||||
if (PlatformInfo.isWeb) {
|
||||
return _handleUploadAttachmentActionOnWeb(
|
||||
uploadId,
|
||||
onSendController,
|
||||
fileInfo,
|
||||
uploadUri,
|
||||
cancelToken: cancelToken);
|
||||
cancelToken: cancelToken,
|
||||
onSendController: onSendController,
|
||||
);
|
||||
} else {
|
||||
final rootIsolateToken = RootIsolateToken.instance;
|
||||
if (rootIsolateToken == null) {
|
||||
throw CanNotGetRootIsolateToken();
|
||||
}
|
||||
|
||||
final mobileFileUpload = fileInfo.toMobileFileUpload();
|
||||
return await _isolateExecutor.execute(
|
||||
arg1: UploadFileArguments(
|
||||
_dioClient,
|
||||
_fileUtils,
|
||||
uploadId,
|
||||
mobileFileUpload,
|
||||
fileInfo,
|
||||
uploadUri,
|
||||
rootIsolateToken,
|
||||
),
|
||||
@@ -75,7 +76,7 @@ class FileUploader {
|
||||
notification: (value) {
|
||||
if (value is Success) {
|
||||
log('FileUploader::uploadAttachment(): onUpdateProgress: $value');
|
||||
onSendController.add(Right(value));
|
||||
onSendController?.add(Right(value));
|
||||
}
|
||||
}
|
||||
)
|
||||
@@ -94,12 +95,15 @@ class FileUploader {
|
||||
await HiveCacheConfig.instance.setUp();
|
||||
|
||||
final headerParam = argsUpload.dioClient.getHeaders();
|
||||
headerParam[HttpHeaders.contentTypeHeader] = argsUpload.mobileFileUpload.mimeType;
|
||||
headerParam[HttpHeaders.contentLengthHeader] = argsUpload.mobileFileUpload.fileSize;
|
||||
headerParam[HttpHeaders.contentTypeHeader] = argsUpload.fileInfo.mimeType;
|
||||
headerParam[HttpHeaders.contentLengthHeader] = argsUpload.fileInfo.fileSize;
|
||||
|
||||
final mapExtra = <String, dynamic>{
|
||||
uploadAttachmentExtraKey: {
|
||||
filePathExtraKey: argsUpload.mobileFileUpload.filePath,
|
||||
if (argsUpload.fileInfo.filePath?.isNotEmpty == true)
|
||||
filePathExtraKey: argsUpload.fileInfo.filePath,
|
||||
if (argsUpload.fileInfo.bytes?.isNotEmpty == true)
|
||||
streamDataExtraKey: BodyBytesStream.fromBytes(argsUpload.fileInfo.bytes!),
|
||||
}
|
||||
};
|
||||
|
||||
@@ -109,31 +113,39 @@ class FileUploader {
|
||||
headers: headerParam,
|
||||
extra: mapExtra
|
||||
),
|
||||
data: File(argsUpload.mobileFileUpload.filePath).openRead(),
|
||||
data: argsUpload.fileInfo.filePath?.isNotEmpty == true
|
||||
? File(argsUpload.fileInfo.filePath!).openRead()
|
||||
: argsUpload.fileInfo.bytes != null
|
||||
? BodyBytesStream.fromBytes(argsUpload.fileInfo.bytes!)
|
||||
: null,
|
||||
onSendProgress: (count, total) {
|
||||
log('FileUploader::_handleUploadAttachmentAction():onSendProgress: FILE[${argsUpload.uploadId.id}] : { PROGRESS = $count | TOTAL = $total}');
|
||||
sendPort.send(
|
||||
UploadingAttachmentUploadState(
|
||||
argsUpload.uploadId,
|
||||
count,
|
||||
argsUpload.mobileFileUpload.fileSize
|
||||
argsUpload.fileInfo.fileSize
|
||||
)
|
||||
);
|
||||
}
|
||||
);
|
||||
log('FileUploader::_handleUploadAttachmentAction(): RESULT_JSON = $resultJson');
|
||||
if (argsUpload.mobileFileUpload.mimeType == FileUtils.TEXT_PLAIN_MIME_TYPE) {
|
||||
final fileCharset = await argsUpload.fileUtils.getCharsetFromBytes(
|
||||
File(argsUpload.mobileFileUpload.filePath).readAsBytesSync()
|
||||
);
|
||||
if (argsUpload.fileInfo.mimeType == FileUtils.TEXT_PLAIN_MIME_TYPE) {
|
||||
final fileBytes = argsUpload.fileInfo.filePath?.isNotEmpty == true
|
||||
? File(argsUpload.fileInfo.filePath!).readAsBytesSync()
|
||||
: argsUpload.fileInfo.bytes;
|
||||
|
||||
final fileCharset = fileBytes != null
|
||||
? await argsUpload.fileUtils.getCharsetFromBytes(fileBytes)
|
||||
: null;
|
||||
return _parsingResponse(
|
||||
resultJson: resultJson,
|
||||
fileName: argsUpload.mobileFileUpload.fileName,
|
||||
fileCharset: fileCharset.toLowerCase());
|
||||
fileName: argsUpload.fileInfo.fileName,
|
||||
fileCharset: fileCharset?.toLowerCase());
|
||||
} else {
|
||||
return _parsingResponse(
|
||||
resultJson: resultJson,
|
||||
fileName: argsUpload.mobileFileUpload.fileName);
|
||||
fileName: argsUpload.fileInfo.fileName);
|
||||
}
|
||||
} on DioError catch (exception) {
|
||||
logError('FileUploader::_handleUploadAttachmentAction():DioError: $exception');
|
||||
@@ -149,10 +161,12 @@ class FileUploader {
|
||||
|
||||
Future<Attachment> _handleUploadAttachmentActionOnWeb(
|
||||
UploadTaskId uploadId,
|
||||
StreamController<Either<Failure, Success>> onSendController,
|
||||
FileInfo fileInfo,
|
||||
Uri uploadUri,
|
||||
{CancelToken? cancelToken}
|
||||
{
|
||||
CancelToken? cancelToken,
|
||||
StreamController<Either<Failure, Success>>? onSendController,
|
||||
}
|
||||
) async {
|
||||
final headerParam = _dioClient.getHeaders();
|
||||
headerParam[HttpHeaders.contentTypeHeader] = fileInfo.mimeType;
|
||||
@@ -160,7 +174,8 @@ class FileUploader {
|
||||
|
||||
final mapExtra = <String, dynamic>{
|
||||
uploadAttachmentExtraKey: {
|
||||
streamDataExtraKey: BodyBytesStream.fromBytes(fileInfo.bytes!),
|
||||
if (fileInfo.bytes?.isNotEmpty == true)
|
||||
streamDataExtraKey: BodyBytesStream.fromBytes(fileInfo.bytes!),
|
||||
}
|
||||
};
|
||||
|
||||
@@ -174,7 +189,7 @@ class FileUploader {
|
||||
cancelToken: cancelToken,
|
||||
onSendProgress: (count, total) {
|
||||
log('FileUploader::_handleUploadAttachmentActionOnWeb():onSendProgress: FILE[${uploadId.id}] : { PROGRESS = $count | TOTAL = $total}');
|
||||
onSendController.add(
|
||||
onSendController?.add(
|
||||
Right(UploadingAttachmentUploadState(
|
||||
uploadId,
|
||||
count,
|
||||
|
||||
@@ -1,17 +1,13 @@
|
||||
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
import 'package:model/upload/file_info.dart';
|
||||
import 'package:tmail_ui_user/features/upload/domain/model/mobile_file_upload.dart';
|
||||
|
||||
extension FileInfoExtension on FileInfo {
|
||||
MobileFileUpload toMobileFileUpload() => MobileFileUpload(fileName, filePath!, fileSize, mimeType);
|
||||
|
||||
FileInfo withInline() => FileInfo(
|
||||
fileName: fileName,
|
||||
fileSize: fileSize,
|
||||
filePath: filePath,
|
||||
bytes: bytes,
|
||||
readStream: readStream,
|
||||
type: type,
|
||||
isInline: true,
|
||||
isShared: isShared);
|
||||
@@ -21,6 +17,5 @@ extension FileInfoExtension on FileInfo {
|
||||
path: filePath,
|
||||
size: fileSize,
|
||||
bytes: bytes,
|
||||
readStream: readStream,
|
||||
);
|
||||
}
|
||||
@@ -8,6 +8,5 @@ extension PlatformFileExtension on PlatformFile {
|
||||
fileSize: size,
|
||||
filePath: PlatformInfo.isWeb ? '' : path ?? '',
|
||||
bytes: bytes,
|
||||
readStream: readStream
|
||||
);
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
class MobileFileUpload with EquatableMixin {
|
||||
final String fileName;
|
||||
final String filePath;
|
||||
final int fileSize;
|
||||
final String mimeType;
|
||||
|
||||
MobileFileUpload(
|
||||
this.fileName,
|
||||
this.filePath,
|
||||
this.fileSize,
|
||||
this.mimeType
|
||||
);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
fileName,
|
||||
filePath,
|
||||
fileSize,
|
||||
mimeType,
|
||||
];
|
||||
}
|
||||
@@ -42,10 +42,10 @@ class UploadAttachment with EquatableMixin {
|
||||
|
||||
final attachment = await fileUploader.uploadAttachment(
|
||||
uploadTaskId,
|
||||
_progressStateController,
|
||||
fileInfo,
|
||||
uploadUri,
|
||||
cancelToken: cancelToken
|
||||
cancelToken: cancelToken,
|
||||
onSendController: _progressStateController,
|
||||
);
|
||||
|
||||
log('UploadAttachment::upload: ATTACHMENT_UPLOADED = $attachment');
|
||||
|
||||
@@ -193,24 +193,24 @@ class UploadController extends BaseController {
|
||||
}
|
||||
|
||||
void initializeUploadAttachments(List<Attachment> attachments) {
|
||||
final listUploadFilesState = attachments
|
||||
.map((attachment) => UploadFileState(
|
||||
UploadTaskId(attachment.blobId!.value),
|
||||
uploadStatus: UploadFileStatus.succeed,
|
||||
attachment: attachment))
|
||||
.toList();
|
||||
_uploadingStateFiles.addAll(listUploadFilesState);
|
||||
_uploadingStateFiles.addAll(
|
||||
attachments.map((attachment) => UploadFileState(
|
||||
UploadTaskId(attachment.blobId!.value),
|
||||
uploadStatus: UploadFileStatus.succeed,
|
||||
attachment: attachment
|
||||
))
|
||||
);
|
||||
_refreshListUploadAttachmentState();
|
||||
}
|
||||
|
||||
void initializeUploadInlineAttachments(List<Attachment> inlineAttachments) {
|
||||
final listUploadInlineImagesState = inlineAttachments
|
||||
.map((inlineAttachment) => UploadFileState(
|
||||
UploadTaskId(inlineAttachment.blobId!.value),
|
||||
uploadStatus: UploadFileStatus.succeed,
|
||||
attachment: inlineAttachment))
|
||||
.toList();
|
||||
_uploadingStateInlineFiles.addAll(listUploadInlineImagesState);
|
||||
_uploadingStateInlineFiles.addAll(
|
||||
inlineAttachments.map((inlineAttachment) => UploadFileState(
|
||||
UploadTaskId(inlineAttachment.blobId!.value),
|
||||
uploadStatus: UploadFileStatus.succeed,
|
||||
attachment: inlineAttachment,
|
||||
))
|
||||
);
|
||||
_refreshListUploadAttachmentState();
|
||||
}
|
||||
|
||||
@@ -428,45 +428,44 @@ class UploadController extends BaseController {
|
||||
}
|
||||
|
||||
List<Attachment> get inlineAttachmentsUploaded {
|
||||
if (_uploadingStateInlineFiles.uploadingStateFiles.isEmpty) {
|
||||
return List.empty();
|
||||
}
|
||||
return _uploadingStateInlineFiles.uploadingStateFiles
|
||||
.whereNotNull()
|
||||
.map((fileState) => fileState.attachment)
|
||||
.whereNotNull()
|
||||
.where((attachment) => attachment.cid != null)
|
||||
.toList();
|
||||
return _uploadingStateInlineFiles.uploadingStateFiles.fold<List<Attachment>>(
|
||||
[],
|
||||
(list, fileState) {
|
||||
final attachment = fileState?.attachment;
|
||||
if (attachment?.cid != null) {
|
||||
list.add(attachment!);
|
||||
}
|
||||
return list;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
List<FileInfo> get inlineAttachmentsPicked {
|
||||
if (_uploadingStateInlineFiles.uploadingStateFiles.isEmpty) {
|
||||
return List.empty();
|
||||
}
|
||||
return _uploadingStateInlineFiles.uploadingStateFiles
|
||||
.whereNotNull()
|
||||
.map((fileState) => fileState.file)
|
||||
.whereNotNull()
|
||||
.toList();
|
||||
return _uploadingStateInlineFiles.uploadingStateFiles.fold<List<FileInfo>>(
|
||||
[],
|
||||
(list, fileState) {
|
||||
final file = fileState?.file;
|
||||
if (file != null) {
|
||||
list.add(file);
|
||||
}
|
||||
return list;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, Attachment> get mapInlineAttachments {
|
||||
final inlineAttachments = _uploadingStateInlineFiles.uploadingStateFiles
|
||||
.whereNotNull()
|
||||
.map((fileState) => fileState.attachment)
|
||||
.whereNotNull()
|
||||
.where((attachment) => attachment.cid != null)
|
||||
.toList();
|
||||
final mapInlineAttachments = _uploadingStateInlineFiles.uploadingStateFiles.fold<Map<String, Attachment>>(
|
||||
{},
|
||||
(map, fileState) {
|
||||
final attachment = fileState?.attachment;
|
||||
if (attachment?.cid != null) {
|
||||
map[attachment!.cid!] = attachment;
|
||||
}
|
||||
return map;
|
||||
},
|
||||
);
|
||||
|
||||
log('UploadController::mapInlineAttachments(): $inlineAttachments');
|
||||
|
||||
if (inlineAttachments.isEmpty) {
|
||||
return {};
|
||||
}
|
||||
|
||||
final mapInlineAttachments = {
|
||||
for (var item in inlineAttachments) item.cid!: item
|
||||
};
|
||||
log('UploadController::mapInlineAttachments(): Found ${mapInlineAttachments.length} inline attachments.');
|
||||
|
||||
return mapInlineAttachments;
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ class UploadFileStateList {
|
||||
return this;
|
||||
}
|
||||
|
||||
UploadFileStateList addAll(List<UploadFileState> elements) {
|
||||
UploadFileStateList addAll(Iterable<UploadFileState> elements) {
|
||||
_uploadingStateFiles.addAll(elements);
|
||||
return this;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user