diff --git a/lib/features/composer/presentation/composer_bindings.dart b/lib/features/composer/presentation/composer_bindings.dart index 064d7d3b6..1bfbddd2a 100644 --- a/lib/features/composer/presentation/composer_bindings.dart +++ b/lib/features/composer/presentation/composer_bindings.dart @@ -3,11 +3,8 @@ import 'package:core/core.dart'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:get/get.dart'; import 'package:tmail_ui_user/features/base/base_bindings.dart'; -import 'package:tmail_ui_user/features/composer/data/datasource/composer_datasource.dart'; import 'package:tmail_ui_user/features/composer/data/datasource/contact_datasource.dart'; -import 'package:tmail_ui_user/features/composer/data/datasource_impl/composer_datasource_impl.dart'; import 'package:tmail_ui_user/features/composer/data/datasource_impl/contact_datasource_impl.dart'; -import 'package:tmail_ui_user/features/composer/data/network/composer_api.dart'; import 'package:tmail_ui_user/features/composer/data/repository/auto_complete_repository_impl.dart'; import 'package:tmail_ui_user/features/composer/data/repository/composer_repository_impl.dart'; import 'package:tmail_ui_user/features/composer/data/repository/contact_repository_impl.dart'; @@ -21,7 +18,6 @@ import 'package:tmail_ui_user/features/composer/domain/usecases/update_email_dra import 'package:tmail_ui_user/features/composer/domain/usecases/upload_attachment_interactor.dart'; import 'package:tmail_ui_user/features/composer/domain/usecases/get_autocomplete_interactor.dart'; import 'package:tmail_ui_user/features/composer/domain/usecases/send_email_interactor.dart'; -import 'package:tmail_ui_user/features/composer/domain/usecases/upload_mutiple_attachment_interactor.dart'; import 'package:tmail_ui_user/features/composer/presentation/composer_controller.dart'; import 'package:tmail_ui_user/features/composer/presentation/extensions/session_extension.dart'; import 'package:tmail_ui_user/features/email/data/datasource/email_datasource.dart'; @@ -41,9 +37,13 @@ import 'package:tmail_ui_user/features/manage_account/data/network/manage_accoun import 'package:tmail_ui_user/features/manage_account/data/repository/manage_account_repository_impl.dart'; import 'package:tmail_ui_user/features/manage_account/domain/repository/manage_account_repository.dart'; import 'package:tmail_ui_user/features/manage_account/domain/usecases/get_all_identities_interactor.dart'; +import 'package:tmail_ui_user/features/upload/data/datasource/attachment_upload_datasource.dart'; +import 'package:tmail_ui_user/features/upload/data/datasource_impl/attachment_upload_datasource_impl.dart'; +import 'package:tmail_ui_user/features/upload/data/network/file_uploader.dart'; import 'package:tmail_ui_user/features/upload/domain/usecases/local_file_picker_interactor.dart'; -import 'package:uuid/uuid.dart'; +import 'package:tmail_ui_user/features/upload/presentation/controller/upload_controller.dart'; import 'package:jmap_dart_client/http/http_client.dart' as jmap_http_client; +import 'package:worker_manager/worker_manager.dart'; class ComposerBindings extends BaseBindings { @@ -57,7 +57,7 @@ class ComposerBindings extends BaseBindings { } void _bindingsUtils() { - Get.lazyPut(() => const Uuid()); + Get.lazyPut(() => FileUploader(Get.find(), Get.find())); } @override @@ -68,7 +68,7 @@ class ComposerBindings extends BaseBindings { dataSources.add(Get.find()); } - Get.lazyPut(() => ComposerDataSourceImpl(Get.find())); + Get.lazyPut(() => AttachmentUploadDataSourceImpl(Get.find())); Get.lazyPut(() => ContactDataSourceImpl()); Get.lazyPut(() => EmailDataSourceImpl(Get.find())); Get.lazyPut(() => HtmlDataSourceImpl( @@ -82,7 +82,7 @@ class ComposerBindings extends BaseBindings { @override void bindingsDataSource() { - Get.lazyPut(() => Get.find()); + Get.lazyPut(() => Get.find()); Get.lazyPut(() => Get.find()); Get.lazyPut(() => Get.find()); Get.lazyPut(() => Get.find()); @@ -91,7 +91,7 @@ class ComposerBindings extends BaseBindings { @override void bindingsRepositoryImpl() { - Get.lazyPut(() => ComposerRepositoryImpl(Get.find())); + Get.lazyPut(() => ComposerRepositoryImpl(Get.find())); Get.lazyPut(() => AutoCompleteRepositoryImpl(dataSources)); Get.lazyPut(() => ContactRepositoryImpl(Get.find())); Get.lazyPut(() => EmailRepositoryImpl( @@ -120,7 +120,6 @@ class ComposerBindings extends BaseBindings { )); Get.lazyPut(() => LocalFilePickerInteractor()); Get.lazyPut(() => UploadAttachmentInteractor(Get.find())); - Get.lazyPut(() => UploadMultipleAttachmentInteractor(Get.find())); Get.lazyPut(() => SendEmailInteractor(Get.find())); Get.lazyPut(() => SaveEmailAsDraftsInteractor(Get.find())); Get.lazyPut(() => GetEmailContentInteractor(Get.find())); @@ -130,18 +129,23 @@ class ComposerBindings extends BaseBindings { @override void bindingsController() { + Get.lazyPut(() => UploadController(Get.find())); Get.lazyPut(() => ComposerController( Get.find(), Get.find(), Get.find(), - Get.find(), Get.find(), Get.find(), - Get.find(), Get.find(), Get.find(), Get.find(), Get.find(), + Get.find(), )); } + + void dispose() { + Get.delete(); + Get.delete(); + } } \ No newline at end of file diff --git a/lib/features/composer/presentation/composer_controller.dart b/lib/features/composer/presentation/composer_controller.dart index fe2023daf..5e97f3a57 100644 --- a/lib/features/composer/presentation/composer_controller.dart +++ b/lib/features/composer/presentation/composer_controller.dart @@ -31,11 +31,9 @@ import 'package:tmail_ui_user/features/composer/domain/model/email_request.dart' import 'package:tmail_ui_user/features/composer/domain/state/get_autocomplete_state.dart'; import 'package:tmail_ui_user/features/composer/domain/usecases/get_autocomplete_interactor.dart'; import 'package:tmail_ui_user/features/composer/domain/usecases/get_autocomplete_with_device_contact_interactor.dart'; -import 'package:tmail_ui_user/features/composer/domain/state/upload_attachment_state.dart'; import 'package:tmail_ui_user/features/composer/domain/usecases/save_email_as_drafts_interactor.dart'; import 'package:tmail_ui_user/features/composer/domain/usecases/send_email_interactor.dart'; import 'package:tmail_ui_user/features/composer/domain/usecases/update_email_drafts_interactor.dart'; -import 'package:tmail_ui_user/features/composer/domain/usecases/upload_mutiple_attachment_interactor.dart'; import 'package:tmail_ui_user/features/composer/presentation/extensions/email_action_type_extension.dart'; import 'package:tmail_ui_user/features/composer/presentation/model/screen_display_mode.dart'; import 'package:tmail_ui_user/features/email/domain/state/get_email_content_state.dart'; @@ -44,8 +42,10 @@ import 'package:tmail_ui_user/features/email/presentation/model/composer_argumen import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart'; import 'package:tmail_ui_user/features/manage_account/domain/state/get_all_identities_state.dart'; import 'package:tmail_ui_user/features/manage_account/domain/usecases/get_all_identities_interactor.dart'; +import 'package:tmail_ui_user/features/upload/domain/model/upload_task_id.dart'; import 'package:tmail_ui_user/features/upload/domain/state/local_file_picker_state.dart'; import 'package:tmail_ui_user/features/upload/domain/usecases/local_file_picker_interactor.dart'; +import 'package:tmail_ui_user/features/upload/presentation/controller/upload_controller.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'; @@ -56,12 +56,12 @@ class ComposerController extends BaseController { final _appToast = Get.find(); final _imagePaths = Get.find(); final _responsiveUtils = Get.find(); + final _uuid = Get.find(); final expandModeAttachments = ExpandMode.COLLAPSE.obs; final composerArguments = Rxn(); final isEnableEmailSendButton = false.obs; final isInitialRecipient = false.obs; - final attachments = [].obs; final emailContents = Rxn>(); final listEmailAddressType = [].obs; final subjectEmail = Rxn(); @@ -75,14 +75,13 @@ class ComposerController extends BaseController { final SendEmailInteractor _sendEmailInteractor; final GetAutoCompleteInteractor _getAutoCompleteInteractor; final GetAutoCompleteWithDeviceContactInteractor _getAutoCompleteWithDeviceContactInteractor; - final Uuid _uuid; final LocalFilePickerInteractor _localFilePickerInteractor; - final UploadMultipleAttachmentInteractor _uploadMultipleAttachmentInteractor; final DeviceInfoPlugin _deviceInfoPlugin; final SaveEmailAsDraftsInteractor _saveEmailAsDraftsInteractor; final GetEmailContentInteractor _getEmailContentInteractor; final UpdateEmailDraftsInteractor _updateEmailDraftsInteractor; final GetAllIdentitiesInteractor _getAllIdentitiesInteractor; + final UploadController uploadController; List listToEmailAddress = []; List listCcEmailAddress = []; @@ -129,14 +128,13 @@ class ComposerController extends BaseController { this._sendEmailInteractor, this._getAutoCompleteInteractor, this._getAutoCompleteWithDeviceContactInteractor, - this._uuid, this._deviceInfoPlugin, this._localFilePickerInteractor, - this._uploadMultipleAttachmentInteractor, this._saveEmailAsDraftsInteractor, this._getEmailContentInteractor, this._updateEmailDraftsInteractor, this._getAllIdentitiesInteractor, + this.uploadController, ); @override @@ -183,18 +181,11 @@ class ComposerController extends BaseController { (failure) { if (failure is LocalFilePickerFailure || failure is LocalFilePickerCancel) { _pickFileFailure(failure); - } else if (failure is UploadAttachmentFailure - || failure is UploadMultipleAttachmentAllFailure) { - _uploadAttachmentsFailure(failure); } }, (success) { if (success is LocalFilePickerSuccess) { _pickFileSuccess(success); - } else if (success is UploadAttachmentSuccess - || success is UploadMultipleAttachmentAllSuccess - || success is UploadMultipleAttachmentHasSomeFailure) { - _uploadAttachmentsSuccess(success); } else if (success is GetEmailContentSuccess) { _getEmailContentSuccess(success); } if (success is GetAllIdentitiesSuccess) { @@ -219,7 +210,7 @@ class ComposerController extends BaseController { } popBack(); } - + void _initEmail() { final arguments = kIsWeb ? mailboxDashBoardController.routerArguments : Get.arguments; if (arguments is ComposerArguments) { @@ -243,8 +234,13 @@ class ComposerController extends BaseController { } void _initAttachments(ComposerArguments arguments) { - attachments.value = arguments.attachments ?? []; - initialAttachments = arguments.attachments ?? []; + if (arguments.attachments?.isNotEmpty == true) { + initialAttachments = arguments.attachments!; + uploadController.initializeUploadAttachments(arguments.attachments!); + } + if (BuildUtils.isWeb) { + expandModeAttachments.value = ExpandMode.EXPAND; + } } void _getAllIdentities() { @@ -466,7 +462,7 @@ class ComposerController extends BaseController { generatePartId: EmailBodyValue(emailBodyText, false, false) }, headerUserAgent: {IndividualHeaderIdentifier.headerUserAgent : userAgent}, - attachments: attachments.isNotEmpty ? _generateAttachments() : null, + attachments: uploadController.generateAttachments(), ); } @@ -485,11 +481,6 @@ class ComposerController extends BaseController { return userAgent; } - Set _generateAttachments() { - return attachments.map((attachment) => - attachment.toEmailBodyPart(ContentDisposition.attachment.value)).toSet(); - } - void sendEmailAction(BuildContext context) async { clearFocusEditor(context); @@ -534,7 +525,19 @@ class ComposerController extends BaseController { return; } - if (!_validateAttachmentsSize()) { + if (!uploadController.allUploadAttachmentsCompleted) { + showConfirmDialogAction( + context, + AppLocalizations.of(context).messageDialogSendEmailUploadingAttachment, + AppLocalizations.of(context).got_it, + () => {}, + title: AppLocalizations.of(context).sending_failed, + icon: SvgPicture.asset(_imagePaths.icSendToastError, fit: BoxFit.fill), + hasCancelButton: false); + return; + } + + if (!uploadController.hasEnoughMaxAttachmentSize()) { showConfirmDialogAction( context, AppLocalizations.of(context).message_dialog_send_email_exceeds_maximum_size( @@ -561,7 +564,7 @@ class ComposerController extends BaseController { final email = await _generateEmail(mapDefaultMailboxId, userProfile); final accountId = session.accounts.keys.first; final sentMailboxId = mapDefaultMailboxId[PresentationMailbox.roleSent]; - final submissionCreateId = Id(_uuid.v1()); + final submissionCreateId = Id(const Uuid().v1()); mailboxDashBoardController.consumeState(_sendEmailInteractor.execute( accountId, @@ -633,88 +636,34 @@ class ComposerController extends BaseController { } } - void _pickFileSuccess(Success success) { - if (success is LocalFilePickerSuccess) { - if (_validateAttachmentsSize(listFiles: success.pickedFiles)) { - _uploadAttachmentsAction(success.pickedFiles); - } 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); - } - } - } - } - - bool _validateAttachmentsSize({List? listFiles}) { - final currentTotalAttachmentsSize = attachments.totalSize(); - log('ComposerController::_validateAttachmentsSize(): $currentTotalAttachmentsSize'); - num uploadedTotalSize = 0; - if (listFiles != null && listFiles.isNotEmpty) { - final uploadedListSize = listFiles.map((file) => file.fileSize).toList(); - uploadedTotalSize = uploadedListSize.reduce((sum, size) => sum + size); - log('ComposerController::_validateAttachmentsSize(): uploadedTotalSize: $uploadedTotalSize'); - } - - final totalSizeReadyToUpload = currentTotalAttachmentsSize + uploadedTotalSize; - log('ComposerController::_validateAttachmentsSize(): totalSizeReadyToUpload: $totalSizeReadyToUpload'); - - final maxSizeAttachmentsPerEmail = mailboxDashBoardController.maxSizeAttachmentsPerEmail?.value; - if (maxSizeAttachmentsPerEmail != null) { - return totalSizeReadyToUpload <= maxSizeAttachmentsPerEmail; + void _pickFileSuccess(LocalFilePickerSuccess success) { + if (uploadController.hasEnoughMaxAttachmentSize(listFiles: success.pickedFiles)) { + _uploadAttachmentsAction(success.pickedFiles); } else { - return false; + 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); + } } } void _uploadAttachmentsAction(List pickedFiles) async { final session = mailboxDashBoardController.sessionCurrent; - if (session != null) { - final accountId = session.accounts.keys.first; - final uploadUrl = session.getUploadUrl(accountId); - consumeState(_uploadMultipleAttachmentInteractor.execute(pickedFiles, accountId, uploadUrl)); + final accountId = mailboxDashBoardController.accountId.value; + if (session != null && accountId != null) { + final uploadUri = session.getUploadUri(accountId); + uploadController.justUploadAttachmentsAction(pickedFiles, uploadUri); } } - void _uploadAttachmentsFailure(Failure failure) { - if (currentContext != null) { - _appToast.showErrorToast(AppLocalizations.of(currentContext!).can_not_upload_this_file_as_attachments); - } - } - - void _uploadAttachmentsSuccess(Success success) { - if (success is UploadAttachmentSuccess) { - attachments.add(success.attachment); - } else if (success is UploadMultipleAttachmentAllSuccess) { - final listAttachment = success.listResults.where((either) => either.isRight()) - .map((either) => either - .map((result) => (result as UploadAttachmentSuccess).attachment) - .toIterable().first) - .toList(); - - attachments.addAll(listAttachment); - } else if (success is UploadMultipleAttachmentHasSomeFailure) { - final listAttachment = success.listResults - .map((either) => either - .map((result) => (result as UploadAttachmentSuccess).attachment) - .toIterable().first) - .toList(); - - attachments.addAll(listAttachment); - } - if (currentContext != null) { - _appToast.showSuccessToast(AppLocalizations.of(currentContext!).attachments_uploaded_successfully); - } - } - - void removeAttachmentAction(Attachment attachmentRemoved) { - attachments.removeWhere((attachment) => attachment == attachmentRemoved); + void deleteAttachmentUploaded(UploadTaskId uploadId) { + uploadController.deleteFileUploaded(uploadId); } Future _isEmailChanged(BuildContext context, ComposerArguments arguments) async { @@ -759,7 +708,7 @@ class ComposerController extends BaseController { final oldBccEmailAddress = recipients.value1; final isBccEmailAddressChanged = !oldBccEmailAddress.isSame(newBccEmailAddress); - final isAttachmentsChanged = !initialAttachments.isSame(attachments.toList()); + final isAttachmentsChanged = !initialAttachments.isSame(uploadController.attachmentsUploaded.toList()); if (isEmailBodyChanged || isEmailSubjectChanged || isToEmailAddressChanged || isCcEmailAddressChanged @@ -816,8 +765,10 @@ class ComposerController extends BaseController { void _getEmailContentSuccess(GetEmailContentSuccess success) { emailContents.value = success.emailContents; - attachments.value = success.attachments; - initialAttachments = success.attachments; + if (success.attachments.isNotEmpty) { + initialAttachments = success.attachments; + uploadController.initializeUploadAttachments(success.attachments); + } } String? getEmailContentDraftsAsHtml() { diff --git a/lib/features/composer/presentation/composer_view.dart b/lib/features/composer/presentation/composer_view.dart index 4aaea1bc5..e0ef85483 100644 --- a/lib/features/composer/presentation/composer_view.dart +++ b/lib/features/composer/presentation/composer_view.dart @@ -14,6 +14,8 @@ import 'package:tmail_ui_user/features/composer/domain/state/upload_attachment_s import 'package:tmail_ui_user/features/composer/presentation/composer_controller.dart'; import 'package:tmail_ui_user/features/composer/presentation/widgets/attachment_file_composer_builder.dart'; import 'package:tmail_ui_user/features/composer/presentation/widgets/email_address_input_builder.dart'; +import 'package:tmail_ui_user/features/upload/presentation/extensions/list_upload_file_state_extension.dart'; +import 'package:tmail_ui_user/features/upload/presentation/model/upload_file_state.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; class ComposerView extends GetWidget { @@ -29,10 +31,7 @@ class ComposerView extends GetWidget { return ResponsiveWidget( responsiveUtils: responsiveUtils, mobile: _buildComposerViewForMobile(context), - landscapeMobile: _buildComposerViewForMobile(context), tablet: _buildComposerViewForTablet(context), - tabletLarge: _buildComposerViewForTablet(context), - desktop: _buildComposerViewForTablet(context), ); } @@ -398,19 +397,26 @@ class ComposerView extends GetWidget { const Divider(color: AppColor.colorDividerComposer, height: 1), Padding(padding: const EdgeInsets.symmetric(horizontal: 16), child: _buildListButton(context)), const Divider(color: AppColor.colorDividerComposer, height: 1), - Obx(() => controller.attachments.isNotEmpty - ? Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: _buildAttachmentsTitle(context, controller.attachments, controller.expandModeAttachments.value)) - : const SizedBox.shrink()), - Obx(() => controller.attachments.isEmpty - ? _buildAttachmentsLoadingView() - : const SizedBox.shrink()), - Obx(() => controller.attachments.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(bottom: 8, left: 16, right: 16), - child: _buildAttachmentsList(context, controller.attachments, controller.expandModeAttachments.value)) - : const SizedBox.shrink()), + Obx(() { + final uploadAttachments = controller.uploadController.listUploadAttachments; + if (uploadAttachments.isEmpty) { + return const SizedBox.shrink(); + } else { + return Column(children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: _buildAttachmentsTitle(context, + uploadAttachments, + controller.expandModeAttachments.value)), + _buildAttachmentsLoadingView(), + Padding( + padding: const EdgeInsets.only(bottom: 8, left: 16, right: 16), + child: _buildAttachmentsList(context, + uploadAttachments, + controller.expandModeAttachments.value)) + ]); + } + }), Padding( padding: const EdgeInsets.only(left: 16, right: 16, bottom: 20), child: _buildComposerEditor(context)), @@ -453,19 +459,26 @@ class ComposerView extends GetWidget { Padding( padding: const EdgeInsets.only(left: 60, right: 25), child: Column(children: [ - Obx(() => controller.attachments.isNotEmpty - ? Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: _buildAttachmentsTitle(context, controller.attachments, controller.expandModeAttachments.value)) - : const SizedBox.shrink()), - Obx(() => controller.attachments.isEmpty - ? _buildAttachmentsLoadingView() - : const SizedBox.shrink()), - Obx(() => controller.attachments.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(bottom: 8, left: 16, right: 16), - child: _buildAttachmentsList(context, controller.attachments, controller.expandModeAttachments.value)) - : const SizedBox.shrink()), + Obx(() { + final uploadAttachments = controller.uploadController.listUploadAttachments; + if (uploadAttachments.isEmpty) { + return const SizedBox.shrink(); + } else { + return Column(children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: _buildAttachmentsTitle(context, + uploadAttachments, + controller.expandModeAttachments.value)), + _buildAttachmentsLoadingView(), + Padding( + padding: const EdgeInsets.only(bottom: 8, left: 16, right: 16), + child: _buildAttachmentsList(context, + uploadAttachments, + controller.expandModeAttachments.value)) + ]); + } + }), Padding( padding: const EdgeInsets.only(left: 16, right: 16, bottom: 20, top: 10), child: _buildComposerEditor(context)), @@ -509,11 +522,15 @@ class ComposerView extends GetWidget { : const SizedBox.shrink())); } - Widget _buildAttachmentsTitle(BuildContext context, List attachments, ExpandMode expandModeAttachment) { + Widget _buildAttachmentsTitle( + BuildContext context, + List uploadFilesState, + ExpandMode expandModeAttachment + ) { return Row( children: [ Text( - '${AppLocalizations.of(context).attachments} (${filesize(attachments.totalSize(), 0)}):', + '${AppLocalizations.of(context).attachments} (${filesize(uploadFilesState.totalSize, 0)}):', style: const TextStyle(fontSize: 12, color: AppColor.colorHintEmailAddressInput, fontWeight: FontWeight.normal)), _buildAttachmentsLoadingView(padding: const EdgeInsets.only(left: 16), size: 16), const Spacer(), @@ -524,7 +541,7 @@ class ComposerView extends GetWidget { child: Text( expandModeAttachment == ExpandMode.EXPAND ? AppLocalizations.of(context).hide - : '${AppLocalizations.of(context).show_all} (${attachments.length})', + : '${AppLocalizations.of(context).show_all} (${uploadFilesState.length})', style: const TextStyle(fontWeight: FontWeight.w500, fontSize: 12, color: AppColor.colorTextButton)), onPressed: () => controller.toggleDisplayAttachments() ) @@ -533,23 +550,28 @@ class ComposerView extends GetWidget { ); } - Widget _buildAttachmentsList(BuildContext context, List attachments, ExpandMode expandMode) { + Widget _buildAttachmentsList( + BuildContext context, + List uploadFilesState, + ExpandMode expandMode + ) { + const double maxHeightItem = 60; if (expandMode == ExpandMode.EXPAND) { return LayoutBuilder(builder: (context, constraints) { return GridView.builder( key: const Key('list_attachment_full'), primary: false, shrinkWrap: true, - itemCount: attachments.length, + itemCount: uploadFilesState.length, gridDelegate: SliverGridDelegateFixedHeight( - height: 60, + height: maxHeightItem, crossAxisCount: _getMaxItemRowListAttachment(context, constraints), crossAxisSpacing: 8.0, mainAxisSpacing: 8.0), - itemBuilder: (context, index) => - (AttachmentFileComposerBuilder(context, imagePaths, attachments[index]) - ..addOnDeleteAttachmentAction((attachment) => controller.removeAttachmentAction(attachment))) - .build() + itemBuilder: (context, index) => AttachmentFileComposerBuilder( + uploadFilesState[index], + onDeleteAttachmentAction: (attachment) => + controller.deleteAttachmentUploaded(attachment.uploadTaskId)) ); }); } else { @@ -557,20 +579,19 @@ class ComposerView extends GetWidget { return Align( alignment: Alignment.centerLeft, child: SizedBox( - height: 60, + height: maxHeightItem, child: ListView.builder( key: const Key('list_attachment_minimize'), shrinkWrap: true, physics: const ClampingScrollPhysics(), scrollDirection: Axis.horizontal, - itemCount: attachments.length, - itemBuilder: (context, index) => - (AttachmentFileComposerBuilder(context, imagePaths, attachments[index], - itemMargin: const EdgeInsets.only(right: 8), - maxWidth: _getMaxWidthItemListAttachment(context, constraints), - maxHeight: 60) - ..addOnDeleteAttachmentAction((attachment) => controller.removeAttachmentAction(attachment))) - .build() + itemCount: uploadFilesState.length, + itemBuilder: (context, index) => AttachmentFileComposerBuilder( + uploadFilesState[index], + itemMargin: const EdgeInsets.only(right: 8), + maxWidth: _getMaxWidthItemListAttachment(context, constraints), + onDeleteAttachmentAction: (attachment) => + controller.deleteAttachmentUploaded(attachment.uploadTaskId)) ) ) ); diff --git a/lib/features/composer/presentation/composer_view_web.dart b/lib/features/composer/presentation/composer_view_web.dart index 38dc84f36..eea368fc6 100644 --- a/lib/features/composer/presentation/composer_view_web.dart +++ b/lib/features/composer/presentation/composer_view_web.dart @@ -15,6 +15,8 @@ import 'package:tmail_ui_user/features/composer/presentation/composer_controller import 'package:tmail_ui_user/features/composer/presentation/model/screen_display_mode.dart'; import 'package:tmail_ui_user/features/composer/presentation/widgets/attachment_file_composer_builder.dart'; import 'package:tmail_ui_user/features/composer/presentation/widgets/email_address_input_builder.dart'; +import 'package:tmail_ui_user/features/upload/presentation/extensions/list_upload_file_state_extension.dart'; +import 'package:tmail_ui_user/features/upload/presentation/model/upload_file_state.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; class ComposerView extends GetWidget { @@ -488,54 +490,65 @@ class ComposerView extends GetWidget { } Widget _buildEditorAndAttachments(BuildContext context) { - return Column( - children: [ - Obx(() => controller.attachments.isNotEmpty - ? Padding( - padding: EdgeInsets.only(top: 4, bottom: 4, left: responsiveUtils.isMobile(context) ? 16 : 20, right: responsiveUtils.isMobile(context) ? 16: 0), - child: _buildAttachmentsTitle(context, controller.attachments, controller.expandModeAttachments.value)) - : const SizedBox.shrink()), - Obx(() => controller.attachments.isEmpty - ? _buildAttachmentsLoadingView() - : const SizedBox.shrink()), - Obx(() => controller.attachments.isNotEmpty - ? Padding( - padding: EdgeInsets.only(bottom: 8, left: responsiveUtils.isMobile(context) ? 16 : 10, right: responsiveUtils.isMobile(context) ? 16 : 10), - child: _buildAttachmentsList(context, controller.attachments, controller.expandModeAttachments.value)) - : const SizedBox.shrink()), - Obx(() { - if (controller.composerArguments.value != null) { - if (controller.composerArguments.value?.emailActionType == EmailActionType.compose) { - final initContent = controller.textEditorWeb ?? ''.addEditorDefaultSpace(); - return Expanded(child: Padding( - padding: EdgeInsets.symmetric(horizontal: responsiveUtils.isMobile(context) ? 8 : 10), - child: _buildEditor(context, initContent))); - } else if (controller.composerArguments.value?.emailActionType == EmailActionType.edit) { - final initContent = controller.textEditorWeb ?? controller.getEmailContentDraftsAsHtml(); - if (initContent != null) { - return Expanded(child: Padding( - padding: EdgeInsets.symmetric(horizontal: responsiveUtils.isMobile(context) ? 8 : 10), - child: _buildEditor(context, initContent))); - } else { - return const Padding( - padding: EdgeInsets.all(16), - child: SizedBox( - width: 30, - height: 30, - child: CupertinoActivityIndicator(color: AppColor.colorLoading))); - } - } else { - final initContent = controller.textEditorWeb ?? controller.getEmailContentQuotedAsHtml(context, controller.composerArguments.value!); - return Expanded(child: Padding( - padding: EdgeInsets.symmetric(horizontal: responsiveUtils.isMobile(context) ? 8 : 10), - child: _buildEditor(context, initContent))); - } - } else { - return const SizedBox.shrink(); - } - }), - ] - ); + return Obx(() { + final uploadAttachments = controller.uploadController.listUploadAttachments; + + return Column( + children: [ + if (uploadAttachments.isNotEmpty) + ...[ + Padding( + padding: EdgeInsets.only( + top: 4, + bottom: 4, + left: responsiveUtils.isMobile(context) ? 16 : 20, + right: responsiveUtils.isMobile(context) ? 16: 0), + child: _buildAttachmentsTitle(context, + uploadAttachments, + controller.expandModeAttachments.value)), + _buildAttachmentsLoadingView(), + Padding( + padding: EdgeInsets.only( + bottom: 8, + left: responsiveUtils.isMobile(context) ? 16 : 10, + right: responsiveUtils.isMobile(context) ? 16 : 10), + child: _buildAttachmentsList(context, + uploadAttachments, + controller.expandModeAttachments.value)) + ], + if (controller.composerArguments.value != null) + _buildComposeEditor(context) + ] + ); + }); + } + + Widget _buildComposeEditor(BuildContext context) { + if (controller.composerArguments.value?.emailActionType == EmailActionType.compose) { + final initContent = controller.textEditorWeb ?? ''.addEditorDefaultSpace(); + return Expanded(child: Padding( + padding: EdgeInsets.symmetric(horizontal: responsiveUtils.isMobile(context) ? 8 : 10), + child: _buildEditor(context, initContent))); + } else if (controller.composerArguments.value?.emailActionType == EmailActionType.edit) { + final initContent = controller.textEditorWeb ?? controller.getEmailContentDraftsAsHtml(); + if (initContent != null) { + return Expanded(child: Padding( + padding: EdgeInsets.symmetric(horizontal: responsiveUtils.isMobile(context) ? 8 : 10), + child: _buildEditor(context, initContent))); + } else { + return const Padding( + padding: EdgeInsets.all(16), + child: SizedBox( + width: 30, + height: 30, + child: CupertinoActivityIndicator(color: AppColor.colorLoading))); + } + } else { + final initContent = controller.textEditorWeb ?? controller.getEmailContentQuotedAsHtml(context, controller.composerArguments.value!); + return Expanded(child: Padding( + padding: EdgeInsets.symmetric(horizontal: responsiveUtils.isMobile(context) ? 8 : 10), + child: _buildEditor(context, initContent))); + } } Widget _buildEditor(BuildContext context, String initContent) { @@ -590,11 +603,14 @@ class ComposerView extends GetWidget { : const SizedBox.shrink())); } - Widget _buildAttachmentsTitle(BuildContext context, List attachments, ExpandMode expandModeAttachment) { + Widget _buildAttachmentsTitle( + BuildContext context, + List uploadFilesState, + ExpandMode expandModeAttachment) { return Row( children: [ Text( - '${AppLocalizations.of(context).attachments} (${filesize(attachments.totalSize(), 0)}):', + '${AppLocalizations.of(context).attachments} (${filesize(uploadFilesState.totalSize, 0)}):', style: const TextStyle(fontSize: 12, color: AppColor.colorHintEmailAddressInput, fontWeight: FontWeight.normal)), _buildAttachmentsLoadingView(padding: const EdgeInsets.only(left: 16), size: 16), const Spacer(), @@ -605,7 +621,7 @@ class ComposerView extends GetWidget { child: Text( expandModeAttachment == ExpandMode.EXPAND ? AppLocalizations.of(context).hide - : '${AppLocalizations.of(context).show_all} (${attachments.length})', + : '${AppLocalizations.of(context).show_all} (${uploadFilesState.length})', style: const TextStyle(fontWeight: FontWeight.w500, fontSize: 12, color: AppColor.colorTextButton)), onPressed: () => controller.toggleDisplayAttachments() ) @@ -614,7 +630,10 @@ class ComposerView extends GetWidget { ); } - Widget _buildAttachmentsList(BuildContext context, List attachments, ExpandMode expandMode) { + Widget _buildAttachmentsList( + BuildContext context, + List uploadFilesState, + ExpandMode expandMode) { if (expandMode == ExpandMode.COLLAPSE) { return const SizedBox.shrink(); } else { @@ -628,14 +647,13 @@ class ComposerView extends GetWidget { shrinkWrap: true, physics: const ClampingScrollPhysics(), scrollDirection: Axis.horizontal, - itemCount: attachments.length, - itemBuilder: (context, index) => - (AttachmentFileComposerBuilder(context, imagePaths, attachments[index], - itemMargin: const EdgeInsets.only(right: 8), - maxWidth: _getMaxWidthItemListAttachment(context, constraints), - maxHeight: 60) - ..addOnDeleteAttachmentAction((attachment) => controller.removeAttachmentAction(attachment))) - .build() + itemCount: uploadFilesState.length, + itemBuilder: (context, index) => AttachmentFileComposerBuilder( + uploadFilesState[index], + itemMargin: const EdgeInsets.only(right: 8), + maxWidth: _getMaxWidthItemListAttachment(context, constraints), + onDeleteAttachmentAction: (attachment) => + controller.deleteAttachmentUploaded(attachment.uploadTaskId)) ) ) ); diff --git a/lib/features/composer/presentation/widgets/attachment_file_composer_builder.dart b/lib/features/composer/presentation/widgets/attachment_file_composer_builder.dart index 9a995841b..941338b1e 100644 --- a/lib/features/composer/presentation/widgets/attachment_file_composer_builder.dart +++ b/lib/features/composer/presentation/widgets/attachment_file_composer_builder.dart @@ -1,88 +1,131 @@ import 'package:core/core.dart'; import 'package:filesize/filesize.dart'; -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:model/model.dart'; +import 'package:get/get.dart'; +import 'package:tmail_ui_user/features/base/mixin/app_loader_mixin.dart'; +import 'package:tmail_ui_user/features/upload/presentation/model/upload_file_state.dart'; +import 'package:tmail_ui_user/features/upload/presentation/model/upload_file_status.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; -typedef OnDeleteAttachmentAction = void Function(Attachment attachment); +typedef OnDeleteAttachmentAction = void Function(UploadFileState fileState); -class AttachmentFileComposerBuilder { +class AttachmentFileComposerBuilder extends StatelessWidget with AppLoaderMixin { - final BuildContext context; - final ImagePaths imagePaths; - final Attachment attachment; + final _imagePaths = Get.find(); + + final UploadFileState fileState; final double? maxWidth; - final double? maxHeight; final EdgeInsets? itemMargin; + final OnDeleteAttachmentAction? onDeleteAttachmentAction; + final Widget? buttonAction; - OnDeleteAttachmentAction? _onDeleteAttachmentAction; + AttachmentFileComposerBuilder(this.fileState, { + super.key, + this.maxWidth, + this.itemMargin, + this.buttonAction, + this.onDeleteAttachmentAction, + }); - Widget? buttonAction; - - AttachmentFileComposerBuilder( - this.context, - this.imagePaths, - this.attachment, - { - this.maxWidth, - this.maxHeight, - this.itemMargin, - } - ); - - void addOnDeleteAttachmentAction(OnDeleteAttachmentAction onDeleteAttachmentAction) { - _onDeleteAttachmentAction = onDeleteAttachmentAction; - } - - Widget build() { + @override + Widget build(BuildContext context) { return Theme( - data: ThemeData( - splashColor: Colors.transparent , - highlightColor: Colors.transparent), - child: Container( - margin: itemMargin ?? EdgeInsets.zero, - padding: EdgeInsets.zero, - alignment: Alignment.center, - width: maxWidth, - height: maxHeight, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10), - border: Border.all(color: AppColor.colorInputBorderCreateMailbox), - color: Colors.white), - child: Stack(children: [ - ListTile( - contentPadding: const EdgeInsets.only(right: kIsWeb ? 16 : 18), + data: ThemeData( + splashColor: Colors.transparent , + highlightColor: Colors.transparent), + child: Container( + margin: itemMargin ?? EdgeInsets.zero, + padding: EdgeInsets.zero, + alignment: Alignment.center, + width: maxWidth, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + border: Border.all(color: AppColor.colorInputBorderCreateMailbox), + color: Colors.white), + child: Stack(children: [ + ListTile( + contentPadding: EdgeInsets.zero, + focusColor: AppColor.primaryColor, + hoverColor: AppColor.primaryColor, onTap: () {}, - leading: Transform( - transform: Matrix4.translationValues(8.0, kIsWeb ? -3.0 : -5.0, 0.0), - child: SvgPicture.asset(imagePaths.icFileAttachment, fit: BoxFit.fill)), + leading: Padding( + padding: const EdgeInsets.only( + left: 8, + bottom: BuildUtils.isWeb ? 6 : 14), + child: SvgPicture.asset( + fileState.getIcon(_imagePaths), + width: 40, + height: 40, + fit: BoxFit.fill), + ), title: Transform( - transform: Matrix4.translationValues(kIsWeb ? -4.0 : -10.0, kIsWeb ? -6.0 : -9.0, 0.0), - child: Text( - attachment.name ?? '', - maxLines: 2, - overflow: TextOverflow.ellipsis, - style: const TextStyle(fontSize: 12, color: AppColor.colorNameEmail, fontWeight: FontWeight.w500), - )), - subtitle: attachment.size != null && attachment.size?.value != 0 + transform: Matrix4.translationValues( + BuildUtils.isWeb ? 0.0 : -8.0, + BuildUtils.isWeb ? -8.0 : -10.0, + 0.0), + child: Padding( + padding: const EdgeInsets.only(right: BuildUtils.isWeb ? 20 : 16), + child: Text( + fileState.fileName, + maxLines: 1, + overflow: CommonTextStyle.defaultTextOverFlow, + style: const TextStyle( + fontSize: 14, + color: Colors.black, + fontWeight: FontWeight.w500), + ), + ) + ), + subtitle: fileState.fileSize != 0 ? Transform( - transform: Matrix4.translationValues(kIsWeb ? -4.0 : -10.0, kIsWeb ? -5.0 : -8.0, 0.0), + transform: Matrix4.translationValues( + BuildUtils.isWeb ? 0.0 : -8.0, + BuildUtils.isWeb ? -8.0 : -10.0, + 0.0), child: Text( - filesize(attachment.size?.value, 0), + filesize(fileState.fileSize), maxLines: 1, - overflow: TextOverflow.ellipsis, - style: const TextStyle(fontSize: 10, color: AppColor.colorContentEmail, fontWeight: FontWeight.normal))) + overflow: CommonTextStyle.defaultTextOverFlow, + style: const TextStyle( + fontSize: 12, + fontWeight: FontWeight.normal, + color: AppColor.colorContentEmail))) : null, - ), - Positioned(right: kIsWeb ? -5 : -12, top: kIsWeb ? -5 : -12, child: buildIconWeb( - icon: SvgPicture.asset(imagePaths.icDeleteAttachment, fit: BoxFit.fill), - tooltip: AppLocalizations.of(context).delete, - onTap: () => _onDeleteAttachmentAction?.call(attachment))) - ]), - ) + ), + Positioned( + right: BuildUtils.isWeb ? -5 : -12, + top: BuildUtils.isWeb ? -5 : -12, + child: buildIconWeb( + icon: SvgPicture.asset(_imagePaths.icDeleteAttachment, fit: BoxFit.fill), + tooltip: AppLocalizations.of(context).delete, + onTap: () { + if (onDeleteAttachmentAction != null) { + onDeleteAttachmentAction!.call(fileState); + } + } + ) + ), + Align(alignment: Alignment.bottomCenter, child: _progressLoading), + ]), + ) ); } + + Widget get _progressLoading { + switch(fileState.uploadStatus) { + case UploadFileStatus.waiting: + return Padding( + padding: const EdgeInsets.only(left: 8, right: 8, top: 50), + child: horizontalLoadingWidget); + case UploadFileStatus.uploading: + return Padding( + padding: const EdgeInsets.only(top: 50), + child: horizontalPercentLoadingWidget(fileState.percentUploading)); + case UploadFileStatus.uploadFailed: + case UploadFileStatus.succeed: + return const SizedBox.shrink(); + } + } } \ No newline at end of file diff --git a/lib/features/email/presentation/email_view.dart b/lib/features/email/presentation/email_view.dart index a00c44aa8..e3ad550bf 100644 --- a/lib/features/email/presentation/email_view.dart +++ b/lib/features/email/presentation/email_view.dart @@ -406,9 +406,11 @@ class EmailView extends GetWidget with NetworkConnectionMixin { } int _getAttachmentLimitDisplayed(BuildContext context) { - if (responsiveUtils.isScreenWithShortestSide(context)) { + if (responsiveUtils.isMobile(context) + || responsiveUtils.isLandscapeMobile(context)) { return 2; - } else if (responsiveUtils.isTablet(context)) { + } else if (responsiveUtils.isTablet(context) || + responsiveUtils.isLandscapeTablet(context)) { return 3; } else { return 4; diff --git a/lib/features/email/presentation/widgets/attachment_file_tile_builder.dart b/lib/features/email/presentation/widgets/attachment_file_tile_builder.dart index 72d6d4c2d..7829d8e5b 100644 --- a/lib/features/email/presentation/widgets/attachment_file_tile_builder.dart +++ b/lib/features/email/presentation/widgets/attachment_file_tile_builder.dart @@ -82,8 +82,8 @@ class AttachmentFileTileBuilder { padding: const EdgeInsets.only(left: 8, bottom: BuildUtils.isWeb ? 6 : 14), child: SvgPicture.asset( _attachment.getIcon(_imagePaths), - width: 44, - height: 44, + width: 40, + height: 40, fit: BoxFit.fill), ), title: Transform( diff --git a/lib/features/mailbox/presentation/mailbox_bindings.dart b/lib/features/mailbox/presentation/mailbox_bindings.dart index 0fc1d6597..f237a043d 100644 --- a/lib/features/mailbox/presentation/mailbox_bindings.dart +++ b/lib/features/mailbox/presentation/mailbox_bindings.dart @@ -31,7 +31,6 @@ import 'package:tmail_ui_user/features/mailbox_creator/domain/usecases/verify_na import 'package:tmail_ui_user/features/thread/data/datasource/thread_datasource.dart'; import 'package:tmail_ui_user/features/thread/data/datasource_impl/thread_datasource_impl.dart'; import 'package:tmail_ui_user/features/thread/data/network/thread_api.dart'; -import 'package:uuid/uuid.dart'; class MailboxBindings extends BaseBindings { @@ -43,7 +42,6 @@ class MailboxBindings extends BaseBindings { void _bindingsUtils() { Get.lazyPut(() => TreeBuilder()); - Get.lazyPut(() => const Uuid()); } @override @@ -57,7 +55,6 @@ class MailboxBindings extends BaseBindings { Get.find(), Get.find(), Get.find(), - Get.find(), Get.find(), )); } diff --git a/lib/features/mailbox/presentation/mailbox_controller.dart b/lib/features/mailbox/presentation/mailbox_controller.dart index 6189c9e0f..5f5a924f5 100644 --- a/lib/features/mailbox/presentation/mailbox_controller.dart +++ b/lib/features/mailbox/presentation/mailbox_controller.dart @@ -74,6 +74,7 @@ class MailboxController extends BaseMailboxController { final _appToast = Get.find(); final _imagePaths = Get.find(); final _responsiveUtils = Get.find(); + final _uuid = Get.find(); final GetAllMailboxInteractor _getAllMailboxInteractor; final RefreshAllMailboxInteractor _refreshAllMailboxInteractor; @@ -83,7 +84,6 @@ class MailboxController extends BaseMailboxController { final VerifyNameInteractor _verifyNameInteractor; final RenameMailboxInteractor _renameMailboxInteractor; final MoveMailboxInteractor _moveMailboxInteractor; - final Uuid _uuid; final listMailboxSearched = [].obs; final searchState = SearchState.initial().obs; @@ -110,7 +110,6 @@ class MailboxController extends BaseMailboxController { this._verifyNameInteractor, this._renameMailboxInteractor, this._moveMailboxInteractor, - this._uuid, treeBuilder, ) : super(treeBuilder); diff --git a/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart b/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart index c43993c9e..5da7ff871 100644 --- a/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart +++ b/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart @@ -21,7 +21,6 @@ import 'package:tmail_ui_user/features/composer/domain/state/save_email_as_draft import 'package:tmail_ui_user/features/composer/domain/state/send_email_state.dart'; import 'package:tmail_ui_user/features/composer/domain/state/update_email_drafts_state.dart'; import 'package:tmail_ui_user/features/composer/presentation/composer_bindings.dart'; -import 'package:tmail_ui_user/features/composer/presentation/composer_controller.dart'; import 'package:tmail_ui_user/features/composer/presentation/extensions/email_action_type_extension.dart'; import 'package:tmail_ui_user/features/email/domain/model/move_action.dart'; import 'package:tmail_ui_user/features/email/domain/model/move_to_mailbox_request.dart'; @@ -384,7 +383,7 @@ class MailboxDashBoardController extends ReloadableController { void closeComposerOverlay() { routerArguments = null; - Get.delete(); + ComposerBindings().dispose(); composerOverlayState.value = ComposerOverlayState.inActive; } diff --git a/lib/features/manage_account/presentation/profiles/identities/identities_bindings.dart b/lib/features/manage_account/presentation/profiles/identities/identities_bindings.dart index 2f14ebc87..9cdde5775 100644 --- a/lib/features/manage_account/presentation/profiles/identities/identities_bindings.dart +++ b/lib/features/manage_account/presentation/profiles/identities/identities_bindings.dart @@ -6,23 +6,15 @@ import 'package:tmail_ui_user/features/manage_account/domain/usecases/delete_ide import 'package:tmail_ui_user/features/manage_account/domain/usecases/edit_identity_interactor.dart'; import 'package:tmail_ui_user/features/manage_account/domain/usecases/get_all_identities_interactor.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/profiles/identities/identities_controller.dart'; -import 'package:uuid/uuid.dart'; class IdentitiesBindings extends BaseBindings { - @override - void dependencies() { - Get.lazyPut(() => const Uuid()); - super.dependencies(); - } - @override void bindingsController() { Get.lazyPut(() => IdentitiesController( Get.find(), Get.find(), Get.find(), - Get.find(), Get.find(), )); } diff --git a/lib/features/manage_account/presentation/profiles/identities/identities_controller.dart b/lib/features/manage_account/presentation/profiles/identities/identities_controller.dart index c5d232532..820b8bc4d 100644 --- a/lib/features/manage_account/presentation/profiles/identities/identities_controller.dart +++ b/lib/features/manage_account/presentation/profiles/identities/identities_controller.dart @@ -32,10 +32,10 @@ class IdentitiesController extends BaseController { final _appToast = Get.find(); final _imagePaths = Get.find(); final _responsiveUtils = Get.find(); + final _uuid = Get.find(); final GetAllIdentitiesInteractor _getAllIdentitiesInteractor; final CreateNewIdentityInteractor _createNewIdentityInteractor; - final Uuid _uuid; final DeleteIdentityInteractor _deleteIdentityInteractor; final EditIdentityInteractor _editIdentityInteractor; @@ -51,7 +51,6 @@ class IdentitiesController extends BaseController { this._getAllIdentitiesInteractor, this._deleteIdentityInteractor, this._createNewIdentityInteractor, - this._uuid, this._editIdentityInteractor, ); diff --git a/lib/l10n/intl_messages.arb b/lib/l10n/intl_messages.arb index e8c507f3e..ae42e8e5a 100644 --- a/lib/l10n/intl_messages.arb +++ b/lib/l10n/intl_messages.arb @@ -1,5 +1,5 @@ { - "@@last_modified": "2022-07-08T15:25:15.196374", + "@@last_modified": "2022-07-05T19:24:56.876056", "initializing_data": "Initializing data...", "@initializing_data": { "type": "text", @@ -1561,5 +1561,11 @@ "type": "text", "placeholders_order": [], "placeholders": {} + }, + "messageDialogSendEmailUploadingAttachment": "Your message could not be sent because it uploading attachment", + "@messageDialogSendEmailUploadingAttachment": { + "type": "text", + "placeholders_order": [], + "placeholders": {} } } \ No newline at end of file diff --git a/lib/main/bindings/core/core_bindings.dart b/lib/main/bindings/core/core_bindings.dart index 84f3d85ed..9262a9850 100644 --- a/lib/main/bindings/core/core_bindings.dart +++ b/lib/main/bindings/core/core_bindings.dart @@ -5,6 +5,7 @@ import 'package:get/get.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:tmail_ui_user/features/email/data/local/html_analyzer.dart'; import 'package:tmail_ui_user/main/utils/email_receive_manager.dart'; +import 'package:uuid/uuid.dart'; class CoreBindings extends Bindings { @@ -18,6 +19,7 @@ class CoreBindings extends Bindings { _bindingToast(); _bindingDeviceManager(); _bindingReceivingSharingStream(); + _bindingUtils(); } void _bindingAppImagePaths() { @@ -53,4 +55,8 @@ class CoreBindings extends Bindings { void _bindingReceivingSharingStream() { Get.put(EmailReceiveManager()); } + + void _bindingUtils() { + Get.put(const Uuid()); + } } \ No newline at end of file diff --git a/lib/main/bindings/network/network_bindings.dart b/lib/main/bindings/network/network_bindings.dart index 7f46048e2..23691195f 100644 --- a/lib/main/bindings/network/network_bindings.dart +++ b/lib/main/bindings/network/network_bindings.dart @@ -7,7 +7,6 @@ import 'package:flutter/foundation.dart'; import 'package:flutter_appauth/flutter_appauth.dart'; import 'package:get/get.dart'; import 'package:jmap_dart_client/http/http_client.dart' as JmapHttpClient; -import 'package:tmail_ui_user/features/composer/data/network/composer_api.dart'; import 'package:tmail_ui_user/features/email/data/network/email_api.dart'; import 'package:tmail_ui_user/features/login/data/local/account_cache_manager.dart'; import 'package:tmail_ui_user/features/login/data/local/token_oidc_cache_manager.dart'; @@ -77,7 +76,6 @@ class NetworkBindings extends Bindings { Get.put(EmailAPI( Get.find(), Get.find())); - Get.put(ComposerAPI(Get.find())); Get.put(ManageAccountAPI(Get.find())); } diff --git a/lib/main/localizations/app_localizations.dart b/lib/main/localizations/app_localizations.dart index 2bc87fa62..1cf90574e 100644 --- a/lib/main/localizations/app_localizations.dart +++ b/lib/main/localizations/app_localizations.dart @@ -1601,4 +1601,11 @@ class AppLocalizations { 'Russian', name: 'languageRussian'); } + + String get messageDialogSendEmailUploadingAttachment { + return Intl.message( + 'Your message could not be sent because it uploading attachment', + name: 'messageDialogSendEmailUploadingAttachment' + ); + } } \ No newline at end of file diff --git a/model/lib/extensions/session_extension.dart b/model/lib/extensions/session_extension.dart index 12be0acac..9fdbd3934 100644 --- a/model/lib/extensions/session_extension.dart +++ b/model/lib/extensions/session_extension.dart @@ -16,12 +16,13 @@ extension SessionExtension on Session { return downloadUrlDecode; } - Uri getUploadUrl(AccountId accountId) { + Uri getUploadUri(AccountId accountId) { final baseUrl = '${uploadUrl.origin}${uploadUrl.path}'; final uploadUriTemplate = UriTemplate('${Uri.decodeFull(baseUrl)}'); final uploadUri = uploadUriTemplate.expand({ 'accountId' : '${accountId.id.value}' }); + log('SessionExtension::getUploadUri(): uploadUri: $uploadUri'); return Uri.parse(uploadUri); } } \ No newline at end of file diff --git a/model/lib/upload/upload_response.dart b/model/lib/upload/upload_response.dart index d503ad699..b714bdd78 100644 --- a/model/lib/upload/upload_response.dart +++ b/model/lib/upload/upload_response.dart @@ -34,7 +34,7 @@ class UploadResponse with EquatableMixin { } extension UploadResponseExtension on UploadResponse { - Attachment toAttachmentFile(String nameFile, {MediaType? mediaType}) { - return Attachment(blobId: blobId, size: UnsignedInt(size), name: nameFile, type: mediaType ?? type); + Attachment toAttachment(String nameFile) { + return Attachment(blobId: blobId, size: UnsignedInt(size), name: nameFile, type: type); } } \ No newline at end of file diff --git a/pubspec.yaml b/pubspec.yaml index 55c04c28b..eb29d3f21 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -172,6 +172,8 @@ dependencies: # Isolate worker_manager: 4.4.0 + async: 2.8.2 + dev_dependencies: flutter_test: sdk: flutter