mirror of
https://code.equilibrium.co.ao/ITO/doneit-web.git
synced 2026-04-19 04:57:52 +00:00
fix all errors
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { RoomTable } from "src/app/infra/database/dexie/instance/chat/schema/room";
|
||||
import { RoomByIdOutputDTO } from "src/app/module/chat/domain/use-case/room/room-get-by-id-use-case.service";
|
||||
import { RoomListItemOutPutDTO } from "src/app/module/chat/domain/use-case/room/room-get-list-use-case.service";
|
||||
import { RoomByIdOutputDTO } from "src/app/core/chat/usecase/room/room-get-by-id-use-case.service";
|
||||
import { RoomListItemOutPutDTO } from "src/app/core/chat/usecase/room/room-get-list-use-case.service";
|
||||
|
||||
export function roomByIdDetermineChanges(serverResponse: RoomByIdOutputDTO, localRooms: RoomTable[]) {
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { RoomType } from "src/app/core/chat/entity/group";
|
||||
import { RoomTable } from "src/app/infra/database/dexie/instance/chat/schema/room";
|
||||
import { RoomListItemOutPutDTO } from "src/app/module/chat/domain/use-case/room/room-get-list-use-case.service";
|
||||
import { RoomListItemOutPutDTO } from "src/app/core/chat/usecase/room/room-get-list-use-case.service";
|
||||
import { SessionStore } from "src/app/store/session.service";
|
||||
|
||||
export function roomListDetermineChanges(serverRooms: RoomListItemOutPutDTO[], localRooms: RoomTable[]) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { MemberTable } from "src/app/infra/database/dexie/instance/chat/schema/members";
|
||||
import { RoomByIdMemberItemOutputDTO } from "src/app/module/chat/domain/use-case/room/room-get-by-id-use-case.service";
|
||||
import { RoomByIdMemberItemOutputDTO } from "src/app/core/chat/usecase/room/room-get-by-id-use-case.service";
|
||||
|
||||
export function roomMemberListDetermineChanges(____serverRooms: RoomByIdMemberItemOutputDTO[], localRooms: MemberTable[], roomId: string) {
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import { z } from 'zod';
|
||||
import { DexieRepository } from 'src/app/infra/repository/dexie/dexie-repository.service';
|
||||
import { ok } from 'neverthrow';
|
||||
import { err, Result } from 'neverthrow';
|
||||
import { MemberListUPdateStatusInputDTO } from '../../../domain/use-case/socket/member-list-update-status-use-case.service';
|
||||
import { MemberListUPdateStatusInputDTO } from '../../../../../core/chat/usecase/socket/member-list-update-status-use-case.service';
|
||||
import { from } from 'rxjs';
|
||||
import { MemberTable, MemberTableSchema } from 'src/app/infra/database/dexie/instance/chat/schema/members';
|
||||
import { chatDatabase } from 'src/app/infra/database/dexie/instance/chat/service';
|
||||
|
||||
@@ -4,9 +4,9 @@ import { ValidateSchema } from 'src/app/services/decorators/validate-schema.deco
|
||||
import { HttpService } from 'src/app/services/http.service';
|
||||
import { DataSourceReturn } from 'src/app/services/Repositorys/type';
|
||||
import { IMemberRemoteRepository } from 'src/app/core/chat/repository/member/member-remote-repository';
|
||||
import { AddMemberToRoomInputDTO, AddMemberToRoomInputDTOSchema } from '../../../domain/use-case/member/member-add-use-case.service';
|
||||
import { MemberSetAdminDTO } from '../../../domain/use-case/member/member-admin-use-case.service';
|
||||
import { UserRemoveListInputDTOSchema, UserRemoveListInputDTO } from '../../../domain/use-case/room/room-leave-by-id-use-case.service';
|
||||
import { UserRemoveListInputDTOSchema, UserRemoveListInputDTO } from '../../../../../core/chat/usecase/room/room-leave-by-id-use-case.service';
|
||||
import { AddMemberToRoomInputDTOSchema, AddMemberToRoomInputDTO } from 'src/app/core/chat/usecase/member/member-add-use-case.service';
|
||||
import { MemberSetAdminDTO } from 'src/app/core/chat/usecase/member/member-admin-use-case.service';
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { SignalRService } from 'src/app/infra/socket/signalR/signal-r.service';
|
||||
import { IMemberSocketRepository } from 'src/app/core/chat/repository/member/member-socket-repository';
|
||||
import { IRemoveRoomMemberOutput, RemoveRoomMemberInput } from '../../../domain/use-case/member/member-remove-socket-use-case.service';
|
||||
import { InstanceId } from '../../../domain/chat-service.service';
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { filter, map, tap } from 'rxjs/operators';
|
||||
import { SocketMessage } from 'src/app/infra/socket/signalR/signalR';
|
||||
import { RemoveRoomMemberInput, IRemoveRoomMemberOutput } from 'src/app/core/chat/usecase/member/member-remove-socket-use-case.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
|
||||
+5
-5
@@ -1,16 +1,16 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { InstanceId } from '../../../domain/chat-service.service';
|
||||
import { MessageUpdateInput } from '../../../domain/use-case/message/message-update-by-id-use-case.service';
|
||||
import { MessageReactionInput } from '../../../domain/use-case/message/message-reaction-by-id-use-case.service';
|
||||
import { MessageUpdateInput } from '../../../../../core/chat/usecase/message/message-update-by-id-use-case.service';
|
||||
import { MessageReactionInput } from '../../../../../core/chat/usecase/message/message-reaction-by-id-use-case.service';
|
||||
import { SignalRService } from 'src/app/infra/socket/signalR/signal-r.service';
|
||||
import { filter, map } from 'rxjs/operators';
|
||||
import { SocketMessage } from 'src/app/infra/socket/signalR/signalR';
|
||||
import { IMessageSocketRepository } from 'src/app/core/chat/repository/message/message-socket-repository';
|
||||
import { MessageCreateOutPutDataDTO, MessageInputDTO } from '../../../domain/use-case/message/message-create-use-case.service';
|
||||
import { MessageMarkAsReadInput } from '../../../domain/use-case/message/message-mark-as-read-use-case.service';
|
||||
import { MessageCreateOutPutDataDTO, MessageInputDTO } from '../../../../../core/chat/usecase/message/message-create-use-case.service';
|
||||
import { MessageMarkAsReadInput } from '../../../../../core/chat/usecase/message/message-mark-as-read-use-case.service';
|
||||
import { MessageOutPutDataDTO } from 'src/app/core/chat/repository/dto/messageOutputDTO';
|
||||
import { MessageDeleteInputDTO } from '../../../domain/use-case/message/message-delete-by-id-live-use-case.service';
|
||||
import { MessageDeleteInputDTO } from '../../../../../core/chat/usecase/message/message-delete-by-id-live-use-case.service';
|
||||
import { BehaviorSubject, Observable } from 'rxjs';
|
||||
|
||||
interface sendDeliverAt {
|
||||
|
||||
@@ -4,7 +4,7 @@ import { DataSourceReturn } from 'src/app/services/Repositorys/type';
|
||||
import { SignalRService } from 'src/app/infra/socket/signalR/signal-r.service';
|
||||
import { HttpAdapter } from 'src/app/infra/http/adapter';
|
||||
import { IMessageGetAllByRoomIdOutPut } from 'src/app/core/chat/usecase/message/message-get-all-by-room-Id';
|
||||
import { IMessageRemoteRepository } from 'src/app/core/chat/repository/message/message-remote-repository';
|
||||
import { IGetMessagesFromRoomParams, IMessageRemoteRepository } from 'src/app/core/chat/repository/message/message-remote-repository';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
@@ -21,9 +21,9 @@ export class MessageRemoteDataSourceService implements IMessageRemoteRepository
|
||||
|
||||
|
||||
// @APIReturn(MessageOutPutDTOSchema, 'get/Messages')
|
||||
async getMessagesFromRoom(id: string): DataSourceReturn<IMessageGetAllByRoomIdOutPut> {
|
||||
async getMessagesFromRoom(input: IGetMessagesFromRoomParams): DataSourceReturn<IMessageGetAllByRoomIdOutPut> {
|
||||
|
||||
var a = await this.http.get<IMessageGetAllByRoomIdOutPut>(`${this.baseUrl}/Room/${id}/Messages`)
|
||||
var a = await this.http.get<IMessageGetAllByRoomIdOutPut>(`${this.baseUrl}/Room/${input.roomId}/Messages?startDate=${encodeURIComponent(input.lastMessageDate)}`)
|
||||
|
||||
return a.map((e) => {
|
||||
return e.data
|
||||
|
||||
@@ -41,8 +41,6 @@ export class RoomLocalRepository extends DexieRepository<RoomTable, RoomTable> i
|
||||
// (modifications as Partial<RoomTable>).messages[0].sentAt = oldValue.messages?.[0]?.sentAt
|
||||
// }
|
||||
|
||||
console.log({modifications, oldValue})
|
||||
|
||||
if((modifications as Partial<RoomTable>).id || oldValue.id) {
|
||||
(modifications as Partial<RoomTable>).local = IDBoolean.false
|
||||
} else {
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Result } from 'neverthrow';
|
||||
import { HttpService } from 'src/app/services/http.service';
|
||||
import { AddMemberToRoomInputDTO } from '../../../domain/use-case/member/member-add-use-case.service';
|
||||
import { DataSourceReturn } from 'src/app/services/Repositorys/type';
|
||||
import { SessionStore } from 'src/app/store/session.service';
|
||||
import { SignalRService } from 'src/app/infra/socket/signalR/signal-r.service';
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { CreateRoomInputDTO, RoomOutPutDTO } from '../../../domain/use-case/room/room-create-use-case.service';
|
||||
import { CreateRoomInputDTO, RoomOutPutDTO } from '../../../../../core/chat/usecase/room/room-create-use-case.service';
|
||||
import { IRoomRemoteRepository } from 'src/app/core/chat/repository/room/room-remote-repository';
|
||||
import { RoomByIdOutputDTO } from 'src/app/module/chat/domain/use-case/room/room-get-by-id-use-case.service';
|
||||
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 { RoomByIdOutputDTO } from 'src/app/core/chat/usecase/room/room-get-by-id-use-case.service';
|
||||
import { RoomUpdateInputDTO, RoomUpdateOutputDTO } from 'src/app/core/chat/usecase/room/room-update-by-id-use-case.service';
|
||||
import { RoomListOutPutDTO } from '../../../../../core/chat/usecase/room/room-get-list-use-case.service';
|
||||
import { z } from 'zod';
|
||||
import { HttpAdapter } from 'src/app/infra/http/adapter';
|
||||
import { AddMemberToRoomInputDTO } from 'src/app/core/chat/usecase/member/member-add-use-case.service';
|
||||
|
||||
const RoomByIdInputDTOSchema = z.string()
|
||||
type RoomByIdInputDTO = z.infer<typeof RoomByIdInputDTOSchema>
|
||||
|
||||
@@ -5,7 +5,7 @@ import { z } from 'zod';
|
||||
import { SocketMessage } from 'src/app/infra/socket/signalR/signalR';
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { IRoomSocketRepository, SocketRoomUpdateOutPut } from 'src/app/core/chat/repository/room/room-socket-repository';
|
||||
import { CreateRoomInputDTO } from '../../../domain/use-case/room/room-create-use-case.service';
|
||||
import { CreateRoomInputDTO } from '../../../../../core/chat/usecase/room/room-create-use-case.service';
|
||||
|
||||
const listenToDeleteRoomInputSchema = z.object({
|
||||
roomId: z.string()
|
||||
|
||||
@@ -1,57 +1,56 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { MessageDeleteLiveUseCaseService } from 'src/app/module/chat/domain/use-case/message/message-delete-by-id-live-use-case.service'
|
||||
import { MessageDeleteLiveUseCaseService } from 'src/app/core/chat/usecase/message/message-delete-by-id-live-use-case.service'
|
||||
import { SessionStore } from 'src/app/store/session.service';
|
||||
import { MessageReactionInput, MessageReactionUseCaseService } from 'src/app/module/chat/domain/use-case/message/message-reaction-by-id-use-case.service';
|
||||
import { MessageUpdateInput, MessageUpdateUseCaseService } from 'src/app/module/chat/domain/use-case/message/message-update-by-id-use-case.service';
|
||||
import { MemberAdminUseCaseService, MemberSetAdminDTO } from 'src/app/module/chat/domain/use-case/member/member-admin-use-case.service';
|
||||
import { MessageCreateUseCaseService } from 'src/app/module/chat/domain/use-case/message/message-create-use-case.service';
|
||||
import { MessageReactionInput, MessageReactionUseCaseService } from 'src/app/core/chat/usecase/message/message-reaction-by-id-use-case.service';
|
||||
import { MessageUpdateInput, MessageUpdateUseCaseService } from 'src/app/core/chat/usecase/message/message-update-by-id-use-case.service';
|
||||
import { MemberAdminUseCaseService, MemberSetAdminDTO } from 'src/app/core/chat/usecase/member/member-admin-use-case.service';
|
||||
import { MessageCreateUseCaseService } from 'src/app/core/chat/usecase/message/message-create-use-case.service';
|
||||
import { SignalRService } from 'src/app/infra/socket/signalR/signal-r.service';
|
||||
import { SocketMessageDeleteUseCaseService } from 'src/app/module/chat/domain/use-case/socket/socket-message-delete-use-case.service';
|
||||
import { SocketMessageUpdateUseCaseService } from 'src/app/module/chat/domain/use-case/socket/socket-message-update-use-case.service';
|
||||
import { SocketMessageCreateUseCaseService } from 'src/app/module/chat/domain/use-case/socket/socket-message-create-use-case.service';
|
||||
import { DownloadMessageAttachmentByMessageId, DownloadMessageAttachmentUserCaseService } from 'src/app/module/chat/domain/use-case/message/message-download-attachment-user-case.service';
|
||||
import { ListenMessageByRoomIdNewUseCase } from 'src/app/module/chat/domain/use-case/message/listen-message-by-roomId.service';
|
||||
import { MemberListUpdateStatusUseCaseService } from 'src/app/module/chat/domain/use-case/socket/member-list-update-status-use-case.service';
|
||||
import { ListenMessageDeleteByRoomIdService } from './use-case/message/listene-message-delete-by-roomId.service';
|
||||
import { ListenMessageUpdateByRoomIdUseCase } from './use-case/message/listen-message-update-by-roomId.service';
|
||||
import { GetRoomByIdUseCaseService } from './use-case/room/room-get-by-id-use-case.service';
|
||||
import { DeleteRoomUseCaseService } from './use-case/room/room-delete-by-id-use-case.service';
|
||||
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 { 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'
|
||||
import { MemberRemoveSocketUseCaseService, RemoveRoomMemberInput } from './use-case/member/member-remove-socket-use-case.service'
|
||||
import { RoomUpdateInputDTO, UpdateRoomByIdUseCaseService } from './use-case/room/room-update-by-id-use-case.service'
|
||||
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 { GetRoomListUseCaseService } from 'src/app/module/chat/domain/use-case/room/room-get-list-use-case.service';
|
||||
import { SocketMessageDeleteUseCaseService } from 'src/app/core/chat/usecase/socket/socket-message-delete-use-case.service';
|
||||
import { SocketMessageUpdateUseCaseService } from 'src/app/core/chat/usecase/socket/socket-message-update-use-case.service';
|
||||
import { SocketMessageCreateUseCaseService } from 'src/app/core/chat/usecase/socket/socket-message-create-use-case.service';
|
||||
import { DownloadMessageAttachmentByMessageId, DownloadMessageAttachmentUserCaseService } from 'src/app/core/chat/usecase/message/message-download-attachment-user-case.service';
|
||||
import { ListenMessageByRoomIdNewUseCase } from 'src/app/core/chat/usecase/message/listen-message-by-roomId.service';
|
||||
import { MemberListUpdateStatusUseCaseService } from 'src/app/core/chat/usecase/socket/member-list-update-status-use-case.service';
|
||||
import { ListenMessageDeleteByRoomIdService } from 'src/app/core/chat/usecase/message/listene-message-delete-by-roomId.service';
|
||||
import { ListenMessageUpdateByRoomIdUseCase } from 'src/app/core/chat/usecase/message/listen-message-update-by-roomId.service';
|
||||
import { GetRoomByIdUseCaseService } from '../../../core/chat/usecase/room/room-get-by-id-use-case.service';
|
||||
import { DeleteRoomUseCaseService } from '../../../core/chat/usecase/room/room-delete-by-id-use-case.service';
|
||||
import { CreateRoomInputDTO, CreateRoomUseCaseService } from '../../../core/chat/usecase/room/room-create-use-case.service';
|
||||
import { RoomLeaveUseCase, UserRemoveListInputDTO } from '../../../core/chat/usecase/room/room-leave-by-id-use-case.service';
|
||||
import { SyncAllRoomMessagesService } from 'src/app/core/chat/usecase/message/sync-all-room-messages.service';
|
||||
import { ListenSendMessageUseCase } from '../../../core/chat/usecase/message/listen-send-message.service';
|
||||
import { SendLocalMessagesUseCaseService } from 'src/app/core/chat/usecase/message/messages-send-offline-use-case.service'
|
||||
import { RemoveMemberUseCaseService } from 'src/app/core/chat/usecase/member/-use-case.service'
|
||||
import { AddMemberToRoomInputDTO, AddMemberUseCaseService } from 'src/app/core/chat/usecase/member/member-add-use-case.service'
|
||||
import { MemberRemoveSocketUseCaseService, RemoveRoomMemberInput } from 'src/app/core/chat/usecase/member/member-remove-socket-use-case.service'
|
||||
import { RoomUpdateInputDTO, UpdateRoomByIdUseCaseService } from '../../../core/chat/usecase/room/room-update-by-id-use-case.service'
|
||||
import { SocketConnectUseCaseService } from 'src/app/core/chat/usecase/socket-connect-use-case.service'
|
||||
import { MessageMarkAsReadUseCaseService } from 'src/app/core/chat/usecase/message/message-mark-as-read-use-case.service'
|
||||
import { MessageMarkAllMessageAsReadByRoomIdInputSchema, MessageMarkAllMessageAsReadByRoomIdService } from 'src/app/core/chat/usecase/message/message-mark-all-message-as-read-by-room-id.service'
|
||||
import { GetRoomListUseCaseService } from 'src/app/core/chat/usecase/room/room-get-list-use-case.service';
|
||||
import { filter, map } from 'rxjs/operators';
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { IMessage, MessageEntity } from '../../../core/chat/entity/message';
|
||||
import { MessageAttachmentByMessageIdInput, MessageAttachmentByMessageIdUseCase } from './use-case/message/message-attachment-by-message-id.service';
|
||||
import { AddMemberToRoomInputDTO } from '../domain/use-case/member/member-add-use-case.service';
|
||||
import { MessageAttachmentByMessageIdInput, MessageAttachmentByMessageIdUseCase } from 'src/app/core/chat/usecase/message/message-attachment-by-message-id.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';
|
||||
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 { MemberListHttpSyncUseCase } from 'src/app/module/chat/domain/use-case/member/member-list-http-sync-use-case.ts.service'
|
||||
import { RoomBoldSyncUseCaseService } from 'src/app/module/chat/domain/use-case/room/room-bold-sync-use-case.service'
|
||||
import { RoomSetLastMessageService } from 'src/app/module/chat/domain/use-case/room/room-set-last-message.service';
|
||||
import { RoomDirectOnSetIdUseCaseInputSchema, RoomDirectOnSetIdUseCaseService } from 'src/app/module/chat/domain/use-case/room/room-direct-on-set-id-use-case.service';
|
||||
import { RoomCreateLocalDirectMessageInputDTOInputDTO, RoomCreateLocalDirectMessageService } from 'src/app/module/chat/domain/use-case/room/room-create-local-direct-message.service';
|
||||
import { RoomGetListOnCreateUseCaseService } from 'src/app/module/chat/domain/use-case/room/room-get-list-on-create-use-case.service';
|
||||
import { IRoomSetLocalToFalseByIdInput, RoomSetLocalToFalseByIdService } from 'src/app/module/chat/domain/use-case/room/room-set-local-to-false-by-id.service';
|
||||
import { RoomUpdateNameSyncService } from 'src/app/module/chat/domain/use-case/room/room-update-name-sync.service';
|
||||
import { IUserPhotoGetByIdInput, UserPhotoGetByIdUseCase } from 'src/app/module/chat/domain/use-case/user-photo/user-photo-get-by-id-use-case.service'
|
||||
import { IMessageLocalGetByIdServiceInput, MessageLocalGetByIdService } from 'src/app/module/chat/domain/use-case/message/message-local-get-by-id.service'
|
||||
import { ContactListService } from './use-case/contact/contact-list.service';
|
||||
import { IRoomGetLocalByIdServiceInput, RoomGetLocalByIdService } from './use-case/room/room-getlocal-by-id.service';
|
||||
import { MessageMarkAsReadInput } from "src/app/core/chat/usecase/message/message-mark-as-read-use-case.service";
|
||||
import { BoldRemoveByRoomIdInput, BoldRemoveByRoomIdService } from 'src/app/core/chat/usecase/bold/bold-remove-by-room-id.service';
|
||||
import { MemberListHttpSyncUseCase } from 'src/app/core/chat/usecase/member/member-list-http-sync-use-case.ts.service'
|
||||
import { RoomBoldSyncUseCaseService } from 'src/app/core/chat/usecase/room/room-bold-sync-use-case.service'
|
||||
import { RoomSetLastMessageService } from 'src/app/core/chat/usecase/room/room-set-last-message.service';
|
||||
import { RoomDirectOnSetIdUseCaseInputSchema, RoomDirectOnSetIdUseCaseService } from 'src/app/core/chat/usecase/room/room-direct-on-set-id-use-case.service';
|
||||
import { RoomCreateLocalDirectMessageInputDTOInputDTO, RoomCreateLocalDirectMessageService } from 'src/app/core/chat/usecase/room/room-create-local-direct-message.service';
|
||||
import { RoomGetListOnCreateUseCaseService } from 'src/app/core/chat/usecase/room/room-get-list-on-create-use-case.service';
|
||||
import { IRoomSetLocalToFalseByIdInput, RoomSetLocalToFalseByIdService } from 'src/app/core/chat/usecase/room/room-set-local-to-false-by-id.service';
|
||||
import { RoomUpdateNameSyncService } from 'src/app/core/chat/usecase/room/room-update-name-sync.service';
|
||||
import { IUserPhotoGetByIdInput, UserPhotoGetByIdUseCase } from 'src/app/core/chat/usecase/user-photo/user-photo-get-by-id-use-case.service'
|
||||
import { IMessageLocalGetByIdServiceInput, MessageLocalGetByIdService } from 'src/app/core/chat/usecase/message/message-local-get-by-id.service'
|
||||
import { ContactListService } from 'src/app/core/chat/usecase/contact/contact-list.service';
|
||||
import { IRoomGetLocalByIdServiceInput, RoomGetLocalByIdService } from '../../../core/chat/usecase/room/room-getlocal-by-id.service';
|
||||
|
||||
|
||||
export const getInstanceId = (): string => {
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
|
||||
import { MemberTable } from "src/app/infra/database/dexie/instance/chat/schema/members";
|
||||
import { RoomByIdMemberItemOutputDTO } from "../use-case/room/room-get-by-id-use-case.service";
|
||||
|
||||
export function MemberListMapper(outputDto: RoomByIdMemberItemOutputDTO, roomId: string): MemberTable {
|
||||
return {
|
||||
roomId: roomId,
|
||||
wxUserId: outputDto.user.wxUserId,
|
||||
wxFullName: outputDto.user.wxFullName,
|
||||
wxeMail: outputDto.user.wxFullName,
|
||||
userPhoto: outputDto.user.userPhoto,
|
||||
joinAt: outputDto.joinAt,
|
||||
isAdmin: outputDto.isAdmin
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
import { MessageEntity, IMessage } from "../../../../core/chat/entity/message";
|
||||
import { MessageOutPutDataDTO } from "src/app/core/chat/repository/dto/messageOutputDTO";
|
||||
import { MessageInputDTO } from "../use-case/message/message-create-use-case.service";
|
||||
|
||||
export class MessageMapper {
|
||||
static toDomain(DTO: MessageOutPutDataDTO) : MessageEntity {
|
||||
return DTO as MessageEntity
|
||||
}
|
||||
|
||||
static fromDomain(entity:IMessage, requestId): MessageInputDTO {
|
||||
return {
|
||||
receiverId: entity.receiverId,
|
||||
canEdit: entity.canEdit,
|
||||
message: entity.message,
|
||||
messageType: entity.messageType,
|
||||
oneShot: entity.oneShot,
|
||||
requireUnlock: entity.requireUnlock,
|
||||
roomId: entity.roomId,
|
||||
senderId: entity.sender.wxUserId,
|
||||
requestId: entity.requestId || requestId,
|
||||
attachment: entity.attachments.map((e)=>({
|
||||
fileType:e.fileType,
|
||||
source: e.source,
|
||||
file: e.file,
|
||||
fileName: e.fileName,
|
||||
applicationId: e.applicationId || 0,
|
||||
docId: Number(e.docId) || 0,
|
||||
mimeType: e.mimeType,
|
||||
description: e.description
|
||||
}))[0] || {}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { BoldRemoveByRoomIdService } from './bold-remove-by-room-id.service';
|
||||
|
||||
describe('BoldRemoveByRoomIdService', () => {
|
||||
let service: BoldRemoveByRoomIdService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
service = TestBed.inject(BoldRemoveByRoomIdService);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -1,33 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { IBoldLocalRepository } from 'src/app/core/chat/repository/bold/bold-local-repository';
|
||||
import { TracingType, XTracerAsync } from 'src/app/services/monitoring/opentelemetry/tracer';
|
||||
import { zodSafeValidation } from 'src/app/utils/zodValidation';
|
||||
import { z } from 'zod';
|
||||
|
||||
|
||||
const BoldRemoveByRoomIdInputSchema = z.object({
|
||||
roomId: z.string()
|
||||
})
|
||||
export type BoldRemoveByRoomIdInput = z.infer<typeof BoldRemoveByRoomIdInputSchema>
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class BoldRemoveByRoomIdService {
|
||||
|
||||
constructor(
|
||||
private boldLocalRepository: IBoldLocalRepository,
|
||||
) { }
|
||||
|
||||
@XTracerAsync({name:'BoldRemoveByRoomIdService', module:'chat', bugPrint: true})
|
||||
async execute(input: BoldRemoveByRoomIdInput, tracing?: TracingType) {
|
||||
|
||||
const validation = zodSafeValidation<any>(BoldRemoveByRoomIdInputSchema, input)
|
||||
|
||||
if(validation.isOk()) {
|
||||
return await this.boldLocalRepository.delete(input.roomId)
|
||||
} else {
|
||||
tracing.hasError("invalid parameter")
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { RoomType } from 'src/app/core/chat/entity/group';
|
||||
import { IRoomLocalRepository } from 'src/app/core/chat/repository/room/room-local-repository';
|
||||
import { IDBoolean } from 'src/app/infra/database/dexie/type';
|
||||
import { ContactRepositoryService } from 'src/app/services/Repositorys/contacts/repository/contacts-repository.service';
|
||||
import { SessionStore } from 'src/app/store/session.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class ContactListService {
|
||||
|
||||
constructor(
|
||||
private contactsRepositoryService: ContactRepositoryService,
|
||||
private roomLocalRepository: IRoomLocalRepository
|
||||
) {}
|
||||
|
||||
async execute() {
|
||||
const [userContact, localDirectRooms] = await Promise.all([
|
||||
this.contactsRepositoryService.getUsers(),
|
||||
this.roomLocalRepository.find({roomType: RoomType.Direct})
|
||||
])
|
||||
|
||||
if(userContact.isOk() && localDirectRooms.isOk()) {
|
||||
const existNames = localDirectRooms.value.filter(e => e.local == IDBoolean.false).map(e => e.roomName);
|
||||
//const existNames = localDirectRooms.value.map(e => e.roomName);
|
||||
|
||||
return userContact.map((list) => {
|
||||
|
||||
return list.data.result.filter((e) => {
|
||||
return !existNames.includes(e.wxFullName) && e.wxUserId != SessionStore.user.UserId
|
||||
})
|
||||
})
|
||||
} else if (userContact.isErr()) {
|
||||
return userContact
|
||||
} else if (localDirectRooms.isErr()) {
|
||||
return localDirectRooms
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { captureAndReraiseAsync } from 'src/app/services/decorators/captureAndReraiseAsync';
|
||||
import { MemberListRemoteRepository } from '../../../data/repository/member/member-list-remote-repository.service';
|
||||
import { UserRemoveListInputDTO } from '../room/room-leave-by-id-use-case.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class RemoveMemberUseCaseService {
|
||||
|
||||
constructor(
|
||||
private memberRemoteDataSourceService: MemberListRemoteRepository,
|
||||
) { }
|
||||
|
||||
|
||||
@captureAndReraiseAsync('RoomRepositoryService/removeMemberToRoom')
|
||||
async execute(data: UserRemoveListInputDTO) {
|
||||
const result = await this.memberRemoteDataSourceService.removeMemberFromRoom(data)
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { captureAndReraiseAsync } from 'src/app/services/decorators/captureAndReraiseAsync';
|
||||
import { z } from 'zod';
|
||||
import { IMemberRemoteRepository } from 'src/app/core/chat/repository/member/member-remote-repository';
|
||||
|
||||
|
||||
export const AddMemberToRoomInputDTOSchema = z.object({
|
||||
id: z.string(),
|
||||
members: z.array(z.number()),
|
||||
});
|
||||
|
||||
export type AddMemberToRoomInputDTO = z.infer<typeof AddMemberToRoomInputDTOSchema>
|
||||
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class AddMemberUseCaseService {
|
||||
|
||||
constructor(
|
||||
private memberRemoteDataSourceService: IMemberRemoteRepository,
|
||||
) { }
|
||||
|
||||
|
||||
|
||||
@captureAndReraiseAsync('RoomRepositoryService/addMemberToRoom')
|
||||
async execute(data: AddMemberToRoomInputDTO) {
|
||||
|
||||
// return this.roomLiveSignalRDataSourceService.addMemberToRoom(data)
|
||||
|
||||
const result = await this.memberRemoteDataSourceService.addMemberToRoom(data)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { z } from "zod";
|
||||
import { ValidateSchema } from 'src/app/services/decorators/validate-schema.decorator';
|
||||
import { IMemberRemoteRepository } from 'src/app/core/chat/repository/member/member-remote-repository';
|
||||
|
||||
// Define the schema for the entire response
|
||||
const MemberSetAdminDTOSchema = z.object({
|
||||
roomId: z.string(),
|
||||
memberId: z.string()
|
||||
});
|
||||
|
||||
export type MemberSetAdminDTO = z.infer<typeof MemberSetAdminDTOSchema>
|
||||
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class MemberAdminUseCaseService {
|
||||
|
||||
constructor(
|
||||
public repository: IMemberRemoteRepository
|
||||
) { }
|
||||
|
||||
@ValidateSchema(MemberSetAdminDTOSchema)
|
||||
execute(input: MemberSetAdminDTO) {
|
||||
|
||||
return this.repository.setAmin(input)
|
||||
}
|
||||
}
|
||||
-61
@@ -1,61 +0,0 @@
|
||||
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<void> {
|
||||
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))
|
||||
]);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { IMemberSocketRepository } from 'src/app/core/chat/repository/member/member-socket-repository';
|
||||
import { z } from 'zod';
|
||||
|
||||
export const RemoveRoomMemberInputSchema = z.object({
|
||||
roomId: z.string(),
|
||||
members: z.number().array()
|
||||
})
|
||||
|
||||
export type RemoveRoomMemberInput = z.infer<typeof RemoveRoomMemberInputSchema>
|
||||
|
||||
|
||||
|
||||
export const RemoveRoomMemberOutputSchema = z.object({
|
||||
userPhoto: z.string().nullable(),
|
||||
wxFullName: z.string().optional(),
|
||||
wxUserId: z.number(),
|
||||
wxeMail: z.string(),
|
||||
}).array()
|
||||
|
||||
export type IRemoveRoomMemberOutput = z.infer<typeof RemoveRoomMemberOutputSchema>
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class MemberRemoveSocketUseCaseService {
|
||||
|
||||
constructor(
|
||||
private socketRepository: IMemberSocketRepository
|
||||
) { }
|
||||
|
||||
async execute(input: RemoveRoomMemberInput) {
|
||||
|
||||
return this.socketRepository.removeMember(input)
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { filter, map } from 'rxjs/operators';
|
||||
import { InstanceId } from '../../chat-service.service';
|
||||
import { MessageEntity } from '../../../../../core/chat/entity/message';
|
||||
import { z } from 'zod';
|
||||
import { IMessageSocketRepository } from 'src/app/core/chat/repository/message/message-socket-repository';
|
||||
|
||||
|
||||
export const ListenMessageByRoomIdNewInputDTOSchema = z.object({
|
||||
roomId: z.string(),
|
||||
});
|
||||
export type ListenMessageByRoomIdNewInputDTO = z.infer<typeof ListenMessageByRoomIdNewInputDTOSchema>
|
||||
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class ListenMessageByRoomIdNewUseCase {
|
||||
|
||||
constructor(
|
||||
private MessageSocketRepositoryService: IMessageSocketRepository
|
||||
) { }
|
||||
|
||||
execute(data: ListenMessageByRoomIdNewInputDTO) {
|
||||
|
||||
return this.MessageSocketRepositoryService.listenToMessages().pipe(
|
||||
map(message => message.data),
|
||||
filter((message) => !message?.requestId?.startsWith(InstanceId) && message?.roomId == data.roomId),
|
||||
map(message => Object.assign(new MessageEntity(), message))
|
||||
)
|
||||
|
||||
}
|
||||
}
|
||||
-27
@@ -1,27 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { filter } from 'rxjs/operators';
|
||||
import { z } from 'zod';
|
||||
import { IMessageSocketRepository } from 'src/app/core/chat/repository/message/message-socket-repository';
|
||||
|
||||
export const ListenMessageUpdateByRoomIdInputDTOSchema = z.object({
|
||||
roomId: z.string(),
|
||||
});
|
||||
export type ListenMessageUpdateByRoomIdInputDTO = z.infer<typeof ListenMessageUpdateByRoomIdInputDTOSchema>
|
||||
|
||||
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class ListenMessageUpdateByRoomIdUseCase {
|
||||
|
||||
constructor(
|
||||
private messageLiveSignalRDataSourceService: IMessageSocketRepository,
|
||||
) { }
|
||||
|
||||
execute(input: ListenMessageUpdateByRoomIdInputDTO) {
|
||||
return this.messageLiveSignalRDataSourceService.listenToUpdateMessages().pipe(
|
||||
filter((message) => input.roomId == message?.roomId )
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { MessageSocketRepositoryService } from 'src/app/module/chat/data/repository/message/message-live-signalr-data-source.service'
|
||||
import { InstanceId } from '../../chat-service.service';
|
||||
import { filter, map } from 'rxjs/operators';
|
||||
import { z } from 'zod';
|
||||
|
||||
export const ListenSendMessageInputDTOSchema = z.object({
|
||||
roomId: z.string(),
|
||||
});
|
||||
export type ListenSendMessageInputDTO = z.infer<typeof ListenSendMessageInputDTOSchema>
|
||||
|
||||
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class ListenSendMessageUseCase {
|
||||
|
||||
constructor(
|
||||
private MessageSocketRepositoryService: MessageSocketRepositoryService
|
||||
) { }
|
||||
|
||||
execute({roomId}: {roomId: string}) {
|
||||
|
||||
return this.MessageSocketRepositoryService.listenToMessages().pipe(
|
||||
map(message => message.data),
|
||||
filter((message) => {
|
||||
|
||||
return message?.requestId?.startsWith(InstanceId) && message?.roomId == roomId
|
||||
}),
|
||||
map(message => message)
|
||||
)
|
||||
|
||||
}
|
||||
}
|
||||
-29
@@ -1,29 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { filter } from 'rxjs/operators';
|
||||
import { SignalRService } from 'src/app/infra/socket/signalR/signal-r.service';
|
||||
import { MessageSocketRepositoryService } from 'src/app/module/chat/data/repository/message/message-live-signalr-data-source.service'
|
||||
import { z } from 'zod';
|
||||
|
||||
export const ListenMessageDeleteByRoomIdInputDTOSchema = z.object({
|
||||
roomId: z.string(),
|
||||
});
|
||||
export type ListenMessageDeleteByRoomIdInputDTO = z.infer<typeof ListenMessageDeleteByRoomIdInputDTOSchema>
|
||||
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class ListenMessageDeleteByRoomIdService {
|
||||
|
||||
constructor(
|
||||
private MessageSocketRepositoryService: MessageSocketRepositoryService,
|
||||
) { }
|
||||
|
||||
execute({roomId}: ListenMessageDeleteByRoomIdInputDTO) {
|
||||
return this.MessageSocketRepositoryService.listenToDeleteMessages().pipe(
|
||||
filter((message) => {
|
||||
return roomId == message?.roomId
|
||||
} )
|
||||
)
|
||||
}
|
||||
}
|
||||
-125
@@ -1,125 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { z } from 'zod';
|
||||
import { AttachmentRemoteDataSourceService } from 'src/app/module/chat/data/repository/attachment/attachment-remote-repository.service'
|
||||
import { AttachmentLocalDataSource } from 'src/app/module/chat/data/repository/attachment/attachment-local-repository.service'
|
||||
import { createBlobUrl } from 'src/app/utils/ToBase64';
|
||||
import { err, Result } from 'neverthrow';
|
||||
import { MessageEntitySchema } from '../../../../../core/chat/entity/message';
|
||||
import { TracingType, XTracerAsync } from 'src/app/services/monitoring/opentelemetry/tracer';
|
||||
import { isHttpResponse } from 'src/app/infra/http/http.service';
|
||||
|
||||
const MessageAttachmentByMessageIdSchema = MessageEntitySchema.pick({
|
||||
$id: true,
|
||||
id: true,
|
||||
attachments: true,
|
||||
})
|
||||
|
||||
export type MessageAttachmentByMessageIdInput = z.infer<typeof MessageAttachmentByMessageIdSchema>
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class MessageAttachmentByMessageIdUseCase {
|
||||
|
||||
constructor(
|
||||
private AttachmentRemoteDataSourceService: AttachmentRemoteDataSourceService,
|
||||
private AttachmentLocalDataSource: AttachmentLocalDataSource
|
||||
) { }
|
||||
|
||||
@XTracerAsync({name:'Message-Attachment-By-MessageIdUseCase', module:'chat', bugPrint: true, waitNThrow: 15000})
|
||||
async execute(input: MessageAttachmentByMessageIdInput, tracing?: TracingType): Promise<Result<string, any>> {
|
||||
|
||||
tracing.setAttribute('messageId', input.id)
|
||||
|
||||
const getLocalAttachment = await this.AttachmentLocalDataSource.findOne({
|
||||
$messageId: input.$id
|
||||
})
|
||||
|
||||
if(getLocalAttachment.isOk() && getLocalAttachment.value) {
|
||||
tracing.setAttribute('download', 'false')
|
||||
|
||||
// has blob
|
||||
if(getLocalAttachment.value.file) {
|
||||
const dataUrl = await createBlobUrl(getLocalAttachment.value.file)
|
||||
|
||||
if(dataUrl.isOk()) {
|
||||
return dataUrl
|
||||
} else {
|
||||
return dataUrl
|
||||
}
|
||||
} else {
|
||||
// has data url
|
||||
return getLocalAttachment.map((e) => {
|
||||
|
||||
// Logger.info('restored file .', {
|
||||
// data: e.base64.slice(0, 100)+'...'
|
||||
// })
|
||||
|
||||
return e.base64
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
tracing.setAttribute('download', 'true')
|
||||
tracing.setAttribute('attachmentId', input.attachments[0].id.toString())
|
||||
|
||||
const httpResult = await this.AttachmentRemoteDataSourceService.getAttachment(input.attachments[0].id)
|
||||
if(httpResult.isErr()) {
|
||||
tracing.hasError('failed to download message attachment', {
|
||||
error: httpResult.error,
|
||||
data: 'document id '+ input.attachments[0].id,
|
||||
messageId: input.id,
|
||||
$messageId: input.$id
|
||||
})
|
||||
|
||||
if(isHttpResponse(httpResult.error)) {
|
||||
tracing.setAttribute('attachmentUrl', httpResult.error.message)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(httpResult.isOk()) {
|
||||
|
||||
const dataUrl = await createBlobUrl(httpResult.value.data)
|
||||
|
||||
if(dataUrl.isOk()) {
|
||||
|
||||
//console.log('done convert')
|
||||
//Logger.info('downloaded file .', {
|
||||
// data: dataUrl.value.slice(0, 100)+'...'
|
||||
//})
|
||||
|
||||
this.AttachmentLocalDataSource.insert({
|
||||
$messageId: input.$id,
|
||||
file: httpResult.value.data,
|
||||
fileType: input.attachments[0].fileType,
|
||||
source: input.attachments[0].source,
|
||||
fileName: input.attachments[0].fileName,
|
||||
applicationId: input.attachments[0].applicationId,
|
||||
docId: input.attachments[0].docId,
|
||||
mimeType: input.attachments[0].mimeType,
|
||||
}).then((e) => {
|
||||
if(e.isErr()) {
|
||||
tracing.hasError('failed to create attachment locally on send message', {
|
||||
error: e.error,
|
||||
// data: dataUrl.value.slice(0, 100)+'...'
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
return dataUrl
|
||||
} else {
|
||||
console.log('dataUrl eerror', dataUrl.error, 'url:,', httpResult.value)
|
||||
return err(false)
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
return httpResult as any
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,222 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { IMessage, MessageAttachmentSource, MessageEntity, MessageEntitySchema, } from '../../../../../core/chat/entity/message';
|
||||
import { z } from 'zod';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { InstanceId } from '../../chat-service.service';
|
||||
import { createBlobFromBase64, createDataURL } from 'src/app/utils/ToBase64';
|
||||
import { zodSafeValidation } from 'src/app/utils/zodValidation';
|
||||
import { Logger } from 'src/app/services/logger/main/service';
|
||||
import { err, Result } from 'neverthrow';
|
||||
import { MessageMapper } from '../../mapper/messageMapper';
|
||||
import { RoomType } from "src/app/core/chat/entity/group";
|
||||
import { TracingType, XTracerAsync } from 'src/app/services/monitoring/opentelemetry/tracer';
|
||||
import { MessageTable } from 'src/app/infra/database/dexie/instance/chat/schema/message';
|
||||
import { MessageAttachmentFileType, MessageOutPutDataDTO } from 'src/app/core/chat/repository/dto/messageOutputDTO';
|
||||
import { IMessageLocalRepository } from 'src/app/core/chat/repository/message/message-local-repository';
|
||||
import { IMessageSocketRepository } from 'src/app/core/chat/repository/message/message-socket-repository';
|
||||
import { IMemberLocalRepository } from 'src/app/core/chat/repository/member/member-local-repository';
|
||||
import { IAttachmentLocalRepository } from 'src/app/core/chat/repository/typing/typing-local-repository';
|
||||
import { base64Schema } from 'src/app/utils/zod';
|
||||
|
||||
|
||||
export const MessageInputDTOSchema = z.object({
|
||||
roomId: z.string().uuid().optional(),
|
||||
receiverId: z.number().optional(),
|
||||
senderId: z.number(),
|
||||
message: z.string().nullable().optional(),
|
||||
messageType: z.number(),
|
||||
canEdit: z.boolean(),
|
||||
oneShot: z.boolean(),
|
||||
requireUnlock: z.boolean(),
|
||||
requestId: z.string(),
|
||||
attachment: z.object({
|
||||
fileType: z.nativeEnum(MessageAttachmentFileType),
|
||||
source: z.nativeEnum(MessageAttachmentSource),
|
||||
file: base64Schema.optional(),
|
||||
fileName: z.string().optional(),
|
||||
applicationId: z.number().optional(),
|
||||
docId: z.number().optional(),
|
||||
mimeType: z.string().nullable().optional(),
|
||||
description: z.string().optional()
|
||||
}).optional()
|
||||
});
|
||||
export type MessageInputDTO = z.infer<typeof MessageInputDTOSchema>
|
||||
|
||||
|
||||
|
||||
export const MessageCreatePutDataDTOSchema = z.object({
|
||||
id: z.string(),
|
||||
roomId: z.string(),
|
||||
sender: z.object({
|
||||
wxUserId: z.number(),
|
||||
wxFullName: z.string(),
|
||||
wxeMail: z.string(),
|
||||
userPhoto: z.string().optional()
|
||||
}),
|
||||
message: z.string().nullable().optional(),
|
||||
messageType: z.number(),
|
||||
sentAt: z.string(),
|
||||
canEdit: z.boolean(),
|
||||
oneShot: z.boolean(),
|
||||
requireUnlock: z.boolean(),
|
||||
requestId: z.string().optional().nullable(),
|
||||
reactions: z.object({
|
||||
id: z.string(),
|
||||
reactedAt: z.string(),
|
||||
reaction: z.string(),
|
||||
sender: z.object({}),
|
||||
}).array(),
|
||||
info: z.array(z.object({
|
||||
memberId: z.number(),
|
||||
readAt: z.string().nullable(),
|
||||
deliverAt: z.string().nullable()
|
||||
})),
|
||||
attachments: z.array(z.object({
|
||||
fileType: z.nativeEnum(MessageAttachmentFileType),
|
||||
source: z.nativeEnum(MessageAttachmentSource),
|
||||
file: z.string().optional(),
|
||||
fileName: z.string().optional(),
|
||||
applicationId: z.number().optional(),
|
||||
docId: z.number().optional(),
|
||||
id: z.string().optional()
|
||||
}))
|
||||
});
|
||||
|
||||
export type MessageCreateOutPutDataDTO = z.infer<typeof MessageCreatePutDataDTOSchema>
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class MessageCreateUseCaseService {
|
||||
|
||||
constructor(
|
||||
private AttachmentLocalRepositoryService: IAttachmentLocalRepository,
|
||||
private messageLocalDataSourceService: IMessageLocalRepository,
|
||||
private messageSocketRepositoryService: IMessageSocketRepository,
|
||||
private MemberListLocalRepository: IMemberLocalRepository
|
||||
) { }
|
||||
|
||||
|
||||
@XTracerAsync({name:'MessageCreateUseCaseService', module:'chat', bugPrint: true, waitNThrow: 5000})
|
||||
async execute(message: IMessage, messageEnum: RoomType, tracing?: TracingType) {
|
||||
|
||||
const validation = zodSafeValidation<IMessage>(MessageEntitySchema, message)
|
||||
|
||||
if(validation.isOk()) {
|
||||
message.sendAttemp++;
|
||||
|
||||
message.requestId = InstanceId +'@'+ uuidv4();
|
||||
message.sending = true;
|
||||
|
||||
const createMessageLocally = await this.messageLocalDataSourceService.insert(message)
|
||||
|
||||
if(createMessageLocally.isOk()) {
|
||||
|
||||
message.$id = createMessageLocally.value
|
||||
|
||||
if(message.hasAttachment) {
|
||||
|
||||
for (const attachment of message.attachments) {
|
||||
|
||||
if(attachment.source != MessageAttachmentSource.Webtrix) {
|
||||
|
||||
this.AttachmentLocalRepositoryService.insert({
|
||||
$messageId: createMessageLocally.value,
|
||||
file: createBlobFromBase64(attachment.file, attachment.mimeType),
|
||||
fileType: attachment.fileType,
|
||||
source: attachment.source,
|
||||
fileName: attachment.fileName,
|
||||
applicationId: attachment.applicationId,
|
||||
docId: attachment.docId,
|
||||
mimeType: attachment.mimeType,
|
||||
base64: createDataURL(attachment.file, attachment.mimeType)
|
||||
}).then((e) => {
|
||||
if(e.isErr()) {
|
||||
Logger.error('failed to create attachment locally on send message', {
|
||||
error: e.error,
|
||||
data: createDataURL(attachment.file, attachment.mimeType).slice(0, 100) +'...'
|
||||
})
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
attachment.safeFile = createDataURL(attachment.file, attachment.mimeType)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//====================
|
||||
message.sending = true
|
||||
|
||||
let sendMessageResult: Result<MessageOutPutDataDTO, any>
|
||||
if(messageEnum == RoomType.Group) {
|
||||
const DTO = MessageMapper.fromDomain(message, message.requestId)
|
||||
sendMessageResult = await this.messageSocketRepositoryService.sendGroupMessage(DTO)
|
||||
} else {
|
||||
const DTO = MessageMapper.fromDomain(message, message.requestId)
|
||||
delete DTO.roomId
|
||||
sendMessageResult = await this.messageSocketRepositoryService.sendDirectMessage(DTO)
|
||||
}
|
||||
|
||||
// return this sendMessageResult
|
||||
|
||||
if(sendMessageResult.isOk()) {
|
||||
|
||||
message.id = sendMessageResult.value.id
|
||||
|
||||
console.log('sendMessageResult', sendMessageResult.value.id)
|
||||
|
||||
if(sendMessageResult.value.sender == undefined || sendMessageResult.value.sender == null) {
|
||||
|
||||
delete sendMessageResult.value.sender
|
||||
}
|
||||
|
||||
let clone: MessageTable = {
|
||||
...sendMessageResult.value,
|
||||
id: sendMessageResult.value.id,
|
||||
$id : message.$id
|
||||
}
|
||||
|
||||
this.messageLocalDataSourceService.update(message.$id, {...clone, sending: false, roomId: clone.roomId}).then((data)=> {
|
||||
if(data.isOk()) {
|
||||
|
||||
} else {
|
||||
tracing.hasError('failed to update send message')
|
||||
console.log(sendMessageResult)
|
||||
console.log(data.error)
|
||||
}
|
||||
})
|
||||
|
||||
return sendMessageResult
|
||||
} else {
|
||||
Logger.error('failed to send message to the server', {
|
||||
error: sendMessageResult.error
|
||||
})
|
||||
await this.messageLocalDataSourceService.update(message.$id, {sending: false, $id: message.$id})
|
||||
return err('no connection')
|
||||
}
|
||||
|
||||
} else {
|
||||
Logger.error('failed to insert locally', {
|
||||
error: createMessageLocally.error.message
|
||||
})
|
||||
}
|
||||
} else {
|
||||
|
||||
if(validation.error.formErrors.fieldErrors.attachments) {
|
||||
Logger.error('failed to send message doe to invalid attachment', {
|
||||
zodErrorList: validation.error.errors,
|
||||
data: message.attachments
|
||||
})
|
||||
} else {
|
||||
Logger.error('failed to send message, validation failed', {
|
||||
zodErrorList: validation.error.errors,
|
||||
data: message
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
-30
@@ -1,30 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { z } from 'zod';
|
||||
import { MessageSocketRepositoryService } from '../../../data/repository/message/message-live-signalr-data-source.service';
|
||||
import { XTracerAsync, TracingType } from 'src/app/services/monitoring/opentelemetry/tracer';
|
||||
|
||||
export const MessageDeleteInputDTOSchema = z.object({
|
||||
requestId: z.string().optional(),
|
||||
roomId: z.string(),
|
||||
messageId: z.string(),
|
||||
senderId: z.number(),
|
||||
});
|
||||
export type MessageDeleteInputDTO = z.infer<typeof MessageDeleteInputDTOSchema>
|
||||
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class MessageDeleteLiveUseCaseService {
|
||||
constructor(
|
||||
public repository: MessageSocketRepositoryService
|
||||
) { }
|
||||
|
||||
@XTracerAsync({name:'MessageDeleteLiveUseCaseService', module:'chat', bugPrint: true, waitNThrow: 5000})
|
||||
async execute(data: MessageDeleteInputDTO, tracing?: TracingType) {
|
||||
tracing.log('MessageDeleteLiveUseCaseService payload', {
|
||||
data: data
|
||||
})
|
||||
return this.repository.sendMessageDelete(data)
|
||||
}
|
||||
}
|
||||
-68
@@ -1,68 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { AttachmentRemoteDataSourceService } from 'src/app/module/chat/data/repository/attachment/attachment-remote-repository.service'
|
||||
import { Logger } from 'src/app/services/logger/main/service';
|
||||
import { convertBlobToDataURL, createBlobUrl } from 'src/app/utils/ToBase64';
|
||||
import { AttachmentLocalDataSource } from 'src/app/module/chat/data/repository/attachment/attachment-local-repository.service'
|
||||
import { z } from 'zod';
|
||||
import { zodSafeValidation } from 'src/app/utils/zodValidation';
|
||||
import { IMessage, MessageEntitySchema } from 'src/app/core/chat/entity/message';
|
||||
|
||||
const DownloadMessageAttachmentByMessageIdSchema = z.object({
|
||||
$messageId: z.string(),
|
||||
id: z.string()
|
||||
})
|
||||
|
||||
export type DownloadMessageAttachmentByMessageId = z.infer<typeof DownloadMessageAttachmentByMessageIdSchema>
|
||||
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class DownloadMessageAttachmentUserCaseService {
|
||||
|
||||
constructor(
|
||||
private AttachmentRemoteDataSourceService: AttachmentRemoteDataSourceService,
|
||||
private AttachmentLocalDataSource: AttachmentLocalDataSource
|
||||
) { }
|
||||
|
||||
async execute(input: DownloadMessageAttachmentByMessageId) {
|
||||
|
||||
const validation = zodSafeValidation<IMessage>(DownloadMessageAttachmentByMessageIdSchema, input)
|
||||
|
||||
if(validation.isOk()) {
|
||||
|
||||
const httpResult = await this.AttachmentRemoteDataSourceService.getAttachment(input.id)
|
||||
return httpResult.asyncMap(async (response) => {
|
||||
|
||||
const dataUrl = await createBlobUrl(response.data)
|
||||
|
||||
if(dataUrl.isOk()) {
|
||||
|
||||
Logger.info('downloaded file #1', {
|
||||
// data: dataUrl.slice(0, 100)+'...',
|
||||
context: 'DownloadMessageAttachmentUserCaseService'
|
||||
})
|
||||
|
||||
this.AttachmentLocalDataSource.insert({
|
||||
$messageId: input.$messageId,
|
||||
id: input.id,
|
||||
file: response.data,
|
||||
})
|
||||
|
||||
return dataUrl.value
|
||||
} else {
|
||||
|
||||
}
|
||||
})
|
||||
} else {
|
||||
|
||||
Logger.error('failed to download message doe to invalid attachment', {
|
||||
zodErrorList: validation.error.errors,
|
||||
data: input
|
||||
})
|
||||
|
||||
return validation
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
-46
@@ -1,46 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { MessageAttachmentByMessageIdInput } from './message-attachment-by-message-id.service';
|
||||
import { AttachmentRemoteDataSourceService } from 'src/app/module/chat/data/repository/attachment/attachment-remote-repository.service'
|
||||
import { AttachmentLocalDataSource } from 'src/app/module/chat/data/repository/attachment/attachment-local-repository.service'
|
||||
import { err, Result } from 'neverthrow';
|
||||
import { AttachmentTableSchema } from 'src/app/infra/database/dexie/instance/chat/schema/attachment';
|
||||
import { z } from 'zod';
|
||||
import { createBlobUrl } from 'src/app/utils/ToBase64';
|
||||
|
||||
const GetMessageAttachmentLocallyByMessageIdSchema = AttachmentTableSchema.pick({
|
||||
$messageId: true
|
||||
})
|
||||
|
||||
export type GetMessageAttachmentLocallyByMessageId = z.infer<typeof GetMessageAttachmentLocallyByMessageIdSchema>
|
||||
|
||||
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class GetMessageAttachmentLocallyUseCaseService {
|
||||
|
||||
constructor(
|
||||
private AttachmentRemoteDataSourceService: AttachmentRemoteDataSourceService,
|
||||
private AttachmentLocalDataSource: AttachmentLocalDataSource
|
||||
) { }
|
||||
|
||||
|
||||
async execute(input: GetMessageAttachmentLocallyByMessageId): Promise<Result<string, any>> {
|
||||
|
||||
const getLocalAttachment = await this.AttachmentLocalDataSource.findOne({
|
||||
$messageId: input.$messageId
|
||||
})
|
||||
|
||||
if(getLocalAttachment.isOk()) {
|
||||
if(getLocalAttachment.value) {
|
||||
const dataUrl = await createBlobUrl(getLocalAttachment.value.file)
|
||||
|
||||
return dataUrl
|
||||
}
|
||||
} else {
|
||||
return err(getLocalAttachment.error)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { IMessageLocalRepository } from 'src/app/core/chat/repository/message/message-local-repository';
|
||||
import { z } from 'zod';
|
||||
|
||||
const messageLocalGetByIdServiceInputSchema = z.object({
|
||||
roomId: z.string().uuid().optional(),
|
||||
receiverId: z.string().optional(),
|
||||
})
|
||||
|
||||
export type IMessageLocalGetByIdServiceInput = z.infer<typeof messageLocalGetByIdServiceInputSchema>
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class MessageLocalGetByIdService {
|
||||
|
||||
constructor(
|
||||
private messageLocalRepository: IMessageLocalRepository
|
||||
) { }
|
||||
|
||||
execute(input: IMessageLocalGetByIdServiceInput) {
|
||||
if(input.roomId && input.receiverId) {
|
||||
|
||||
return this.messageLocalRepository.getDirectMessages({
|
||||
roomId: input.roomId,
|
||||
receiverId: input.receiverId
|
||||
})
|
||||
}
|
||||
else if(input.roomId) {
|
||||
return this.messageLocalRepository.find({roomId: input.roomId})
|
||||
} else if (input.receiverId) {
|
||||
return this.messageLocalRepository.find({receiverId: parseInt(input.receiverId)})
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
-43
@@ -1,43 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { z } from 'zod';
|
||||
import { MessageLocalDataSourceService } from 'src/app/module/chat/data/repository/message/message-local-data-source.service'
|
||||
import { MessageSocketRepositoryService } from 'src/app/module/chat/data/repository/message/message-live-signalr-data-source.service'
|
||||
import { SessionStore } from 'src/app/store/session.service';
|
||||
|
||||
const MessageMarkAllMessageAsReadByRoomIdInputSchema = z.object({
|
||||
roomId: z.string(),
|
||||
})
|
||||
|
||||
export type MessageMarkAllMessageAsReadByRoomIdInputSchema = z.infer<typeof MessageMarkAllMessageAsReadByRoomIdInputSchema>
|
||||
|
||||
|
||||
/**
|
||||
* @description avoid using it, avoid duplicate query. do it on the UI layer as the component load the message.
|
||||
*/
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class MessageMarkAllMessageAsReadByRoomIdService {
|
||||
|
||||
constructor(
|
||||
private MessageLocalDataSourceService: MessageLocalDataSourceService,
|
||||
private MessageSocketRepositoryService: MessageSocketRepositoryService
|
||||
) { }
|
||||
|
||||
|
||||
async execute(input: MessageMarkAllMessageAsReadByRoomIdInputSchema) {
|
||||
const messages = await this.MessageLocalDataSourceService.find({roomId:input.roomId})
|
||||
|
||||
if(messages.isOk()) {
|
||||
for(const message of messages.value) {
|
||||
this.MessageSocketRepositoryService.sendReadAt({
|
||||
memberId: SessionStore.user.UserId,
|
||||
messageId: message.id,
|
||||
roomId: input.roomId,
|
||||
requestId: 'uuid'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { MessageSocketRepositoryService } from '../../../data/repository/message/message-live-signalr-data-source.service';
|
||||
import { XTracerAsync, TracingType } from 'src/app/services/monitoring/opentelemetry/tracer';
|
||||
import { z } from 'zod';
|
||||
|
||||
export const MessageMarkAsReadInputSchema = z.object({
|
||||
memberId: z.number(),
|
||||
messageId: z.string(),
|
||||
roomId: z.string(),
|
||||
requestId: z.string()
|
||||
})
|
||||
|
||||
export type MessageMarkAsReadInput = z.infer<typeof MessageMarkAsReadInputSchema>
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class MessageMarkAsReadUseCaseService {
|
||||
|
||||
constructor(
|
||||
private MessageSocketRepositoryService: MessageSocketRepositoryService,
|
||||
) { }
|
||||
|
||||
|
||||
@XTracerAsync({name:'MessageMarkAsReadUseCaseService', module:'chat', bugPrint: true, waitNThrow: 5000})
|
||||
async execute(sendReadAt: MessageMarkAsReadInput, tracing?: TracingType) {
|
||||
const result = await this.MessageSocketRepositoryService.sendReadAt(sendReadAt as any)
|
||||
|
||||
if(result.isErr()) {
|
||||
tracing.setAttribute('meesageId', sendReadAt.messageId)
|
||||
tracing.hasError('failed to read message')
|
||||
}
|
||||
|
||||
return result
|
||||
|
||||
}
|
||||
}
|
||||
-31
@@ -1,31 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { object, z } from 'zod';
|
||||
import { ValidateSchema } from 'src/app/services/decorators/validate-schema.decorator';
|
||||
import { MessageRemoteDataSourceService } from '../../../data/repository/message/message-remote-data-source.service';
|
||||
import { MessageSocketRepositoryService } from '../../../data/repository/message/message-live-signalr-data-source.service';
|
||||
|
||||
|
||||
const MessageReactionInputDTOSchema = z.object({
|
||||
memberId: z.number(),
|
||||
messageId: z.string(),
|
||||
roomId: z.string(),
|
||||
reaction: z.string(),
|
||||
requestId: z.string().optional()
|
||||
})
|
||||
|
||||
export type MessageReactionInput = z.infer< typeof MessageReactionInputDTOSchema>
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class MessageReactionUseCaseService {
|
||||
|
||||
constructor(
|
||||
public repository: MessageSocketRepositoryService
|
||||
) { }
|
||||
|
||||
@ValidateSchema(MessageReactionInputDTOSchema)
|
||||
execute(input: MessageReactionInput) {
|
||||
return this.repository.reactToMessageSocket(input)
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { z } from 'zod';
|
||||
import { ValidateSchema } from 'src/app/services/decorators/validate-schema.decorator';
|
||||
import { MessageRemoteDataSourceService } from '../../../data/repository/message/message-remote-data-source.service';
|
||||
import { MessageSocketRepositoryService } from '../../../data/repository/message/message-live-signalr-data-source.service';
|
||||
|
||||
|
||||
const MessageUpdateInputDTOSchema = z.object({
|
||||
memberId: z.number(),
|
||||
messageId: z.string(),
|
||||
roomId: z.string(),
|
||||
message: z.string().optional().nullable(),
|
||||
requestId: z.string().optional()
|
||||
})
|
||||
|
||||
export type MessageUpdateInput = z.infer< typeof MessageUpdateInputDTOSchema>
|
||||
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class MessageUpdateUseCaseService {
|
||||
|
||||
constructor(
|
||||
public repository: MessageSocketRepositoryService
|
||||
) { }
|
||||
|
||||
@ValidateSchema(MessageUpdateInputDTOSchema)
|
||||
execute(input: MessageUpdateInput) {
|
||||
return this.repository.updateMessage(input);
|
||||
}
|
||||
|
||||
}
|
||||
-118
@@ -1,118 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { MessageLocalDataSourceService } from '../../../data/repository/message/message-local-data-source.service';
|
||||
import { MessageSocketRepositoryService } from '../../../data/repository/message/message-live-signalr-data-source.service';
|
||||
import { InstanceId } from '../../chat-service.service';
|
||||
import { MessageMapper } from '../../mapper/messageMapper';
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { AttachmentLocalDataSource } from '../../../data/repository/attachment/attachment-local-repository.service';
|
||||
import { RoomLocalRepository } from '../../../data/repository/room/room-local-repository.service';
|
||||
import { MemberListLocalRepository } from 'src/app/module/chat/data/repository/member/member-list-local-repository.service'
|
||||
import { Result } from 'neverthrow';
|
||||
import { RoomType } from 'src/app/core/chat/entity/group';
|
||||
import { MessageTable } from 'src/app/infra/database/dexie/instance/chat/schema/message';
|
||||
import { MessageOutPutDataDTO } from 'src/app/core/chat/repository/dto/messageOutputDTO';
|
||||
import { IDBoolean } from 'src/app/infra/database/dexie/type';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class SendLocalMessagesUseCaseService {
|
||||
|
||||
constructor(
|
||||
private MessageSocketRepositoryService: MessageSocketRepositoryService,
|
||||
private messageLocalDataSourceService: MessageLocalDataSourceService,
|
||||
private AttachmentRepositoryService: AttachmentLocalDataSource,
|
||||
private roomLocalDataSourceService: RoomLocalRepository,
|
||||
private MemberListLocalRepository: MemberListLocalRepository,
|
||||
private messageSocketRepositoryService: MessageSocketRepositoryService,
|
||||
) { }
|
||||
|
||||
async execute() {
|
||||
|
||||
const allRooms = await this.roomLocalDataSourceService.findAll()
|
||||
const messages = await this.messageLocalDataSourceService.getOfflineMessages()
|
||||
|
||||
if(allRooms.isOk()) {
|
||||
if(allRooms.value.length == 0) {
|
||||
|
||||
} else {
|
||||
//const removeLocalRooms = allRooms.value.filter((e)=> e.local == IDBoolean.false)
|
||||
|
||||
console.log({localM: messages});
|
||||
|
||||
for(const message of messages) {
|
||||
const room = allRooms.value.find(e => e.id == message.roomId || e.$id == message.roomId)
|
||||
|
||||
if(room) {
|
||||
|
||||
const attachments = await this.AttachmentRepositoryService.find({$messageId: message.$id})
|
||||
|
||||
if(attachments.isOk()) {
|
||||
|
||||
message.attachments = attachments.value.map(e => ({
|
||||
fileType: e.fileType,
|
||||
source: e.source,
|
||||
fileName: e.fileName,
|
||||
applicationId: e.applicationId,
|
||||
docId: e.docId,
|
||||
id: e.id,
|
||||
mimeType: e.mimeType,
|
||||
description: e.description,
|
||||
file: e.base64.split(',')[1]
|
||||
}))
|
||||
console.log('to upload', messages)
|
||||
const requestId = InstanceId +'@'+ uuidv4();
|
||||
|
||||
await this.messageLocalDataSourceService.update(message.$id, { sending: true })
|
||||
|
||||
let sendMessageResult: Result<MessageOutPutDataDTO, any>
|
||||
if(room.roomType == RoomType.Group) {
|
||||
const DTO = MessageMapper.fromDomain(message, message.requestId)
|
||||
sendMessageResult = await this.MessageSocketRepositoryService.sendGroupMessage(DTO)
|
||||
} else {
|
||||
|
||||
const DTO = MessageMapper.fromDomain(message, message.requestId)
|
||||
sendMessageResult = await this.messageSocketRepositoryService.sendDirectMessage(DTO)
|
||||
|
||||
if(sendMessageResult.isOk() && room.local == IDBoolean.true) {
|
||||
|
||||
this.roomLocalDataSourceService.update(room.$id, {
|
||||
local: IDBoolean.false,
|
||||
id: sendMessageResult.value.roomId
|
||||
})
|
||||
room.local = IDBoolean.false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(sendMessageResult?.isOk()) {
|
||||
|
||||
if(sendMessageResult.value.sender == undefined || sendMessageResult.value.sender == null) {
|
||||
|
||||
delete sendMessageResult.value.sender
|
||||
}
|
||||
|
||||
let clone: MessageTable = {
|
||||
...sendMessageResult.value,
|
||||
id: sendMessageResult.value.id,
|
||||
$id : message.$id
|
||||
}
|
||||
|
||||
clone.sending = false
|
||||
console.log({clone})
|
||||
console.log('send message local '+ messages.length)
|
||||
|
||||
this.messageLocalDataSourceService.update(message.$id, {id: sendMessageResult.value.id, sending: false})
|
||||
} else {
|
||||
this.messageLocalDataSourceService.update(message.$id, {sending: false})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { MessageLocalDataSourceService } from '../../../data/repository/message/message-local-data-source.service';
|
||||
import { messageListDetermineChanges } from '../../../data/async/list/rooms/messageListChangedetector';
|
||||
import { MessageRemoteDataSourceService } from '../../../data/repository/message/message-remote-data-source.service';
|
||||
import { MessageSocketRepositoryService } from '../../../data/repository/message/message-live-signalr-data-source.service';
|
||||
import { ok } from 'neverthrow';
|
||||
import { RoomLocalRepository } from '../../../data/repository/room/room-local-repository.service';
|
||||
import { Logger } from 'src/app/services/logger/main/service';
|
||||
import { XTracerAsync, TracingType } from 'src/app/services/monitoring/opentelemetry/tracer';
|
||||
import { MessageTable } from 'src/app/infra/database/dexie/instance/chat/schema/message';
|
||||
import { IDBoolean } from 'src/app/infra/database/dexie/type';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class SyncAllRoomMessagesService {
|
||||
|
||||
constructor(
|
||||
private messageLocalDataSourceService: MessageLocalDataSourceService,
|
||||
private messageRemoteDataSourceService: MessageRemoteDataSourceService,
|
||||
private MessageSocketRepositoryService: MessageSocketRepositoryService,
|
||||
private roomLocalDataSourceService: RoomLocalRepository,
|
||||
) { }
|
||||
|
||||
@XTracerAsync({name:'SyncAllRoomMessagesService', module:'chat', bugPrint: true})
|
||||
async execute(tracing?: TracingType) {
|
||||
|
||||
const allRooms = await this.roomLocalDataSourceService.findAll()
|
||||
|
||||
if(allRooms.isOk()) {
|
||||
if(allRooms.value.length == 0) {
|
||||
tracing.addEvent('no need to sync')
|
||||
} else {
|
||||
tracing.addEvent('total sync '+ allRooms.value.length)
|
||||
}
|
||||
|
||||
let n =0
|
||||
|
||||
const removeLocalRooms = allRooms.value.filter((e)=> e.local != IDBoolean.true)
|
||||
|
||||
const roomPromises = removeLocalRooms.map(async (room) => {
|
||||
const [result, localResult] = await Promise.all([
|
||||
this.messageRemoteDataSourceService.getMessagesFromRoom(room.id),
|
||||
this.messageLocalDataSourceService.getItems(room.id)
|
||||
]);
|
||||
|
||||
tracing.addEvent('async n ' + n);
|
||||
n++;
|
||||
|
||||
if (result.isOk()) {
|
||||
const { addedItems, changedItems, deletedItems } = messageListDetermineChanges(result.value.data, localResult);
|
||||
|
||||
for (const message of changedItems) {
|
||||
|
||||
let clone: MessageTable = { ...message, roomId: room.id };
|
||||
this.messageLocalDataSourceService.update(clone.$id, clone);
|
||||
}
|
||||
|
||||
for (const message of addedItems) {
|
||||
let clone: MessageTable = { ...message, roomId: room.id };
|
||||
// You can perform operations with addedItems here if needed
|
||||
}
|
||||
|
||||
this.messageLocalDataSourceService.insertMany(addedItems.reverse().map(e => {
|
||||
e.origin = 'history'
|
||||
return e
|
||||
}));
|
||||
} else {
|
||||
Logger.error('failed to get room message ' + room.id);
|
||||
}
|
||||
});
|
||||
|
||||
// Wait for all the promises to resolve
|
||||
await Promise.all(roomPromises);
|
||||
|
||||
return ok(true)
|
||||
} else {
|
||||
console.log('sync all error', allRooms)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,131 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { filter, map } from 'rxjs/operators';
|
||||
import { IMessageSocketRepository } from 'src/app/core/chat/repository/message/message-socket-repository';
|
||||
import { MessageEntity } from 'src/app/core/chat/entity/message';
|
||||
import { IBoldLocalRepository } from 'src/app/core/chat/repository/bold/bold-local-repository';
|
||||
import { IMessageLocalRepository } from 'src/app/core/chat/repository/message/message-local-repository';
|
||||
import { InstanceId } from '../../chat-service.service';
|
||||
import { HttpAdapter } from 'src/app/infra/http/adapter';
|
||||
import { SessionStore } from 'src/app/store/session.service';
|
||||
import { TracingType, XTracerAsync } from 'src/app/services/monitoring/opentelemetry/tracer';
|
||||
import { IRoomLocalRepository } from 'src/app/core/chat/repository/room/room-local-repository';
|
||||
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 { messageListDetermineChanges } from '../../../data/async/list/rooms/messageListChangedetector';
|
||||
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class RoomBoldSyncUseCaseService {
|
||||
|
||||
constructor(
|
||||
private MessageSocketRepositoryService: IMessageSocketRepository,
|
||||
private boldLocalRepository: IBoldLocalRepository,
|
||||
private http: HttpAdapter,
|
||||
private messageLocalRepository: IMessageLocalRepository,
|
||||
private roomLocalDataSourceService: IRoomLocalRepository,
|
||||
) {
|
||||
this.listenToIncomingMessage();
|
||||
// this.loadHistory()
|
||||
//this.onInsertToDB()
|
||||
this.listenToUpdateMessages();
|
||||
this.loadHistory()
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @description listen to all incoming message and set bold to true
|
||||
*/
|
||||
private listenToIncomingMessage() {
|
||||
return this.MessageSocketRepositoryService.listenToMessages().pipe(
|
||||
map(message => message.data),
|
||||
filter((message) => !message?.requestId?.startsWith(InstanceId)),
|
||||
map(message => Object.assign(new MessageEntity(), message)),
|
||||
filter((message) => !message.meSender())
|
||||
).subscribe(async (message) => {
|
||||
|
||||
const result = await this.boldLocalRepository.findOne({roomId: message.roomId})
|
||||
|
||||
if(result.isOk() && !result.value) {
|
||||
const result = await this.boldLocalRepository.insert({roomId: message.roomId, bold: 1})
|
||||
} else if(result.isOk() && result.value.bold == 0) {
|
||||
const result = await this.boldLocalRepository.update(message.roomId, {bold: 1})
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @description Listen to all update message. If the incoming updated message has readAt my me and is the last message then remove bold
|
||||
*/
|
||||
private listenToUpdateMessages() {
|
||||
return this.MessageSocketRepositoryService.listenToUpdateMessages().pipe(
|
||||
filter((message) => !message?.requestId?.startsWith(InstanceId)),
|
||||
map(message => Object.assign(new MessageEntity(), message))
|
||||
).subscribe(async (message) => {
|
||||
|
||||
const haveSeen = MessageEntity.haveSeen(message.info)
|
||||
|
||||
if(haveSeen) {
|
||||
|
||||
const result = await this.boldLocalRepository.findOne({roomId: message.roomId})
|
||||
|
||||
if(result.isOk() && result.value?.bold == 1) {
|
||||
const lastMessage = await this.roomLocalDataSourceService.findOne({id: message.roomId})
|
||||
if(lastMessage.isOk()) {
|
||||
if(lastMessage.value.messages[0].id == message.id) {
|
||||
const result = await this.boldLocalRepository.update(message.roomId, {bold: 0})
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @description set bold base on the last message on load history. If the last message has readAt by me then remove bold in case not set bold
|
||||
*/
|
||||
@XTracerAsync({name:'RoomBoldSyncUseCaseService/loadHistory', module:'chat', bugPrint: true})
|
||||
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.roomLocalDataSourceService.findOne({id: roomId})
|
||||
|
||||
const message = Object.assign(new MessageEntity(), loadHistoryFirstMessage)
|
||||
const haveSeen = message.haveSeen()
|
||||
|
||||
if(haveSeen ===false && message.meSender() == false) {
|
||||
await this.boldLocalRepository.open()
|
||||
const result = await this.boldLocalRepository.findOne({roomId: roomId})
|
||||
|
||||
if(result.isOk() && !result.value) {
|
||||
const result = await this.boldLocalRepository.insert({roomId: roomId, bold: 1})
|
||||
} else if(result.isOk() && result.value.bold == 0) {
|
||||
const result = await this.boldLocalRepository.update(roomId, {bold: 1})
|
||||
} else {
|
||||
// tracing.hasError("failed to set bold",{})
|
||||
}
|
||||
} else {
|
||||
const result = await this.boldLocalRepository.update(roomId, {bold: 0})
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { z } from 'zod';
|
||||
import { IRoomLocalRepository } from 'src/app/core/chat/repository/room/room-local-repository';
|
||||
import { SessionStore } from 'src/app/store/session.service';
|
||||
import { RoomType } from 'src/app/core/chat/entity/group';
|
||||
import { IDBoolean } from 'src/app/infra/database/dexie/type';
|
||||
|
||||
|
||||
export const RoomCreateLocalDirectMessageInputDTOSchema = z.object({
|
||||
roomName: z.string(),
|
||||
members: z.array(z.number()),
|
||||
receiverId: z.number().optional(),
|
||||
});
|
||||
export type RoomCreateLocalDirectMessageInputDTOInputDTO = z.infer<typeof RoomCreateLocalDirectMessageInputDTOSchema>
|
||||
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class RoomCreateLocalDirectMessageService {
|
||||
|
||||
constructor(
|
||||
private roomLocalRepository: IRoomLocalRepository
|
||||
) { }
|
||||
|
||||
async execute(input: RoomCreateLocalDirectMessageInputDTOInputDTO) {
|
||||
return await this.roomLocalRepository.insert({
|
||||
roomName: input.roomName,
|
||||
bold: 0,
|
||||
createdAt: new Date().toISOString(),
|
||||
createdBy: {
|
||||
userPhoto: '',
|
||||
wxeMail: SessionStore.user.Email,
|
||||
wxFullName: SessionStore.user.FullName,
|
||||
wxUserId: SessionStore.user.UserId
|
||||
},
|
||||
$id: input.receiverId.toString(),
|
||||
messages: [],
|
||||
roomType: RoomType.Direct,
|
||||
local: IDBoolean.true,
|
||||
receiverId: input.receiverId,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { SessionStore } from 'src/app/store/session.service';
|
||||
import { TracingType, XTracerAsync } from 'src/app/services/monitoring/opentelemetry/tracer';
|
||||
import { z } from "zod";
|
||||
import { IRoomRemoteRepository } from 'src/app/core/chat/repository/room/room-remote-repository';
|
||||
import { IRoomLocalRepository } from 'src/app/core/chat/repository/room/room-local-repository';
|
||||
import { IRoomSocketRepository } from 'src/app/core/chat/repository/room/room-socket-repository';
|
||||
|
||||
export const CreateRoomInputDTOSchema = z.object({
|
||||
roomName: z.string(),
|
||||
createdBy: z.number(),
|
||||
roomType: z.number(),
|
||||
expirationDate: z.string().nullable().optional(),
|
||||
members: z.array(z.number())
|
||||
});
|
||||
export type CreateRoomInputDTO = z.infer<typeof CreateRoomInputDTOSchema>
|
||||
|
||||
|
||||
export const RoomOutPutDTOSchema = z.object({
|
||||
success: z.boolean(),
|
||||
message: z.string(),
|
||||
data: z.object({
|
||||
id: z.string(),
|
||||
roomName: z.string(),
|
||||
createdBy: z.any().nullable(),
|
||||
createdAt: z.string(),
|
||||
expirationDate: z.string().nullable(),
|
||||
roomType: z.any()
|
||||
})
|
||||
});
|
||||
export type RoomOutPutDTO = z.infer<typeof RoomOutPutDTOSchema>
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class CreateRoomUseCaseService {
|
||||
|
||||
constructor(
|
||||
private roomRemoteDataSourceService: IRoomRemoteRepository,
|
||||
private roomLocalDataSourceService: IRoomLocalRepository,
|
||||
private RoomSocketRepositoryService: IRoomSocketRepository
|
||||
) { }
|
||||
|
||||
@XTracerAsync({name:'room-create-use-case.service', module:'chat', bugPrint: true, waitNThrow: 5000})
|
||||
async execute(data: CreateRoomInputDTO, tracing?: TracingType) {
|
||||
|
||||
const result = await this.RoomSocketRepositoryService.CreateGroup(data)
|
||||
|
||||
console.log('history', result)
|
||||
// const result = await this.roomRemoteDataSourceService.createRoom(data)
|
||||
|
||||
if(result.isOk()) {
|
||||
|
||||
return result
|
||||
} else {
|
||||
tracing.hasError("socket close");
|
||||
console.log(result.error)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { captureAndReraiseAsync } from 'src/app/services/decorators/captureAndReraiseAsync';
|
||||
import { z } from "zod";
|
||||
import { IRoomRemoteRepository } from 'src/app/core/chat/repository/room/room-remote-repository';
|
||||
import { IRoomLocalRepository } from 'src/app/core/chat/repository/room/room-local-repository';
|
||||
import { isHttpResponse } from 'src/app/infra/http/http.service';
|
||||
|
||||
export const DeleteRoomByIdInputDTOSchema = z.string()
|
||||
export type DeleteRoomByIdInputDTO = z.infer<typeof DeleteRoomByIdInputDTOSchema>
|
||||
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class DeleteRoomUseCaseService {
|
||||
|
||||
constructor(
|
||||
private roomRemoteDataSourceService: IRoomRemoteRepository,
|
||||
// private roomMemoryDataSourceService: Store<RoomRemoteDataSourceState>,
|
||||
private roomLocalDataSourceService: IRoomLocalRepository,
|
||||
) { }
|
||||
|
||||
|
||||
@captureAndReraiseAsync('RoomRepositoryService/deleteRoomById')
|
||||
async execute(id: DeleteRoomByIdInputDTO) {
|
||||
const result = await this.roomRemoteDataSourceService.deleteRoom(id)
|
||||
|
||||
if(result.isOk()) {
|
||||
|
||||
const room = await this.roomLocalDataSourceService.findOne({
|
||||
id: id
|
||||
})
|
||||
|
||||
if(room.isOk()) {
|
||||
const result = await this.roomLocalDataSourceService.delete(room.value.$id)
|
||||
}
|
||||
|
||||
return result
|
||||
} else if (isHttpResponse(result.error)) {
|
||||
if(result.error.status == 404) {
|
||||
const room = await this.roomLocalDataSourceService.findOne({
|
||||
id: id
|
||||
})
|
||||
|
||||
if(room.isOk()) {
|
||||
const result = await this.roomLocalDataSourceService.delete(room.value.$id)
|
||||
}
|
||||
}
|
||||
// this.httpErrorHandle.httpStatusHandle(result.error)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { filter } from 'rxjs/operators';
|
||||
import { IRoomLocalRepository } from 'src/app/core/chat/repository/room/room-local-repository';
|
||||
import { z } from 'zod';
|
||||
|
||||
const RoomDirectOnSetIdUseCaseInputSchema = z.object({
|
||||
$roomId: z.string()
|
||||
})
|
||||
|
||||
export type RoomDirectOnSetIdUseCaseInputSchema = z.infer<typeof RoomDirectOnSetIdUseCaseInputSchema>
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class RoomDirectOnSetIdUseCaseService {
|
||||
|
||||
constructor(
|
||||
private roomLocalRepository: IRoomLocalRepository
|
||||
) { }
|
||||
|
||||
execute(input: RoomDirectOnSetIdUseCaseInputSchema) {
|
||||
|
||||
return this.roomLocalRepository.OnSetIdToDirectRoom().pipe(
|
||||
filter((data)=> data?.$id == input.$roomId)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,129 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { isHttpResponse } from 'src/app/infra/http/http.service';
|
||||
import { captureAndReraiseAsync } from 'src/app/services/decorators/captureAndReraiseAsync';
|
||||
import { z } from 'zod';
|
||||
import { IRoomRemoteRepository } from 'src/app/core/chat/repository/room/room-remote-repository';
|
||||
import { IMemberLocalRepository } from 'src/app/core/chat/repository/member/member-local-repository';
|
||||
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 { diff, addedDiff, deletedDiff, updatedDiff, detailedDiff } from 'deep-object-diff';
|
||||
import { zodSafeValidation } from 'src/app/utils/zodValidation';
|
||||
import { CronJobService } from 'src/app/utils/task-scheduler'
|
||||
|
||||
const UserSchema = z.object({
|
||||
wxUserId: z.number(),
|
||||
wxFullName: z.string(),
|
||||
wxeMail: z.string(),
|
||||
userPhoto: z.string().nullable(),
|
||||
});
|
||||
|
||||
const MemberSchema = z.object({
|
||||
id: z.string(),
|
||||
user: UserSchema,
|
||||
joinAt: z.string(),
|
||||
isAdmin: z.boolean()
|
||||
});
|
||||
|
||||
export const RoomByIdOutputDTOSchema = z.object({
|
||||
success: z.boolean(),
|
||||
message: z.string(),
|
||||
data: z.object({
|
||||
id: z.string(),
|
||||
roomName: z.string(),
|
||||
createdBy: UserSchema,
|
||||
createdAt: z.string(),
|
||||
expirationDate: z.string().nullable(),
|
||||
roomType: z.number(),
|
||||
members: z.array(MemberSchema),
|
||||
}),
|
||||
})
|
||||
|
||||
export type RoomByIdMemberItemOutputDTO = z.infer<typeof MemberSchema>
|
||||
export type RoomByIdOutputDTO = z.infer<typeof RoomByIdOutputDTOSchema>
|
||||
|
||||
|
||||
|
||||
export const RoomByIdInputDTOSchema = z.string()
|
||||
export type RoomByIdInputDTO = z.infer<typeof RoomByIdInputDTOSchema>
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class GetRoomByIdUseCaseService {
|
||||
|
||||
constructor(
|
||||
private roomRemoteDataSourceService: IRoomRemoteRepository,
|
||||
private roomLocalDataSourceService: IRoomLocalRepository,
|
||||
private MemberListLocalRepository: IMemberLocalRepository,
|
||||
private CronJobService: CronJobService
|
||||
) { }
|
||||
|
||||
@captureAndReraiseAsync('RoomRepositoryService/getRoomById')
|
||||
async execute(id: RoomByIdInputDTO) {
|
||||
|
||||
const result = await this.roomRemoteDataSourceService.getRoom(id)
|
||||
|
||||
if(result.isOk()) {
|
||||
const validData = zodSafeValidation<RoomByIdOutputDTO>(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) {
|
||||
const room = GetRoomByIdMapper.toDomain(validData.value)
|
||||
|
||||
const added: Partial<RoomEntity> = addedDiff(getRoomById.value, room);
|
||||
const deleted: Partial<RoomEntity> = deletedDiff(getRoomById.value, room);
|
||||
const updated: Partial<RoomEntity> = 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) {
|
||||
const room = GetRoomByIdMapper.toDomain(validData.value)
|
||||
const createResult = await this.roomLocalDataSourceService.insert(room)
|
||||
|
||||
if(createResult.isErr()) {
|
||||
console.error('createResultErr', createResult.error);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if(validData.value.data.expirationDate) {
|
||||
this.CronJobService.createCronJob(`remove expired room ${id}`, new Date(validData.value.data.expirationDate), () => {
|
||||
setTimeout(() => {
|
||||
this.execute(id);
|
||||
}, 60000);
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
|
||||
} else if (isHttpResponse(result.error) ) {
|
||||
if(result.error.status == 404) {
|
||||
await this.roomLocalDataSourceService.delete(id)
|
||||
}
|
||||
// this.httpErrorHandle.httpStatusHandle(result.error)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { GetRoomListUseCaseService } from './room-get-list-use-case.service'
|
||||
import { RoomSocketRepositoryService } from '../../../data/repository/room/room-socket-repository.service'
|
||||
import { IRoomLocalRepository } from 'src/app/core/chat/repository/room/room-local-repository';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class RoomGetListOnCreateUseCaseService {
|
||||
|
||||
constructor(
|
||||
private RoomSocketRepositoryService: RoomSocketRepositoryService,
|
||||
private getRoomListUseCaseService: GetRoomListUseCaseService,
|
||||
private roomLocalDataSourceService: IRoomLocalRepository,
|
||||
) {
|
||||
this.init()
|
||||
}
|
||||
|
||||
|
||||
private init() {
|
||||
this.OnReceiveCreateRoom()
|
||||
this.OnDeleteCreateRoom()
|
||||
}
|
||||
|
||||
|
||||
private async OnReceiveCreateRoom() {
|
||||
this.RoomSocketRepositoryService.listenToCreateRoom().subscribe(async(data)=> {
|
||||
|
||||
setTimeout(async () => {
|
||||
const findLocally = await this.roomLocalDataSourceService.findOne({id:(data.data as any).id})
|
||||
|
||||
if(findLocally.isOk() && !findLocally.value) {
|
||||
this.getRoomListUseCaseService.execute()
|
||||
}
|
||||
|
||||
}, 1000);
|
||||
|
||||
|
||||
// const result = await this.roomRemoteDataSourceService.getRoom(id)
|
||||
// console.log('OnReceiveCreateRoom', data)
|
||||
//this.getRoomListUseCaseService.execute()
|
||||
})
|
||||
}
|
||||
|
||||
private OnDeleteCreateRoom() {
|
||||
this.RoomSocketRepositoryService.listenToDeleteRoom().subscribe((data)=> {
|
||||
console.log('OnDeleteCreateRoom', data)
|
||||
this.getRoomListUseCaseService.execute()
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,169 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { roomListDetermineChanges } from '../../../data/async/list/rooms/roomListChangeDetector';
|
||||
import { captureAndReraiseAsync } from 'src/app/services/decorators/captureAndReraiseAsync';
|
||||
import { CronJobService } from 'src/app/utils/task-scheduler'
|
||||
import { z } from "zod";
|
||||
import { IRoomRemoteRepository } from 'src/app/core/chat/repository/room/room-remote-repository';
|
||||
import { IRoomLocalRepository } from 'src/app/core/chat/repository/room/room-local-repository';
|
||||
import { MessageEntitySchema } from 'src/app/core/chat/entity/message';
|
||||
import { GetRoomListMapper } from 'src/app/core/chat/mapper/getRoomListMapper';
|
||||
import { IDBoolean } from 'src/app/infra/database/dexie/type';
|
||||
import { RoomType } from 'src/app/core/chat/entity/group';
|
||||
import { Logger } from 'src/app/services/logger/main/service';
|
||||
|
||||
|
||||
const CreatedBySchema = z.object({
|
||||
wxUserId: z.number(),
|
||||
wxFullName: z.string(),
|
||||
wxeMail: z.string().email(),
|
||||
userPhoto: z.string().nullable()// api check
|
||||
});
|
||||
|
||||
const RoomListItemOutPutDTOSchema = z.object({
|
||||
chatRoom: z.object({
|
||||
id: z.string(),
|
||||
roomName: z.string(),
|
||||
createdBy: CreatedBySchema,
|
||||
createdAt: z.string(),
|
||||
expirationDate: z.string().nullable(), // api check
|
||||
roomType: z.number(),
|
||||
messages: MessageEntitySchema.array(),
|
||||
user1: CreatedBySchema.nullable(),
|
||||
user2: CreatedBySchema.nullable()
|
||||
}),
|
||||
joinAt: z.string()
|
||||
})
|
||||
|
||||
|
||||
// Define the schema for the entire response
|
||||
export const RoomListOutPutDTOSchema = z.object({
|
||||
success: z.boolean(),
|
||||
message: z.string(),
|
||||
data: z.array(RoomListItemOutPutDTOSchema),
|
||||
});
|
||||
|
||||
export type RoomListItemOutPutDTO = z.infer<typeof RoomListItemOutPutDTOSchema>
|
||||
|
||||
export type RoomListOutPutDTO = z.infer<typeof RoomListOutPutDTOSchema>
|
||||
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class GetRoomListUseCaseService {
|
||||
|
||||
constructor(
|
||||
private roomRemoteDataSourceService: IRoomRemoteRepository,
|
||||
private roomLocalDataSourceService: IRoomLocalRepository,
|
||||
private CronJobService: CronJobService
|
||||
) { }
|
||||
|
||||
@captureAndReraiseAsync('RoomRepositoryService/list')
|
||||
async execute() {
|
||||
console.log('update===============')
|
||||
const result = await this.roomRemoteDataSourceService.getRoomList()
|
||||
|
||||
const localList = await this.roomLocalDataSourceService.findAll()
|
||||
|
||||
if(localList.isOk()) {
|
||||
if(result.isOk()) {
|
||||
|
||||
const filterValidateRooms = result.value.data.filter(e => {
|
||||
if(e.chatRoom.roomType == RoomType.Direct) {
|
||||
|
||||
if(e.chatRoom.user1 != null && e.chatRoom.user2 != null || e.chatRoom.user1?.wxUserId == e.chatRoom.user2?.wxUserId) {
|
||||
return true
|
||||
} else {
|
||||
Logger.error("direct room invalid data from, GetRoomListUseCaseService.execute", {
|
||||
data: e.chatRoom,
|
||||
user1: e.chatRoom.user1,
|
||||
user2: e.chatRoom.user2
|
||||
})
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
const { roomsToDelete, roomsToInsert, roomsToUpdate } = roomListDetermineChanges(filterValidateRooms, localList.value)
|
||||
|
||||
console.log({roomsToDelete, roomsToInsert, roomsToUpdate})
|
||||
|
||||
// sometime api return duplicated rooms
|
||||
const insertedIds = []
|
||||
|
||||
if(roomsToInsert) {
|
||||
const roomsToInsertEntity = GetRoomListMapper.toDomain(roomsToInsert)
|
||||
for( const room of roomsToInsertEntity) {
|
||||
|
||||
if(room.roomType == RoomType.Direct) {
|
||||
if(room.$id) {
|
||||
this.roomLocalDataSourceService.insert(room).then((result) => {
|
||||
|
||||
if( result.isErr() &&
|
||||
result.error.DBErrorName == 'ConstraintError') {
|
||||
this.roomLocalDataSourceService.update(room.$id, room).then((result) => {
|
||||
if(result.isErr()) {
|
||||
console.log('failed to update room id')
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// prevent to insert the same room due to server duplication
|
||||
if(!insertedIds.find(e => room.id)) {
|
||||
|
||||
const createResult = this.roomLocalDataSourceService.insert(room)
|
||||
|
||||
insertedIds.push(room.id)
|
||||
|
||||
createResult.then((result) => {
|
||||
if(result.isErr()) {
|
||||
console.log('error', result.error)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if(roomsToUpdate.length >= 1) {
|
||||
const roomsToUpdateEntity = GetRoomListMapper.toDomain(roomsToUpdate)
|
||||
this.roomLocalDataSourceService.updateMany(roomsToUpdateEntity)
|
||||
}
|
||||
|
||||
for( const room of roomsToDelete) {
|
||||
if(room.local == IDBoolean.false) {
|
||||
const findResult = this.roomLocalDataSourceService.findOne({id:room.id})
|
||||
findResult.then((result) => {
|
||||
if(result.isOk() && result.value) {
|
||||
this.roomLocalDataSourceService.delete(result.value.$id)
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
for(const room of filterValidateRooms) {
|
||||
if(room.chatRoom.expirationDate) {
|
||||
|
||||
|
||||
this.CronJobService.createCronJob('remove expired room list', new Date(room.chatRoom.expirationDate), () => {
|
||||
setTimeout(() => {
|
||||
this.execute();
|
||||
}, 60000);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { IRoomLocalRepository } from 'src/app/core/chat/repository/room/room-local-repository';
|
||||
import { z } from 'zod';
|
||||
|
||||
const RoomGetLocalByIdServiceInputSchema = z.object({
|
||||
$roomId: z.string()
|
||||
})
|
||||
|
||||
export type IRoomGetLocalByIdServiceInput = z.infer<typeof RoomGetLocalByIdServiceInputSchema >
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class RoomGetLocalByIdService {
|
||||
|
||||
constructor(
|
||||
private roomLocalDataSourceService: IRoomLocalRepository,
|
||||
) { }
|
||||
|
||||
async execute(input: IRoomGetLocalByIdServiceInput) {
|
||||
return await this.roomLocalDataSourceService.findOne({$id: input.$roomId})
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { z } from "zod";
|
||||
import { IMemberRemoteRepository } from 'src/app/core/chat/repository/member/member-remote-repository';
|
||||
import { IRoomLocalRepository } from 'src/app/core/chat/repository/room/room-local-repository';
|
||||
import { isHttpResponse } from 'src/app/infra/http/http.service';
|
||||
|
||||
// Define the schema for the entire response
|
||||
export const UserRemoveListInputDTOSchema = z.object({
|
||||
id: z.string(),
|
||||
members: z.array(z.number())
|
||||
});
|
||||
|
||||
export type UserRemoveListInputDTO = z.infer<typeof UserRemoveListInputDTOSchema>
|
||||
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class RoomLeaveUseCase {
|
||||
|
||||
constructor(
|
||||
private memberRemoteDataSourceService: IMemberRemoteRepository,
|
||||
private roomLocalDataSourceService: IRoomLocalRepository,
|
||||
) { }
|
||||
|
||||
|
||||
|
||||
async execute(data: UserRemoveListInputDTO) {
|
||||
const result = await this.memberRemoteDataSourceService.removeMemberFromRoom(data)
|
||||
|
||||
if(result.isOk()) {
|
||||
this.roomLocalDataSourceService.delete(data.id)
|
||||
} else if (isHttpResponse(result.error)) {
|
||||
if(result.error.status == 404) {
|
||||
await this.roomLocalDataSourceService.delete(data.id)
|
||||
|
||||
}
|
||||
// this.httpErrorHandle.httpStatusHandle(result.error)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
@@ -1,244 +0,0 @@
|
||||
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')
|
||||
}
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { IRoomLocalRepository } from 'src/app/core/chat/repository/room/room-local-repository';
|
||||
import { IDBoolean } from 'src/app/infra/database/dexie/type';
|
||||
import { z } from 'zod';
|
||||
|
||||
const RoomSetLocalToFalseByIdInputSchema = z.object({
|
||||
$roomId: z.string(),
|
||||
roomId: z.string()
|
||||
})
|
||||
|
||||
export type IRoomSetLocalToFalseByIdInput = z.infer<typeof RoomSetLocalToFalseByIdInputSchema >
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class RoomSetLocalToFalseByIdService {
|
||||
|
||||
constructor(
|
||||
private roomLocalDataSourceService: IRoomLocalRepository,
|
||||
) { }
|
||||
|
||||
execute(input: IRoomSetLocalToFalseByIdInput) {
|
||||
return this.roomLocalDataSourceService.update(input.$roomId, {
|
||||
local: IDBoolean.false,
|
||||
id: input.roomId
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { captureAndReraiseAsync } from 'src/app/services/decorators/captureAndReraiseAsync';
|
||||
import { z } from "zod";
|
||||
import { DataSourceReturn } from 'src/app/services/Repositorys/type';
|
||||
import { IRoomLocalRepository } from 'src/app/core/chat/repository/room/room-local-repository';
|
||||
import { IRoomRemoteRepository } from 'src/app/core/chat/repository/room/room-remote-repository';
|
||||
|
||||
export const RoomUpdateInputDTOSchema = z.object({
|
||||
roomName: z.string(),
|
||||
roomId: z.string(),
|
||||
roomType: z.number(),
|
||||
});
|
||||
export type RoomUpdateInputDTO = z.infer<typeof RoomUpdateInputDTOSchema>
|
||||
|
||||
|
||||
|
||||
const UserSchema = z.object({
|
||||
wxUserId: z.number(),
|
||||
wxFullName: z.string(),
|
||||
wxeMail: z.string(),
|
||||
userPhoto: z.string().nullable(),
|
||||
});
|
||||
const MemberSchema = z.object({
|
||||
id: z.string(),
|
||||
user: UserSchema,
|
||||
joinAt: z.string(),
|
||||
});
|
||||
|
||||
export const RoomUpdateOutputDTOSchema = z.object({
|
||||
success: z.boolean(),
|
||||
message: z.string(),
|
||||
data: z.object({
|
||||
id: z.string(),
|
||||
roomName: z.string(),
|
||||
createdBy: UserSchema,
|
||||
createdAt: z.string(),
|
||||
expirationDate: z.string().nullable(),
|
||||
roomType: z.number(),
|
||||
members: z.array(MemberSchema),
|
||||
}),
|
||||
});
|
||||
export type RoomUpdateOutputDTO = z.infer<typeof RoomUpdateOutputDTOSchema>
|
||||
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class UpdateRoomByIdUseCaseService {
|
||||
|
||||
constructor(
|
||||
private roomRemoteDataSourceService: IRoomRemoteRepository,
|
||||
private roomLocalDataSourceService: IRoomLocalRepository,
|
||||
) { }
|
||||
|
||||
|
||||
@captureAndReraiseAsync('RoomRepositoryService/updateRoomBy')
|
||||
async execute(data: RoomUpdateInputDTO): Promise<DataSourceReturn<RoomUpdateOutputDTO>> {
|
||||
|
||||
const result = await this.roomRemoteDataSourceService.updateRoom(data)
|
||||
|
||||
if(result.isOk()) {
|
||||
const localList = await this.roomLocalDataSourceService.findAll()
|
||||
// const { roomsToDelete, roomsToInsert, roomsToUpdate } = roomListDetermineChanges([result.value.data], localList)
|
||||
|
||||
// for( const roomData of roomsToUpdate) {
|
||||
// if(!roomData.chatRoom.createdBy?.wxUserId) {
|
||||
// delete roomData.chatRoom.createdBy;
|
||||
// }
|
||||
|
||||
// this.roomLocalDataSourceService.updateRoom(roomData.chatRoom)
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { IRoomSocketRepository } from 'src/app/core/chat/repository/room/room-socket-repository';
|
||||
import { GetRoomByIdUseCaseService } from './room-get-by-id-use-case.service'
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class RoomUpdateNameSyncService {
|
||||
|
||||
constructor(
|
||||
private GetRoomByIdUseCaseService: GetRoomByIdUseCaseService,
|
||||
private roomSocketRepository: IRoomSocketRepository
|
||||
) {
|
||||
// this.watch()
|
||||
}
|
||||
|
||||
|
||||
private watch() {
|
||||
this.roomSocketRepository.listenToRoomUpdate().subscribe((event) => {
|
||||
console.log('listenToRoomUpdate')
|
||||
this.GetRoomByIdUseCaseService.execute(event.data.id)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { MessageSocketRepositoryService } from 'src/app/module/chat/data/repository/message/message-live-signalr-data-source.service';
|
||||
import { XTracerAsync } from 'src/app/services/monitoring/opentelemetry/tracer';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class SocketConnectUseCaseService {
|
||||
|
||||
constructor(
|
||||
private MessageSocketRepositoryService: MessageSocketRepositoryService
|
||||
) { }
|
||||
|
||||
@XTracerAsync({name:'SocketConnectUseCaseService', module:'chat', bugPrint: true})
|
||||
async execute() {
|
||||
return await this.MessageSocketRepositoryService.connect()
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { MessageSocketRepositoryService } from 'src/app/module/chat/data/repository/message/message-live-signalr-data-source.service';
|
||||
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class SocketJoinUseCaseService {
|
||||
|
||||
constructor(
|
||||
private MessageSocketRepositoryService: MessageSocketRepositoryService
|
||||
) { }
|
||||
|
||||
|
||||
execute() {
|
||||
|
||||
this.MessageSocketRepositoryService.sendDirectMessage
|
||||
}
|
||||
}
|
||||
-30
@@ -1,30 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { z } from 'zod';
|
||||
import { ValidateSchema } from 'src/app/services/decorators/validate-schema.decorator';
|
||||
import { MemberListLocalRepository } from 'src/app/module/chat/data/repository/member/member-list-local-repository.service'
|
||||
|
||||
export const MemberListUPdateStatus = z.object({
|
||||
key: z.string(),
|
||||
value: z.object({
|
||||
userId: z.number(),
|
||||
userName: z.string()
|
||||
})
|
||||
}).array();
|
||||
export type MemberListUPdateStatusInputDTO = z.infer<typeof MemberListUPdateStatus>
|
||||
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class MemberListUpdateStatusUseCaseService {
|
||||
|
||||
constructor(
|
||||
private MemberListLocalRepository: MemberListLocalRepository
|
||||
) { }
|
||||
|
||||
|
||||
@ValidateSchema(MemberListUPdateStatus)
|
||||
execute(input: MemberListUPdateStatusInputDTO) {
|
||||
return this.MemberListLocalRepository.updateMembersStatus(input)
|
||||
}
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
import { Injectable, Input } from '@angular/core';
|
||||
import { MessageLocalDataSourceService } from '../../../data/repository/message/message-local-data-source.service';
|
||||
import { TracingType, XTracerAsync } from 'src/app/services/monitoring/opentelemetry/tracer';
|
||||
import { ParamsValidation } from 'src/app/services/decorators/validate-schema.decorator';
|
||||
import { MessageEntitySchema } from 'src/app/core/chat/entity/message';
|
||||
import { z } from 'zod';
|
||||
|
||||
const SocketMessageCreateOutputSchema = MessageEntitySchema.pick({
|
||||
id: true,
|
||||
attachments: true,
|
||||
canEdit: true,
|
||||
editedAt: true,
|
||||
info: true,
|
||||
isDeleted: true,
|
||||
message: true,
|
||||
messageType: true,
|
||||
oneShot: true,
|
||||
reactions: true,
|
||||
receiverId: true,
|
||||
requireUnlock: true,
|
||||
roomId: true,
|
||||
sender: true,
|
||||
sending: true,
|
||||
sentAt: true,
|
||||
})
|
||||
|
||||
export type ISocketMessageCreateOutput = z.infer<typeof SocketMessageCreateOutputSchema>
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class SocketMessageCreateUseCaseService {
|
||||
|
||||
private broadcastChannel: BroadcastChannel;
|
||||
private processedMessages = new Set<string>();
|
||||
|
||||
constructor(
|
||||
private messageLocalDataSourceService: MessageLocalDataSourceService,
|
||||
) {
|
||||
this.broadcastChannel = new BroadcastChannel('socket-message');
|
||||
this.broadcastChannel.onmessage = (event) => {
|
||||
console.log('hello', event.data)
|
||||
const messageId = event.data;
|
||||
this.processedMessages.add(messageId);
|
||||
};
|
||||
|
||||
// this.broadcastChannel.postMessage('incomingMessage.id');
|
||||
}
|
||||
|
||||
@XTracerAsync({name:'Socket-Message-Create-UseCase', module:'chat', bugPrint: true})
|
||||
async execute(input: ISocketMessageCreateOutput, tracing?: TracingType) {
|
||||
|
||||
this.broadcastChannel.postMessage(input.id);
|
||||
ParamsValidation(SocketMessageCreateOutputSchema, input, tracing)
|
||||
|
||||
const incomingMessage = {
|
||||
...input,
|
||||
sending: false
|
||||
}
|
||||
|
||||
// Check if the message ID already exists in the processedMessages set
|
||||
if (this.processedMessages.has(incomingMessage.id)) {
|
||||
console.warn(`Duplicate message detected: ${incomingMessage.id}`);
|
||||
return; // Exit early to prevent duplicate handling
|
||||
} else {
|
||||
console.log('no duplicate')
|
||||
}
|
||||
|
||||
// Add the message ID to the processedMessages set and broadcast it
|
||||
this.processedMessages.add(incomingMessage.id);
|
||||
|
||||
|
||||
console.log('create message', { incomingMessage });
|
||||
|
||||
tracing?.addEvent("Message Create start");
|
||||
const result = await this.messageLocalDataSourceService.insert(incomingMessage);
|
||||
tracing?.addEvent("Message Create end");
|
||||
|
||||
if (result.isOk()) {
|
||||
// Optionally, you can handle post-insertion logic here
|
||||
} else {
|
||||
tracing?.addEvent("error while creating message");
|
||||
tracing.log("error while creating message", {
|
||||
error: result.error
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { MessageLocalDataSourceService } from '../../../data/repository/message/message-local-data-source.service';
|
||||
import { MessageEntitySchema } from 'src/app/core/chat/entity/message';
|
||||
import { z } from 'zod';
|
||||
import { TracingType, XTracerAsync } from 'src/app/services/monitoring/opentelemetry/tracer';
|
||||
|
||||
const SocketMessageDeleteOutputSchema = MessageEntitySchema.pick({
|
||||
id: true,
|
||||
attachments: true,
|
||||
canEdit: true,
|
||||
editedAt: true,
|
||||
info: true,
|
||||
isDeleted: true,
|
||||
message: true,
|
||||
messageType: true,
|
||||
oneShot: true,
|
||||
reactions: true,
|
||||
receiverId: true,
|
||||
requireUnlock: true,
|
||||
roomId: true,
|
||||
sender: true,
|
||||
sending: true,
|
||||
sentAt: true,
|
||||
})
|
||||
|
||||
|
||||
export type ISocketMessageDeleteOutput = z.infer<typeof SocketMessageDeleteOutputSchema>
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class SocketMessageDeleteUseCaseService {
|
||||
|
||||
constructor(
|
||||
private messageLocalDataSourceService: MessageLocalDataSourceService
|
||||
) { }
|
||||
|
||||
|
||||
@XTracerAsync({name:'Socket-Message-Delete-UseCase', module:'chat', bugPrint: true})
|
||||
async execute(input: ISocketMessageDeleteOutput, tracing?: TracingType) {
|
||||
const result = await this.messageLocalDataSourceService.findOne({id: input.id})
|
||||
|
||||
if(result.isOk() && result.value) {
|
||||
|
||||
tracing?.addEvent("Message found")
|
||||
const updateResult = await this.messageLocalDataSourceService.update(result.value.$id, { isDeleted: true })
|
||||
return updateResult
|
||||
}else {
|
||||
tracing.hasError("failed to delete message")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { MessageLocalDataSourceService } from '../../../data/repository/message/message-local-data-source.service';
|
||||
import { ParamsValidation, SafeValidateSchema, ValidateSchema } from 'src/app/services/decorators/validate-schema.decorator';
|
||||
import { TracingType, XTracerAsync } from 'src/app/services/monitoring/opentelemetry/tracer';
|
||||
import { MessageEntitySchema } from 'src/app/core/chat/entity/message';
|
||||
import { z } from 'zod';
|
||||
import { MessageTable } from 'src/app/infra/database/dexie/instance/chat/schema/message';
|
||||
import { MessageOutPutDataDTOSchema } from 'src/app/core/chat/repository/dto/messageOutputDTO';
|
||||
|
||||
|
||||
const SocketMessageUpdateOutputSchema = MessageEntitySchema.pick({
|
||||
id: true,
|
||||
attachments: true,
|
||||
canEdit: true,
|
||||
editedAt: true,
|
||||
info: true,
|
||||
isDeleted: true,
|
||||
message: true,
|
||||
messageType: true,
|
||||
oneShot: true,
|
||||
reactions: true,
|
||||
receiverId: true,
|
||||
requireUnlock: true,
|
||||
roomId: true,
|
||||
sender: true,
|
||||
sending: true,
|
||||
sentAt: true,
|
||||
})
|
||||
|
||||
export type ISocketMessageUpdateOutput = z.infer<typeof SocketMessageUpdateOutputSchema>
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class SocketMessageUpdateUseCaseService {
|
||||
|
||||
constructor(
|
||||
private messageLocalDataSourceService: MessageLocalDataSourceService
|
||||
) { }
|
||||
|
||||
|
||||
@XTracerAsync({name:'Socket-Message-Update-UseCase', bugPrint: true, module:'chat',})
|
||||
async execute(input: ISocketMessageUpdateOutput, tracing?: TracingType) {
|
||||
|
||||
ParamsValidation(MessageOutPutDataDTOSchema, input, tracing)
|
||||
tracing?.addEvent("Message existe?")
|
||||
const result = await this.messageLocalDataSourceService.findOne({id: input.id})
|
||||
|
||||
const messageToSave: MessageTable = input
|
||||
messageToSave.sending = false
|
||||
|
||||
if(result.isOk() && result.value) {
|
||||
|
||||
tracing?.addEvent("Message found")
|
||||
const updateResult = await this.messageLocalDataSourceService.update(result.value.$id, messageToSave)
|
||||
tracing.setAttribute('outcome', 'success')
|
||||
return updateResult
|
||||
} else if(result.isOk() && !result.value) {
|
||||
tracing?.addEvent("Message not found")
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { SessionStore } from 'src/app/store/session.service';
|
||||
import { UserTypingRemoteRepositoryService } from '../../../data/repository/typing/user-typing-live-data-source.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class SendTypingUseCaseService {
|
||||
|
||||
constructor(
|
||||
private UserTypingRemoteRepositoryService: UserTypingRemoteRepositoryService,
|
||||
) { }
|
||||
|
||||
|
||||
execute(roomId) {
|
||||
return this.UserTypingRemoteRepositoryService.sendTyping(roomId)
|
||||
}
|
||||
}
|
||||
-49
@@ -1,49 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { IUserPhotoLocalRepository } from 'src/app/core/chat/repository/user-photo/user-photo-local-repository';
|
||||
import { IUserPhotoRemoteRepository } from 'src/app/core/chat/repository/user-photo/user-photo-remote-repository';
|
||||
import { UserPhotoTableSchema } from 'src/app/infra/database/dexie/instance/chat/schema/user-foto';
|
||||
import { z } from 'zod';
|
||||
|
||||
export const UserPhotoGetByIdInputSchema = UserPhotoTableSchema.pick({
|
||||
attachmentId: true,
|
||||
wxUserId: true,
|
||||
})
|
||||
|
||||
export type IUserPhotoGetByIdInput = z.infer<typeof UserPhotoGetByIdInputSchema>
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class UserPhotoGetByIdUseCase {
|
||||
|
||||
constructor(
|
||||
private userPhotoLocalRepository: IUserPhotoLocalRepository,
|
||||
private userPhotoRemoteRepository: IUserPhotoRemoteRepository
|
||||
) { }
|
||||
|
||||
async execute(input: IUserPhotoGetByIdInput) {
|
||||
|
||||
const result = await this.userPhotoLocalRepository.findOne({wxUserId: input.wxUserId})
|
||||
if(result.isOk() && result.value) {
|
||||
return result.map(e => {
|
||||
return e.file
|
||||
})
|
||||
} else if(result.isOk() && !result.value) {
|
||||
const remoteResult = await this.userPhotoRemoteRepository.getUserPhotoByAttachmentId({attachmentId: input.attachmentId})
|
||||
|
||||
if(remoteResult.isOk()) {
|
||||
this.userPhotoLocalRepository.insert({
|
||||
wxUserId: input.wxUserId,
|
||||
file: remoteResult.value.data,
|
||||
attachmentId: input.attachmentId
|
||||
})
|
||||
}
|
||||
|
||||
return remoteResult.map(e => {
|
||||
return e.data
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user