import { Component, OnInit } from '@angular/core'; import { ModalController, NavParams, Platform, LoadingController } from '@ionic/angular'; /* import {Plugins, CameraResultType, CameraSource} from '@capacitor/core'; */ import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser'; import { PublicationsService } from 'src/app/services/publications.service'; import { Publication } from 'src/app/models/publication'; import { Image } from 'src/app/models/image'; import { PhotoService } from 'src/app/services/photo.service'; //Capacitor import { ToastService } from 'src/app/services/toast.service'; import { FormControl, FormGroup, Validators } from '@angular/forms'; import { ThemePalette } from '@angular/material/core'; import { formatDate } from 'src/plugin/momentG.js' import { ThemeService } from 'src/app/services/theme.service'; import { Camera, CameraResultType, CameraSource, Photo } from '@capacitor/camera'; import { Filesystem, Directory, Encoding, FilesystemDirectory, FilesystemEncoding } from '@capacitor/filesystem'; import { NgxImageCompressService } from "ngx-image-compress"; import { HttpErrorHandle } from 'src/app/services/http-error-handle.service'; import { PublicationFolderService } from 'src/app/store/publication-folder.service'; import { RouteService } from 'src/app/services/route.service'; import { FileService } from 'src/app/services/functions/file.service'; import { readAndCompressImage } from 'browser-image-resizer'; import { FilePicker } from '@capawesome/capacitor-file-picker'; import { CapacitorVideoPlayer } from 'capacitor-video-player'; import { CaptureError, CaptureImageOptions, MediaCapture, MediaFile } from '@awesome-cordova-plugins/media-capture/ngx'; import { Capacitor } from '@capacitor/core'; import { File as IonicFile } from '@ionic-native/file/ngx'; import { Media } from '@ionic-native/media/ngx'; import { checkFileTypeService } from 'src/app/services/checkFileType.service'; import { FileValidatorService } from "src/app/services/file/file-validator.service" import { App } from '@capacitor/app'; import { NavigationExtras, Router } from '@angular/router'; import { VideoconvertService } from 'src/app/services/videoconvert.service' import { PublicationAttachmentEntity } from 'src/app/shared/publication/upload/upload-streaming.service'; import { PublicationFromMvService } from "src/app/shared/publication/upload/publication-from-mv.service" import { File } from '../../../models/chatMethod'; import { CropImagePage } from 'src/app/modals/crop-image/crop-image.page'; const config = { quality: 0.5, maxWidth: 800, maxHeight: 600, debug: true }; const IMAGE_DIR = 'stored-images'; /* const { VideoRecorder } = Plugin; */ interface LocalFile { name: string; path: string; data: string; } /* const config_video: VideoRecorderPreviewFrame = { id: 'video-record', stackPosition: 'front', // 'front' overlays your app', 'back' places behind your app. width: 'fill', height: 'fill', x: 0, y: 0, borderRadius: 0 }; */ @Component({ selector: 'app-new-publication', templateUrl: './new-publication.page.html', styleUrls: ['./new-publication.page.scss'], }) export class NewPublicationPage implements OnInit { images: LocalFile[] = []; // date picker public date: any; public disabled = false; public showSpinners = true; public showSeconds = false; public touchUi = false; public enableMeridian = false; public minDate = new Date().toISOString().slice(0, 10) public endMinDate = new Date(new Date().getTime() + 15 * 60000); public stepHour = 1; public stepMinute = 15; public stepSecond = 5; public color: ThemePalette = 'primary'; Form: FormGroup; validateFrom = false showLoader: boolean; folderId: string; image: Image = new Image(); publicationType: string; publicationTitle: string; imgUrl: any; Defaultimage: any = ''; photo: SafeResourceUrl; guestPicture: any; capturedImage: any = ''; capturedVideo: any = ''; capturedImageTitle: any; public photos: any[] = []; pictureExiste = false imgResultBeforeCompress: string; imgResultAfterCompress: string; convertBlobToBase64Worker; intent: any; video: any; photoOrVideo: boolean = false; fileType = ""; filecontent: boolean; // Set a limit for the number of images to display displayLimit = 4; filesSizeSum = 0; constructor( private modalController: ModalController, public photoService: PhotoService, private navParams: NavParams, private publications: PublicationsService, private toastService: ToastService, public ThemeService: ThemeService, private platform: Platform, private loadingCtrl: LoadingController, public imageCompress: NgxImageCompressService, private httpErrorHandle: HttpErrorHandle, public PublicationFolderService: PublicationFolderService, private RouteService: RouteService, public FileService: FileService, private mediaCapture: MediaCapture, public checkFileType: checkFileTypeService, private FileValidatorService: FileValidatorService, private router: Router, private videoconvertService: VideoconvertService, public PublicationFromMvService: PublicationFromMvService, ) { this.publicationType = this.navParams.get('publicationType'); this.folderId = this.navParams.get('folderId'); const publication = this.navParams.get('publication'); if (publication && typeof publication?.Files == 'object') { this.filecontent = true; const newFiles: PublicationAttachmentEntity[] = publication.Files.map(e => { return new PublicationAttachmentEntity( { base64: e.FileBase64, extension: e.FileExtension, OriginalFileName: e.OriginalFileName, FileType: this.checkFileType.checkFileType(e.FileExtension) as any } ) }) for (const files of newFiles) { this.PublicationFromMvService.form.Files.push(files) } } this.publicationTitle = 'Nova Publicação'; this.intent = this.navParams.get('intent'); this.convertBlobToBase64Worker = new Worker(new URL('./convertBlobToBase64.worker.js', import.meta.url)); this.PublicationFromMvService.clear() } ngOnInit() { this.reciveSharedContent(); this.setTitle(); Filesystem.mkdir({ path: IMAGE_DIR, directory: Directory.Data, recursive: true }); /* try { document.addEventListener("click", clickOutside, false); function clickOutside(e) { const inside = document.getElementById('container-multiselect').contains(e.target); this.photoOrVideo = false; console.log(this.photoOrVideo) } } catch (error) { console.log('click butto', error) } */ } // in use async takePicture() { const capturedImage = await Camera.getPhoto({ quality: 50, // allowEditing: true, resultType: CameraResultType.Base64, source: CameraSource.Camera }); this.capturedImage = 'data:image/jpeg;base64,' + capturedImage.base64String; this.capturedImageTitle = 'foto'; this.showCroppModal(); } async laodPicture() { const capturedImage = await Camera.getPhoto({ quality: 90, resultType: CameraResultType.Base64, source: CameraSource.Photos }); this.capturedImage = 'data:image/jpeg;base64,' + capturedImage.base64String; this.capturedImageTitle = 'foto'; const compressedImage = await this.compressImageBase64( this.capturedImage, 800, // maxWidth 800, // maxHeight 0.9 // quality ).then((picture) => { console.log('Selected: ', picture) this.capturedImage = picture }); } async startVideoRecording() { try { let options: CaptureImageOptions = { limit: 1 } const data: any = await this.mediaCapture.captureVideo(options) this.video = data[0]; console.log('video record', data) data.forEach(async element => { this.filesSizeSum = this.filesSizeSum + element.size // element.size try { if (this.platform.is('ios')) { this.recordevideoIos(element.fullPath, element) } else { this.recordVideoAndroid(element.fullPath, element) } } catch (e) { console.error('Unable to write file', e); } }); } catch (error) { console.log('record video error: ', error) } } async loadVideo() { const result = await FilePicker.pickMedia({ multiple: true, }); console.log(result.files) result.files.forEach(async element => { this.filesSizeSum = this.filesSizeSum + element.size if (this.fileSizeToMB(this.filesSizeSum) <= 20) { console.log('pass size verificartion') if (this.checkFileType.checkFileType(element.mimeType) == 'video' && this.platform.is('ios')) { let resultUrl = decodeURIComponent(element.path); console.log('pass type verification ', resultUrl) try { this.recordevideoIos(resultUrl, element) } catch (error) { console.log('upload video error: ', error) } } else if (this.checkFileType.checkFileType(element.mimeType) == 'image' || this.checkFileType.checkFileType(element.mimeType) == 'video') { let resultUrl = decodeURIComponent(element.path); console.log('pass type verification ', resultUrl) try { this.loadVideoAndroid(resultUrl, element) } catch (error) { console.log('upload video error: ', error) } } } else { if (this.PublicationFromMvService.form.Files.length === 0) this.filesSizeSum = 0 this.httpErrorHandle.validationMessagge('filessize') } }); }; chossePhotoOrVideo() { this.photoOrVideo = !this.photoOrVideo } imageSize(image) { var canvas = document.createElement('canvas'); var ctx = canvas.getContext('2d'); canvas.width = 100 canvas.height = 34 ctx.drawImage(image, 0, 0); document.body.appendChild(canvas); } convertBlobToBase64 = (blob: Blob) => new Promise((resolve, reject) => { const reader = new FileReader; reader.onerror = reject; reader.onload = () => { resolve(reader.result); }; reader.readAsDataURL(blob); }).catch((error) => { console.error(error); }); /* // in use async laodPicture() { const capturedImage = await Camera.getPhoto({ quality: 90, // allowEditing: true, resultType: CameraResultType.Uri, source: CameraSource.Photos }); const response = await fetch(capturedImage.webPath!); const blob = await response.blob(); this.convertBlobToBase64Worker.postMessage(blob); this.convertBlobToBase64Worker.onmessage = async (oEvent)=> { this.capturedImage = oEvent.data this.capturedImageTitle = 'foto' } } */ runValidation() { this.validateFrom = true } injectValidation() { this.Form = new FormGroup({ Subject: new FormControl(this.PublicationFromMvService.form.Title, [ Validators.required, // Validators.minLength(4) ]), capturedImage: new FormControl(this.capturedImage, [ ]), Message: new FormControl(this.PublicationFromMvService.form.Message, [ Validators.required, Validators.maxLength(1000) ]) }) } async save() { this.injectValidation() this.runValidation() if (this.Form.invalid) return false if (this.PublicationFromMvService.form.Files.length != 0) { if (!window["sharedContent"]) { this.close(); } else { alert('dont close') } this.PublicationFromMvService.publicationType = this.publicationType as any this.PublicationFromMvService.setFolderId(this.folderId) await this.PublicationFromMvService.save() } else { this.httpErrorHandle.validationMessagge("noFileSelected") } } ngOnDestroy() { // if(!this.PublicationFromMvService.form.send) { // this.PublicationFromMvService.cancel() // } } close() { alert('close'); this.modalController.dismiss(this.PublicationFromMvService.form).then(() => { this.showLoader = true; }); } clear() { this.capturedImageTitle = null; this.PublicationFromMvService.form.Files = []; } setTitle() { if (this.publicationType == '1') { this.publicationTitle = 'Nova Publicação Rápida'; } else if (this.publicationType == '2') { this.publicationTitle = 'Nova Publicação'; } else if (this.publicationType == '3') { this.publicationTitle = 'Editar Publicação'; } } compressFile() { //this.imgResultBeforeCompress = image;s this.imageCompress.getOrientation(this.capturedImage).then((orientation) => { this.imageCompress.compressFile(this.capturedImage, orientation, 90, 90).then( result => { this.capturedImage = result; } ); }); } deletePublicationImage() { this.PublicationFromMvService.form.Files = [] } async compressImageBase64(base64String: string, maxWidth: number, maxHeight: number, quality: number): Promise { return new Promise((resolve, reject) => { const image = new (window as any).Image(); image.src = base64String; image.onload = async () => { const canvas = document.createElement('canvas'); let newWidth = image.width; let newHeight = image.height; if (newWidth > maxWidth) { newHeight *= maxWidth / newWidth; newWidth = maxWidth; } if (newHeight > maxHeight) { newWidth *= maxHeight / newHeight; newHeight = maxHeight; } canvas.width = newWidth; canvas.height = newHeight; const context = canvas.getContext('2d'); context?.drawImage(image, 0, 0, newWidth, newHeight); const compressedBase64 = canvas.toDataURL('image/jpeg', quality); resolve(compressedBase64); }; image.onerror = (error) => { reject(error); }; }); } _getBase64(file) { return new Promise((resolve, reject) => { var reader = new FileReader(); reader.readAsDataURL(file); reader.onload = function () { resolve(reader.result) }; reader.onerror = function (error) { console.log('Error: ', error); }; }) } async copyVideoToDataDirectory(videoFile: any): Promise { try { const { uri } = videoFile; const fileName = uri.substring(uri.lastIndexOf('/') + 1); const targetPath = Directory.Data + fileName; // Set your target directory path await Filesystem.copy({ from: uri, to: targetPath, }); return targetPath; } catch (error) { console.error(error); return null; } } async convertVideoToBase64(videoPath: string): Promise { try { const file = await Filesystem.readFile({ path: videoPath, directory: FilesystemDirectory.Data }); if (file.data) { return 'data:video/mp4;base64,' + file.data; } else { throw new Error('Failed to read the video file.'); } } catch (error) { console.error(error); return null; } } async copyAndReadFile(filePath: string): Promise { try { // Copy the file to the app's data directory const copyResult = await Filesystem.copy({ from: filePath, to: '20231110_125118.mp4', // or any desired name directory: Directory.Data, }); const copiedFilePath = copyResult.uri; // Use 'uri' instead of 'to' // Read the copied file as base64 const readResult = await Filesystem.readFile({ path: copiedFilePath, directory: Directory.Data, encoding: Encoding.UTF8, }); const base64Data = readResult.data; console.log('Base64 data:', base64Data); return base64Data; } catch (error) { console.error('Error copying/reading file:', error); throw error; } } removeTextBeforeSlash(inputString, controlString) { if (inputString.includes(controlString)) { const parts = inputString.split(controlString); return parts.length > 1 ? parts[1] : inputString; } else { return inputString; } } reciveSharedContent() { if (this.intent) { this.filecontent = true console.log(this.intent) let filesArray = []; let fistFile = { title: this.intent.title, type: this.intent.type, url: this.intent.url } if (this.intent?.additionalItems) { filesArray = this.intent?.additionalItems; } filesArray.push(fistFile) filesArray.forEach(element => { let FileExtension = this.removeTextBeforeSlash(element.title, '.') if (this.checkFileType.checkFileType(FileExtension) == 'image' || this.checkFileType.checkFileType(FileExtension) == 'video') { let resultUrl = decodeURIComponent(element.url); if (this.platform.is('ios')) { const stringGerada = this.gerarStringAleatoria(); console.log(stringGerada); this.shareContentIso(resultUrl, FileExtension, stringGerada) } else { this.shareContentAndroid(resultUrl, FileExtension) } /* Filesystem.readFile({ path: resultUrl }).then(async (content) => { let fileObject; try { if (this.checkFileType.checkFileType(FileExtension) == 'image') { fileObject = { FileBase64: this.removeTextBeforeSlash(content.data, ','), FileExtension: FileExtension, OriginalFileName: 'shared', } } else if (this.checkFileType.checkFileType(FileExtension) == 'video') { fileObject = { FileBase64: 'data:video/mp4;base64,' + this.removeTextBeforeSlash(content.data, ','), FileExtension: FileExtension, OriginalFileName: 'shared', } } console.log('shared base', content.data) this.seletedContent.push(fileObject) } catch (error) { console.log('error shared filesystem', error) } }) */ } else { this.httpErrorHandle.validationMessagge('filetype'); } }); } } fileSizeToMB(sizeInBytes) { var sizeInMB = (sizeInBytes / (1024 * 1024)).toFixed(2); console.log(sizeInMB + 'MB'); return parseInt(sizeInMB) } deleteFromSeletedContent(index) { this.PublicationFromMvService.form.Files.splice(index, 1) } async recordevideoIos(fullPath, element) { try { const directory = await Filesystem.getUri({ directory: Directory.Cache, path: '', }); const stringGerada = this.gerarStringAleatoria(); this.videoconvertService.convertVideo(fullPath, directory.uri, stringGerada, 'mp4').then(async () => { await Filesystem.readFile({ path: `${directory.uri}${stringGerada}.mp4` }) .then(async (content) => { this.filecontent = true; const file = new File([element.blob], element.name); const newAttachment = new PublicationAttachmentEntity( { base64: 'data:video/mp4;base64,' + content.data, extension: 'mp4', blobFile: file, FileType: this.checkFileType.checkFileType('mp4') as any, OriginalFileName: 'load video' } ) this.PublicationFromMvService.form.Files.push(newAttachment) const deleteSecretFile = async () => { await Filesystem.deleteFile({ path: `${stringGerada}.mp4`, directory: Directory.Cache, }); }; await deleteSecretFile().then((value) => { console.log('delete file', value) }) }) .catch((erro) => console.error('read converted video erro ', erro)); }); } catch (error) { console.log('record video ios erro, ', error) } } async recordVideoAndroid(fullPath, element) { try { const savedFile = await Filesystem.copy({ from: fullPath, to: "video.mp4", toDirectory: FilesystemDirectory.Data }); console.log(savedFile.uri) Filesystem.readFile({ path: savedFile.uri }) .then(async (content) => { this.filecontent = true; const file = new File([element.blob], element.name); window['a'] = element const newAttachment = new PublicationAttachmentEntity( { base64: 'data:video/mp4;base64,' + content.data, extension: 'mp4', blobFile: file, FileType: this.checkFileType.checkFileType('mp4') as any, OriginalFileName: 'load video' } ) this.PublicationFromMvService.form.Files.push(newAttachment) }) .catch((error) => console.error('reade converted video erro ', error)); } catch (error) { console.log('record video android erro ', error) } } loadVideoIso() { } loadVideoAndroid(resultUrl, element) { Filesystem.readFile({ path: resultUrl }) .then(async (content) => { this.filecontent = true; if (this.removeTextBeforeSlash(element.mimeType, '/') == "mp4") { const newAttachment = new PublicationAttachmentEntity( { base64: content.data, extension: this.removeTextBeforeSlash(element.mimeType, '/'), FileType: this.checkFileType.checkFileType(this.removeTextBeforeSlash(element.mimeType, '/')) as any, OriginalFileName: 'load video' } ) newAttachment.needUpload() this.PublicationFromMvService.form.Files.push(newAttachment) } else { this.capturedImage = 'data:image/jpeg;base64,' + content.data; this.showCroppModal() /* const newAttachment = new PublicationAttachmentEntity( { base64: 'data:image/jpeg;base64,' + content.data, extension: this.removeTextBeforeSlash(element.mimeType, '/'), FileType: this.checkFileType.checkFileType(this.removeTextBeforeSlash(element.mimeType, '/')) as any, OriginalFileName: 'image' } ) this.PublicationFromMvService.form.Files.push(newAttachment) */ } }) .catch((err) => console.error(err)); } gerarStringAleatoria() { const caracteres = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; let stringAleatoria = ''; for (let i = 0; i < 4; i++) { const indiceAleatorio = Math.floor(Math.random() * caracteres.length); stringAleatoria += caracteres.charAt(indiceAleatorio); } return stringAleatoria; } async shareContentIso(fullPath, FileExtension, filename) { console.log({fullPath, FileExtension, filename}) try { if (this.checkFileType.checkFileType(FileExtension) == 'image') { Filesystem.readFile({ path: fullPath }).then(async (content) => { try { console.log('shared base', content.data) this.capturedImage = 'data:image/jpeg;base64,' + this.removeTextBeforeSlash(content.data, ','); this.showCroppModal() } catch (error) { console.log('error shared filesystem', error) } }) } else if (this.checkFileType.checkFileType(FileExtension) == 'video') { const directory = await Filesystem.getUri({ directory: Directory.Cache, path: '', }); this.videoconvertService.convertVideo(fullPath, directory.uri, filename, 'mp4').then(async () => { await Filesystem.readFile({ path: `${directory.uri}${filename}.mp4` }) .then(async (content) => { console.log(content.data) this.filecontent = true; /* fileObject = { FileBase64: this.removeTextBeforeSlash(content.data, ','), FileExtension: 'mp4', OriginalFileName: 'shared', } */ const newAttachment = new PublicationAttachmentEntity( { base64: content.data, extension: 'mp4', FileType: this.checkFileType.checkFileType('mp4') as any, OriginalFileName: 'shared' } ) newAttachment.needUpload() this.PublicationFromMvService.form.Files.push(newAttachment) const deleteSecretFile = async () => { await Filesystem.deleteFile({ path: `${filename}.mp4`, directory: Directory.Cache, }); }; deleteSecretFile().then((value) => { console.log('delete file', value) }) .catch((erro) => console.error('read converted video erro ', erro)); }); }); } } catch (error) { console.log('record video ios erro, ', error) } } shareContentAndroid(resultUrl, FileExtension) { console.log({resultUrl, FileExtension}) Filesystem.readFile({ path: resultUrl }).then(async (content) => { try { if (this.checkFileType.checkFileType(FileExtension) == 'image') { this.capturedImage = 'data:image/jpeg;base64,' + this.removeTextBeforeSlash(content.data, ','); this.showCroppModal() } else if (this.checkFileType.checkFileType(FileExtension) == 'video') { let newAttachment = new PublicationAttachmentEntity( { base64: content.data, extension: 'mp4', FileType: this.checkFileType.checkFileType('mp4') as any, OriginalFileName: 'shared' } ) newAttachment.needUpload() this.PublicationFromMvService.form.Files.push(newAttachment) } console.log('shared base', content.data) } catch (error) { console.log('error shared filesystem', error) } }) } async showCroppModal() { const modal = await this.modalController.create({ component: CropImagePage, componentProps: { base64ToCroppe: this.capturedImage }, cssClass: 'modal modal-desktop' }); modal.onDidDismiss().then((res) => { if (res) { this.capturedImage = res.data this.filecontent = true; this.photoOrVideo = false; const newAttachment = new PublicationAttachmentEntity( { base64: res.data.base64ToCroppe, extension: 'jpeg', OriginalFileName: "image", FileType: 'image' } ) this.PublicationFromMvService.form.Files.push(newAttachment) } }, (error) => { console.log(error) }); await modal.present(); } }