TF-2602 Set charset for attachment with mimeType=text/plain when sent email on mobile
Signed-off-by: dab246 <tdvu@linagora.com>
This commit is contained in:
@@ -81,7 +81,11 @@ class ComposerBindings extends BaseBindings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _bindingsUtils() {
|
void _bindingsUtils() {
|
||||||
Get.lazyPut(() => FileUploader(Get.find<DioClient>(tag: BindingTag.isolateTag), Get.find<Executor>()));
|
Get.lazyPut(() => FileUploader(
|
||||||
|
Get.find<DioClient>(tag: BindingTag.isolateTag),
|
||||||
|
Get.find<Executor>(),
|
||||||
|
Get.find<FileUtils>(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
|
|
||||||
import 'package:core/data/network/dio_client.dart';
|
import 'package:core/data/network/dio_client.dart';
|
||||||
|
import 'package:core/utils/file_utils.dart';
|
||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
import 'package:tmail_ui_user/features/base/isolate/background_isolate_binary_messenger/background_isolate_binary_messenger.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/mobile_file_upload.dart';
|
||||||
@@ -8,6 +9,7 @@ import 'package:tmail_ui_user/features/upload/domain/model/upload_task_id.dart';
|
|||||||
class UploadFileArguments with EquatableMixin {
|
class UploadFileArguments with EquatableMixin {
|
||||||
|
|
||||||
final DioClient dioClient;
|
final DioClient dioClient;
|
||||||
|
final FileUtils fileUtils;
|
||||||
final UploadTaskId uploadId;
|
final UploadTaskId uploadId;
|
||||||
final MobileFileUpload mobileFileUpload;
|
final MobileFileUpload mobileFileUpload;
|
||||||
final Uri uploadUri;
|
final Uri uploadUri;
|
||||||
@@ -15,6 +17,7 @@ class UploadFileArguments with EquatableMixin {
|
|||||||
|
|
||||||
UploadFileArguments(
|
UploadFileArguments(
|
||||||
this.dioClient,
|
this.dioClient,
|
||||||
|
this.fileUtils,
|
||||||
this.uploadId,
|
this.uploadId,
|
||||||
this.mobileFileUpload,
|
this.mobileFileUpload,
|
||||||
this.uploadUri,
|
this.uploadUri,
|
||||||
@@ -24,6 +27,7 @@ class UploadFileArguments with EquatableMixin {
|
|||||||
@override
|
@override
|
||||||
List<Object?> get props => [
|
List<Object?> get props => [
|
||||||
dioClient,
|
dioClient,
|
||||||
|
fileUtils,
|
||||||
uploadId,
|
uploadId,
|
||||||
mobileFileUpload,
|
mobileFileUpload,
|
||||||
uploadUri,
|
uploadUri,
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import 'package:core/data/network/dio_client.dart';
|
|||||||
import 'package:core/presentation/state/failure.dart';
|
import 'package:core/presentation/state/failure.dart';
|
||||||
import 'package:core/presentation/state/success.dart';
|
import 'package:core/presentation/state/success.dart';
|
||||||
import 'package:core/utils/app_logger.dart';
|
import 'package:core/utils/app_logger.dart';
|
||||||
|
import 'package:core/utils/file_utils.dart';
|
||||||
import 'package:core/utils/platform_info.dart';
|
import 'package:core/utils/platform_info.dart';
|
||||||
import 'package:dartz/dartz.dart';
|
import 'package:dartz/dartz.dart';
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
@@ -32,10 +33,15 @@ class FileUploader {
|
|||||||
|
|
||||||
final DioClient _dioClient;
|
final DioClient _dioClient;
|
||||||
final worker.Executor _isolateExecutor;
|
final worker.Executor _isolateExecutor;
|
||||||
|
final FileUtils _fileUtils;
|
||||||
|
|
||||||
FileUploader(this._dioClient, this._isolateExecutor);
|
FileUploader(
|
||||||
|
this._dioClient,
|
||||||
|
this._isolateExecutor,
|
||||||
|
this._fileUtils,
|
||||||
|
);
|
||||||
|
|
||||||
Future<Attachment?> uploadAttachment(
|
Future<Attachment> uploadAttachment(
|
||||||
UploadTaskId uploadId,
|
UploadTaskId uploadId,
|
||||||
StreamController<Either<Failure, Success>> onSendController,
|
StreamController<Either<Failure, Success>> onSendController,
|
||||||
FileInfo fileInfo,
|
FileInfo fileInfo,
|
||||||
@@ -59,6 +65,7 @@ class FileUploader {
|
|||||||
return await _isolateExecutor.execute(
|
return await _isolateExecutor.execute(
|
||||||
arg1: UploadFileArguments(
|
arg1: UploadFileArguments(
|
||||||
_dioClient,
|
_dioClient,
|
||||||
|
_fileUtils,
|
||||||
uploadId,
|
uploadId,
|
||||||
mobileFileUpload,
|
mobileFileUpload,
|
||||||
uploadUri,
|
uploadUri,
|
||||||
@@ -77,7 +84,7 @@ class FileUploader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<Attachment?> _handleUploadAttachmentAction(
|
static Future<Attachment> _handleUploadAttachmentAction(
|
||||||
UploadFileArguments argsUpload,
|
UploadFileArguments argsUpload,
|
||||||
worker.TypeSendPort sendPort
|
worker.TypeSendPort sendPort
|
||||||
) async {
|
) async {
|
||||||
@@ -104,7 +111,7 @@ class FileUploader {
|
|||||||
),
|
),
|
||||||
data: File(argsUpload.mobileFileUpload.filePath).openRead(),
|
data: File(argsUpload.mobileFileUpload.filePath).openRead(),
|
||||||
onSendProgress: (count, total) {
|
onSendProgress: (count, total) {
|
||||||
log('FileUploader::_handleUploadAttachmentAction():onSendProgress: [${argsUpload.uploadId.id}] = $count');
|
log('FileUploader::_handleUploadAttachmentAction():onSendProgress: FILE[${argsUpload.uploadId.id}] : { PROGRESS = $count | TOTAL = $total}');
|
||||||
sendPort.send(
|
sendPort.send(
|
||||||
UploadingAttachmentUploadState(
|
UploadingAttachmentUploadState(
|
||||||
argsUpload.uploadId,
|
argsUpload.uploadId,
|
||||||
@@ -114,11 +121,18 @@ class FileUploader {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
log('FileUploader::_handleUploadAttachmentAction():resultJson: $resultJson');
|
log('FileUploader::_handleUploadAttachmentAction(): RESULT_JSON = $resultJson');
|
||||||
return _parsingResponse(
|
if (argsUpload.mobileFileUpload.mimeType == FileUtils.TEXT_PLAIN_MIME_TYPE) {
|
||||||
resultJson: resultJson,
|
final fileCharset = await argsUpload.fileUtils.getFileCharset(argsUpload.mobileFileUpload.filePath);
|
||||||
fileName: argsUpload.mobileFileUpload.fileName
|
return _parsingResponse(
|
||||||
);
|
resultJson: resultJson,
|
||||||
|
fileName: argsUpload.mobileFileUpload.fileName,
|
||||||
|
fileCharset: fileCharset);
|
||||||
|
} else {
|
||||||
|
return _parsingResponse(
|
||||||
|
resultJson: resultJson,
|
||||||
|
fileName: argsUpload.mobileFileUpload.fileName);
|
||||||
|
}
|
||||||
} on DioError catch (exception) {
|
} on DioError catch (exception) {
|
||||||
logError('FileUploader::_handleUploadAttachmentAction():DioError: $exception');
|
logError('FileUploader::_handleUploadAttachmentAction():DioError: $exception');
|
||||||
|
|
||||||
@@ -131,7 +145,7 @@ class FileUploader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Attachment?> _handleUploadAttachmentActionOnWeb(
|
Future<Attachment> _handleUploadAttachmentActionOnWeb(
|
||||||
UploadTaskId uploadId,
|
UploadTaskId uploadId,
|
||||||
StreamController<Either<Failure, Success>> onSendController,
|
StreamController<Either<Failure, Success>> onSendController,
|
||||||
FileInfo fileInfo,
|
FileInfo fileInfo,
|
||||||
@@ -171,13 +185,18 @@ class FileUploader {
|
|||||||
return _parsingResponse(resultJson: resultJson, fileName: fileInfo.fileName);
|
return _parsingResponse(resultJson: resultJson, fileName: fileInfo.fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Attachment? _parsingResponse({dynamic resultJson, required String fileName}) {
|
static Attachment _parsingResponse({
|
||||||
log('FileUploader::_parsingResponse():resultJson: $resultJson');
|
dynamic resultJson,
|
||||||
|
required String fileName,
|
||||||
|
String? fileCharset
|
||||||
|
}) {
|
||||||
if (resultJson != null) {
|
if (resultJson != null) {
|
||||||
final decodeJson = resultJson is Map ? resultJson : jsonDecode(resultJson);
|
final decodeJson = resultJson is Map ? resultJson : jsonDecode(resultJson);
|
||||||
final uploadResponse = UploadResponse.fromJson(decodeJson);
|
final uploadResponse = UploadResponse.fromJson(decodeJson);
|
||||||
log('FileUploader::_parsingResponse():uploadResponse: ${uploadResponse.toString()}');
|
log('FileUploader::_parsingResponse(): UploadResponse = $uploadResponse');
|
||||||
return uploadResponse.toAttachment(fileName);
|
return uploadResponse.toAttachment(
|
||||||
|
nameFile: fileName,
|
||||||
|
charset: fileCharset);
|
||||||
} else {
|
} else {
|
||||||
logError('FileUploader::_parsingResponse(): DataResponseIsNullException');
|
logError('FileUploader::_parsingResponse(): DataResponseIsNullException');
|
||||||
throw DataResponseIsNullException();
|
throw DataResponseIsNullException();
|
||||||
|
|||||||
@@ -5,12 +5,12 @@ import 'package:core/presentation/state/failure.dart';
|
|||||||
import 'package:core/presentation/state/success.dart';
|
import 'package:core/presentation/state/success.dart';
|
||||||
import 'package:core/utils/app_logger.dart';
|
import 'package:core/utils/app_logger.dart';
|
||||||
import 'package:dartz/dartz.dart';
|
import 'package:dartz/dartz.dart';
|
||||||
|
import 'package:dio/dio.dart';
|
||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
import 'package:model/upload/file_info.dart';
|
import 'package:model/upload/file_info.dart';
|
||||||
import 'package:tmail_ui_user/features/upload/data/network/file_uploader.dart';
|
import 'package:tmail_ui_user/features/upload/data/network/file_uploader.dart';
|
||||||
import 'package:tmail_ui_user/features/upload/domain/model/upload_task_id.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/features/upload/domain/state/attachment_upload_state.dart';
|
||||||
import 'package:dio/dio.dart';
|
|
||||||
|
|
||||||
class UploadAttachment with EquatableMixin {
|
class UploadAttachment with EquatableMixin {
|
||||||
|
|
||||||
@@ -48,17 +48,15 @@ class UploadAttachment with EquatableMixin {
|
|||||||
cancelToken: cancelToken
|
cancelToken: cancelToken
|
||||||
);
|
);
|
||||||
|
|
||||||
|
log('UploadAttachment::upload: ATTACHMENT_UPLOADED = $attachment');
|
||||||
|
|
||||||
if (cancelToken?.isCancelled == true) {
|
if (cancelToken?.isCancelled == true) {
|
||||||
_updateEvent(Left(CancelAttachmentUploadState(uploadTaskId)));
|
_updateEvent(Left(CancelAttachmentUploadState(uploadTaskId)));
|
||||||
await _progressStateController.close();
|
await _progressStateController.close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attachment != null) {
|
_updateEvent(Right(SuccessAttachmentUploadState(uploadTaskId, attachment, fileInfo)));
|
||||||
_updateEvent(Right(SuccessAttachmentUploadState(uploadTaskId, attachment, fileInfo)));
|
|
||||||
} else {
|
|
||||||
_updateEvent(Left(ErrorAttachmentUploadState(uploadId: uploadTaskId)));
|
|
||||||
}
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logError('UploadAttachment::upload():ERROR: $e');
|
logError('UploadAttachment::upload():ERROR: $e');
|
||||||
if (e is DioError && e.type == DioErrorType.cancel) {
|
if (e is DioError && e.type == DioErrorType.cancel) {
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ class Attachment with EquatableMixin {
|
|||||||
final MediaType? type;
|
final MediaType? type;
|
||||||
final String? cid;
|
final String? cid;
|
||||||
final ContentDisposition? disposition;
|
final ContentDisposition? disposition;
|
||||||
|
final String? charset;
|
||||||
|
|
||||||
Attachment({
|
Attachment({
|
||||||
this.partId,
|
this.partId,
|
||||||
@@ -29,6 +30,7 @@ class Attachment with EquatableMixin {
|
|||||||
this.type,
|
this.type,
|
||||||
this.cid,
|
this.cid,
|
||||||
this.disposition,
|
this.disposition,
|
||||||
|
this.charset,
|
||||||
});
|
});
|
||||||
|
|
||||||
bool noCid() => cid == null || cid?.isEmpty == true;
|
bool noCid() => cid == null || cid?.isEmpty == true;
|
||||||
@@ -59,7 +61,16 @@ class Attachment with EquatableMixin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object?> get props => [partId, blobId, size, name, type, cid, disposition];
|
List<Object?> get props => [
|
||||||
|
partId,
|
||||||
|
blobId,
|
||||||
|
size,
|
||||||
|
name,
|
||||||
|
type,
|
||||||
|
cid,
|
||||||
|
disposition,
|
||||||
|
charset
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ContentDisposition {
|
enum ContentDisposition {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ extension AttachmentExtension on Attachment {
|
|||||||
name: name,
|
name: name,
|
||||||
type: type,
|
type: type,
|
||||||
cid: cid,
|
cid: cid,
|
||||||
charset: charset,
|
charset: charset ?? this.charset,
|
||||||
disposition: disposition?.name ?? ContentDisposition.attachment.name);
|
disposition: disposition?.name ?? ContentDisposition.attachment.name);
|
||||||
|
|
||||||
Attachment toAttachmentWithDisposition({
|
Attachment toAttachmentWithDisposition({
|
||||||
@@ -25,7 +25,8 @@ extension AttachmentExtension on Attachment {
|
|||||||
name: name,
|
name: name,
|
||||||
type: type,
|
type: type,
|
||||||
cid: cid ?? this.cid,
|
cid: cid ?? this.cid,
|
||||||
disposition: disposition ?? this.disposition
|
disposition: disposition ?? this.disposition,
|
||||||
|
charset: charset
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,5 +9,6 @@ extension EmailBodyPartExtension on EmailBodyPart {
|
|||||||
name: name,
|
name: name,
|
||||||
type: type,
|
type: type,
|
||||||
cid: cid,
|
cid: cid,
|
||||||
|
charset: charset,
|
||||||
disposition: disposition.toContentDisposition());
|
disposition: disposition.toContentDisposition());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,13 @@ class UploadResponse with EquatableMixin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension UploadResponseExtension on UploadResponse {
|
extension UploadResponseExtension on UploadResponse {
|
||||||
Attachment toAttachment(String nameFile) {
|
Attachment toAttachment({required String nameFile, String? charset}) {
|
||||||
return Attachment(blobId: blobId, size: UnsignedInt(size), name: nameFile, type: type);
|
return Attachment(
|
||||||
|
blobId: blobId,
|
||||||
|
size: UnsignedInt(size),
|
||||||
|
name: nameFile,
|
||||||
|
type: type,
|
||||||
|
charset: charset
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user