import { AfterViewChecked, AfterViewInit, Component, ElementRef, ChangeDetectorRef, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, SimpleChanges, ViewChild } from '@angular/core'; import { AnimationController, GestureController, IonSlides, ModalController, PopoverController } from '@ionic/angular'; import { AlertService } from 'src/app/services/alert.service'; import { AuthService } from 'src/app/services/auth.service'; import { ChatService } from 'src/app/services/chat.service'; import { ToastService } from 'src/app/services/toast.service'; import { ChatOptionsPopoverPage } from 'src/app/shared/popover/chat-options-popover/chat-options-popover.page'; import { MessagesOptionsPage } from 'src/app/shared/popover/messages-options/messages-options.page'; import { ContactsPage } from '../new-group/contacts/contacts.page'; import { Router } from '@angular/router'; import { ChatOptionsFeaturesPage } from 'src/app/modals/chat-options-features/chat-options-features.page'; import { ChatMessageStore } from 'src/app/store/chat/chat-message.service'; import { ChatUserStorage } from 'src/app/store/chat/chat-user.service'; import { TimeService } from 'src/app/services/functions/time.service'; import { FileService } from 'src/app/services/functions/file.service'; import { HttpClient, HttpEventType } from '@angular/common/http'; import { ViewDocumentPage } from 'src/app/modals/view-document/view-document.page'; import { ThemeService } from 'src/app/services/theme.service' import { ViewMediaPage } from 'src/app/modals/view-media/view-media.page'; import { SqliteService } from 'src/app/services/sqlite.service'; import { StorageService } from 'src/app/services/storage.service'; import { Directory, Filesystem } from '@capacitor/filesystem'; import { ViewEventPage } from 'src/app/modals/view-event/view-event.page'; import { Storage } from '@ionic/storage'; import { WsChatMethodsService } from 'src/app/services/chat/ws-chat-methods.service' import { WsChatService } from 'src/app/services/chat/ws-chat.service' import { MessageService } from 'src/app/services/chat/message.service'; import { AttachmentsService } from 'src/app/services/attachments.service'; import { CameraService } from 'src/app/services/camera.service'; import { FileType } from 'src/app/models/fileType'; import { SearchPage } from 'src/app/pages/search/search.page'; import { ProcessesService } from 'src/app/services/processes.service'; import { FileToBase64Service } from 'src/app/services/file/file-to-base64.service'; import { Camera, CameraResultType, CameraSource } from '@capacitor/camera'; import { DocumentViewer, DocumentViewerOptions} from '@ionic-native/document-viewer'; const IMAGE_DIR = 'stored-images'; @Component({ selector: 'app-messages', templateUrl: './messages.page.html', styleUrls: ['./messages.page.scss'], }) export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy { showLoader: boolean; @ViewChild('scrollMe') private myScrollContainer: ElementRef; @ViewChild('message-item') messageContainer: ElementRef; loggedUser: any; messages: any; dm: any; userPresence = ''; dmUsers: any; checktimeOut: boolean; members: any; downloadProgess = 0; @Input() roomId: string; @Input() showMessages: string; @Output() openNewEventPage: EventEmitter = new EventEmitter(); @Output() getDirectMessages: EventEmitter = new EventEmitter(); chatMessageStore = ChatMessageStore chatUserStorage = ChatUserStorage scrollingOnce: boolean = true; private scrollChangeCallback: () => void; currentPosition: any; startPosition: number; mesageItemDropdownOptions: boolean = false; scrollToBottomBtn = false; longPressActive = false; frameUrl: any; downloadFile: any; massages: MessageService[] = [] constructor( public popoverController: PopoverController, private modalController: ModalController, /* private navParams: NavParams, */ private chatService: ChatService, private authService: AuthService, private animationController: AnimationController, private alertService: AlertService, private toastService: ToastService, private route: Router, private timeService: TimeService, private fileService: FileService, private gestureController: GestureController, private http: HttpClient, public ThemeService: ThemeService, private changeDetectorRef: ChangeDetectorRef, private sqliteservice: SqliteService, private storageservice: StorageService, private router: Router, private storage: Storage, public wsChatMethodsService: WsChatMethodsService, public WsChatService: WsChatService, private AttachmentsService: AttachmentsService, private CameraService: CameraService, private processesService: ProcessesService, private fileToBase64Service: FileToBase64Service, ) { this.loggedUser = authService.ValidatedUserChat['data']; } ngOnChanges(changes: SimpleChanges): void { this.wsChatMethodsService.getDmRoom(this.roomId).loadHistory({}) this.wsChatMethodsService.getDmRoom(this.roomId).scrollDown = this.scrollToBottomClicked this.wsChatMethodsService.openRoom(this.roomId) this.wsChatMethodsService.getDmRoom(this.roomId).uploadAttachment = async (formData) => { let guid: any = await this.AttachmentsService.uploadFile(formData).toPromise() } setTimeout(() => { this.scrollToBottomClicked() }, 150) } ngOnInit() { this.scrollToBottom(); this.getChatMembers(); } onPressingMessage() { const gesture = this.gestureController.create({ el: this.messageContainer.nativeElement, gestureName: 'long-press', onStart: ev => { this.longPressActive = true; console.log('Pressing'); }, onEnd: ev => { this.longPressActive = false; console.log('Stop pressing'); } }); } notImplemented() { this.alertService.presentAlert('Funcionalidade em desenvolvimento'); } load = () => { this.checktimeOut = true; this.getChatMembers(); } doRefresh(ev: any) { this.load(); ev.target.complete(); } scrollToBottom = () => { try { if (this.scrollingOnce) { this.myScrollContainer.nativeElement.scrollTop = this.myScrollContainer.nativeElement.scrollHeight; //this.scrollingOnce = false; } } catch (err) { } } scrollToBottomClicked = () => { console.log('scroll') try { this.myScrollContainer.nativeElement.scrollTop = this.myScrollContainer.nativeElement.scrollHeight; //this.scrollingOnce = false; } catch (err) { } } ngAfterViewInit() { this.scrollChangeCallback = () => this.onContentScrolled(event); window.addEventListener('scroll', this.scrollChangeCallback, true); } onContentScrolled(e) { this.startPosition = e.srcElement.scrollTop; let scroll = e.srcElement.scrollTop; let windowHeight = e.srcElement.scrollHeight; let containerHeight = windowHeight - e.srcElement.clientHeight; if (scroll > this.currentPosition) { //alert('BOTTOM'); } else { //alert('UP'); this.scrollingOnce = false; } if ((containerHeight - 100) > scroll) { this.scrollToBottomBtn = true; } else { this.scrollToBottomBtn = false; } this.currentPosition = scroll; } ngOnDestroy() { this.checktimeOut = false; window.removeEventListener('scroll', this.scrollChangeCallback, true); } openBookMeetingComponent() { let data = { roomId: this.roomId, members: this.members } this.openNewEventPage.emit(data); } showDateDuration(start: any) { return this.timeService.showDateDuration(start); } async goToEvent(eventId: any) { let classs; if (window.innerWidth < 701) { classs = 'modal modal-desktop' } else { classs = 'modal modal-desktop showAsideOptions' } const modal = await this.modalController.create({ component: ViewEventPage, componentProps: { eventId: eventId, }, cssClass: classs, }); await modal.present(); modal.onDidDismiss().then((res) => { console.log(res); }); } sendMessage() { this.wsChatMethodsService.getDmRoom(this.roomId).send({}) } deleteMessage(msgId: string) { const room = this.wsChatMethodsService.getDmRoom(this.roomId) this.alertService.confirmDeleteMessage(msgId, room); } async viewDocument(msg: any, url?: string) { if (msg.file.type == "application/img") { let response: any = await this.AttachmentsService.getFile(msg.file.guid).toPromise(); console.log(response); alert(response); //this.openPreview(msg); } else if (msg.file.type == "application/webtrix") { this.openViewDocumentModal(msg.file); } else { let fullUrl; fullUrl = "https://gabinetedigitalchat.dyndns.info" + url; //fullUrl = "http://www.africau.edu/images/default/sample.pdf"; this.frameUrl = fullUrl; this.chatService.getDocumentDetails(fullUrl); } } async openViewDocumentModal(file: any) { let task = { serialNumber: '', taskStartDate: '', isEvent: true, workflowInstanceDataFields: { FolderID: '', Subject: file.Assunto, SourceSecFsID: file.ApplicationId, SourceType: 'DOC', SourceID: file.DocId, DispatchNumber: '' } } let doc = { "Id": "", "ParentId": "", "Source": 1, "ApplicationId": file.ApplicationId, "CreateDate": "", "Data": null, "Description": "", "Link": null, "SourceId": file.DocId, "SourceName": file.Assunto, "Stakeholders": "", } const modal = await this.modalController.create({ component: ViewDocumentPage, componentProps: { trustedUrl: '', file: { title: file.Assunto, url: '', title_link: '', }, Document: doc, applicationId: file.ApplicationId, docId: file.DocId, folderId: '', task: task }, cssClass: 'modal modal-desktop' }); await modal.present(); } getChatMembers() { console.log(this.roomId); //this.showLoader = true; this.chatService.getMembers(this.roomId).subscribe(res => { this.members = res['members']; this.dmUsers = res['members'].filter(data => data.username != this.loggedUser.me.username) console.log(res); console.log(this.dmUsers); this.showLoader = false; }); } async openMessagesOptions(ev: any) { const popover = await this.popoverController.create({ component: MessagesOptionsPage, componentProps: { roomId: this.dm._id, }, cssClass: 'messages-options', event: ev, translucent: true, }); return await popover.present(); } async addContacts() { const modal = await this.modalController.create({ component: ContactsPage, componentProps: {}, cssClass: 'contacts', backdropDismiss: false }); await modal.present(); modal.onDidDismiss(); } openSendMessageOptions(ev?: any) { if (window.innerWidth < 701) { console.log('mobile'); this.openChatOptions(ev); } else { console.log('desktop'); this._openChatOptions(); } } async openChatOptions(ev: any) { const popover = await this.popoverController.create({ component: ChatOptionsPopoverPage, cssClass: 'chat-options-popover', event: ev, translucent: true }); return await popover.present(); } async _openMessagesOptions() { const enterAnimation = (baseEl: any) => { const backdropAnimation = this.animationController.create() .addElement(baseEl.querySelector('ion-backdrop')!) .fromTo('opacity', '0.01', 'var(--backdrop-opacity)'); const wrapperAnimation = this.animationController.create() .addElement(baseEl.querySelector('.modal-wrapper')!) .keyframes([ { offset: 0, opacity: '1', right: '-100%' }, { offset: 1, opacity: '1', right: '0px' } ]); return this.animationController.create() .addElement(baseEl) .easing('ease-out') .duration(500) .addAnimation([backdropAnimation, wrapperAnimation]); } const leaveAnimation = (baseEl: any) => { return enterAnimation(baseEl).direction('reverse'); } /* const popover = await this.popoverController.create({ component: MessagesOptionsPage, componentProps: { roomId: this.dm._id, }, cssClass: 'messages-options', event: ev, translucent: true, }); return await popover.present(); */ const modal = await this.modalController.create({ enterAnimation, leaveAnimation, component: MessagesOptionsPage, cssClass: 'model profile-modal search-submodal', componentProps: { roomId: this.roomId, } }); return await modal.present(); } async takePictureMobile() { const roomId = this.roomId const file = await Camera.getPhoto({ quality: 90, // allowEditing: true, resultType: CameraResultType.Base64, source: CameraSource.Camera }); console.log('ADDFILECHAT', file) //const imageData = await this.fileToBase64Service.convert(file) //console.log('ADDFILECHAT', imageData) const response = await fetch('data:image/jpeg;base64,'+ file.base64String!); const blob = await response.blob(); const formData = new FormData(); formData.append("blobFile", blob); this.wsChatMethodsService.getDmRoom(roomId).send({ file: { "type": "application/img", "guid": '', }, temporaryData: formData, attachments: [{ "title": file.path , "image_url": 'data:image/jpeg;base64,' +file.base64String, "text": "description", "title_link_download": false, }] }) } async takePicture() { const roomId = this.roomId const image = await this.CameraService.takePicture(); await this.fileService.saveImage(image) const lastphoto: any = await this.fileService.loadFiles(); const { capturedImage, capturedImageTitle} = await this.fileService.loadFileData(lastphoto); const base64 = await fetch(capturedImage); console.log('imsge take picture', image) const blob = await base64.blob(); const formData = new FormData(); formData.append("blobFile", blob); console.log('formData', formData) this.wsChatMethodsService.getDmRoom(roomId).send({ file: { "type": "application/img", "guid": '' }, temporaryData: formData, attachments: [{ "title": capturedImageTitle , "image_url": capturedImage, "text": "description", "title_link_download": false, }] }) } async addImage() { this.addFileToChatMobile(['image/apng', 'image/jpeg', 'image/png']) } async addFile() { this.addFileToChat(['.doc', '.docx', '.pdf']) } async addFileWebtrix() { const modal = await this.modalController.create({ component: SearchPage, cssClass: 'group-messages modal-desktop search-modal search-modal-to-desktop', componentProps: { type: 'AccoesPresidenciais & ArquivoDespachoElect', select: true, showSearchInput: true, } }); await modal.present(); modal.onDidDismiss().then(async res=>{ const data = res.data; const roomId = this.roomId if(data.selected) { this.wsChatMethodsService.getDmRoom(roomId).send({ file:{ "name": res.data.selected.Assunto, "type": "application/webtrix", "ApplicationId": res.data.selected.ApplicationType, "DocId": res.data.selected.Id, "Assunto": res.data.selected.Assunto, }, attachments: [{ "title": res.data.selected.Assunto, "description": res.data.selected.DocTypeDesc, "title_link_download": true, "type": "webtrix", "text": res.data.selected.DocTypeDesc, "thumb_url": "https://static.ichimura.ed.jp/uploads/2017/10/pdf-icon.png", }], }) } }); } async addFileToChatMobile(types: typeof FileType[] ) { const roomId = this.roomId const file = await Camera.getPhoto({ quality: 90, // allowEditing: true, resultType: CameraResultType.Base64, source: CameraSource.Photos }); console.log('ADDFILECHAT', file) //const imageData = await this.fileToBase64Service.convert(file) //console.log('ADDFILECHAT', imageData) const response = await fetch('data:image/jpeg;base64,'+ file.base64String!); const blob = await response.blob(); const formData = new FormData(); formData.append("blobFile", blob); this.wsChatMethodsService.getDmRoom(roomId).send({ file: { "type": "application/img", "guid": '' }, temporaryData: formData, attachments: [{ "title": file.path , "image_url": 'data:image/jpeg;base64,' +file.base64String, "text": "description", "title_link_download": false, }] }) } async addFileToChat(types: typeof FileType[] ) { const roomId = this.roomId const file: any = await this.fileService.getFileFromDevice(types); console.log('Add file', file) /* const imageData = await this.fileToBase64Service.convert(file).then((filee) => { console.log('Add file', filee) }) */ const blob = new Blob([file],{type: file.type}) console.log('Add file', blob) const formData = new FormData(); formData.append("blobFile", blob); this.wsChatMethodsService.getDmRoom(roomId).send({ file: { "type": file.type, "guid": '', }, attachments: [{ "title": file.name , "name": file.name , // "text": "description", "image_url": file, // rocketchat "title_link_download": false, }], temporaryData: formData }) } bookMeeting() { let data = { roomId: this.roomId, members: this.members } this.openNewEventPage.emit(data); } chatsend() { } async _openChatOptions() { const roomId = this.roomId; const enterAnimation = (baseEl: any) => { const backdropAnimation = this.animationController.create() .addElement(baseEl.querySelector('ion-backdrop')!) .fromTo('opacity', '0.01', 'var(--backdrop-opacity)'); const wrapperAnimation = this.animationController.create() .addElement(baseEl.querySelector('.modal-wrapper')!) .keyframes([ { offset: 0, opacity: '1', right: '-100%' }, { offset: 1, opacity: '1', right: '0px' } ]); return this.animationController.create() .addElement(baseEl) .easing('ease-out') .duration(500) .addAnimation([backdropAnimation, wrapperAnimation]); } const leaveAnimation = (baseEl: any) => { return enterAnimation(baseEl).direction('reverse'); } const modal = await this.modalController.create({ enterAnimation, leaveAnimation, component: ChatOptionsFeaturesPage, cssClass: 'model profile-modal search-submodal', componentProps: { roomId: this.roomId, members: this.members, } }); await modal.present(); modal.onDidDismiss().then( async (res) => { console.log(res['data']); if (res['data'] == 'meeting') { //this.closeAllDesktopComponents.emit(); let data = { roomId: this.roomId, members: this.members } this.openNewEventPage.emit(data); } else if (res['data'] == 'take-picture') { this.takePictureMobile() } else if (res['data'] == 'add-picture') { this.addImage() } else if (res['data'] == 'add-document') { this.addFile() } else if (res['data'] == 'documentoGestaoDocumental') { this.addFileWebtrix() this.showLoader = false; } }); } downloadFileMsg(msg: MessageService) { console.log('FILE TYPE', msg.file.type) this.downloadFile = ""; if (msg.file.type == "application/img") { this.AttachmentsService.downloadFile(msg.file.guid).subscribe(async (event) => { console.log('FILE TYPE 22', msg.file.guid) var name = msg.file.guid; if (event.type === HttpEventType.DownloadProgress) { //this.downloadProgess = Math.round((100 * event.loaded) / event.total); console.log('FILE TYPE 33', msg.file.type) } else if (event.type === HttpEventType.Response) { this.downloadFile = 'data:image/jpeg;base64,' + btoa(new Uint8Array(event.body).reduce((data, byte) => data + String.fromCharCode(byte), '')); msg.file = { guid: msg.file.guid, image_url: this.downloadFile, type: msg.file.type } await this.storage.set(msg.file.guid, this.downloadFile).then(() => { console.log('IMAGE SAVED') }); } }); } } pdfPreviwe() { const options: DocumentViewerOptions = { title: 'My App' }; DocumentViewer.viewDocument } async openPreview(msg) { if (msg.file.image_url === null || msg.file.image_url === '' ) { this.downloadFileMsg(msg) } else { const modal = await this.modalController.create({ component: ViewMediaPage, cssClass: 'modal modal-desktop', componentProps: { image: msg.file.image_url, username: msg.u.name, _updatedAt: msg._updatedAt } }); modal.present(); } } }