diff --git a/src/app/core/chat/entity/group.ts b/src/app/core/chat/entity/group.ts index ca81c9323..aaa599bd9 100644 --- a/src/app/core/chat/entity/group.ts +++ b/src/app/core/chat/entity/group.ts @@ -1,6 +1,7 @@ import { SessionStore } from "src/app/store/session.service"; import { BaseEntity } from "src/app/utils/entity"; import { z } from "zod" +import { MessageEntitySchema } from "./message"; export enum RoomType { Group = 1, @@ -33,12 +34,13 @@ export const RoomEntitySchema = z.object({ createdAt: z.any(), expirationDate: z.any().nullable(), roomType: z.nativeEnum(RoomType), - members: z.array(MemberSchema).optional() + members: z.array(MemberSchema).optional(), + messages: MessageEntitySchema.array().optional() }) -export type IRoomEntity = z.infer +export type IRoom = z.infer -export class RoomEntity extends BaseEntity(RoomEntitySchema) implements IRoomEntity{ +export class RoomEntity extends BaseEntity(RoomEntitySchema) implements IRoom{ id: typeof RoomEntitySchema._input.id roomName: typeof RoomEntitySchema._input.roomName @@ -47,8 +49,10 @@ export class RoomEntity extends BaseEntity(RoomEntitySchema) implem expirationDate: typeof RoomEntitySchema._input.expirationDate roomType: typeof RoomEntitySchema._input.roomType members: typeof RoomEntitySchema._input.members + messages: typeof RoomEntitySchema._input.messages + displayDate = '' - constructor(data: IRoomEntity) { + constructor(data: IRoom) { super(); Object.assign(this, data) if(data.roomType == RoomType.Direct) { diff --git a/src/app/core/chat/entity/message.ts b/src/app/core/chat/entity/message.ts index 22de23e96..c5bd0d854 100644 --- a/src/app/core/chat/entity/message.ts +++ b/src/app/core/chat/entity/message.ts @@ -36,7 +36,7 @@ export const MessageEntitySchema = z.object({ wxUserId: z.number(), wxFullName: z.string(), wxeMail: z.string(), - userPhoto: z.string(), + userPhoto: z.string().nullable(), }), reactions: z.object({ id: z.string(), @@ -61,7 +61,7 @@ export const MessageEntitySchema = z.object({ mimeType: z.string().optional(), safeFile: z.any().optional(), description: z.string().nullable().optional() - })).optional() + })).optional(), }) export type IMessage = z.infer; diff --git a/src/app/core/chat/mapper/getRoomListMapper.ts b/src/app/core/chat/mapper/getRoomListMapper.ts index 2e0583e43..a9c0bc66c 100644 --- a/src/app/core/chat/mapper/getRoomListMapper.ts +++ b/src/app/core/chat/mapper/getRoomListMapper.ts @@ -1,6 +1,5 @@ import { RoomListItemOutPutDTO } from "src/app/module/chat/domain/use-case/room/room-get-list-use-case.service"; import { RoomEntity } from "../entity/group"; -import { captureAndReraiseAsync } from "src/app/services/decorators/captureAndReraiseAsync"; export class GetRoomListMapper{ @@ -24,7 +23,8 @@ export class GetRoomListMapper{ wxFullName: b.wxFullName, wxUserId: b.wxUserId } - })) + })), + messages: roomData.chatRoom.messages, })); } diff --git a/src/app/infra/database/dexie/instance/chat/schema/room.ts b/src/app/infra/database/dexie/instance/chat/schema/room.ts index db9a3ecba..caf6f5103 100644 --- a/src/app/infra/database/dexie/instance/chat/schema/room.ts +++ b/src/app/infra/database/dexie/instance/chat/schema/room.ts @@ -1,6 +1,7 @@ import { z } from "zod"; import { EntityTable } from 'Dexie'; import { RoomType } from "src/app/core/chat/entity/group"; +import { MessageEntity, MessageEntitySchema } from "src/app/core/chat/entity/message"; export const RoomTableSchema = z.object({ id: z.string(), @@ -13,9 +14,10 @@ export const RoomTableSchema = z.object({ }), createdAt: z.any(), expirationDate: z.any().nullable(), - roomType: z.nativeEnum(RoomType) + roomType: z.nativeEnum(RoomType), + messages: MessageEntitySchema.array().optional() }) export type RoomTable = z.infer export type DexieRoomsTable = EntityTable; -export const RoomTableColumn = 'id, createdBy, roomName, roomType, expirationDate, lastMessage' +export const RoomTableColumn = 'id, createdBy, roomName, roomType, expirationDate, lastMessage' \ No newline at end of file diff --git a/src/app/module/chat/chat.module.ts b/src/app/module/chat/chat.module.ts index 5752e01cf..dcdc26e78 100644 --- a/src/app/module/chat/chat.module.ts +++ b/src/app/module/chat/chat.module.ts @@ -37,6 +37,7 @@ import { DistributionService } from './domain/service/distribution.service' import { BoldLocalRepository } from './data/repository/bold/bold-local-repository'; import { IBoldLocalRepository } from 'src/app/core/chat/repository/bold/bold-local-repository'; import { BoldService } from 'src/app/module/chat/domain/service/bold.service' +import { RoomLastMessageService } from 'src/app/module/chat/domain/service/room-last-message.service' @NgModule({ imports: [HttpModule], providers: [ @@ -118,7 +119,8 @@ export class ChatModule { private UserTypingRemoteRepositoryService: UserTypingRemoteRepositoryService, private RoomService: RoomService, private DistributionService: DistributionService, - private BoldService: BoldService + private BoldService: BoldService, + private RoomLastMessageService: RoomLastMessageService ) { this.RoomService.init() diff --git a/src/app/module/chat/data/async/list/rooms/roomListChangeDetector.ts b/src/app/module/chat/data/async/list/rooms/roomListChangeDetector.ts index b74d2b3e5..35719ba17 100644 --- a/src/app/module/chat/data/async/list/rooms/roomListChangeDetector.ts +++ b/src/app/module/chat/data/async/list/rooms/roomListChangeDetector.ts @@ -14,7 +14,8 @@ export function roomListDetermineChanges(serverRooms: RoomListItemOutPutDTO[], l room.chatRoom.roomName !== localRoom.roomName && room.chatRoom.roomType == RoomType.Group || room.chatRoom.createdBy.wxUserId !== localRoom.createdBy.wxUserId || room.chatRoom.createdAt !== localRoom.createdAt || - room.chatRoom.expirationDate !== localRoom.expirationDate // || + room.chatRoom.expirationDate !== localRoom.expirationDate || + room.chatRoom.messages?.[0]?.id !== localRoom.messages?.[0]?.id // room.chatRoom.roomType !== localRoom.roomType ); }); diff --git a/src/app/module/chat/domain/chat-service.service.ts b/src/app/module/chat/domain/chat-service.service.ts index 5c0585217..57baaf8cc 100644 --- a/src/app/module/chat/domain/chat-service.service.ts +++ b/src/app/module/chat/domain/chat-service.service.ts @@ -19,7 +19,7 @@ import { DeleteRoomUseCaseService } from './use-case/room/room-delete-by-id-use- import { CreateRoomInputDTO, CreateRoomUseCaseService } from './use-case/room/room-create-use-case.service'; import { RoomLeaveUseCase, UserRemoveListInputDTO } from './use-case/room/room-leave-by-id-use-case.service'; import { SyncAllRoomMessagesService } from './use-case/message/sync-all-room-messages.service'; -import { ListenSendMessageUseCase } from './use-case/message/listen-send-message.service' +import { ListenSendMessageUseCase } from './use-case/message/listen-send-message.service'; import { SendLocalMessagesUseCaseService } from './use-case/message/messages-send-offline-use-case.service' import { RemoveMemberUseCaseService } from './use-case/member/-use-case.service' import { AddMemberUseCaseService } from './use-case/member/member-add-use-case.service' @@ -27,13 +27,12 @@ import { RoomUpdateInputDTO, UpdateRoomByIdUseCaseService } from './use-case/roo import { SocketConnectUseCaseService } from './use-case/socket-connect-use-case.service' import { MessageMarkAsReadUseCaseService } from './use-case/message/message-mark-as-read-use-case.service' import { MessageMarkAllMessageAsReadByRoomIdInputSchema, MessageMarkAllMessageAsReadByRoomIdService } from './use-case/message/message-mark-all-message-as-read-by-room-id.service' -import { GetMessageAttachmentLocallyByMessageId, GetMessageAttachmentLocallyUseCaseService } from 'src/app/module/chat/domain/use-case/message/message-get-attachment-localy-use-case.service'; import { GetRoomListUseCaseService } from 'src/app/module/chat/domain/use-case/room/room-get-list-use-case.service'; import { filter } from 'rxjs/operators'; import { v4 as uuidv4 } from 'uuid' import { MessageEntity } from '../../../core/chat/entity/message'; -import { MessageAttachmentByMessageIdInput, MessageAttachmentByMessageIdUseCase } from './use-case/message/message-attachment-by-message-id.service'; -import { AddMemberToRoomInputDTO, AddMemberToRoomInputDTOSchema } from '../domain/use-case/member/member-add-use-case.service'; +import { MessageAttachmentByMessageIdUseCase } from './use-case/message/message-attachment-by-message-id.service'; +import { AddMemberToRoomInputDTO } from '../domain/use-case/member/member-add-use-case.service'; import { RoomType } from "src/app/core/chat/entity/group"; import { HttpListenToMessageLoadHistoryAdapter } from './adapter' import { HttpListenToMessageLoadHistoryUseCaseInput } from 'src/app/core/chat/usecase/message/http-listen-to-message-load-history-by-roomId-use-case'; @@ -65,7 +64,6 @@ export class ChatServiceService { private MessageAttachmentByMessageIdService: MessageAttachmentByMessageIdUseCase, private SyncAllRoomMessagesService: SyncAllRoomMessagesService, private DownloadMessageAttachmentUserCaseService: DownloadMessageAttachmentUserCaseService, - private GetMessageAttachmentLocallyUseCaseService: GetMessageAttachmentLocallyUseCaseService, private GetRoomListUseCaseService: GetRoomListUseCaseService, private GetRoomByIdUseCaseService: GetRoomByIdUseCaseService, private DeleteRoomUseCaseService: DeleteRoomUseCaseService, diff --git a/src/app/module/chat/domain/service/distribution.service.ts b/src/app/module/chat/domain/service/distribution.service.ts index e2dbc5b6f..7b415563c 100644 --- a/src/app/module/chat/domain/service/distribution.service.ts +++ b/src/app/module/chat/domain/service/distribution.service.ts @@ -23,9 +23,7 @@ export class DistributionService { constructor( private http: HttpAdapter, private distributionLocalRepository: IDistributionLocalRepository - ) { - // this.listenToLoadHistory() - } + ) {} listenToLoadHistory() { return this.http.listen().pipe( diff --git a/src/app/module/chat/domain/service/room-last-message.service.spec.ts b/src/app/module/chat/domain/service/room-last-message.service.spec.ts new file mode 100644 index 000000000..660392bf3 --- /dev/null +++ b/src/app/module/chat/domain/service/room-last-message.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { RoomLastMessageService } from './room-last-message.service'; + +describe('RoomLastMessageService', () => { + let service: RoomLastMessageService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(RoomLastMessageService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); 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 new file mode 100644 index 000000000..e26526bde --- /dev/null +++ b/src/app/module/chat/domain/service/room-last-message.service.ts @@ -0,0 +1,33 @@ +import { Injectable } from '@angular/core'; +import { filter, map } from 'rxjs/operators'; +import { MessageEntity } from 'src/app/core/chat/entity/message'; +import { IMessageSocketRepository } from 'src/app/core/chat/repository/message/message-socket-repository'; +import { InstanceId } from '../chat-service.service'; +import { IRoomLocalRepository } from 'src/app/core/chat/repository/room/room-local-repository'; + +@Injectable({ + providedIn: 'root' +}) +export class RoomLastMessageService { + + 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] + }) + + }); + + } +} diff --git a/src/app/ui/chat/chat.page.html b/src/app/ui/chat/chat.page.html index 4b8b34d9c..f5ce7fd39 100644 --- a/src/app/ui/chat/chat.page.html +++ b/src/app/ui/chat/chat.page.html @@ -68,16 +68,19 @@ - +
+ {{ room.displayDate }} +
{{ expirationDate[room.id] !== null ? expirationDate[room.id] + ' seconds left' : '' }}
- +
+
{{room.messages[0].message}}
+ + +
@@ -106,16 +109,20 @@ +
+ {{ room.displayDate }} +
{{ expirationDate[room.id] !== null ? expirationDate[room.id] + ' seconds left' : '' }}
- +
+
{{room?.messages?.[0]?.message}}
+ + +
diff --git a/src/app/ui/chat/chat.page.ts b/src/app/ui/chat/chat.page.ts index 8c16c6489..5f3a88d55 100644 --- a/src/app/ui/chat/chat.page.ts +++ b/src/app/ui/chat/chat.page.ts @@ -22,9 +22,10 @@ import { RoomLocalRepository } from 'src/app/module/chat/data/repository/room/ro import { map, tap } from 'rxjs/operators'; import { interval, Subscription } from 'rxjs'; import { RoomTable } from 'src/app/infra/database/dexie/instance/chat/schema/room'; -import { RoomType } from 'src/app/core/chat/entity/group'; +import { RoomEntity, RoomType } from 'src/app/core/chat/entity/group'; import { BoldLocalRepository } from 'src/app/module/chat/data/repository/bold/bold-local-repository' import { BoldTable } from 'src/app/infra/database/dexie/instance/chat/schema/bold'; +import { RoomViewModel } from './store/model/room'; @Component({ selector: 'app-chat', templateUrl: './chat.page.html', @@ -104,12 +105,13 @@ export class ChatPage implements OnInit { ngOnInit() { this.items$ = this.roomLocalDataSourceService.getItemsLive().pipe( - map(rooms => rooms.map(room => ({ - ...room, - minutesLeft: this.getSecondsLeft(room.expirationDate) - }))), + map((roomList) => roomList.map((room)=> new RoomViewModel(room))), tap((roomList) => { - this.rooms = 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 + ) }) ); @@ -125,7 +127,7 @@ export class ChatPage implements OnInit { // Subscribe to the interval observable this.intervalSubscription = interval$.subscribe(); - this.ChatServiceService.getRoomList() + // this.ChatServiceService.getRoomList() this.hideRefreshButton(); diff --git a/src/app/ui/chat/store/model/room.ts b/src/app/ui/chat/store/model/room.ts new file mode 100644 index 000000000..8291f68a1 --- /dev/null +++ b/src/app/ui/chat/store/model/room.ts @@ -0,0 +1,61 @@ +import { IRoom, RoomEntitySchema } from "src/app/core/chat/entity/group"; + +export class RoomViewModel implements IRoom { + + + id: typeof RoomEntitySchema._input.id + roomName: typeof RoomEntitySchema._input.roomName + createdBy: typeof RoomEntitySchema._input.createdBy + createdAt: typeof RoomEntitySchema._input.createdAt + expirationDate: typeof RoomEntitySchema._input.expirationDate + roomType: typeof RoomEntitySchema._input.roomType + members: typeof RoomEntitySchema._input.members + messages: typeof RoomEntitySchema._input.messages + displayDate = '' + + constructor(model: IRoom) { + Object.assign(this, model) + this.formatarData() + } + + formatarData() { + if(this.messages?.[0]?.sentAt) { + + const dataMensagem = new Date(this.messages[0].sentAt); + const agora = new Date(); + + const hoje = new Date(agora.getFullYear(), agora.getMonth(), agora.getDate()); + const ontem = new Date(hoje); + ontem.setDate(hoje.getDate() - 1); + + const diasDaSemana = ["Domingo", "Segunda-feira", "Terça-feira", "Quarta-feira", "Quinta-feira", "Sexta-feira", "Sábado"]; + + // Verifica se a mensagem foi enviada hoje + if (dataMensagem >= hoje) { + this.displayDate = dataMensagem.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', hour12: false }); + return + } + + // Verifica se a mensagem foi enviada ontem + if (dataMensagem >= ontem && dataMensagem < hoje) { + this.displayDate = "Ontem"; + return + } + + // Verifica se a mensagem foi enviada nesta semana + const inicioDaSemana = new Date(hoje); + inicioDaSemana.setDate(hoje.getDate() - hoje.getDay()); + + if (dataMensagem >= inicioDaSemana) { + this.displayDate = diasDaSemana[dataMensagem.getDay()]; + return + } + + // Se a mensagem foi enviada antes desta semana + this.displayDate = dataMensagem.toLocaleDateString("pt-BR"); // Formato: DD/MM/AAAA + return + + } + + } +} \ No newline at end of file