TF-725 Handle upload inline image to server

This commit is contained in:
dab246
2022-07-20 16:47:32 +07:00
committed by Dat H. Pham
parent d823862726
commit d416f858c7
3 changed files with 128 additions and 6 deletions
@@ -53,7 +53,7 @@ class UploadAttachment extends Equatable {
}
if (attachment != null) {
_updateEvent(Right(SuccessAttachmentUploadState(uploadTaskId, attachment)));
_updateEvent(Right(SuccessAttachmentUploadState(uploadTaskId, attachment, fileInfo)));
} else {
_updateEvent(Left(ErrorAttachmentUploadState(uploadTaskId)));
}
@@ -2,6 +2,7 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:model/email/attachment.dart';
import 'package:model/upload/file_info.dart';
import 'package:tmail_ui_user/features/upload/domain/model/upload_task_id.dart';
class PendingAttachmentUploadState extends Success {
@@ -29,11 +30,12 @@ class UploadingAttachmentUploadState extends Success {
class SuccessAttachmentUploadState extends Success {
final UploadTaskId uploadId;
final Attachment attachment;
final FileInfo fileInfo;
SuccessAttachmentUploadState(this.uploadId, this.attachment);
SuccessAttachmentUploadState(this.uploadId, this.attachment, this.fileInfo);
@override
List<Object?> get props => [uploadId, attachment];
List<Object?> get props => [uploadId, attachment, fileInfo];
}
class ErrorAttachmentUploadState extends Failure {
@@ -24,21 +24,27 @@ import 'package:tmail_ui_user/features/upload/presentation/model/upload_file_sta
import 'package:tmail_ui_user/features/upload/presentation/model/upload_file_status.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
import 'package:uuid/uuid.dart';
class UploadController extends GetxController {
final _imagePaths = Get.find<ImagePaths>();
final _appToast = Get.find<AppToast>();
final _uuid = Get.find<Uuid>();
final _mailboxDashBoardController = Get.find<MailboxDashBoardController>();
final UploadAttachmentInteractor _uploadAttachmentInteractor;
final listUploadAttachments = <UploadFileState>[].obs;
final uploadInlineViewState = Rx<Either<Failure, Success>>(Right(UIState.idle));
final StreamGroup<Either<Failure, Success>> _progressUploadStateStreamGroup
= StreamGroup<Either<Failure, Success>>.broadcast();
final StreamGroup<Either<Failure, Success>> _progressUploadInlineImageStateStreamGroup
= StreamGroup<Either<Failure, Success>>.broadcast();
final UploadFileStateList _uploadingStateFiles = UploadFileStateList();
final UploadFileStateList _uploadingStateInlineFiles = UploadFileStateList();
UploadController(this._uploadAttachmentInteractor);
@@ -52,11 +58,14 @@ class UploadController extends GetxController {
void onClose() {
_uploadingStateFiles.clear();
_progressUploadStateStreamGroup.close();
_uploadingStateInlineFiles.clear();
_progressUploadInlineImageStateStreamGroup.close();
super.onClose();
}
void _registerProgressUploadStateStream() {
_progressUploadStateStreamGroup.stream.listen(_handleProgressUploadStateStream);
_progressUploadInlineImageStateStreamGroup.stream.listen(_handleProgressUploadInlineImageStateStream);
}
void _handleProgressUploadStateStream(Either<Failure, Success> uploadState) {
@@ -103,12 +112,67 @@ class UploadController extends GetxController {
);
_refreshListUploadAttachmentState();
_handleUploadAttachmentsSuccess(success);
if (success.attachment.disposition == ContentDisposition.attachment) {
_handleUploadAttachmentsSuccess(success);
} else {
_handleUploadInlineAttachmentsSuccess(success);
}
}
}
);
}
void _handleProgressUploadInlineImageStateStream(Either<Failure, Success> uploadState) {
uploadState.fold(
(failure) {
log('UploadController::_handleProgressUploadInlineImageStateStream():failure: $failure');
if (failure is ErrorAttachmentUploadState) {
uploadInlineViewState.value = Left(failure);
_deleteInlineFileUploaded(failure.uploadId);
}
},
(success) {
if (success is UploadingAttachmentUploadState) {
log('UploadController::_handleProgressUploadInlineImageStateStream():uploading[${success.uploadId}]: ${success.progress}');
_uploadingStateInlineFiles.updateElementByUploadTaskId(
success.uploadId,
(currentState) {
if (currentState?.uploadStatus.completed ?? false) {
return currentState;
} else {
return currentState?.copyWith(
uploadingProgress: (success.progress * 100 / success.total).floor(),
uploadStatus: UploadFileStatus.uploading);
}
}
);
uploadInlineViewState.value = Right(success);
} else if (success is SuccessAttachmentUploadState) {
log('UploadController::_handleProgressUploadInlineImageStateStream():succeed[${success.uploadId}]');
final inlineAttachment = success.attachment.toAttachmentWithDisposition(
disposition: ContentDisposition.inline,
cid: _uuid.v1());
_uploadingStateInlineFiles.updateElementByUploadTaskId(
success.uploadId,
(currentState) {
final newState = currentState?.copyWith(
uploadingProgress: 100,
uploadStatus: UploadFileStatus.succeed,
attachment: inlineAttachment
);
return newState;
},
);
final newUploadSuccess = SuccessAttachmentUploadState(
success.uploadId,
inlineAttachment,
success.fileInfo);
_handleUploadInlineAttachmentsSuccess(newUploadSuccess);
}
}
);
}
void initializeUploadAttachments(List<Attachment> attachments) {
final listUploadFilesState = attachments
.map((attachment) => UploadFileState(
@@ -170,8 +234,9 @@ class UploadController extends GetxController {
return null;
}
return attachmentsUploaded
.map((attachment) => attachment.toEmailBodyPart(ContentDisposition.attachment.value))
.toSet();
.map((attachment) => attachment.toEmailBodyPart(
disposition: ContentDisposition.attachment.value))
.toSet();
}
void _handleUploadAttachmentsFailure(ErrorAttachmentUploadState failure) {
@@ -185,6 +250,7 @@ class UploadController extends GetxController {
}
void _handleUploadAttachmentsSuccess(SuccessAttachmentUploadState success) {
log('UploadController::_handleUploadAttachmentsSuccess(): $success');
if (currentContext != null && currentOverlayContext != null && _uploadingStateFiles.allSuccess) {
_appToast.showToastWithIcon(currentOverlayContext!,
message: AppLocalizations.of(currentContext!).attachments_uploaded_successfully,
@@ -218,4 +284,58 @@ class UploadController extends GetxController {
return listUploadAttachments
.every((uploadFile) => uploadFile.uploadStatus.completed);
}
Future<void> uploadInlineImage(FileInfo uploadFile, Uri uploadUri) async {
log('UploadAttachmentManager::uploadInlineImage(): ${uploadFile.fileName}');
final cancelToken = CancelToken();
final uploadAttachment = _uploadAttachmentInteractor.execute(
uploadFile,
uploadUri,
cancelToken: cancelToken);
_uploadingStateInlineFiles.add(UploadFileState(
uploadAttachment.uploadTaskId,
file: uploadFile,
cancelToken: cancelToken));
await _progressUploadInlineImageStateStreamGroup.add(uploadAttachment.progressState);
}
void _deleteInlineFileUploaded(UploadTaskId uploadId) {
_uploadingStateInlineFiles.deleteElementByUploadTaskId(uploadId);
}
void clearInlineFileUploaded() {
_uploadingStateInlineFiles.clear();
}
void _handleUploadInlineAttachmentsSuccess(SuccessAttachmentUploadState success) {
uploadInlineViewState.value = Right(success);
}
void clearUploadInlineViewState() {
uploadInlineViewState.value = Right(UIState.idle);
}
Map<String, Attachment> get mapInlineAttachments {
final inlineAttachments = _uploadingStateInlineFiles.uploadingStateFiles
.whereNotNull()
.map((fileState) => fileState.attachment)
.whereNotNull()
.where((attachment) => attachment.cid != null)
.toList();
log('UploadController::mapInlineAttachments(): $inlineAttachments');
if (inlineAttachments.isEmpty) {
return {};
}
final mapInlineAttachments = {
for (var item in inlineAttachments) item.cid!: item
};
return mapInlineAttachments;
}
}