From ea4ca5c34c62ab602b2e9302767e7af5119fa34f Mon Sep 17 00:00:00 2001 From: Peter Maquiran Date: Wed, 14 Aug 2024 15:29:16 +0100 Subject: [PATCH] fix chat --- .../dexie/dexie-repository.service.ts | 20 ++-- src/app/module/chat/chat.module.ts | 6 +- .../list/rooms/messageListChangedetector.ts | 2 + .../room/rooom-local-data-source.service.ts | 13 +-- .../chat/data/dto/message/messageInputDtO.ts | 2 +- .../chat/data/dto/message/messageOutputDTO.ts | 2 +- .../repository/message-respository.service.ts | 8 +- .../repository/room-repository.service.ts | 17 ++- .../chat/domain/chat-service.service.ts | 8 +- .../message-create-use-case.service.ts | 22 ++-- .../message-update-use-case.service.ts | 2 +- .../sync-all-room-messages.service.ts | 29 +++++ .../chat/infra/database/dexie/schema/room.ts | 2 +- .../infra/database/dexie/schema/typing.ts | 2 +- .../chat/infra/database/dexie/service.ts | 10 +- .../pages/chat/messages/messages.page.html | 4 +- src/app/pages/chat/messages/messages.page.ts | 109 +++++++++++++++++- src/app/pages/login/login.page.ts | 13 ++- src/app/shared/chat/messages/messages.page.ts | 79 ++++++++++--- 19 files changed, 270 insertions(+), 80 deletions(-) create mode 100644 src/app/module/chat/domain/use-case/sync-all-room-messages.service.ts diff --git a/src/app/infra/repository/dexie/dexie-repository.service.ts b/src/app/infra/repository/dexie/dexie-repository.service.ts index 6fa47ee3b..5a97c8fcb 100644 --- a/src/app/infra/repository/dexie/dexie-repository.service.ts +++ b/src/app/infra/repository/dexie/dexie-repository.service.ts @@ -14,20 +14,20 @@ export class DexieRepository { constructor(table: EntityTable, ZodSchema: ZodSchema) { this.table = table as any this.ZodSchema = ZodSchema - this.ZodPartialSchema = (ZodSchema as ZodObject).partial() as any; + this.ZodPartialSchema = (ZodSchema as ZodObject).partial() as any; } async insert(document: T): Promise> { - - const dataValidation = this.ZodSchema.safeParse(document) - if(dataValidation.success) { + const dataValidation = this.ZodSchema.safeParse(document) + + if(dataValidation.success) { try { const id = await this.table.add(dataValidation.data); return ok(id); } catch (error) { return err(new Error('Failed to insert document: ' + error.message)); - } + } } else { return err((dataValidation as unknown as ZodError)) } @@ -52,7 +52,7 @@ export class DexieRepository { async update(id: any, updatedDocument: Partial) { - const dataValidation = this.ZodPartialSchema.safeParse(document) + const dataValidation = this.ZodPartialSchema.safeParse(updatedDocument) if(dataValidation.success) { try { @@ -84,9 +84,10 @@ export class DexieRepository { } } - async find(filter: Object) { + async find(filter: Object): Promise> { try { - const documents = await this.table.where(filter).toArray(); + const documents: any = await this.table.where(filter).toArray(); + console.log('documents', {documents}) return ok(documents); } catch (error) { return err(new Error('Failed to find documents: ' + error.message)); @@ -104,7 +105,8 @@ export class DexieRepository { async findAll(): Promise> { try { - const documents = await this.table.toArray(); + console.log(this.table) + const documents = await this.table.toArray() return ok(documents); } catch (error) { return err(new Error('Failed to retrieve all documents: ' + error.message)); diff --git a/src/app/module/chat/chat.module.ts b/src/app/module/chat/chat.module.ts index a7e102d06..2562f3f0d 100644 --- a/src/app/module/chat/chat.module.ts +++ b/src/app/module/chat/chat.module.ts @@ -2,6 +2,7 @@ import { NgModule } from '@angular/core'; import { SignalRService } from 'src/app/module/chat/infra/socket/signal-r.service' import { SyncMessageRepositoryService } from './data/service/sync-repository/sync-message-repository.service'; import { UserTypingAsyncService } from 'src/app/module/chat/data/async/socket/user-typing-async.service' +import { ChatServiceService } from 'src/app/module/chat/domain/chat-service.service' @NgModule({ imports: [ @@ -19,10 +20,10 @@ export class ChatModule { constructor( private message: SyncMessageRepositoryService, private SignalRService: SignalRService, - private UserTypingAsyncService: UserTypingAsyncService + private UserTypingAsyncService: UserTypingAsyncService, + private ChatServiceService: ChatServiceService ) { - this.triggerToSendOfflineMessages() } @@ -32,6 +33,7 @@ export class ChatModule { result.subscribe((value) => { if(value) { + this.ChatServiceService.asyncAllRoomMessage(); this.message.sendLocalMessages() } }) diff --git a/src/app/module/chat/data/async/list/rooms/messageListChangedetector.ts b/src/app/module/chat/data/async/list/rooms/messageListChangedetector.ts index 7712914f9..8fe22c622 100644 --- a/src/app/module/chat/data/async/list/rooms/messageListChangedetector.ts +++ b/src/app/module/chat/data/async/list/rooms/messageListChangedetector.ts @@ -1,6 +1,8 @@ import { RoomListItemOutPutDTO, RoomListOutPutDTO } from "../../../dto/room/roomListOutputDTO"; export function messageListDetermineChanges(serverList: any[], localList: any[]) { + + localList = localList.filter(e => e.id) // Convert lists to dictionaries for easier comparison const localDict = localList.reduce((acc, item) => { acc[item.id] = item; diff --git a/src/app/module/chat/data/data-source/room/rooom-local-data-source.service.ts b/src/app/module/chat/data/data-source/room/rooom-local-data-source.service.ts index 4fd0f6c8f..e492d5b36 100644 --- a/src/app/module/chat/data/data-source/room/rooom-local-data-source.service.ts +++ b/src/app/module/chat/data/data-source/room/rooom-local-data-source.service.ts @@ -8,20 +8,19 @@ import { MemberListUPdateStatusInputDTO } from '../../../domain/use-case/socket/ import { MemberTable } from '../../../infra/database/dexie/schema/members'; import { chatDatabase } from '../../../infra/database/dexie/service'; import { RoomTable, RoomTableSchema } from '../../../infra/database/dexie/schema/room'; +import { DexieRepository } from 'src/app/infra/repository/dexie/dexie-repository.service'; @Injectable({ providedIn: 'root' }) -export class RoomLocalDataSourceService { - - - constructor() {} - - - async removeUserTyping() { +export class RoomLocalDataSourceService extends DexieRepository { + constructor() { + super(chatDatabase.room, RoomTableSchema) } + async removeUserTyping() {} + @ValidateSchema(RoomTableSchema) async createRoom(data: RoomTable) { try { diff --git a/src/app/module/chat/data/dto/message/messageInputDtO.ts b/src/app/module/chat/data/dto/message/messageInputDtO.ts index f02eb1710..f52ac9377 100644 --- a/src/app/module/chat/data/dto/message/messageInputDtO.ts +++ b/src/app/module/chat/data/dto/message/messageInputDtO.ts @@ -4,7 +4,7 @@ import { MessageAttachmentFileType, MessageAttachmentSource } from "./messageOut export const MessageInputDTOSchema = z.object({ roomId: z.string().uuid(), senderId: z.number(), - message: z.string(), + message: z.string().nullable().optional(), messageType: z.number(), canEdit: z.boolean(), oneShot: z.boolean(), diff --git a/src/app/module/chat/data/dto/message/messageOutputDTO.ts b/src/app/module/chat/data/dto/message/messageOutputDTO.ts index 675bb821e..5cf63a55a 100644 --- a/src/app/module/chat/data/dto/message/messageOutputDTO.ts +++ b/src/app/module/chat/data/dto/message/messageOutputDTO.ts @@ -21,7 +21,7 @@ export const MessageOutPutDataDTOSchema = z.object({ wxeMail: z.string(), userPhoto: z.string().optional() }), - message: z.string().nullable(), + message: z.string().nullable().optional(), messageType: z.number(), sentAt: z.string(), canEdit: z.boolean(), diff --git a/src/app/module/chat/data/repository/message-respository.service.ts b/src/app/module/chat/data/repository/message-respository.service.ts index 742904faa..e584d107e 100644 --- a/src/app/module/chat/data/repository/message-respository.service.ts +++ b/src/app/module/chat/data/repository/message-respository.service.ts @@ -32,7 +32,7 @@ export class MessageRepositoryService { async createMessageLocally(entity: MessageEntity) { //const requestId = InstanceId +'@'+ uuidv4(); - + const localActionResult = await this.messageLocalDataSourceService.sendMessage(entity) return localActionResult.map(e => { @@ -112,8 +112,6 @@ export class MessageRepositoryService { const { addedItems, changedItems, deletedItems } = messageListDetermineChanges(result.value.data, localResult) - console.log({addedItems, changedItems}); - for(const message of changedItems) { let clone: MessageTable = message clone.roomId = id @@ -123,16 +121,16 @@ export class MessageRepositoryService { for(const message of addedItems) { let clone: MessageTable = message clone.roomId = id - } + this.messageLocalDataSourceService.createManyMessage(addedItems.reverse()) for(const message of deletedItems) { this.messageLocalDataSourceService.deleteByMessageId(message.id) } - + return ok(addedItems) } return result } diff --git a/src/app/module/chat/data/repository/room-repository.service.ts b/src/app/module/chat/data/repository/room-repository.service.ts index 58c5bb79a..5826fff2e 100644 --- a/src/app/module/chat/data/repository/room-repository.service.ts +++ b/src/app/module/chat/data/repository/room-repository.service.ts @@ -12,11 +12,9 @@ import { RoomUpdateInputDTO } from '../dto/room/roomUpdateInputDTO'; import { SessionStore } from 'src/app/store/session.service'; import { RoomLiveDataSourceService } from '../data-source/room/room-live-data-source.service'; import { isHttpResponse } from 'src/app/services/http.service'; -import { MessageLiveDataSourceService } from '../data-source/message/message-live-data-source.service'; import { MemberListUPdateStatusInputDTO } from '../../domain/use-case/socket/member-list-update-status-use-case.service'; import { MemberSetAdminDTO } from '../../domain/use-case/member-admin-use-case.service'; import { MemberListMapper } from '../../domain/mapper/memberLIstMapper'; -import { SignalRService } from '../../infra/socket/signal-r.service'; function date(isoDateString) { @@ -91,6 +89,11 @@ export class RoomRepositoryService { return result } + + async getRoomList() { + return await this.roomLocalDataSourceService.getRoomList() + } + @captureAndReraiseAsync('RoomRepositoryService/updateRoomBy') async updateRoomBy(data: RoomUpdateInputDTO) { @@ -293,4 +296,14 @@ export class RoomRepositoryService { getRoomMemberNoneAdminByIdLive(roomId) { return this.roomLocalDataSourceService.getRoomMemberNoneAdminByIdLive(roomId) } + + + get find() { + return this.roomLocalDataSourceService.find + } + + get findAll() { + return this.roomLocalDataSourceService.findAll + } + } diff --git a/src/app/module/chat/domain/chat-service.service.ts b/src/app/module/chat/domain/chat-service.service.ts index 584bac83d..2222633a4 100644 --- a/src/app/module/chat/domain/chat-service.service.ts +++ b/src/app/module/chat/domain/chat-service.service.ts @@ -13,6 +13,7 @@ import { ListenMessageByRoomIdNewUseCase } from 'src/app/module/chat/domain/use- import { MemberListUpdateStatusUseCaseService } from 'src/app/module/chat/domain/use-case/socket/member-list-update-status-use-case.service'; import { ListenMessageDeleteByRoomIdService } from './use-case/listene-message-delete-by-roomId.service'; import { ListenMessageUpdateByRoomIdUseCase } from './use-case/listen-message-update-by-roomId.service'; +import { SyncAllRoomMessagesService } from './use-case/sync-all-room-messages.service'; import { ListenSendMessageUseCase } from './use-case/listen-send-message.service' import { filter } from 'rxjs/operators'; import { v4 as uuidv4 } from 'uuid' @@ -42,7 +43,8 @@ export class ChatServiceService { private ListenMessageDeleteService: ListenMessageDeleteByRoomIdService, private ListenMessageUpdateByRoomIdUseCase: ListenMessageUpdateByRoomIdUseCase, private ListenSendMessageUseCase: ListenSendMessageUseCase, - private MessageAttachmentByMessageIdService: MessageAttachmentByMessageIdUseCase + private MessageAttachmentByMessageIdService: MessageAttachmentByMessageIdUseCase, + private SyncAllRoomMessagesService: SyncAllRoomMessagesService ) { this.messageLiveSignalRDataSourceService.getMessageDelete() .pipe() @@ -119,6 +121,10 @@ export class ChatServiceService { return this.MessageCreateUseCaseService.execute(input); } + asyncAllRoomMessage() { + return this.SyncAllRoomMessagesService.execute() + } + getMessageAttachmentByMessageId(input: MessageAttachmentByMessageIdInput) { return this.MessageAttachmentByMessageIdService.execute(input) } diff --git a/src/app/module/chat/domain/use-case/message-create-use-case.service.ts b/src/app/module/chat/domain/use-case/message-create-use-case.service.ts index 31f98b95c..cdb7fd2b9 100644 --- a/src/app/module/chat/domain/use-case/message-create-use-case.service.ts +++ b/src/app/module/chat/domain/use-case/message-create-use-case.service.ts @@ -37,34 +37,28 @@ export class MessageCreateUseCaseService { const createMessageLocally = await this.MessageRepositoryService.createMessageLocally(message) if(createMessageLocally.isOk()) { - + console.log('==========================',message); if(message.hasAttachment) { - + for (const attachment of message.attachments) { - + const createAttachmentLocally = this.AttachmentRepositoryService.create({ $messageId: createMessageLocally.value.$id, - file: createDataURL(attachment.file, attachment.mimeType) + file: createDataURL(attachment.file, attachment.mimeType) }) attachment.safeFile = createDataURL(attachment.file, attachment.mimeType) } - + } const sendToServer = await this.MessageRepositoryService.sendMessage(message) - // if(sendToServer.isOk()) { - // for (const attachment of message.attachments) { - - // const attachment = await this.AttachmentRepositoryService.findOne({ - // $messageId: createMessageLocally.value.$id - // }) - // } - - // } + if(!sendToServer.isOk()) { + console.log('sendToServer error', sendToServer.error) + } return sendToServer diff --git a/src/app/module/chat/domain/use-case/message-update-use-case.service.ts b/src/app/module/chat/domain/use-case/message-update-use-case.service.ts index c04e2b256..d88b9b0f1 100644 --- a/src/app/module/chat/domain/use-case/message-update-use-case.service.ts +++ b/src/app/module/chat/domain/use-case/message-update-use-case.service.ts @@ -7,7 +7,7 @@ const MessageUpdateInputDTOSchema = z.object({ memberId: z.number(), messageId: z.string(), roomId: z.string(), - message: z.string(), + message: z.string().optional().nullable(), requestId: z.string().optional() }) diff --git a/src/app/module/chat/domain/use-case/sync-all-room-messages.service.ts b/src/app/module/chat/domain/use-case/sync-all-room-messages.service.ts new file mode 100644 index 000000000..e94f0e628 --- /dev/null +++ b/src/app/module/chat/domain/use-case/sync-all-room-messages.service.ts @@ -0,0 +1,29 @@ +import { Injectable } from '@angular/core'; +import { RoomRepositoryService } from 'src/app/module/chat/data/repository/room-repository.service' +import { MessageRepositoryService } from 'src/app/module/chat/data/repository/message-respository.service' +import { RoomTable } from '../../infra/database/dexie/schema/room'; + +@Injectable({ + providedIn: 'root' +}) +export class SyncAllRoomMessagesService { + + constructor( + private RoomRepositoryService: RoomRepositoryService, + private MessageRepositoryService: MessageRepositoryService + ) { } + + async execute() { + + const allRooms: RoomTable[] = await this.RoomRepositoryService.getRoomList() + + if(allRooms) { + for(const room of allRooms) { + this.MessageRepositoryService.listAllMessagesByRoomId(room.id) + } + } else { + console.log('get all error', allRooms) + } + + } +} diff --git a/src/app/module/chat/infra/database/dexie/schema/room.ts b/src/app/module/chat/infra/database/dexie/schema/room.ts index e478dbe95..b06096101 100644 --- a/src/app/module/chat/infra/database/dexie/schema/room.ts +++ b/src/app/module/chat/infra/database/dexie/schema/room.ts @@ -15,5 +15,5 @@ export const RoomTableSchema = z.object({ }) export type RoomTable = z.infer -export type DexieRoomsTableSchema = EntityTable; +export type DexieRoomsTable = EntityTable; export const RoomTableColumn = 'id, createdBy, roomName, roomType, expirationDate, lastMessage' diff --git a/src/app/module/chat/infra/database/dexie/schema/typing.ts b/src/app/module/chat/infra/database/dexie/schema/typing.ts index 2cddf27f3..7f13af779 100644 --- a/src/app/module/chat/infra/database/dexie/schema/typing.ts +++ b/src/app/module/chat/infra/database/dexie/schema/typing.ts @@ -10,5 +10,5 @@ export const TypingTableSchema = z.object({ }) export type TypingTable = z.infer -export type DexieTypingsTableSchema = EntityTable; +export type DexieTypingsTable = EntityTable; export const TypingTableColumn = 'id, userId, userName, chatRoomId, entryDate' diff --git a/src/app/module/chat/infra/database/dexie/service.ts b/src/app/module/chat/infra/database/dexie/service.ts index 74dd783c0..1063c8c38 100644 --- a/src/app/module/chat/infra/database/dexie/service.ts +++ b/src/app/module/chat/infra/database/dexie/service.ts @@ -1,9 +1,9 @@ -import { Dexie, EntityTable, liveQuery } from 'Dexie'; +import { Dexie } from 'Dexie'; import { DexieMessageTable, messageTableColumn, MessageTable } from './schema/message'; import { DexieMembersTableSchema, MemberTableColumn } from './schema/members'; -import { DexieRoomsTableSchema, RoomTableColumn } from './schema/room'; -import { DexieTypingsTableSchema, TypingTableColumn } from './schema/typing'; +import { DexieRoomsTable, RoomTableColumn } from './schema/room'; +import { DexieTypingsTable, TypingTableColumn } from './schema/typing'; import { MessageEntity } from '../../../domain/entity/message'; import { AttachmentTable, AttachmentTableColumn, DexieAttachmentsTableSchema } from './schema/attachment'; // import DexieMemory from 'dexie-in-memory'; @@ -12,8 +12,8 @@ import { AttachmentTable, AttachmentTableColumn, DexieAttachmentsTableSchema } f export const chatDatabase = new Dexie('chat-database-infra') as Dexie & { message: DexieMessageTable, members: DexieMembersTableSchema, - room: DexieRoomsTableSchema, - typing: DexieTypingsTableSchema, + room: DexieRoomsTable, + typing: DexieTypingsTable, attachment: DexieAttachmentsTableSchema, }; diff --git a/src/app/pages/chat/messages/messages.page.html b/src/app/pages/chat/messages/messages.page.html index 4b47aa8ce..8306cecd4 100644 --- a/src/app/pages/chat/messages/messages.page.html +++ b/src/app/pages/chat/messages/messages.page.html @@ -47,7 +47,7 @@
@@ -62,7 +62,7 @@
- {{ attachment.fileName}} + {{ attachment.fileName }} diff --git a/src/app/pages/chat/messages/messages.page.ts b/src/app/pages/chat/messages/messages.page.ts index dbbb1cf36..683166f15 100644 --- a/src/app/pages/chat/messages/messages.page.ts +++ b/src/app/pages/chat/messages/messages.page.ts @@ -36,16 +36,14 @@ import { sanitize } from "sanitize-filename-ts"; import { FilePicker } from '@capawesome/capacitor-file-picker'; //====== 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'; -import { MessageInputDTO } from 'src/app/module/chat/data/dto/message/messageInputDtO'; import { RoomListItemOutPutDTO } from 'src/app/module/chat/data/dto/room/roomListOutputDTO'; import { UserTypingServiceRepository } from 'src/app/module/chat/data/repository/user-typing-repository.service'; import { ChatServiceService } from 'src/app/module/chat/domain/chat-service.service'; import { EditMessagePage } from 'src/app/modals/edit-message/edit-message.page'; -import { tap } from 'rxjs/operators'; import { MessageEntity } from 'src/app/module/chat/domain/entity/message'; import { MemberTable } from 'src/app/module/chat/infra/database/dexie/schema/members'; import { TypingTable } from 'src/app/module/chat/infra/database/dexie/schema/typing'; @@ -54,7 +52,6 @@ import { MessageAttachmentFileType, MessageAttachmentSource } from 'src/app/modu import { compressImageBase64 } from 'src/app/utils/imageCompressore'; import { FilePickerService } from 'src/app/infra/file-picker/file-picker.service' import { FilePickerMobileService } from 'src/app/infra/file-picker/mobile/file-picker-mobile.service' -import { AttachmentsPageRoutingModule } from '../../events/attachments/attachments-routing.module'; const IMAGE_DIR = 'stored-images'; @@ -132,6 +129,13 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy { emojis: string[] = ['😊', '😂', '❤️', '👍', '😢']; // Add more emojis as needed textField = '' + + messageReceiveSubject: Subscription + messageDeleteSubject: Subscription + messageUpdateSubject: Subscription + messageSendSubject: Subscription + messages1: {[key: string]: MessageEntity[]} = {} + constructor( public popoverController: PopoverController, private modalController: ModalController, @@ -168,8 +172,13 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy { this.roomData$ = this.roomRepositoryService.getItemByIdLive(this.roomId) - this.roomMessage$ = this.messageRepositoryService.getItemsLive(this.roomId) + 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) @@ -266,6 +275,96 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy { }, 1000) } + + + listenToIncomingMessage() { + this.messageReceiveSubject?.unsubscribe(); + this.messageReceiveSubject = this.chatServiceService.listenToIncomingMessage(this.roomId).subscribe(async (message) => { + this.messages1[this.roomId].push(message as MessageEntity) + + if(message.hasAttachment) { + + const result = await this.chatServiceService.getMessageAttachmentByMessageId({ + $messageId: message.$id, + id: message.attachments[0].id + }) + + if(result.isOk()) { + + message.attachments[0].safeFile = result.value + + } + } + + setTimeout(() => { + this.scrollToBottomClicked() + }, 100) + }); + } + + listenToDeleteMessage() { + this.messageDeleteSubject?.unsubscribe(); + + this.messageDeleteSubject = this.chatServiceService.listenToDeleteMessage(this.roomId).subscribe((deleteMessage) => { + console.log('delete class', deleteMessage); + + 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) => { + + 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 + + let attachmentIndex = 0; + + for(const message of updateMessage.attachments) { + console.log('set attachmen id', message) + this.messages1[this.roomId][index].attachments[attachmentIndex].id = message.id + attachmentIndex++; + } + + } else { + // console.log('message not found'); + } + }); + } + async loadFiles() { this.storage.get('fileName').then((fileName) => { diff --git a/src/app/pages/login/login.page.ts b/src/app/pages/login/login.page.ts index 3a62061cd..f7d143e84 100644 --- a/src/app/pages/login/login.page.ts +++ b/src/app/pages/login/login.page.ts @@ -11,15 +11,14 @@ import { ClearStoreService } from 'src/app/services/clear-store.service'; import { ChangeProfileService } from 'src/app/services/change-profile.service'; import { ThemeService } from 'src/app/services/theme.service'; import { PermissionService } from 'src/app/services/permission.service'; -// import { ChatSystemService } from 'src/app/services/chat/chat-system.service'; import { ChatService } from 'src/app/services/chat.service'; import { NotificationHolderService } from 'src/app/store/notification-holder.service'; import { Platform } from '@ionic/angular'; -import { FirstEnterService } from '../../services/first-enter.service'; import { Storage } from '@ionic/storage'; import { StorageService } from 'src/app/services/storage.service'; -import { DeviceService } from 'src/app/services/device.service' import { Cy } from 'cypress/enum' +import { ChatServiceService } from 'src/app/module/chat/domain/chat-service.service'; + @Component({ selector: 'app-login', templateUrl: './login.page.html', @@ -54,11 +53,10 @@ export class LoginPage implements OnInit { // public ChatSystemService: ChatSystemService, private ChatService: ChatService, private platform: Platform, - private FirstEnterService: FirstEnterService, private storage: Storage, private storageService: StorageService, private NotificationHolderService: NotificationHolderService, - private DeviceService: DeviceService + private ChatServiceService: ChatServiceService ) { } ngOnInit() { } @@ -152,8 +150,9 @@ export class LoginPage implements OnInit { } - this.changeProfileService.runLogin(); + this.changeProfileService.runLogin(); + this.ChatServiceService.asyncAllRoomMessage() this.getToken(); SessionStore.setInativity(true); SessionStore.hasPassLogin = true; @@ -180,6 +179,8 @@ export class LoginPage implements OnInit { this.ChatService.setheader(); } this.storageService.remove("Notifications") + + this.ChatServiceService.asyncAllRoomMessage() this.getToken(); if (!this.platform.is('desktop') && !this.platform.is('mobileweb')) { diff --git a/src/app/shared/chat/messages/messages.page.ts b/src/app/shared/chat/messages/messages.page.ts index 977b5cfd1..536d04391 100644 --- a/src/app/shared/chat/messages/messages.page.ts +++ b/src/app/shared/chat/messages/messages.page.ts @@ -167,17 +167,19 @@ 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.getMessages(); + this.listenToIncomingMessage(); + this.listenToDeleteMessage(); this.listenToUpdateMessage(); - this.listenToSendMessage() + 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) - this.messageRepositoryService.listAllMessagesByRoomId(this.roomId) + this.messageRepositoryService.listAllMessagesByRoomId(this.roomId).then(()=> { + // this.getMessages(); + }) this.userTypingServiceRepository.getUserTypingLive().subscribe((e) => { const arrayNames = e.map(e => e.userName) @@ -190,44 +192,79 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy } async getMessages() { - this.messages1[this.roomId] = [] let messages = await this.messageRepositoryService.getItems(this.roomId) - this.messages1[this.roomId].unshift(...messages) + this.messages1[this.roomId] = messages + + this.messages1[this.roomId] = this.sortBySentAt(this.messages1[this.roomId]) + this.loadAttachment() setTimeout(() => { this.scrollToBottomClicked() }, 100) - + } async loadAttachment() { for(const message of this.messages1[this.roomId]) { if(message.hasAttachment) { - + const result = await this.chatServiceService.getMessageAttachmentByMessageId({ $messageId: message.$id, - id: message.attachments[0].id + id: message.attachments[0].id }) if(result.isOk()) { - + message.attachments[0].safeFile = result.value } } } - + } + // Sorting function + sortBySentAt (arr, order = 'asc') { + return arr.sort((a, b) => { + // Handle null or undefined sentAt + const dateA = a.sentAt ? new Date(a.sentAt).getTime() : Number.MAX_VALUE; + const dateB = b.sentAt ? new Date(b.sentAt).getTime() : Number.MAX_VALUE; + + if (order === 'asc') { + return dateA - dateB; + } else { + return dateB - dateA; + } + }); + }; + + listenToIncomingMessage() { this.messageReceiveSubject?.unsubscribe(); - this.messageReceiveSubject = this.chatServiceService.listenToIncomingMessage(this.roomId).subscribe((message) => { + this.messageReceiveSubject = this.chatServiceService.listenToIncomingMessage(this.roomId).subscribe(async (message) => { this.messages1[this.roomId].push(message as MessageEntity) - this.scrollToBottomClicked() + + if(message.hasAttachment) { + + const result = await this.chatServiceService.getMessageAttachmentByMessageId({ + $messageId: message.$id, + id: message.attachments[0].id + }) + + if(result.isOk()) { + + message.attachments[0].safeFile = result.value + + } + } + + setTimeout(() => { + this.scrollToBottomClicked() + }, 100) }); } @@ -531,6 +568,8 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy const message = new MessageEntity(); message.roomId = this.roomId + message.sentAt = new Date().toISOString() + message.sender = { userPhoto: '', wxeMail: SessionStore.user.Email, @@ -601,6 +640,7 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy wxFullName: SessionStore.user.FullName, wxUserId: SessionStore.user.UserId } + message.sentAt = new Date().toISOString() this.textField = '' this.messages1[this.roomId].push(message) @@ -608,9 +648,6 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy this.scrollToBottomClicked() }, 100) const data = await this.chatServiceService.sendMessage(message) - - - console.log({data}) } @@ -778,6 +815,8 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy wxUserId: SessionStore.user.UserId } + message.sentAt = new Date().toISOString() + message.attachments = [{ file: compressedImage.value, fileName: "foto", @@ -826,6 +865,8 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy message.message = this.textField message.roomId = this.roomId + message.sentAt = new Date().toISOString() + message.sender = { userPhoto: '', wxeMail: SessionStore.user.Email, @@ -876,6 +917,8 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy const message = new MessageEntity(); message.roomId = this.roomId + message.sentAt = new Date().toISOString() + message.sender = { userPhoto: '', wxeMail: SessionStore.user.Email, @@ -931,6 +974,8 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy const message = new MessageEntity(); message.roomId = this.roomId + message.sentAt = new Date().toISOString() + message.sender = { userPhoto: '', wxeMail: SessionStore.user.Email,