This commit is contained in:
Peter Maquiran
2024-08-13 10:52:35 +01:00
parent 5b31a186c2
commit 251f533a68
53 changed files with 985 additions and 453 deletions
@@ -1,6 +1,5 @@
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { ThemeService } from 'src/app/services/theme.service'
// import { ChatSystemService } from 'src/app/services/chat/chat-system.service';
import { ContactRepositoryService } from 'src/app/services/Repositorys/contacts/repository/contacts-repository.service';
import { UserContacts } from 'src/app/services/Repositorys/contacts/data-source/contacts-data-source.service';
import { RoomRepositoryService } from 'src/app/module/chat/data/repository/room-repository.service'
@@ -26,7 +25,6 @@ export class GroupContactsPage implements OnInit {
@Output() openGroupMessage:EventEmitter<any> = new EventEmitter<any>();
@Output() openGroupContacts:EventEmitter<any> = new EventEmitter<any>();
currentMembers:UserContacts[];
allChatUsers: UserContacts[] = [];
userContainer: {[key: string]: ( UserContacts & {isChecked: boolean})[] } = {}
@@ -59,13 +57,13 @@ export class GroupContactsPage implements OnInit {
id: this.roomId,
members: this.selectedUsers
})
if(addMembers.isOk()) {
// this.addContacts(this.roomId);
this.openGroupMessage.emit(this.roomId);
this.RoomRepositoryService.getRoomById(this.roomId)
} else if(addMembers.error instanceof HttpRequest) {
this.httpErrorHandle.httpStatusHandle(addMembers.error)
}
// if(addMembers.isOk()) {
// // this.addContacts(this.roomId);
// this.openGroupMessage.emit(this.roomId);
// this.RoomRepositoryService.getRoomById(this.roomId)
// } else if(addMembers.error instanceof HttpRequest) {
// this.httpErrorHandle.httpStatusHandle(addMembers.error)
// }
} else {
this.openGroupMessage.emit(this.roomId);
}
@@ -3,7 +3,7 @@
<div class="main-header">
<div class="header-top">
<div class="middle">
<ion-label class="title">{{ ChatSystemService.getGroupRoom(roomId).name.split('-').join(' ') }}</ion-label>
<!-- <ion-label class="title">{{ ChatSystemService.getGroupRoom(roomId).name.split('-').join(' ') }}</ion-label> -->
</div>
<div class="right">
<!-- <div (click)=" ChatSystemService.getGroupRoom(this.roomId).deleteAll()">delete all</div> -->
@@ -18,11 +18,11 @@
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " src="assets/icon/icons-user.svg"></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " src="assets/icon/theme/gov/icons-user.svg"></ion-icon>
</div>
<div class="header-bottom-contacts" *ngIf="ChatSystemService.getGroupRoom(roomId)">
<!-- <div class="header-bottom-contacts" *ngIf="ChatSystemService.getGroupRoom(roomId)">
<ion-label class="contacts-list" *ngFor="let member of ChatSystemService.getGroupRoom(roomId).membersExcludeMe; let last = last" >
{{member.name}}<span *ngIf="!last">, </span>
</ion-label>
</div>
</div> -->
</div>
</div>
@@ -42,7 +42,7 @@
<ion-label>A conversa original mantêm-se como chat individual</ion-label>
</div>
<div class="messages-list-item-wrapper container-width-100" *ngFor="let msg of ChatSystemService.getGroupRoom(roomId).messages; let last = last">
<div class="messages-list-item-wrapper container-width-100" *ngFor="let msg of []; let last = last">
<div class="message-item incoming-{{msg.u.username!=sessionStore.user.UserName}} max-width-45" *ngIf="msg.t != 'r' && msg.t != 'ul' && msg.t != 'au' && msg.t != 'ru' && msg.msg !=''" [class.dateLabel]="msg.dateLabel">
<div class="message-item-options d-flex justify-content-end" *ngIf="!msg.dateLabel">
<fa-icon [matMenuTriggerFor]="beforeMenu" icon="chevron-down" class="message-options-icon cursor-pointer"></fa-icon>
@@ -213,7 +213,7 @@
{{last ? scrollToBottom() : ''}}
</div>
<div *ngIf="msg.t == 'au' && msg.msg != sessionStore.user.UserName">
<div *ngFor="let user of ChatSystemService.users">
<div *ngFor="let user of []">
<div *ngIf="msg.msg == user.username" class="info-text-leave">
<ion-label>Adicionou {{user.name}}</ion-label><br />
</div>
@@ -252,15 +252,15 @@
<ion-footer>
<div class="typing" *ngIf="ChatSystemService.getGroupRoom(roomId).otherUserType == true">
<ngx-letters-avatar *ngIf="showAvatar"
<!-- <div class="typing" >
<ngx-letters-avatar *ngIf="showAvatar"
[avatarName]= "ChatSystemService.getGroupRoom(roomId).name"
[width]="30"
[circular]="true"
fontFamily="Roboto"></ngx-letters-avatar>
{{ ChatSystemService.getGroupRoom(roomId).userThatIsTyping }} está a escrever...
</div>
</div> -->
<div class="width-100 pl-20 pr-20">
<span *ngIf="!lastAudioRecorded">{{durationDisplay}}</span>
@@ -298,7 +298,7 @@
<div class="width-100">
<div *ngIf="!recording && !lastAudioRecorded" class="type-message">
<ion-textarea autocomplete="on" autocorrect="on" spellcheck="true" (keyup.enter)="sendMessage()" clearOnEdit="true" placeholder="Escrever uma mensagem" class="message-input" rows="1" [(ngModel)]="ChatSystemService.getGroupRoom(roomId).message" (ionChange)="ChatSystemService.getGroupRoom(roomId).sendTyping()"></ion-textarea>
<ion-textarea autocomplete="on" autocorrect="on" spellcheck="true" (keyup.enter)="sendMessage()" clearOnEdit="true" placeholder="Escrever uma mensagem" class="message-input" rows="1" ></ion-textarea>
</div>
<div *ngIf="recording" class="d-flex align-items-center justify-content-center">
<button (click)="stopRecording()" class="btn-no-color d-flex align-items-center justify-content-center">
@@ -307,7 +307,7 @@
</div>
</div>
<div class="btn-send">
<!-- <div class="btn-send">
<button #recordbtn *ngIf="!ChatSystemService.getGroupRoom(roomId).message && !lastAudioRecorded" (click)="startRecording()" class="btn-no-color">
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " class="chat-icon-send" src="assets/icon/theme/default/icons-chat-record-audio.svg"></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " class="chat-icon-send" src="assets/icon/theme/gov/icons-chat-record-audio.svg"></ion-icon>
@@ -320,7 +320,7 @@
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " class="chat-icon-send" src="assets/icon/theme/gov/icons-chat-send.svg"></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " class="chat-icon-send" src="assets/icon/theme/gov/icons-chat-send.svg"></ion-icon>
</button>
</div>
</div> -->
</div>
</ion-footer>
@@ -44,14 +44,30 @@
<div class="messages height-100 width-100 d-flex flex-column" #scrollMe >
<div
*ngFor="let message of (roomMessage$ | async)" class="messages-list-item-wrapper"
*ngFor="let message of messages1[roomId]" class="messages-list-item-wrapper"
[ngClass]="{'my-message': message.sender.wxUserId === sessionStore.user.UserId, 'other-message': message.sender.wxUserId !== sessionStore.user.UserId}"
>
<div class="message-container">
<div class="d-flex justify-content-between">
<div>
{{ message.message }}
<div>
{{ message.message }}
</div>
<div *ngFor="let attachment of message.attachment">
<div *ngIf="attachment.fileType == 1">
<ion-icon src="assets/icon/webtrix.svg" class="file-icon font-25"></ion-icon>
<ion-label>{{ attachment.fileName}}</ion-label>
<!-- <ion-icon *ngIf="ThemeService.currentTheme == 'default' && attachment.type != 'webtrix' && !( msg.downloadLoader == true || msg.uploadingFile == true ) " class="icon-download" src="assets/icon/theme/default/icons-download.svg" slot="end"></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' && attachment.type != 'webtrix' && !( msg.downloadLoader == true || msg.uploadingFile == true ) " class="icon-download" src="assets/icon/theme/gov/icons-download.svg" slot="end"></ion-icon>
<ion-icon *ngIf="( msg.downloadLoader == true || msg.uploadingFile == true )" class="icon-download" src="assets/gif/theme/{{ThemeService.currentTheme}}/Blocks-loader.svg" slot="end"></ion-icon> -->
</div>
</div>
</div>
<div>
+131 -38
View File
@@ -1,8 +1,6 @@
import { AfterViewInit, Component, ElementRef, EventEmitter, HostListener, Input, OnChanges, OnDestroy, OnInit, Output, SimpleChanges, ViewChild } from '@angular/core';
import { AfterViewInit, Component, ElementRef, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, SimpleChanges, ViewChild } from '@angular/core';
import { AnimationController, GestureController, IonRange, ModalController, PopoverController } from '@ionic/angular';
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 { ChatOptionsFeaturesPage } from 'src/app/modals/chat-options-features/chat-options-features.page';
import { ChatMessageStore } from 'src/app/store/chat/chat-message.service';
@@ -12,12 +10,10 @@ import { FileService } from 'src/app/services/functions/file.service';
import { ViewDocumentPage } from 'src/app/modals/view-document/view-document.page';
import { ThemeService } from 'src/app/services/theme.service';
import { ViewEventPage } from 'src/app/modals/view-event/view-event.page';
import { Storage } from '@ionic/storage';
import { FileType } from 'src/app/models/fileType';
import { SearchPage } from 'src/app/pages/search/search.page';
import { Camera, CameraResultType, CameraSource } from '@capacitor/camera';
import { DocumentViewer, DocumentViewerOptions } from '@ionic-native/document-viewer';
import { VoiceRecorder, RecordingData, GenericResponse } from 'capacitor-voice-recorder';
import { CameraResultType } from '@capacitor/camera';
import { RecordingData } from 'capacitor-voice-recorder';
import { Filesystem, Directory } from '@capacitor/filesystem';
import { DomSanitizer } from '@angular/platform-browser';
import { Platform } from '@ionic/angular';
@@ -29,7 +25,7 @@ import { ViewMediaPage } from 'src/app/modals/view-media/view-media.page';
import { PermissionService } from 'src/app/services/permission.service';
import { ChatPopoverPage } from '../../popover/chat-popover/chat-popover.page';
import { Observable as DexieObservable } from 'Dexie';
import { Observable, Subscription } from 'rxjs';
import { Subscription } from 'rxjs';
import { MessageRepositoryService } from 'src/app/module/chat/data/repository/message-respository.service'
import { RoomRepositoryService } from 'src/app/module/chat/data/repository/room-repository.service'
import { MessageTable } from 'src/app/module/chat/infra/database/dexie/schema/message';
@@ -45,9 +41,10 @@ import { JSFileToBase64 } from 'src/app/utils/ToBase64';
import { CameraService } from 'src/app/infra/camera/camera.service'
import { compressImageBase64 } from '../../../utils/imageCompressore';
import { FilePickerWebService } from 'src/app/infra/file-picker/web/file-picker-web.service'
import { FilePickerService } from 'src/app/infra/file-picker/file-picker.service'
import { allowedDocExtension } from 'src/app/utils/allowedDocExtension';
import { SpeakerService, StartRecordingResultError, StopRecordingResultError } from 'src/app/infra/speaker/speaker.service'
const IMAGE_DIR = 'stored-images';
@Component({
selector: 'app-messages',
templateUrl: './messages.page.html',
@@ -59,7 +56,6 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
@ViewChild('scrollMe') private myScrollContainer: ElementRef;
@ViewChild('message-item') messageContainer: ElementRef;
messages: any;
dm: any;
userPresence = '';
dmUsers: any;
@@ -116,6 +112,7 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
roomName: any;
isAdmin = true;
roomCountDownDate: string;
audioMimeType = ''
textField = ''
@@ -132,18 +129,24 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
totalMessage = 0
recordData:RecordingData
messages: MessageEntity[] = []
messageReceiveSubject: Subscription
messageDeleteSubject: Subscription
messageUpdateSubject: Subscription
messageSendSubject: Subscription
messages1: {[key: string]: MessageEntity[]} = {}
constructor(
public popoverController: PopoverController,
private modalController: ModalController,
/* private navParams: NavParams, */
private animationController: AnimationController,
private toastService: ToastService,
private timeService: TimeService,
private fileService: FileService,
private gestureController: GestureController,
public ThemeService: ThemeService,
private storage: Storage,
// public RochetChatConnectorService: RochetChatConnectorService,
private sanitiser: DomSanitizer,
private file: File,
private platform: Platform,
@@ -155,6 +158,7 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
private chatServiceService: ChatServiceService,
private CameraService: CameraService,
private FilePickerWebService: FilePickerWebService,
private FilePickerService: FilePickerService,
private SpeakerService: SpeakerService
) {
// update
@@ -163,9 +167,13 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
ngOnChanges(changes: SimpleChanges): void {
this.roomData$ = this.roomRepositoryService.getItemByIdLive(this.roomId)
this.getMessages()
this.listenToIncomingMessage()
this.listenToDeleteMessage()
this.listenToUpdateMessage();
this.listenToSendMessage()
this.roomMessage$ = this.messageRepositoryService.getItemsLive(this.roomId)
this.roomMembers$ = this.roomRepositoryService.getRoomMemberByIdLive(this.roomId) as any
this.roomStatus$ = this.roomRepositoryService.getRoomStatus(this.roomId)
this.roomRepositoryService.getRoomById(this.roomId)
@@ -179,25 +187,77 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
(this.myInputRef.nativeElement as HTMLDivElement).innerHTML = '::'+ uniqueArray
})
}
this.newMessagesStream?.unsubscribe()
this.newMessagesStream = this.messageRepositoryService.subscribeToNewMessages(this.roomId).subscribe((e) => {
async getMessages() {
this.messages1[this.roomId] = []
setTimeout(() => {
this.scrollToBottomClicked()
}, 200)
const messages = await this.messageRepositoryService.getItems(this.roomId)
this.messages1[this.roomId].unshift(...messages)
}
setTimeout(() => {
this.scrollToBottomClicked()
}, 500)
listenToIncomingMessage() {
this.messageReceiveSubject?.unsubscribe();
this.messageReceiveSubject = this.chatServiceService.listenToIncomingMessage(this.roomId).subscribe((message) => {
this.messages1[this.roomId].push(message as MessageEntity)
this.scrollToBottomClicked()
});
}
})
listenToDeleteMessage() {
this.messageDeleteSubject?.unsubscribe();
//this.userTyping$ = this.userTypingMemoryDataSource.select(state => state) as any
this.messageDeleteSubject = this.chatServiceService.listenToDeleteMessage(this.roomId).subscribe((deleteMessage) => {
console.log('delete class', deleteMessage);
// let a = this.userTypingMemoryDataSource.select(state => state).subscribe((e) => {
// this.userTyping$ = e as any
// })
const index = this.messages1[this.roomId].findIndex(e => e?.id === deleteMessage.id); // Use triple equals for comparison
if (index !== -1) { // Check if the item was found
console.log('delete ==')
this.messages1[this.roomId].splice(index, 1);
// console.log('removed index', index);
} else {
// console.log('message not found');
}
});
}
listenToUpdateMessage() {
this.messageUpdateSubject?.unsubscribe();
this.messageUpdateSubject = this.chatServiceService.listenToUpdateMessage(this.roomId).subscribe((updateMessage) => {
console.log('update message', updateMessage);
const index = this.messages1[this.roomId].findIndex(e => e?.id === updateMessage.id); // Use triple equals for comparison
if (index !== -1) { // Check if the item was found
console.log('update ==')
this.messages1[this.roomId][index].message = updateMessage.message
this.messages1[this.roomId][index].reactions = updateMessage.reactions
} else {
// console.log('message not found');
}
});
}
listenToSendMessage() {
this.messageSendSubject?.unsubscribe();
this.messageSendSubject = this.chatServiceService.listenToSendMessage(this.roomId).subscribe((updateMessage) => {
console.log('update message', updateMessage);
const index = this.messages1[this.roomId].findIndex(e => e?.requestId === updateMessage.requestId); // Use triple equals for comparison
if (index !== -1) { // Check if the item was found
console.log('update ==')
this.messages1[this.roomId][index].id = updateMessage.id
} else {
// console.log('message not found');
}
});
}
@@ -409,9 +469,9 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
this.recording = false;
const recordData = stop.value
this.recordData = recordData
this.audioMimeType = recordData.value.mimeType
if (recordData.value.recordDataBase64.includes('data:audio')) {
console.log({recordData})
this.audioRecordedDataUrl = recordData.value.recordDataBase64
this.audioRecordedSafe = this.sanitiser.bypassSecurityTrustResourceUrl(recordData.value.recordDataBase64);
}
@@ -448,11 +508,16 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
file: encodedData,
fileName: "audio",
source: MessageAttachmentSource.Device,
fileType: MessageAttachmentFileType.Audio
fileType: MessageAttachmentFileType.Audio,
mimeType: this.audioMimeType
}]
this.chatServiceService.sendMessage(message)
this.messages1[this.roomId].push(message)
setTimeout(() => {
this.scrollToBottomClicked()
}, 100)
this.deleteRecording();
}
@@ -490,7 +555,7 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
await modal.present();
}
sendMessage() {
async sendMessage() {
const message = new MessageEntity();
message.message = this.textField
@@ -503,9 +568,16 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
wxUserId: SessionStore.user.UserId
}
this.chatServiceService.sendMessage(message)
this.textField = ''
this.messages1[this.roomId].push(message)
setTimeout(() => {
this.scrollToBottomClicked()
}, 100)
const data = await this.chatServiceService.sendMessage(message)
console.log({data})
}
@@ -676,9 +748,14 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
file: compressedImage.value,
fileName: "foto",
source: MessageAttachmentSource.Device,
fileType: MessageAttachmentFileType.Image
fileType: MessageAttachmentFileType.Image,
mimeType: picture.value.format
}]
this.messages1[this.roomId].push(message)
setTimeout(() => {
this.scrollToBottomClicked()
}, 100)
this.chatServiceService.sendMessage(message)
}
@@ -729,6 +806,10 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
docId: res.data.selected.Id,
}]
this.messages1[this.roomId].push(message)
setTimeout(() => {
this.scrollToBottomClicked()
}, 100)
this.chatServiceService.sendMessage(message)
this.textField = ''
@@ -740,7 +821,7 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
async pickPicture() {
const file = await this.FilePickerWebService.getPicture({
const file = await this.FilePickerService.getPicture({
cameraResultType: CameraResultType.Base64
})
@@ -769,12 +850,19 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
}
message.attachments = [{
file: compressedImage.value,
file: file.value.base64String,
fileName: "foto",
source: MessageAttachmentSource.Device,
fileType: MessageAttachmentFileType.Image
fileType: MessageAttachmentFileType.Image,
mimeType: 'image/'+file.value.format,
description: ''
}]
this.messages1[this.roomId].push(message)
setTimeout(() => {
this.scrollToBottomClicked()
}, 100)
this.chatServiceService.sendMessage(message)
}
}
@@ -821,9 +909,14 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
file: fileBase64.value,
fileName: file.value.name,
source: MessageAttachmentSource.Device,
fileType: MessageAttachmentFileType.Doc
fileType: MessageAttachmentFileType.Doc,
mimeType: file.value.type
}]
this.messages1[this.roomId].push(message)
setTimeout(() => {
this.scrollToBottomClicked()
}, 100)
this.chatServiceService.sendMessage(message)
}