import { Injectable } from '@angular/core'; import { HttpErrorHandle } from 'src/app/services/http-error-handle.service'; import { PublicationsService } from 'src/app/services/publications.service'; import { ToastService } from 'src/app/services/toast.service'; import { PublicationFolderService } from 'src/app/store/publication-folder.service'; import { Chunks, ChunksBase64, IOUploadError, PublicationAttachmentEntity, PublicationFormModel, UploadFileUseCase } from './upload-streaming.service'; import { ObjectMergeNotification } from 'src/app/services/socket-connection-mcr.service'; import { v4 as uuidv4 } from 'uuid' import { Result } from 'neverthrow'; import { IPublicationFormModelEntity } from '../new-publication/interface/interface'; import { CMAPIService } from "src/app/shared/repository/CMAPI/cmapi.service" import { App } from '@capacitor/app'; import { ModalController, NavParams, Platform, LoadingController } from '@ionic/angular'; import { Router } from '@angular/router'; enum ActionType { newRapid = "1", new = "2", edit = "3" } @Injectable({ providedIn: 'any' }) export class PublicationFromMvService { id: string = uuidv4() private UploadFileUseCase = new UploadFileUseCase() form = new PublicationFormModel() ObjectMergeNotification = new ObjectMergeNotification() totalPercentage = 0 publicationType: ActionType folderId: string constructor( private publications: PublicationsService, private toastService: ToastService, private httpErroHandle: HttpErrorHandle, public PublicationFolderService: PublicationFolderService, private CMAPIService: CMAPIService, public publicationFolderService: PublicationFolderService, private platform: Platform, private modalController: ModalController, private router: Router, ) {} clear() { this.id = uuidv4() this.UploadFileUseCase = new UploadFileUseCase() this.form = new PublicationFormModel() this.ObjectMergeNotification = new ObjectMergeNotification() this.totalPercentage = 0 this.ObjectMergeNotification.connect(); window['upload-header-set-add'](this.id, this.totalPercentage, this.save) } cancel() { window['upload-header-set-remove'](this.id) } setFolderId(folderId) { this.folderId = folderId } save = async() => { const needChunk = this.needToUploadChunk() if (this.publicationType == ActionType.edit) { if (this.form.Files.length >= 1) { // const loader = this.toastService.loading() this.form.send = true const upload = await this.uploadVideosFiles() console.log('release chunks') const needChunk = this.needToUploadChunk() if(needChunk.length == 0 ) { window['upload-header-set-percentage'](this.id, 50) } else { window['upload-header-set-percentage'](this.id, 100) } if(upload) { this.form.Files = this.form.Files.map((e:PublicationAttachmentEntity) => { if(e.FileType == 'video' && e.toUpload) { e.OriginalFileName = e?.chucksManager?.path?.replace(".mp4", "") || e.OriginalFileName e.FileExtension = e.FileExtension || "mp4" } return e }) } const publication: any = Object.assign({}, this.form) publication.Files = publication.Files.map( (e:PublicationAttachmentEntity) => ({ FileBase64: e.url, FileExtension: e.FileExtension, OriginalFileName: e.OriginalFileName || 'foto' })) publication.ProcessId = this.folderId if(this.form.cancel) { window['upload-header-set-remove'](this.id); return false } try { const response = await this.publications.UpdatePublication(publication.ProcessId, publication).toPromise() if (this.form.cancel == false) { this.httpErroHandle.httpsSucessMessagge('Editar publicação') } this.publicationFolderService.getPublicationsIds(this.folderId) window['upload-header-set-remove'](this.id); // this.goBack(); } catch (error) { this.httpErroHandle.httpStatusHandle(error) if (error.status == 404) { this.PublicationFolderService.deletePost(this.form.ProcessId, this.form.DocumentId) } else { window['upload-header-set-retry'](this.id) } } finally { // loader.remove() } } else { this.toastService._badRequest("É necessário adicionar uma imagem ou vídeo") } } else { let time = new Date() if (this.form.Files.length >= 1) { // const loader = this.toastService.loading() this.form.send = true const upload = await this.uploadVideosFiles() const needChunk = this.needToUploadChunk() if(needChunk.length ==0 ) { window['upload-header-set-percentage'](this.id, 50) } else { window['upload-header-set-percentage'](this.id, 100) } console.log('release chunk') if(upload) { this.form.Files = this.form.Files.map((e:PublicationAttachmentEntity) => { console.log({e}) if(e.FileType == 'video' && e.toUpload) { e.OriginalFileName = e?.chucksManager?.path?.replace(".mp4", "") || e.OriginalFileName e.FileExtension = e.FileExtension || "mp4" e.Base64 = '' } if(e.FileType == 'video' && !e.toUpload) { e.Base64 = e.url } return e }) } else { window['upload-header-set-retry'](this.id) this.toastService._badRequest("ocorreu um erro ao enviar o ficheiro") return true // loader.remove() } const publication: any = Object.assign({}, this.form) publication.Files = publication.Files.map( (e:PublicationAttachmentEntity) => ({ FileBase64: e.Base64, FileExtension: e.FileExtension, OriginalFileName: e.OriginalFileName || 'foto' })) publication.DocumentId = null; publication.ProcessId = this.folderId if(this.form.cancel == true) { window['upload-header-set-remove'](this.id); return false } try { await this.publications.CreatePublication(publication.ProcessId, publication).toPromise() if (this.publicationType == '1') { this.httpErroHandle.httpsSucessMessagge('Criar publicação') } else if (this.publicationType == '2') { this.httpErroHandle.httpsSucessMessagge('Criar publicação') } // this.goBackToViewPublications.emit(); window['upload-header-set-remove'](this.id); this.doneUpload() this.publicationFolderService.getPublicationsIds(this.folderId) } catch (error) { window['upload-header-set-retry'](this.id) this.httpErroHandle.httpStatusHandle(error) } finally { // loader.remove() } } else { this.toastService._badRequest("É necessário adicionar uma imagem ou vídeo") } } // this.PublicationHolderService.setPublication(this.publicationFormMV) this.ObjectMergeNotification.close() } doneUpload() { if (window["sharedContent"]) { if (this.platform.is('android')) { window["sharedContent"] = null; } else { window["sharedContent"] = null; } } } needToUploadChunk() { return this.form.Files.filter( e => e.FileType == "video" && e.toUpload) } setDataToFrom(data: IPublicationFormModelEntity) { this.form.setData(data) } private getVideoFiles() { return this.form.Files.filter( x => x.FileType == 'video') } async commit(PublicationAttachmentEntity: PublicationAttachmentEntity) { PublicationAttachmentEntity.chucksManager.doneChunkUpload() const mergeRequest = await this.ObjectMergeNotification.socket.commit(PublicationAttachmentEntity.chucksManager.path) if(mergeRequest.isOk()) { console.log("commit") PublicationAttachmentEntity.chucksManager.contentSetReady() return true } else { console.log('no commit') return false } } private upload(PublicationAttachmentEntity: PublicationAttachmentEntity) { return new Promise(async (resolve, reject)=> { if(!PublicationAttachmentEntity.hasChunkManger) { if(PublicationAttachmentEntity.hasBlob) { const fileBlob = PublicationAttachmentEntity.blobFile; const fileChunks = new Chunks({chunkSize: 50 }) fileChunks.setFile(fileBlob) PublicationAttachmentEntity.setChunkManger(fileChunks) } else { const Base64 = PublicationAttachmentEntity.Base64; const fileChunks = new ChunksBase64({chunkSize: 1000 }) fileChunks.setFile(Base64) PublicationAttachmentEntity.setChunkManger(fileChunks) } PublicationAttachmentEntity.chucksManager.updateTotalPercentageTrigger = () => { this.uploadPercentage() } } let attemp = 0; let result: Result if( PublicationAttachmentEntity.chucksManager.isUploading == false && PublicationAttachmentEntity.chucksManager.doneUpload == false) { do { attemp++ PublicationAttachmentEntity.chucksManager.clearManualRetry() PublicationAttachmentEntity.chucksManager.setUploading() result = await this.UploadFileUseCase.execute(PublicationAttachmentEntity) PublicationAttachmentEntity.chucksManager.clearUploading() } while (attemp<3 && result.isErr() && result.error == 'slow') if(result.isErr()) { PublicationAttachmentEntity.chucksManager.setManualRetry() resolve(false) } else { return await resolve(this.commit(PublicationAttachmentEntity)) } } else if ( PublicationAttachmentEntity.chucksManager.contentReady == false) { console.log("try to send again") return await resolve(this.commit(PublicationAttachmentEntity)) } else { console.log('already uploading') resolve(true) } }) } uploadVideosFiles(): Promise { return new Promise((resolve, reject) => { // this.ObjectMergeNotification.socket.registerWhenConnected(() => { const videosFiles = this.getVideoFiles() window['upload-header-set-percentage'](this.id, 1) window['upload-header-remove-retry'](this.id); const videosFilesToUploads = videosFiles.filter( e => e.FileType == "video" && e.toUpload) const Promises: Promise[] = [] for(const file of videosFilesToUploads) { const promise = this.upload(file) Promises.push(promise) } console.log('Promises', Promises) // Use Promise.all to wait for all promises to resolve Promise.all(Promises) .then((results) => { // Check if every promise resolved successfully const allPromisesResolvedSuccessfully = results.every((result) => result == true); if (allPromisesResolvedSuccessfully) { console.log('All promises resolved successfully.'); resolve(true) } else { window['upload-header-set-retry'](this.id); resolve(false) console.log('Some promises failed to resolve successfully.'); } }) .catch((error) => { resolve(false) console.error('An error occurred while resolving promises:', error); }); //}) }) } uploadPercentage() { const videosFiles = this.getVideoFiles() const percentageArray = videosFiles.map((e) => e.chucksManager.calculatePercentage()) // Check if the array is not empty if (percentageArray.length === 0) { window['upload-header-set-percentage'](this.id, this.totalPercentage) return 0; } else { console.log("===============!!==========================================") let sum = percentageArray.reduce((acc, percentage) => acc + percentage, 0); // Calculate the average percentage let averagePercentage = sum / percentageArray.length; this.totalPercentage = averagePercentage window['upload-header-set-percentage'](this.id, this.totalPercentage) return averagePercentage; } } }