mirror of
https://code.equilibrium.co.ao/ITO/doneit-web.git
synced 2026-04-18 20:47:54 +00:00
497 lines
15 KiB
TypeScript
497 lines
15 KiB
TypeScript
import { Injectable } from '@angular/core';
|
|
import { MessageViewModal } from './model/message';
|
|
import { MessageLocalDataSourceService } from 'src/app/module/chat/data/repository/message/message-local-data-source.service';
|
|
import { whatsappDate } from '../../shared/utils/whatappdate';
|
|
import { XBallon } from '../utils/messageBallon';
|
|
import { Observable, Subscription } from 'rxjs';
|
|
import { RoomLocalRepository } from 'src/app/module/chat/data/repository/room/room-local-repository.service'
|
|
import { RoomViewModel } from './model/room';
|
|
import { IDBoolean } from 'src/app/infra/database/dexie/type';
|
|
import { ChatServiceService } from 'src/app/module/chat/domain/chat-service.service';
|
|
import { MessageAttachmentSource, MessageEntitySchema } from 'src/app/core/chat/entity/message';
|
|
import { SessionStore } from 'src/app/store/session.service';
|
|
import { Logger } from 'src/app/services/logger/main/service';
|
|
import { Observable as DexieObservable } from 'Dexie';
|
|
import { tap } from 'rxjs/operators';
|
|
import { MemberTable } from 'src/app/infra/database/dexie/instance/chat/schema/members';
|
|
import { MessageTable } from 'src/app/infra/database/dexie/instance/chat/schema/message';
|
|
import { MemberListLocalRepository } from 'src/app/module/chat/data/repository/member/member-list-local-repository.service'
|
|
import { UserTypingLocalRepository } from 'src/app/module/chat/data/repository/typing/user-typing-local-data-source.service';
|
|
import { Result } from 'neverthrow';
|
|
import { MessageOutPutDataDTO } from 'src/app/core/chat/repository/dto/messageOutputDTO';
|
|
import { UserTypingRemoteRepositoryService } from 'src/app/module/chat/data/repository/typing/user-typing-live-data-source.service';
|
|
|
|
@Injectable({
|
|
providedIn: 'root'
|
|
})
|
|
export class RoomStore {
|
|
|
|
messages1: {[key: string]: MessageViewModal[]} = {}
|
|
room!: RoomViewModel
|
|
date: {[key: string]: Object} = {}
|
|
messageReceiveSubject: Subscription
|
|
messageDeleteSubject: Subscription
|
|
messageUpdateSubject: Subscription
|
|
messageSendSubject: Subscription
|
|
messageTypingSubject: Subscription
|
|
messageOnReconnectSubject: Subscription
|
|
messageOnSetRoomId: Subscription
|
|
messageRoomData: Subscription
|
|
newMessagesStream!: Subscription
|
|
|
|
roomStatus$: DexieObservable<Boolean >
|
|
roomMessage$: DexieObservable<MessageTable[]>
|
|
roomMembers$: Observable<MemberTable[] | undefined>
|
|
userTyping$: string[] = []
|
|
|
|
totalMembers = 0
|
|
members: MemberTable[] = []
|
|
isAdmin = true;
|
|
|
|
scrollToBottomClicked = ()=> {}
|
|
|
|
constructor(
|
|
private RoomLocalRepository: RoomLocalRepository,
|
|
private chatServiceService: ChatServiceService,
|
|
private MemberListLocalRepository: MemberListLocalRepository,
|
|
private userTypingLocalRepository: UserTypingLocalRepository,
|
|
private UserTypingRemoteRepositoryService: UserTypingRemoteRepositoryService,
|
|
) {}
|
|
|
|
async start(room: RoomViewModel) {
|
|
|
|
this.room = room
|
|
|
|
if(this.room.local == IDBoolean.false) {
|
|
this.subscribeToChanges()
|
|
await this.getMessages()
|
|
} else {
|
|
await this.getMessages()
|
|
}
|
|
|
|
this.messageRoomData?.unsubscribe();
|
|
|
|
this.messageRoomData = this.RoomLocalRepository.getRoomByIdLive(this.room.$id).subscribe(e => {
|
|
if(e) {
|
|
this.room = new RoomViewModel(e)
|
|
|
|
}
|
|
})
|
|
|
|
this.messageOnSetRoomId?.unsubscribe()
|
|
|
|
if(this.room.local == IDBoolean.true) {
|
|
this.messageOnSetRoomId = this.chatServiceService.roomDirectOnSetId({$roomId: this.room.$id}).subscribe((data) => {
|
|
this.messageOnSetRoomId?.unsubscribe()
|
|
|
|
this.room = new RoomViewModel(data)
|
|
|
|
const hasMyMessage = this.messages1[this.room.$id].find(e => e.sender.wxUserId == SessionStore.user.UserId)
|
|
|
|
if(!hasMyMessage) {
|
|
setTimeout(() => {
|
|
this.getMessages()
|
|
}, 500)
|
|
}
|
|
|
|
setTimeout(() => {
|
|
this.subscribeToChanges()
|
|
}, 500)
|
|
|
|
})
|
|
}
|
|
}
|
|
|
|
stop() {
|
|
this.messageReceiveSubject?.unsubscribe();
|
|
this.messageDeleteSubject?.unsubscribe();
|
|
this.messageUpdateSubject?.unsubscribe();
|
|
this.messageSendSubject?.unsubscribe();
|
|
this.messageTypingSubject?.unsubscribe();
|
|
this.messageOnReconnectSubject?.unsubscribe();
|
|
this.messageOnSetRoomId?.unsubscribe();
|
|
this.newMessagesStream?.unsubscribe();
|
|
}
|
|
|
|
subscribeToChanges() {
|
|
this.listenToIncomingMessage();
|
|
this.listenToDeleteMessage();
|
|
this.listenToUpdateMessage();
|
|
this.listenToSendMessage();
|
|
|
|
this.roomMembers$ = this.MemberListLocalRepository.getRoomMemberByIdLive(this.room.id).pipe(
|
|
tap((members) => {
|
|
this.totalMembers = members.length
|
|
this.members = members
|
|
for(const member of members) {
|
|
if(member.wxUserId == SessionStore.user.UserId) {
|
|
this.isAdmin = member.isAdmin
|
|
}
|
|
}
|
|
})
|
|
)
|
|
|
|
this.roomStatus$ = this.MemberListLocalRepository.allMemberOnline(this.room.id)
|
|
|
|
this.messageTypingSubject?.unsubscribe()
|
|
this.messageTypingSubject = this.userTypingLocalRepository.getUserTypingLiveByRoomId(this.room.id).subscribe((e) => {
|
|
const arrayNames = e.filter((b)=> b.userId != SessionStore.user.UserId).map(e => e.userName)
|
|
|
|
const uniqueArray = [...new Set(arrayNames)];
|
|
this.userTyping$ = uniqueArray
|
|
|
|
}) as any
|
|
|
|
this.updateRoomDetails()
|
|
}
|
|
|
|
|
|
listenToSendMessage() {
|
|
this.messageSendSubject?.unsubscribe();
|
|
|
|
this.messageSendSubject = this.chatServiceService.listenToSendMessage(this.room.id).subscribe((updateMessage) => {
|
|
|
|
const index = this.messages1[this.room.$id].findIndex(e => e?.requestId === updateMessage.requestId); // Use triple equals for comparison
|
|
|
|
if (index !== -1) { // Check if the item was found
|
|
|
|
this.messages1[this.room.$id][index].id = updateMessage.id
|
|
this.messages1[this.room.$id][index].info = updateMessage.info
|
|
|
|
let attachmentIndex = 0;
|
|
|
|
for(const message of updateMessage.attachments) {
|
|
|
|
this.messages1[this.room.$id][index].attachments[attachmentIndex].id = message.id
|
|
attachmentIndex++;
|
|
}
|
|
|
|
} else {
|
|
console.log('not found message to update ui');
|
|
}
|
|
});
|
|
}
|
|
|
|
listenToUpdateMessage() {
|
|
this.messageUpdateSubject?.unsubscribe();
|
|
|
|
// console.log('liste to update')
|
|
this.messageUpdateSubject = this.chatServiceService.listenToUpdateMessage(this.room.id).subscribe((updateMessage) => {
|
|
|
|
const index = this.messages1[this.room.$id].findIndex(e => e?.id === updateMessage.id); // Use triple equals for comparison
|
|
|
|
if (index !== -1) { // Check if the item was found
|
|
this.messages1[this.room.$id][index].info = updateMessage.info
|
|
this.messages1[this.room.$id][index].message = updateMessage.message
|
|
this.messages1[this.room.$id][index].reactions = updateMessage.reactions
|
|
} else {
|
|
// console.log('message not found');
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
listenToIncomingMessage() {
|
|
this.messageReceiveSubject?.unsubscribe();
|
|
this.messageReceiveSubject = this.chatServiceService.listenToIncomingMessage(this.room.id).subscribe(async (_message) => {
|
|
|
|
const date = whatsappDate(_message.sentAt, false)
|
|
if(!this.date[date]) {
|
|
this.date[date] = true
|
|
const Ballon = XBallon(_message)
|
|
this.messages1[this.room.$id].push(Ballon)
|
|
}
|
|
|
|
const message = new MessageViewModal(_message)
|
|
this.messages1[this.room.$id].push(new MessageViewModal(message))
|
|
|
|
if(message.hasAttachment) {
|
|
|
|
const result = await this.chatServiceService.downloadMessageAttachmentByMessageId({
|
|
$messageId: message.id,
|
|
id: message.attachments[0].id
|
|
})
|
|
|
|
if(result.isOk()) {
|
|
message.attachments[0].safeFile = result.value
|
|
if((result.value as unknown as string).startsWith('blob:http')) {
|
|
message.attachments[0].blobURl = true
|
|
} else {
|
|
message.attachments[0].blobURl = false
|
|
}
|
|
}
|
|
}
|
|
|
|
this.chatServiceService.sendReadAt({
|
|
memberId: SessionStore.user.UserId,
|
|
messageId: message.id,
|
|
requestId: '',
|
|
roomId: this.room.id
|
|
})
|
|
|
|
setTimeout(() => {
|
|
this.scrollToBottomClicked()
|
|
}, 100)
|
|
|
|
|
|
setTimeout(() => {
|
|
this.removeBold()
|
|
}, 1000)
|
|
});
|
|
|
|
}
|
|
|
|
removeBold() {
|
|
if(!this.room?.local) {
|
|
this.chatServiceService.removeBoldFromRoom({roomId: this.room.id})
|
|
}
|
|
}
|
|
|
|
listenToDeleteMessage() {
|
|
this.messageDeleteSubject?.unsubscribe();
|
|
|
|
this.messageDeleteSubject = this.chatServiceService.listenToDeleteMessage(this.room.id).subscribe((deleteMessage) => {
|
|
console.log('delete class', deleteMessage);
|
|
|
|
const index = this.messages1[this.room.$id].findIndex(e =>
|
|
typeof e?.id == 'string' && e?.id === deleteMessage.id ||
|
|
typeof e?.requestId == 'string' && e?.requestId == deleteMessage.requestId);
|
|
|
|
try {
|
|
console.log(this.messages1[this.room.$id][index])
|
|
this.messages1[this.room.$id][index].delete()
|
|
} catch (e) {
|
|
console.log('delete', e)
|
|
}
|
|
});
|
|
}
|
|
|
|
async getMessages() {
|
|
|
|
// dont remove this line
|
|
this.messages1[this.room.$id] = []
|
|
|
|
let messages = await this.chatServiceService.messageLocalGetById({
|
|
roomId: this.room.id,
|
|
receiverId: this.room?.receiverId?.toString()
|
|
})
|
|
|
|
if(messages.isOk()) {
|
|
this.messages1[this.room.$id] = []
|
|
this.date = {}
|
|
const allMessage = [];
|
|
|
|
//console.time("mappingTime");
|
|
const sortMessages = messages.value.sort((a, b) => new Date(a.sentAt).getTime() - new Date(b.sentAt).getTime())
|
|
|
|
for(const message of sortMessages) {
|
|
const date = whatsappDate(message.sentAt, false)
|
|
if(!this.date[date]) {
|
|
this.date[date] = true
|
|
const Ballon = XBallon(message)
|
|
allMessage.push(Ballon)
|
|
}
|
|
|
|
allMessage.push(new MessageViewModal(message))
|
|
}
|
|
//console.timeEnd("mappingTime");
|
|
this.messages1[this.room.$id]
|
|
this.messages1[this.room.$id] = allMessage
|
|
|
|
|
|
|
|
// if(messages.length >= 1) {
|
|
// this.messages1[this.room.$id].push(LastMessage)
|
|
// }
|
|
|
|
this.loadAttachment()
|
|
setTimeout(() => {
|
|
this.sendReadMessage()
|
|
}, 1000)
|
|
|
|
if(this.room.$id) {
|
|
this.onReconnectGetMessages()
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
async loadAttachment() {
|
|
for(const message of this.messages1[this.room.$id]) {
|
|
if(message.hasAttachment && message.attachments[0].source != MessageAttachmentSource.Webtrix) {
|
|
|
|
this.chatServiceService.getMessageAttachmentByMessageId(message).then((result)=> {
|
|
if(result.isOk()) {
|
|
message.attachments[0].safeFile = result.value
|
|
|
|
if(result.value.startsWith('blob:http')) {
|
|
message.attachments[0].blobURl = true
|
|
}
|
|
}
|
|
})
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
sendReadMessage() {
|
|
|
|
if(this.room.local == IDBoolean.false) {
|
|
for(const message of this.messages1[this.room.$id]) {
|
|
|
|
if(!message.meSender()) {
|
|
const me = message.haveSeen(message.info)
|
|
|
|
if(!me) {
|
|
Logger.info('send read at, sender '+ message.sender.wxFullName+ ' '+ message.message +'message id'+ message.id)
|
|
|
|
this.chatServiceService.sendReadAt({
|
|
memberId: SessionStore.user.UserId,
|
|
messageId: message.id,
|
|
requestId: '',
|
|
roomId: this.room.id
|
|
})
|
|
} else {
|
|
// console.log('no need', message )
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
console.log('dont read for this room')
|
|
}
|
|
}
|
|
|
|
onReconnectGetMessages() {
|
|
this.messageOnReconnectSubject?.unsubscribe()
|
|
this.messageOnReconnectSubject = this.chatServiceService.listenToMessageLoadHistory({roomId: this.room.id}).subscribe((messages) => {
|
|
|
|
for(const message of messages.data.reverse()) {
|
|
const found = this.messages1[this.room.$id].find((e) => e.id == message.id)
|
|
|
|
const date = whatsappDate(message.sentAt, false)
|
|
if(!this.date[date]) {
|
|
this.date[date] = true
|
|
const Ballon = XBallon(message)
|
|
this.messages1[this.room.$id].push(Ballon)
|
|
}
|
|
|
|
if(!found) {
|
|
const msg = new MessageViewModal(message as any)
|
|
Object.assign(msg, message)
|
|
this.messages1[this.room.$id].push(msg)
|
|
}
|
|
}
|
|
|
|
|
|
})
|
|
}
|
|
|
|
|
|
updateRoomDetails() {
|
|
this.chatServiceService.getRoomById(this.room.id)
|
|
}
|
|
|
|
|
|
createMessage() {
|
|
const message = new MessageViewModal();
|
|
|
|
if(this.room.id) {
|
|
message.roomId = this.room.id
|
|
}
|
|
|
|
message.sentAt = new Date().toISOString()
|
|
|
|
message.sender = {
|
|
userPhoto: '',
|
|
wxeMail: SessionStore.user.Email,
|
|
wxFullName: SessionStore.user.FullName,
|
|
wxUserId: SessionStore.user.UserId
|
|
}
|
|
|
|
message.sentAt = new Date().toISOString()
|
|
if(this.room.receiverId) {
|
|
message.receiverId = this.room.receiverId
|
|
}
|
|
|
|
return message
|
|
}
|
|
|
|
async messageResult(result: Promise<Result<MessageOutPutDataDTO, any>> ) {
|
|
// let message = await result
|
|
|
|
|
|
// if(message.isOk() && this.room.local == IDBoolean.true) {
|
|
// this.room.local = IDBoolean.false;
|
|
|
|
// console.log('enter')
|
|
// await this.chatServiceService.roomSetLocalToFalseById({
|
|
// $roomId: this.room.$id,
|
|
// roomId: message.value.roomId
|
|
// })
|
|
|
|
// this.room.id = message.value.roomId
|
|
// this.subscribeToChanges()
|
|
// }
|
|
}
|
|
|
|
|
|
addReaction(message: any, emoji: string) {
|
|
// Logic to add reaction to the message
|
|
console.log(`Reacting to message ${message.id} with emoji ${emoji.codePointAt(0).toString(16)}`);
|
|
|
|
this.chatServiceService.reactToMessage({
|
|
memberId: SessionStore.user.UserId,
|
|
messageId: message.id,
|
|
roomId: this.room.id,
|
|
reaction: emoji,
|
|
requestId: ''
|
|
})
|
|
|
|
}
|
|
|
|
sendTyping() {
|
|
this.UserTypingRemoteRepositoryService.sendTyping(this.room.id)
|
|
}
|
|
|
|
updateMessage({messageId, message}) {
|
|
this.chatServiceService.updateMessage({
|
|
memberId: SessionStore.user.UserId,
|
|
message,
|
|
messageId,
|
|
requestId: '',
|
|
roomId: this.room.id
|
|
})
|
|
}
|
|
|
|
messageDelete(message: MessageViewModal) {
|
|
this.chatServiceService.messageDelete({
|
|
messageId: message.id,
|
|
roomId: this.room.id,
|
|
})
|
|
}
|
|
|
|
|
|
async sendMessage(text:string, attachment?: typeof MessageEntitySchema._type.attachments) {
|
|
|
|
const message = this.createMessage();
|
|
message.message = text
|
|
|
|
const date = whatsappDate(message.sentAt, false)
|
|
if(!this.date[date]) {
|
|
this.date[date] = true
|
|
const Ballon = XBallon(message)
|
|
this.messages1[this.room.$id].push(Ballon)
|
|
}
|
|
|
|
if(attachment) {
|
|
message.attachments = attachment
|
|
}
|
|
|
|
this.messages1[this.room.$id].push(message)
|
|
let sendMessage = this.chatServiceService.sendMessage(message, this.room.roomType)
|
|
this.messageResult(sendMessage)
|
|
|
|
}
|
|
}
|