import { Injectable } from '@angular/core'; import { IMessageSocketRepository } from 'src/app/core/chat/repository/message/message-socket-repository'; import { IRoomLocalRepository } from 'src/app/core/chat/repository/room/room-local-repository'; import { filter, map, tap } from 'rxjs/operators'; import { MessageEntity } from 'src/app/core/chat/entity/message'; import { HttpAdapter } from 'src/app/infra/http/adapter'; import { IMessageGetAllByRoomIdOutPut } from 'src/app/core/chat/usecase/message/message-get-all-by-room-Id'; import { RoomEntity } from 'src/app/core/chat/entity/group'; import { RoomTable } from 'src/app/infra/database/dexie/instance/chat/schema/room'; import { IMessageLocalRepository } from 'src/app/core/chat/repository/message/message-local-repository'; import { messageListDetermineChanges } from '../../../data/async/list/rooms/messageListChangedetector'; import { IDBoolean } from 'src/app/infra/database/dexie/type'; @Injectable({ providedIn: 'root' }) export class RoomSetLastMessageService { constructor( private roomLocalRepository: IRoomLocalRepository, private messageSocketRepository: IMessageSocketRepository, private messageLocalRepository: IMessageLocalRepository, private http: HttpAdapter, ) { this.listenToIncomingMessage() this.listenToOnSendDataToSocket() this.loadHistory() this.listenToUpdateMessage() } private listenToUpdateMessage() { let roomList: RoomTable[] = [] this.roomLocalRepository.getItemsLive().pipe( tap((_roomList) => { roomList = _roomList }) ).subscribe(); this.messageSocketRepository.listenToUpdateMessages().subscribe(async(_message) => { const message = {..._message} for(const room of roomList) { if(room.messages?.[0]?.id == message.id) { const result = await this.roomLocalRepository.update(room.$id, { messages: [message] }) if(result.isErr()) { console.log('failed to update last message') } else { // console.log('set last message') } } } }) this.messageSocketRepository.listenToDeleteMessages().subscribe(async(_message) => { const message = {..._message} for(const room of roomList) { if(room.messages?.[0]?.id == message.id) { // incoming _message does not have sender const messageToUpdate = ({...room.messages?.[0],isDeleted: true}) const result = await this.roomLocalRepository.update(room.$id, { messages: [messageToUpdate] }) if(result.isErr()) { console.log('failed to update last message') } else { console.log('set last message') } } } }) } private listenToIncomingMessage() { return this.messageSocketRepository.listenToMessages() .subscribe(async (e) => { const message = Object.assign(new MessageEntity(), e.data) if(message?.roomId) { console.log('listenToIncomingMessage', message.roomId) const findRoom = await this.roomLocalRepository.findOne({ id: message.roomId }) if(findRoom.isOk() && findRoom.value) { const result = await this.roomLocalRepository.update(findRoom.value.$id, { messages: [message] }) if(result.isErr()) { console.log('failed to update last message') } else { console.log('set last message') } } else if (findRoom.isOk() && !findRoom.value && e.payload.receiverId) { // console.log('new room', e) const findLocalDirectRoom = await this.roomLocalRepository.findOne({ receiverId: e.payload.receiverId }) if(findLocalDirectRoom.isOk() && findLocalDirectRoom.value) { findLocalDirectRoom.value.id = message.roomId findLocalDirectRoom.value.local = IDBoolean.false findLocalDirectRoom.value.messages = [message]; await findLocalDirectRoom.value.save() } } } }); } // local storage private listenToOnSendDataToSocket() { this.messageLocalRepository.onCreateObservable().subscribe(async (message) => { if(message?.roomId) { setTimeout(async() => { if(message.origin != 'history') { const findRoom = await this.roomLocalRepository.findOne({ id: message.roomId }) if(findRoom.isOk() && findRoom.value) { const result = await this.roomLocalRepository.update(findRoom.value.$id, { messages: [message] }) if(result.isErr()) { console.log('failed to update last message') } else { console.log('set last message') } } else if (message.receiverId) { // direct message and first message const findRoom = await this.roomLocalRepository.findOne({ receiverId: message.receiverId }) if(findRoom.isOk() && findRoom.value) { const result = await this.roomLocalRepository.update(findRoom.value.$id, { messages: [message] }) } } } }, 100) } }) } private loadHistory() { const regex = new RegExp("Room\\/([0-9a-fA-F]{8})-([0-9a-fA-F]{4})-([0-9a-fA-F]{4})-([0-9a-fA-F]{4})-([0-9a-fA-F]{12})\\/Messages"); return this.http.listen().pipe( filter((response: any)=> { return response?.isOk() && regex.test(response.value.url) && response.value.url.endsWith('/Messages') }), map((response: any) => response.value.data as IMessageGetAllByRoomIdOutPut) ).subscribe(async (data)=> { const loadHistoryFirstMessage = data.data[0] if(loadHistoryFirstMessage) { const roomId = loadHistoryFirstMessage.roomId const room = await this.roomLocalRepository.findOne({id: roomId}) if(room.isOk() && room.value) { const roomEntity = new RoomEntity(room.value) if(!roomEntity.hasLastMessage()) { await this.roomLocalRepository.update(loadHistoryFirstMessage.roomId, { messages: [loadHistoryFirstMessage] }) } else if (roomEntity.hasLastMessage()) { const localLastMessageDate = new Date(room.value.messages[0].sentAt).getTime() const loadHistoryLastMessageDate = new Date(loadHistoryFirstMessage.sentAt).getTime() if(loadHistoryFirstMessage.id == room.value.messages?.[0]?.id) { const { addedItems, changedItems, deletedItems } = messageListDetermineChanges([loadHistoryFirstMessage], room.value.messages); for (const message of changedItems) { const result = await this.roomLocalRepository.update(room.value.$id, { messages: [message] }) } // do nothing } else if(loadHistoryLastMessageDate>localLastMessageDate) { // await this.roomLocalRepository.update(loadHistoryFirstMessage.roomId, { // messages: [loadHistoryFirstMessage] // }) const result = await this.roomLocalRepository.update(room.value.$id, { messages: [loadHistoryFirstMessage] }) if(result.isErr()) { console.log('failed to update last message') } else { console.log('set last message') } } else if(loadHistoryLastMessageDate == localLastMessageDate) { // do nothing } else if(room.value.messages[0].isDeleted != loadHistoryFirstMessage.isDeleted) { // await this.roomLocalRepository.update(loadHistoryFirstMessage.roomId, { // messages: [loadHistoryFirstMessage] // }) const result = await this.roomLocalRepository.update(room.value.$id, { messages: [loadHistoryFirstMessage] }) if(result.isErr()) { console.log('failed to update last message') } else { console.log('set last message') } } } } else { console.log('cant find room locally') } } }) } }