diff --git a/src/app/core/chat/entity/message.ts b/src/app/core/chat/entity/message.ts index c5bd0d854..58827fccc 100644 --- a/src/app/core/chat/entity/message.ts +++ b/src/app/core/chat/entity/message.ts @@ -21,7 +21,7 @@ export enum IMessageType { export const MessageEntitySchema = z.object({ $id: z.any().optional(), - id: z.string().optional(), + id: z.string().uuid().optional(), roomId: z.string().uuid().optional(), receiverId: z.number().optional(), message: z.string().nullable().optional(), diff --git a/src/app/core/chat/repository/room/room-local-repository.ts b/src/app/core/chat/repository/room/room-local-repository.ts index 6d80479ec..b37bec155 100644 --- a/src/app/core/chat/repository/room/room-local-repository.ts +++ b/src/app/core/chat/repository/room/room-local-repository.ts @@ -8,5 +8,5 @@ import { Observable } from "rxjs"; export abstract class IRoomLocalRepository extends DexieRepository { abstract getItemsLive(): Observable - abstract getRoomByIdLive(id: any) : DexieObservable -} \ No newline at end of file + abstract getRoomByIdLive(id: any) : Observable +} diff --git a/src/app/infra/database/dexie/instance/chat/schema/message.ts b/src/app/infra/database/dexie/instance/chat/schema/message.ts index 20e2ec27a..345688444 100644 --- a/src/app/infra/database/dexie/instance/chat/schema/message.ts +++ b/src/app/infra/database/dexie/instance/chat/schema/message.ts @@ -4,7 +4,7 @@ import { z } from 'zod'; export const MessageTableSchema = z.object({ $id: z.number().optional(), - id: z.string().optional(), + id: z.string().uuid().optional(), roomId: z.string().uuid().optional(), message: z.string().nullable().optional(), messageType: z.number(), diff --git a/src/app/infra/http/http.service.ts b/src/app/infra/http/http.service.ts index 86eb448f0..c6c06967f 100644 --- a/src/app/infra/http/http.service.ts +++ b/src/app/infra/http/http.service.ts @@ -11,7 +11,7 @@ import { BehaviorSubject } from 'rxjs'; export class HttpService { private responseSubject = new BehaviorSubject, HttpErrorResponse>>(null); - + constructor(private http: HttpClient) { } async post(url: string, body: any): Promise, HttpErrorResponse>> { @@ -21,7 +21,8 @@ export class HttpService { data: response.body, status: response.status, headers: response.headers, - url: response.url || url + url: response.url || url, + method: '', } this.responseSubject.next(ok(data)) return ok(data); @@ -36,6 +37,7 @@ export class HttpService { const response = await this.http.get(url, { ...options, observe: 'response' }).toPromise(); const data = { + method: 'GET', data: response.body, status: response.status, headers: response.headers, @@ -58,7 +60,8 @@ export class HttpService { data: response.body, status: response.status, headers: response.headers, - url: response.url || url + url: response.url || url, + method: '', } this.responseSubject.next(ok(data)) @@ -77,7 +80,8 @@ export class HttpService { data: response.body, status: response.status, headers: response.headers, - url: response.url || url + url: response.url || url, + method: '', } this.responseSubject.next(ok(data)) @@ -101,7 +105,8 @@ export class HttpService { data: response?.body, status: response?.status, headers: response?.headers, - url: response?.url || url + url: response?.url || url, + method: '', } this.responseSubject.next(ok(data)) diff --git a/src/app/infra/http/type.ts b/src/app/infra/http/type.ts index 81d98edc4..072e888b4 100644 --- a/src/app/infra/http/type.ts +++ b/src/app/infra/http/type.ts @@ -10,4 +10,5 @@ export interface HttpResult { status: number; headers: HttpHeaders; url: string; + method: string } diff --git a/src/app/infra/socket/signalR/signalR.ts b/src/app/infra/socket/signalR/signalR.ts index ace273838..751a467d2 100644 --- a/src/app/infra/socket/signalR/signalR.ts +++ b/src/app/infra/socket/signalR/signalR.ts @@ -73,7 +73,7 @@ export class SignalRConnection { this.pendingRequests.forEach((_, requestId) => { const data = this.pendingRequests.get(requestId); - + if(data) { const { reject } = data reject(err({ @@ -81,7 +81,7 @@ export class SignalRConnection { })); this.pendingRequests.delete(requestId); } - + }); if(this.reconnect) { @@ -122,20 +122,19 @@ export class SignalRConnection { if(this.connectionStateSubject.value == true) { try { this.pendingRequests.set(input.data.requestId, { resolve, reject: (data: any) => resolve(data) }); - + this.hubConnection.invoke(input.method, input.data) this.sendDataSubject.pipe( filter((message) => { - console.log(message) return input.data.requestId == message?.data.requestId || - input.data.roomName == message?.data.roomName + input?.data?.roomName == message?.data.roomName && typeof input?.data?.roomName == 'string' }), first() ).subscribe(value => { resolve(ok(value.data as unknown as T)) - // console.log('Received valid value:', value); + console.log('Received valid value:', value); }); } catch(error) { @@ -154,7 +153,7 @@ export class SignalRConnection { } private addMessageListener(): void { - + const methods = ['ReceiveMessage', 'TypingMessage', 'AvailableUsers', 'ReadAt', 'DeleteMessage', 'UpdateMessage', 'GroupAddedMembers', 'GroupDeletedMembers', 'UserAddGroup'] @@ -191,7 +190,7 @@ export class SignalRConnection { this.connectionStateSubject.next(false); this.pendingRequests.forEach((_, requestId) => { const data = this.pendingRequests.get(requestId); - + if(data) { const { reject } = data reject(err({ @@ -199,7 +198,7 @@ export class SignalRConnection { })); this.pendingRequests.delete(requestId); } - + }); }) .catch(err => console.log('Error while closing connection: ' + err)); diff --git a/src/app/module/chat/data/repository/message/message-live-signalr-data-source.service.ts b/src/app/module/chat/data/repository/message/message-live-signalr-data-source.service.ts index c798d5597..df5c3e24a 100644 --- a/src/app/module/chat/data/repository/message/message-live-signalr-data-source.service.ts +++ b/src/app/module/chat/data/repository/message/message-live-signalr-data-source.service.ts @@ -49,6 +49,10 @@ export class MessageSocketRepositoryService implements IMessageSocketRepository data: data, }) + if(result.isOk()) { + console.log('recieve', result.value) + } + return result; } diff --git a/src/app/module/chat/data/repository/message/message-local-data-source.service.ts b/src/app/module/chat/data/repository/message/message-local-data-source.service.ts index f45862036..fd7a45bc6 100644 --- a/src/app/module/chat/data/repository/message/message-local-data-source.service.ts +++ b/src/app/module/chat/data/repository/message/message-local-data-source.service.ts @@ -6,6 +6,8 @@ import { Observable as DexieObservable, PromiseExtended } from 'Dexie'; import { MessageTable, MessageTableSchema } from 'src/app/infra/database/dexie/instance/chat/schema/message'; import { chatDatabase } from 'src/app/infra/database/dexie/service'; import { IMessageLocalRepository } from 'src/app/core/chat/repository/message/message-local-repository'; +import { combineLatest, from, Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; @Injectable({ providedIn: 'root' @@ -49,5 +51,25 @@ export class MessageLocalDataSourceService extends DexieRepository { + const observables = roomIds.map(roomId => + from (liveQuery(async() =>{ + const messages = await chatDatabase.message + .where('roomId') + .equals(roomId) + .reverse() + .sortBy('timestamp') + + return messages[0] || null; // Return the first item (latest message) or null if no message + })).pipe( + map((message) => ({ roomId, message: message || null })) // Attach roomId to the result + ) + ); + + return combineLatest(observables); // Combine all observables into one array of results + } } diff --git a/src/app/module/chat/data/repository/room/room-local-repository.service.ts b/src/app/module/chat/data/repository/room/room-local-repository.service.ts index 9abf60e7e..787b9d422 100644 --- a/src/app/module/chat/data/repository/room/room-local-repository.service.ts +++ b/src/app/module/chat/data/repository/room/room-local-repository.service.ts @@ -20,7 +20,7 @@ export class RoomLocalRepository extends DexieRepository i } getRoomByIdLive(id: any) { - return liveQuery(() => chatDatabase.room.get(id)); + return from(liveQuery(() => chatDatabase.room.get(id))); } } diff --git a/src/app/module/chat/data/repository/room/room-remote-repository.service.ts b/src/app/module/chat/data/repository/room/room-remote-repository.service.ts index d3ffcbac9..1110bc5c5 100644 --- a/src/app/module/chat/data/repository/room/room-remote-repository.service.ts +++ b/src/app/module/chat/data/repository/room/room-remote-repository.service.ts @@ -12,6 +12,7 @@ import { RoomByIdOutputDTO } from 'src/app/module/chat/domain/use-case/room/room import { RoomUpdateInputDTO, RoomUpdateOutputDTO } from 'src/app/module/chat/domain/use-case/room/room-update-by-id-use-case.service'; import { RoomListOutPutDTO } from '../../../domain/use-case/room/room-get-list-use-case.service'; import { z } from 'zod'; +import { HttpAdapter } from 'src/app/infra/http/adapter'; const RoomByIdInputDTOSchema = z.string() type RoomByIdInputDTO = z.infer @@ -27,6 +28,7 @@ export class RoomRemoteDataSourceService implements IRoomRemoteRepository { constructor( private httpService: HttpService, private socket: SignalRService, + private Http: HttpAdapter ) {} @@ -39,13 +41,17 @@ export class RoomRemoteDataSourceService implements IRoomRemoteRepository { //@APIReturn(RoomListOutPutDTOSchema, 'get/Room') async getRoomList(): Promise> { - return await this.httpService.get(`${this.baseUrl}/Room?userId=${SessionStore.user.UserId}`); + const result = await this.Http.get(`${this.baseUrl}/Room?userId=${SessionStore.user.UserId}`); + + return result.map((e)=> e.data) } //@ValidateSchema(RoomByIdInputDTOSchema) //@APIReturn(RoomByIdOutputDTOSchema,'get/Room/${id}') async getRoom(id: RoomByIdInputDTO): DataSourceReturn { - return await this.httpService.get(`${this.baseUrl}/Room/${id}`); + const result = await this.Http.get(`${this.baseUrl}/Room/${id}`); + + return result.map((e)=> e.data) } //@ValidateSchema(RoomUpdateInputDTOSchema) diff --git a/src/app/module/chat/data/repository/typing/user-typing-live-data-source.service.ts b/src/app/module/chat/data/repository/typing/user-typing-live-data-source.service.ts index 85f372c5b..04eec867a 100644 --- a/src/app/module/chat/data/repository/typing/user-typing-live-data-source.service.ts +++ b/src/app/module/chat/data/repository/typing/user-typing-live-data-source.service.ts @@ -5,6 +5,8 @@ import { filter, map } from 'rxjs/operators'; import { SocketMessage } from 'src/app/infra/socket/signalR/signalR'; import { ITypingRemoteRepository } from 'src/app/core/chat/repository/typing/typing-remote-repository'; import { z } from "zod" +import { InstanceId } from '../../../domain/chat-service.service'; +import { v4 as uuidv4 } from 'uuid' export const UserTypingDTOSchema = z.object({ requestId: z.string(), @@ -29,10 +31,10 @@ export class UserTypingRemoteRepositoryService implements ITypingRemoteRepositor return this.socket.sendData({ method: 'Typing', data: { - roomId, + roomId, UserName:SessionStore.user.FullName, userId:SessionStore.user.UserId, - requestId: '', + requestId: InstanceId +'@'+ uuidv4(), }, }) } diff --git a/src/app/module/chat/domain/chat-service.service.ts b/src/app/module/chat/domain/chat-service.service.ts index 57baaf8cc..39c8d7357 100644 --- a/src/app/module/chat/domain/chat-service.service.ts +++ b/src/app/module/chat/domain/chat-service.service.ts @@ -38,7 +38,8 @@ import { HttpListenToMessageLoadHistoryAdapter } from './adapter' import { HttpListenToMessageLoadHistoryUseCaseInput } from 'src/app/core/chat/usecase/message/http-listen-to-message-load-history-by-roomId-use-case'; import { MessageSocketRepositoryService } from 'src/app/module/chat/data/repository/message/message-live-signalr-data-source.service' import { MessageMarkAsReadInput } from "src/app/module/chat/domain/use-case/message/message-mark-as-read-use-case.service"; -import { BoldRemoveByRoomIdInput, BoldRemoveByRoomIdService } from 'src/app/module/chat/domain/use-case/bold/bold-remove-by-room-id.service' +import { BoldRemoveByRoomIdInput, BoldRemoveByRoomIdService } from 'src/app/module/chat/domain/use-case/bold/bold-remove-by-room-id.service'; +import { MemberListHttpSyncUseCase } from 'src/app/module/chat/domain/use-case/member/member-list-http-sync-use-case.ts.service' export const InstanceId = uuidv4(); @Injectable({ @@ -78,7 +79,8 @@ export class ChatServiceService { private MessageMarkAllMessageAsReadByRoomIdService: MessageMarkAllMessageAsReadByRoomIdService, private HttpListenToMessageLoadHistory: HttpListenToMessageLoadHistoryAdapter, private MessageSocketRepositoryService: MessageSocketRepositoryService, - private BoldRemoveByRoomIdService: BoldRemoveByRoomIdService + private BoldRemoveByRoomIdService: BoldRemoveByRoomIdService, + private MemberListHttpSyncUseCase: MemberListHttpSyncUseCase ) { this.MessageSocketRepositoryService.listenToDeleteMessages() .pipe() diff --git a/src/app/module/chat/domain/service/room-last-message.service.ts b/src/app/module/chat/domain/service/room-last-message.service.ts index e26526bde..ae7a13cfb 100644 --- a/src/app/module/chat/domain/service/room-last-message.service.ts +++ b/src/app/module/chat/domain/service/room-last-message.service.ts @@ -13,11 +13,10 @@ export class RoomLastMessageService { constructor( private MessageSocketRepositoryService: IMessageSocketRepository, private roomLocalRepository: IRoomLocalRepository - ) { + ) { this.listenToIncomingMessage() } - listenToIncomingMessage() { return this.MessageSocketRepositoryService.listenToMessages().pipe( filter((message) => !message?.requestId?.startsWith(InstanceId)), @@ -26,7 +25,7 @@ export class RoomLastMessageService { this.roomLocalRepository.update(message.roomId, { messages: [message] }) - + }); } diff --git a/src/app/module/chat/domain/use-case/member/member-list-http-sync-use-case.ts.service.ts b/src/app/module/chat/domain/use-case/member/member-list-http-sync-use-case.ts.service.ts new file mode 100644 index 000000000..52a061156 --- /dev/null +++ b/src/app/module/chat/domain/use-case/member/member-list-http-sync-use-case.ts.service.ts @@ -0,0 +1,61 @@ +import { Injectable } from '@angular/core'; +import { filter, map } from 'rxjs/operators'; +import { HttpAdapter } from 'src/app/infra/http/adapter'; +import { RoomByIdOutputDTO } from '../../../domain/use-case/room/room-get-by-id-use-case.service'; +import { IMemberLocalRepository } from 'src/app/core/chat/repository/member/member-local-repository'; +import { MemberListMapper } from '../../../domain/mapper/memberLIstMapper'; +import { roomMemberListDetermineChanges } from '../../../data/async/list/rooms/roomMembersChangeDetector'; +@Injectable({ + providedIn: 'root' +}) +export class MemberListHttpSyncUseCase { + + constructor( + private http: HttpAdapter, + private memberLocalRepository: IMemberLocalRepository + ) { + + // this.http.listen().pipe( + // filter((response)=> { + // if(response?.isOk()) { + // return response.value.url.includes('/Room/') && typeof response.value?.data?.data?.roomName == 'string' + // } + + // return false + // }), + // map((response: any) => response.value.data as RoomByIdOutputDTO) + // ) + // .subscribe(async (data) => { + + // this.syncMembers(data) + // }) + } + + private async syncMembers(roomData: RoomByIdOutputDTO): Promise { + const roomId = roomData.data.id; + + // Fetch local members and determine changes + const localList = await this.memberLocalRepository.getRoomMemberById(roomId); + const { membersToInsert, membersToUpdate, membersToDelete } = roomMemberListDetermineChanges(roomData.data.members, localList, roomId); + + // Sync members + // for (const user of membersToInsert) { + // await this.memberLocalRepository.addMember(MemberListMapper(user, roomId)); + // } + // for (const user of membersToUpdate) { + // await this.memberLocalRepository.updateMemberRole(MemberListMapper(user, roomId)); + // } + // for (const user of membersToDelete) { + // await this.memberLocalRepository.removeMemberFromRoom(user.$roomIdUserId); + // } + + // console.log({membersToInsert, membersToUpdate, membersToDelete}) + + await Promise.all([ + ...membersToInsert.map(user => this.memberLocalRepository.addMember(MemberListMapper(user, roomId))), + ...membersToUpdate.map(user => this.memberLocalRepository.updateMemberRole(MemberListMapper(user, roomId))), + ...membersToDelete.map(user => this.memberLocalRepository.removeMemberFromRoom(user.$roomIdUserId)) + ]); + + } +} diff --git a/src/app/module/chat/domain/use-case/message/message-create-use-case.service.ts b/src/app/module/chat/domain/use-case/message/message-create-use-case.service.ts index eea173cdf..58ecad23f 100644 --- a/src/app/module/chat/domain/use-case/message/message-create-use-case.service.ts +++ b/src/app/module/chat/domain/use-case/message/message-create-use-case.service.ts @@ -161,6 +161,8 @@ export class MessageCreateUseCaseService { if(sendMessageResult.isOk()) { + console.log('sendMessageResult', sendMessageResult.value.id) + if(sendMessageResult.value.sender == undefined || sendMessageResult.value.sender == null) { delete sendMessageResult.value.sender @@ -172,7 +174,15 @@ export class MessageCreateUseCaseService { $id : message.$id } - this.messageLocalDataSourceService.update(message.$id, {...clone, sending: false, roomId: message.roomId}) + this.messageLocalDataSourceService.update(message.$id, {...clone, sending: false, roomId: message.roomId}).then((data)=> { + if(data.isOk()) { + + } else { + tracing.hasError('failed to update send message') + console.log(sendMessageResult) + console.log(data.error) + } + }) return sendMessageResult } else { diff --git a/src/app/module/chat/domain/use-case/room/room-create-use-case.service.ts b/src/app/module/chat/domain/use-case/room/room-create-use-case.service.ts index 37163c1a5..7094bcc03 100644 --- a/src/app/module/chat/domain/use-case/room/room-create-use-case.service.ts +++ b/src/app/module/chat/domain/use-case/room/room-create-use-case.service.ts @@ -48,24 +48,10 @@ export class CreateRoomUseCaseService { console.log('history', result) // const result = await this.roomRemoteDataSourceService.createRoom(data) - + if(result.isOk()) { - console.log('create rooms',result.value) - if(!result?.value?.createdBy) { - - let dataObject; - - result.value.createdBy = { - wxeMail: SessionStore.user.Email, - wxFullName: SessionStore.user.FullName, - wxUserId: SessionStore.user.UserId, - } - dataObject = result.value - } - - const localResult = await this.roomLocalDataSourceService.insert(result.value) - return localResult.map(e => result.value) + return result } else { tracing.hasError("socket close"); console.log(result.error) diff --git a/src/app/module/chat/domain/use-case/room/room-get-by-id-use-case.service.ts b/src/app/module/chat/domain/use-case/room/room-get-by-id-use-case.service.ts index 7bd4fde67..89f2f9efe 100644 --- a/src/app/module/chat/domain/use-case/room/room-get-by-id-use-case.service.ts +++ b/src/app/module/chat/domain/use-case/room/room-get-by-id-use-case.service.ts @@ -1,9 +1,5 @@ import { Injectable } from '@angular/core'; -import { id } from 'date-fns/locale'; import { isHttpResponse } from 'src/app/services/http.service'; -import { roomListDetermineChanges } from '../../../data/async/list/rooms/roomListChangeDetector'; -import { roomMemberListDetermineChanges } from '../../../data/async/list/rooms/roomMembersChangeDetector'; -import { MemberListMapper } from '../../mapper/memberLIstMapper'; import { captureAndReraiseAsync } from 'src/app/services/decorators/captureAndReraiseAsync'; import { z } from 'zod'; import { IRoomRemoteRepository } from 'src/app/core/chat/repository/room/room-remote-repository'; @@ -11,8 +7,6 @@ import { IMemberLocalRepository } from 'src/app/core/chat/repository/member/memb import { IRoomLocalRepository } from 'src/app/core/chat/repository/room/room-local-repository'; import { GetRoomByIdMapper } from 'src/app/core/chat/mapper/getRoomByIdMapper'; import { RoomEntity, RoomType } from 'src/app/core/chat/entity/group'; -import { GetRoomListMapper } from 'src/app/core/chat/mapper/getRoomListMapper'; -import { roomByIdDetermineChanges } from '../../../data/async/list/rooms/roomByIdChangeDetector'; import { diff, addedDiff, deletedDiff, updatedDiff, detailedDiff } from 'deep-object-diff'; import { zodSafeValidation } from 'src/app/utils/zodValidation'; @@ -66,63 +60,46 @@ export class GetRoomByIdUseCaseService { @captureAndReraiseAsync('RoomRepositoryService/getRoomById') async execute(id: RoomByIdInputDTO) { const result = await this.roomRemoteDataSourceService.getRoom(id) - + if(result.isOk()) { const validData = zodSafeValidation(RoomByIdOutputDTOSchema, result.value) if(validData.isOk()) { const localListRoom = await this.roomLocalDataSourceService.findAll() if(localListRoom.isOk()) { - + const getRoomById = await this.roomLocalDataSourceService.findOne({id:validData.value.data.id}) if(getRoomById.isOk() && getRoomById.value) { console.log(validData.value) const room = GetRoomByIdMapper.toDomain(validData.value) - + const added: Partial = addedDiff(getRoomById.value, room); const deleted: Partial = deletedDiff(getRoomById.value, room); const updated: Partial = updatedDiff(getRoomById.value, room); - + delete added.members if(room.roomType == RoomType.Direct) { delete updated.roomName } - + if(Object.keys(added).length >= 1 || Object.keys(updated).length >= 1) { console.log('added', added); console.log('deleted', deleted); console.log('updated', updated); this.roomLocalDataSourceService.update(room.id, room) } - + } else if (getRoomById.isOk() && !getRoomById.value) { console.log(validData.value) const room = GetRoomByIdMapper.toDomain(validData.value) this.roomLocalDataSourceService.insert(room) } - - - // ============================ - const localList = await this.MemberListLocalRepository.getRoomMemberById(id) - - const { membersToInsert, membersToUpdate, membersToDelete } = roomMemberListDetermineChanges(validData.value.data.members, localList, id) - - for (const user of membersToInsert) { - await this.MemberListLocalRepository.addMember(MemberListMapper(user, id)) - } - - for (const user of membersToUpdate) { - await this.MemberListLocalRepository.updateMemberRole(MemberListMapper(user, id)) - } - - for(const user of membersToDelete) { - await this.MemberListLocalRepository.removeMemberFromRoom(user.$roomIdUserId) - } + } } else { } - + } else if (isHttpResponse(result.error) ) { @@ -134,4 +111,4 @@ export class GetRoomByIdUseCaseService { return result } -} \ No newline at end of file +} diff --git a/src/app/module/chat/domain/use-case/room/room-set-last-message.service.spec.ts b/src/app/module/chat/domain/use-case/room/room-set-last-message.service.spec.ts new file mode 100644 index 000000000..8f9271d5a --- /dev/null +++ b/src/app/module/chat/domain/use-case/room/room-set-last-message.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { RoomSetLastMessageService } from './room-set-last-message.service'; + +describe('RoomSetLastMessageService', () => { + let service: RoomSetLastMessageService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(RoomSetLastMessageService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/module/chat/domain/use-case/room/room-set-last-message.service.ts b/src/app/module/chat/domain/use-case/room/room-set-last-message.service.ts new file mode 100644 index 000000000..b96658bf9 --- /dev/null +++ b/src/app/module/chat/domain/use-case/room/room-set-last-message.service.ts @@ -0,0 +1,36 @@ +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 } from 'rxjs/operators'; +import { InstanceId } from '../../chat-service.service'; +import { MessageEntity } from 'src/app/core/chat/entity/message'; + +@Injectable({ + providedIn: 'root' +}) +export class RoomSetLastMessageService { + + constructor( + private MessageSocketRepositoryService: IMessageSocketRepository, + private roomLocalRepository: IRoomLocalRepository + ) { + // this.listenToIncomingMessage() + } + + listenToIncomingMessage() { + return this.MessageSocketRepositoryService.listenToMessages().pipe( + filter((message) => !message?.requestId?.startsWith(InstanceId)), + map(message => Object.assign(new MessageEntity(), message)) + ).subscribe(async (message) => { + this.roomLocalRepository.update(message.roomId, { + messages: [message] + }) + + }); + + } + + listenToOnSendDataToSocket() { + + } +} diff --git a/src/app/ui/chat/chat-routing.module.ts b/src/app/ui/chat/chat-routing.module.ts index f36c1ab6a..9da4a7c8f 100644 --- a/src/app/ui/chat/chat-routing.module.ts +++ b/src/app/ui/chat/chat-routing.module.ts @@ -36,10 +36,6 @@ const routes: Routes = [ path: 'chat-message-debugging', loadChildren: () => import('./modal/chat-message-debugging/chat-message-debugging.module').then( m => m.ChatMessageDebuggingPageModule) }, - { - path: 'add-user', - loadChildren: () => import('./component/add-user/add-user.module').then( m => m.AddUserPageModule) - }, { path: 'empty-chat', loadChildren: () => import('./component/empty-chat/empty-chat.module').then( m => m.EmptyChatPageModule) diff --git a/src/app/ui/chat/chat.page.html b/src/app/ui/chat/chat.page.html index 93c0b4073..8a1653fe9 100644 --- a/src/app/ui/chat/chat.page.html +++ b/src/app/ui/chat/chat.page.html @@ -39,94 +39,60 @@ + + +
+
+
+
+ + + + + + + + +
+
+
+
+ + +
+
+ {{room.roomName}} +
+
+
+
+
+
+ {{ room.displayDate }} +
+
+
+ + {{ expirationDate[room.id] !== null ? expirationDate[room.id] + ' seconds left' : '' }} +
+
+
{{room.messages[0].message}}
+ + +
+
+
+
+
- - -
-
- - - - - -
-
-
-
- - -
-
- {{room.roomName}} -
-
-
-
-
-
- {{ room.displayDate }} -
-
-
- - {{ expirationDate[room.id] !== null ? expirationDate[room.id] + ' seconds left' : '' }} -
-
-
{{room.messages[0].message}}
- - -
-
-
-
-
- - -
-
- - -
-
-
-
- - -
-
- {{room.roomName}} -
-
-
-
-
-
- {{ room.displayDate }} -
- -
-
- - {{ expirationDate[room.id] !== null ? expirationDate[room.id] + ' seconds left' : '' }} -
-
-
{{room?.messages?.[0]?.message}}
- - -
-
-
-
-
+
@@ -142,6 +108,7 @@ ; //items$!: DexieObservable; items$!: Observable; - private rooms: RoomTable[] = []; + rooms: RoomViewModel[] = []; private subscription: Subscription; expirationDate = {} private intervalSubscription: Subscription; @@ -67,6 +68,11 @@ export class ChatPage implements OnInit { RoomType = RoomType boldTable: {[key: string]: BoldTable} = {} + private roomListSubject = new BehaviorSubject<{ id: string, name: string }[]>([]); + roomsWithLastMessages: { name: string, lastMessage: any }[] = []; + private subscription1: Subscription; + + RoomSelected!: RoomViewModel; constructor( private modalController: ModalController, @@ -77,7 +83,8 @@ export class ChatPage implements OnInit { public RouteService: RouteService, private ChatServiceService: ChatServiceService, private roomLocalDataSourceService: RoomLocalRepository, - private boldLocalRepository: BoldLocalRepository + private boldLocalRepository: BoldLocalRepository, + private MessageLocalDataSourceService: MessageLocalDataSourceService ) { window.onresize = (event) => { @@ -100,20 +107,61 @@ export class ChatPage implements OnInit { } + + // Method to update the room list + // updateRoomList(newRoomList: { id: string, name: string }[]): void { + // this.roomListSubject.next(newRoomList); + // } // Fetch all items using useLiveQuery - ngOnInit() { - this.items$ = this.roomLocalDataSourceService.getItemsLive().pipe( + updatemessage(sortedRooms) { + this.rooms = sortedRooms + + this.rooms.sort((a, b) => + new Date(b.messages?.[0]?.sentAt as string).getTime() - + new Date(a.messages?.[0]?.sentAt as string).getTime() + ); + this.RoomSelected = this.rooms.filter(e => e.id == this.idSelected)[0] + + + } + ngOnInit() { + // this.subscription = this.roomListSubject.pipe( + // switchMap(roomList => + // this.MessageLocalDataSourceService.getLastMessageForRooms(roomList.map(room => room.id)) + // ) + // ).subscribe(lastMessages => { + // this.roomsWithLastMessages = this.roomListSubject.value.map(room => ({ + // name: room.name, + // lastMessage: lastMessages.find(msg => msg.roomId === room.id)?.message || null + // })); + // this.roomsWithLastMessages.sort((a, b) => + // new Date(b.lastMessage.messages?.[0]?.sentAt as unknown as string) as unknown as number - + // (new Date(a.lastMessage.messages?.[0]?.sentAt as unknown as string) as any) as unknown as number + // ) + // }); + + // // Initialize room list (can be loaded from a service, API, etc.) + // this.roomListSubject.next([ + // { id: '1135e73c-af8e-416c-a51f-1602b4770cf7', name: 'Room 1' } + // // Add more rooms as needed + // ]); + + this.roomLocalDataSourceService.getItemsLive().pipe( map((roomList) => roomList.map((room)=> new RoomViewModel(room))), tap((roomList) => { - this.rooms = roomList.sort((a, b) => - - new Date(b.messages?.[0]?.sentAt as unknown as string) as unknown as number - - (new Date(a.messages?.[0]?.sentAt as unknown as string) as any) as unknown as number - ) + + roomList.sort((a, b) => + new Date(b.messages?.[0]?.sentAt as string).getTime() - + new Date(a.messages?.[0]?.sentAt as string).getTime() + ); + + console.log('update') + + this.updatemessage(roomList) }) - ); + ).subscribe() // Create the interval observable const interval$ = interval(1000).pipe( @@ -286,9 +334,10 @@ export class ChatPage implements OnInit { this.idSelected = ''; this.showEmptyComponent = true; } - openGroupContactsPage(data) { + openGroupContactsPage(roomId) { this.idSelected = ''; - this.groupRoomId = data; + this.groupRoomId = roomId; + this.RoomSelected = this.rooms.filter(e => e.id == roomId)[0] this.closeAllDesktopComponents(); if (window.innerWidth < 701) { @@ -299,15 +348,16 @@ export class ChatPage implements OnInit { } - openMessagesPage(rid) { + openMessagesPage(roomId) { // this.chatService.refreshtoken(); - this.roomId = rid; + this.roomId = roomId; + this.RoomSelected = this.rooms.filter(e => e.id == roomId)[0] if (window.innerWidth < 701) { - this.openMessagesModal(rid); + this.openMessagesModal(roomId); } else { - this.idSelected = rid; + this.idSelected = roomId; this.closeAllDesktopComponents(); this.showEmptyComponent = false; this.showMessages = true; @@ -351,23 +401,6 @@ export class ChatPage implements OnInit { } } - openGroupMessagesPage(rid) { - - this.roomId = rid; - if (window.innerWidth < 701) { - this.openGroupMessagesModal(rid); - } - else { - this.idSelected = rid; - this.closeAllDesktopComponents(); - this.showEmptyComponent = false; - - - this.showMessages = true; - } - } - - doRefresh(event) { setTimeout(() => { try { diff --git a/src/app/ui/chat/component/add-user/add-user-routing.module.ts b/src/app/ui/chat/component/add-user/add-user-routing.module.ts deleted file mode 100644 index 49bc8b4fe..000000000 --- a/src/app/ui/chat/component/add-user/add-user-routing.module.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { NgModule } from '@angular/core'; -import { Routes, RouterModule } from '@angular/router'; - -import { AddUserPage } from './add-user.page'; - -const routes: Routes = [ - { - path: '', - component: AddUserPage - } -]; - -@NgModule({ - imports: [RouterModule.forChild(routes)], - exports: [RouterModule], -}) -export class AddUserPageRoutingModule {} diff --git a/src/app/ui/chat/component/add-user/add-user.module.ts b/src/app/ui/chat/component/add-user/add-user.module.ts deleted file mode 100644 index 78b0aaeca..000000000 --- a/src/app/ui/chat/component/add-user/add-user.module.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { FormsModule } from '@angular/forms'; - -import { IonicModule } from '@ionic/angular'; - -import { AddUserPageRoutingModule } from './add-user-routing.module'; - -import { AddUserPage } from './add-user.page'; - -@NgModule({ - imports: [ - CommonModule, - FormsModule, - IonicModule, - AddUserPageRoutingModule - ], - declarations: [AddUserPage] -}) -export class AddUserPageModule {} diff --git a/src/app/ui/chat/component/add-user/add-user.page.html b/src/app/ui/chat/component/add-user/add-user.page.html deleted file mode 100644 index c4bb0ea98..000000000 --- a/src/app/ui/chat/component/add-user/add-user.page.html +++ /dev/null @@ -1,9 +0,0 @@ - - - addUser - - - - - - diff --git a/src/app/ui/chat/component/add-user/add-user.page.scss b/src/app/ui/chat/component/add-user/add-user.page.scss deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/app/ui/chat/component/add-user/add-user.page.spec.ts b/src/app/ui/chat/component/add-user/add-user.page.spec.ts deleted file mode 100644 index 382032742..000000000 --- a/src/app/ui/chat/component/add-user/add-user.page.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; -import { IonicModule } from '@ionic/angular'; - -import { AddUserPage } from './add-user.page'; - -describe('AddUserPage', () => { - let component: AddUserPage; - let fixture: ComponentFixture; - - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule({ - declarations: [ AddUserPage ], - imports: [IonicModule.forRoot()] - }).compileComponents(); - - fixture = TestBed.createComponent(AddUserPage); - component = fixture.componentInstance; - fixture.detectChanges(); - })); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/src/app/ui/chat/component/add-user/add-user.page.ts b/src/app/ui/chat/component/add-user/add-user.page.ts deleted file mode 100644 index e35b74795..000000000 --- a/src/app/ui/chat/component/add-user/add-user.page.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Component, OnInit } from '@angular/core'; - -@Component({ - selector: 'app-add-user', - templateUrl: './add-user.page.html', - styleUrls: ['./add-user.page.scss'], -}) -export class AddUserPage implements OnInit { - - constructor() { } - - ngOnInit() { - } - -} diff --git a/src/app/ui/chat/component/messages/messages.page.html b/src/app/ui/chat/component/messages/messages.page.html index 015cdbff9..4afcac668 100644 --- a/src/app/ui/chat/component/messages/messages.page.html +++ b/src/app/ui/chat/component/messages/messages.page.html @@ -3,12 +3,12 @@
- {{ roomData.roomName }} + {{ room.roomName }}
-