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 } 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 } 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" 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; publication: Publication; pub: Publication = new Publication(); 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; seletedContent: any[] = [] // 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 ) { this.publicationType = this.navParams.get('publicationType'); this.folderId = this.navParams.get('folderId'); this.publication = this.navParams.get('publication'); if (this.publication) { this.seletedContent = this.publication.Files; this.filecontent = true; } console.log('Edit', this.publication) this.publicationTitle = 'Nova Publicação'; this.intent = this.navParams.get('intent'); this.convertBlobToBase64Worker = new Worker(new URL('./convertBlobToBase64.worker.js', import.meta.url)); } ngOnInit() { this.reciveSharedContent(); this.setTitle(); Filesystem.mkdir({ path: IMAGE_DIR, directory: Directory.Data, recursive: true }); document.addEventListener("click", clickOutside, false); function clickOutside(e) { const inside = document.getElementById('container-multiselect').contains(e.target); this.photoOrVideo = false; console.log(this.photoOrVideo) } } // in use async takePicture() { const capturedImage = await Camera.getPhoto({ quality: 50, // allowEditing: true, resultType: CameraResultType.Base64, source: CameraSource.Camera }); console.log(capturedImage) this.capturedImage = 'data:image/jpeg;base64,' + capturedImage.base64String; this.capturedImageTitle = 'foto'; if (this.fileSizeToMB(capturedImage.base64String.length) <= 20) { const compressedImage = await this.compressImageBase64( this.capturedImage, 800, // maxWidth 800, // maxHeight 0.9 // quality ).then((picture) => { console.log('take picture', this.removeTextBeforeSlash(picture, ','),) this.filecontent = true; this.photoOrVideo = false; let fileObject = { FileBase64: this.removeTextBeforeSlash(picture, ','), FileExtension: capturedImage.format, OriginalFileName: 'image' } this.seletedContent.push(fileObject) }); } else { if (this.seletedContent.length === 0) this.filesSizeSum = 0 this.httpErrorHandle.validationMessagge('filessize'); } } 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(data) data.forEach(async element => { this.filesSizeSum = this.filesSizeSum + element.size if (this.fileSizeToMB(this.filesSizeSum) <= 20) { const savedFile = await Filesystem.copy({ from: element.fullPath, // directory prop removed, Capacitor parses filename for us to: "video.mp4", toDirectory: FilesystemDirectory.Data }); console.log(savedFile.uri) Filesystem.readFile({ path: savedFile.uri }) .then(async (content) => { this.filecontent = true; let fileObject = { FileBase64: 'data:video/mp4;base64,' + content.data, FileExtension: 'mp4', OriginalFileName: 'video' } this.seletedContent.push(fileObject) }) .catch((err) => console.error(err)); } else { if (this.seletedContent.length === 0) this.filesSizeSum = 0 this.httpErrorHandle.validationMessagge('filessize') } }); } catch (error) { console.log('record video error: ', error) } } async loadVideo() { const result = await FilePicker.pickMedia ({ multiple: true, }); console.log(result.files) result.files.forEach(element => { this.filesSizeSum = this.filesSizeSum + element.size if (this.fileSizeToMB(this.filesSizeSum) <= 20) { if (this.checkFileType.checkFileType(element.mimeType) == 'image' || this.checkFileType.checkFileType(element.mimeType) == 'video') { let resultUrl = decodeURIComponent(element.path); try { Filesystem.readFile({ path: resultUrl }) .then(async (content) => { console.log(result) console.log(content) this.filecontent = true; let fileObject; if(this.removeTextBeforeSlash(element.mimeType, '/') == "mp4") { fileObject = { FileBase64: 'data:video/mp4;base64,'+ content.data, FileExtension: this.removeTextBeforeSlash(element.mimeType, '/'), OriginalFileName: 'video' } } else { fileObject = { FileBase64: content.data, FileExtension: this.removeTextBeforeSlash(element.mimeType, '/'), OriginalFileName: 'image' } } this.seletedContent.push(fileObject) }) .catch((err) => console.error(err)); } catch (error) { console.log('upload video error: ', error) } } } else { if (this.seletedContent.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.pub.Title, [ Validators.required, // Validators.minLength(4) ]), capturedImage: new FormControl(this.capturedImage, [ ]), Message: new FormControl(this.pub.Message, [ Validators.required, Validators.maxLength(1000) ]) }) } async save() { this.injectValidation() this.runValidation() if (this.Form.invalid) return false if (this.publicationType == '3') { const loader = this.toastService.loading() // has file if (this.PublicationFolderService.PublicationHasImage(this.publication)) { this.publication = { DateIndex: this.publication.DateIndex, DocumentId: this.publication.DocumentId, ProcessId: this.publication.ProcessId, Title: this.pub.Title, Message: this.pub.Message, DatePublication: this.publication.DatePublication, OriginalFileName: this.publication.OriginalFileName, Files: this.seletedContent, } /* } else if (this.capturedVideo != '' && this.capturedImage == '') { this.publication = { DateIndex: this.publication.DateIndex, DocumentId: this.publication.DocumentId, ProcessId: this.publication.ProcessId, Title: this.pub.Title, Message: this.pub.Message, DatePublication: this.publication.DatePublication, OriginalFileName: this.publication.OriginalFileName || 'video', Files: this.seletedContent, FileExtension: 'mp4', } } */ // no names } else if (!this.PublicationFolderService.PublicationHasImage(this.publication)) { this.publication = { DateIndex: this.publication.DateIndex, DocumentId: this.publication.DocumentId, ProcessId: this.publication.ProcessId, Title: this.pub.Title, Message: this.pub.Message, DatePublication: this.publication.DatePublication, OriginalFileName: this.publication.OriginalFileName, Files: this.seletedContent, } } /* else { this.publication = { DateIndex: this.publication.DateIndex, DocumentId: this.publication.DocumentId, ProcessId: this.publication.ProcessId, Title: this.pub.Title, Message: this.pub.Message, DatePublication: this.publication.DatePublication, OriginalFileName: this.publication.OriginalFileName, FileBase64: this.publication.FileBase64, FileExtension: this.publication.FileExtension || 'jpeg', } } */ try { const response = await this.publications.UpdatePublication(this.publication.ProcessId, this.publication).toPromise() this.httpErrorHandle.httpsSucessMessagge('Editar publicação') console.log({ response }) this.close(); } catch (error) { if (error.status == 404) { this.PublicationFolderService.deletePost(this.publication.ProcessId, this.publication.DocumentId) this.close(); } this.httpErrorHandle.httpStatusHandle(error) } finally { loader.remove() } } else { const date = formatDate(new Date(), 'yyyy-MM-dd HH:mm:ss') /* this.seletedContent = this.seletedContent.map((e) => { if(e.FileExtension == "mp4") { return { FileBase64: e.FileBase64, FileExtension: 'data:video/mp4;base64,'+e.FileExtension, OriginalFileName: "video", } } return e }) */ /* if (this.capturedImage != '') { */ this.publication = { DateIndex: date, DocumentId: null, ProcessId: this.folderId, Title: this.pub.Title, Message: this.pub.Message, DatePublication: date, OriginalFileName: this.capturedImageTitle || 'foto', Files: this.seletedContent, /* FileExtension: 'jpeg', */ } /* } else if (this.capturedVideo != '') { this.publication = { DateIndex: date, DocumentId: null, ProcessId: this.folderId, Title: this.pub.Title, Message: this.pub.Message, DatePublication: date, OriginalFileName: this.capturedImageTitle || 'video', Files: this.seletedContent, FileExtension: 'mp4', } } */ const loader = this.toastService.loading() try { await this.publications.CreatePublication(this.folderId, this.publication).toPromise(); this.close(); this.httpErrorHandle.httpsSucessMessagge('Criar publicação') window["sharedContent"] = null; window["endSharedContent"] = null; this.close(); } catch (error) { this.httpErrorHandle.httpStatusHandle(error) } finally { loader.remove() } } this.PublicationFolderService.getPublicationsIds(this.folderId) } close() { this.modalController.dismiss(this.publication).then(() => { this.showLoader = true; }); } clear() { this.capturedImageTitle = null; this.seletedContent = []; } 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'; this.pub = this.navParams.get('publication'); } } 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.seletedContent = [] } 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); Filesystem.readFile({ path: resultUrl }).then(async (content) => { console.log('shared base', content.data) let fileObject = { FileBase64: this.removeTextBeforeSlash(content.data, ','), FileExtension: FileExtension, OriginalFileName: 'shared', } this.seletedContent.push(fileObject) }) } else { this.httpErrorHandle.validationMessagge('filetype'); } }); } } fileSizeToMB(sizeInBytes) { var sizeInMB = (sizeInBytes / (1024 * 1024)).toFixed(2); console.log(sizeInMB + 'MB'); return parseInt(sizeInMB) } deleteFromSeletedContent(index) { this.seletedContent.splice(index, 1) } }