diff --git a/src/app/module/chat/chat.module.ts b/src/app/module/chat/chat.module.ts index 928136a19..e30ad4a9e 100644 --- a/src/app/module/chat/chat.module.ts +++ b/src/app/module/chat/chat.module.ts @@ -5,7 +5,7 @@ import { skip, switchMap } from 'rxjs/operators'; import { SessionStore } from 'src/app/store/session.service'; import { Subject, timer } from 'rxjs'; import { UserTypingLocalRepository } from './data/repository/user-typing-local-data-source.service'; - +import { RoomService } from 'src/app/module/chat/domain/service/room.service' @NgModule({ imports: [], providers: [], @@ -22,8 +22,10 @@ export class ChatModule { private ChatServiceService: ChatServiceService, private signalR: SignalRService, private localDataSource: UserTypingLocalRepository, + private RoomService: RoomService ) { + this.RoomService.init() this.syncMessage() this.listenToTyping() } diff --git a/src/app/module/chat/data/repository/message/message-live-signalr-data-source.service.ts b/src/app/module/chat/data/repository/message/message-live-signalr-data-source.service.ts index e7f8f025a..af4f13cdd 100644 --- a/src/app/module/chat/data/repository/message/message-live-signalr-data-source.service.ts +++ b/src/app/module/chat/data/repository/message/message-live-signalr-data-source.service.ts @@ -8,6 +8,7 @@ import { InstanceId } from '../../../domain/chat-service.service'; import { MessageUpdateInput } from '../../../domain/use-case/message-update-by-id-use-case.service'; import { MessageOutPutDataDTO } from '../../dto/message/messageOutputDTO'; import { MessageInputDTO } from '../../dto/message/messageInputDtO'; +import { MessageReactionInput } from '../../../domain/use-case/message-reaction-by-id-use-case.service'; interface msgObj { roomId: string; @@ -48,15 +49,18 @@ export class MessageSocketRepositoryService { return this.socket.establishConnection(); } - async sendMessage(data: msgObj) { + async join() { + return await this.socket.join() + } - try { - const result = await this.socket.sendMessage(data) - return ok(result) - } catch (e) { - return err(e) - } + async sendGroupMessage(data: MessageInputDTO) { + const result = await this.socket.sendData({ + method: 'sendMessage', + data: data, + }) + + return result; } async sendDirectMessage(data: MessageInputDTO) { @@ -86,6 +90,15 @@ export class MessageSocketRepositoryService { return result; } + async sendDelete(data: MessageDeleteInputDTO) { + const result = await this.socket.sendData({ + method: 'ReadAt', + data: data, + }) + + return result; + } + listenToMessages() { return this.socket.getMessage() } @@ -101,7 +114,7 @@ export class MessageSocketRepositoryService { } - reactToMessageSocket(data) { + reactToMessageSocket(data: MessageReactionInput) { this.socket.sendData({ method: 'ReactMessage', data @@ -115,23 +128,17 @@ export class MessageSocketRepositoryService { }) } - sendTyping(roomId) { - return this.socket.sendTyping({ - roomId, - UserName:SessionStore.user.FullName, - userId: SessionStore.user.UserId - }) - } - sendMessageDelete(data: MessageDeleteInputDTO) { data['requestId'] = InstanceId +'@'+ uuidv4(); - return this.socket.sendMessageDelete(data) + const result = this.socket.sendData({ + method: 'DeleteMessage', + data: data, + }) + + return result; } - - - } diff --git a/src/app/module/chat/data/repository/room-local-repository.service.ts b/src/app/module/chat/data/repository/room/room-local-repository.service.ts similarity index 88% rename from src/app/module/chat/data/repository/room-local-repository.service.ts rename to src/app/module/chat/data/repository/room/room-local-repository.service.ts index 748ff080c..ed980c211 100644 --- a/src/app/module/chat/data/repository/room-local-repository.service.ts +++ b/src/app/module/chat/data/repository/room/room-local-repository.service.ts @@ -1,11 +1,11 @@ import { Injectable } from '@angular/core'; -import { RoomListItemOutPutDTO, RoomListOutPutDTO } from '../dto/room/roomListOutputDTO'; +import { RoomListItemOutPutDTO, RoomListOutPutDTO } from '../../dto/room/roomListOutputDTO'; import { liveQuery, Observable } from 'Dexie'; import { err, ok, Result } from 'neverthrow'; import { z } from 'zod'; import { ValidateSchema } from 'src/app/services/decorators/validate-schema.decorator'; -import { chatDatabase } from '../../infra/database/dexie/service'; -import { RoomTable, RoomTableSchema } from '../../infra/database/dexie/schema/room'; +import { chatDatabase } from '../../../infra/database/dexie/service'; +import { RoomTable, RoomTableSchema } from '../../../infra/database/dexie/schema/room'; import { DexieRepository } from 'src/app/infra/repository/dexie/dexie-repository.service'; import { from } from 'rxjs'; diff --git a/src/app/module/chat/data/repository/room-remote-repository.service.ts b/src/app/module/chat/data/repository/room/room-remote-repository.service.ts similarity index 79% rename from src/app/module/chat/data/repository/room-remote-repository.service.ts rename to src/app/module/chat/data/repository/room/room-remote-repository.service.ts index a8012169b..f764cedc3 100644 --- a/src/app/module/chat/data/repository/room-remote-repository.service.ts +++ b/src/app/module/chat/data/repository/room/room-remote-repository.service.ts @@ -1,21 +1,21 @@ import { Injectable } from '@angular/core'; import { Result } from 'neverthrow'; import { HttpService } from 'src/app/services/http.service'; -import { RoomListOutPutDTO, RoomListOutPutDTOSchema } from '../dto/room/roomListOutputDTO'; -import { RoomInputDTO, RoomInputDTOSchema } from '../dto/room/roomInputDTO'; -import { RoomOutPutDTO, RoomOutPutDTOSchema } from '../dto/room/roomOutputDTO'; -import { AddMemberToRoomInputDTO, AddMemberToRoomInputDTOSchema } from '../dto/room/addMemberToRoomInputDto'; +import { RoomListOutPutDTO, RoomListOutPutDTOSchema } from '../../dto/room/roomListOutputDTO'; +import { RoomInputDTO, RoomInputDTOSchema } from '../../dto/room/roomInputDTO'; +import { RoomOutPutDTO, RoomOutPutDTOSchema } from '../../dto/room/roomOutputDTO'; +import { AddMemberToRoomInputDTO, AddMemberToRoomInputDTOSchema } from '../../dto/room/addMemberToRoomInputDto'; import { ValidateSchema } from 'src/app/services/decorators/validate-schema.decorator'; -import { RoomByIdInputDTO, RoomByIdInputDTOSchema } from '../dto/room/roomByIdInputDTO'; -import { RoomByIdOutputDTO, RoomByIdOutputDTOSchema } from '../dto/room/roomByIdOutputDTO'; +import { RoomByIdInputDTO, RoomByIdInputDTOSchema } from '../../dto/room/roomByIdInputDTO'; +import { RoomByIdOutputDTO, RoomByIdOutputDTOSchema } from '../../dto/room/roomByIdOutputDTO'; import { APIReturn } from 'src/app/services/decorators/api-validate-schema.decorator'; -import { UserRemoveListInputDTO, UserRemoveListInputDTOSchema } from '../dto/room/userRemoveListInputDTO'; -import { RoomUpdateInputDTO, RoomUpdateInputDTOSchema } from '../dto/room/roomUpdateInputDTO'; -import { RoomUpdateOutputDTO } from '../dto/room/roomUpdateOutputDTO'; +import { UserRemoveListInputDTO, UserRemoveListInputDTOSchema } from '../../dto/room/userRemoveListInputDTO'; +import { RoomUpdateInputDTO, RoomUpdateInputDTOSchema } from '../../dto/room/roomUpdateInputDTO'; +import { RoomUpdateOutputDTO } from '../../dto/room/roomUpdateOutputDTO'; import { DataSourceReturn } from 'src/app/services/Repositorys/type'; import { SessionStore } from 'src/app/store/session.service'; -import { MemberSetAdminDTO } from '../../domain/use-case/member-admin-use-case.service'; -import { SignalRService } from '../../infra/socket/signal-r.service'; +import { MemberSetAdminDTO } from '../../../domain/use-case/member-admin-use-case.service'; +import { SignalRService } from '../../../infra/socket/signal-r.service'; import { v4 as uuidv4 } from 'uuid' @Injectable({ diff --git a/src/app/module/chat/data/repository/room/room-socket-repository.service.spec.ts b/src/app/module/chat/data/repository/room/room-socket-repository.service.spec.ts new file mode 100644 index 000000000..d2760d731 --- /dev/null +++ b/src/app/module/chat/data/repository/room/room-socket-repository.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { RoomSocketRepositoryService } from './room-socket-repository.service'; + +describe('RoomSocketRepositoryService', () => { + let service: RoomSocketRepositoryService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(RoomSocketRepositoryService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/module/chat/data/repository/room/room-socket-repository.service.ts b/src/app/module/chat/data/repository/room/room-socket-repository.service.ts new file mode 100644 index 000000000..4f217d85a --- /dev/null +++ b/src/app/module/chat/data/repository/room/room-socket-repository.service.ts @@ -0,0 +1,36 @@ +import { Injectable } from '@angular/core'; +import { SignalRService } from '../../../infra/socket/signal-r.service'; +import { filter, map } from 'rxjs/operators'; +import { z } from 'zod'; +import { SocketMessage } from '../../../infra/socket/signalR'; + +const listenToDeleteRoomInputSchema = z.object({ + roomId: z.string() +}) + +export type ListenToDeleteRoomInput = z.infer + +@Injectable({ + providedIn: 'root' +}) +export class RoomSocketRepositoryService { + + constructor( + private socket: SignalRService + ) { } + + listenToCreateRoom() { + return this.socket.getData().pipe( + filter((data) => data.method == 'UserAddGroup') + ) + } + + listenToDeleteRoom() { + return this.socket.getData().pipe( + filter((data): data is SocketMessage => + data?.method === 'UserRemoveGroup' + ), + map((e) => e.data) + ); + } +} diff --git a/src/app/module/chat/data/repository/user-typing-live-data-source.service.ts b/src/app/module/chat/data/repository/user-typing-live-data-source.service.ts index 9f057a032..7786c4d1d 100644 --- a/src/app/module/chat/data/repository/user-typing-live-data-source.service.ts +++ b/src/app/module/chat/data/repository/user-typing-live-data-source.service.ts @@ -8,14 +8,17 @@ import { SessionStore } from 'src/app/store/session.service'; export class UserTypingRemoteRepositoryService { constructor( - private SignalRLiveDataSourceService: SignalRService + private socket: SignalRService ) { } - sendTyping(roomId, ) { - return this.SignalRLiveDataSourceService.sendTyping({ - roomId, - UserName:SessionStore.user.FullName, - userId:SessionStore.user.UserId + sendTyping(roomId) { + return this.socket.sendData({ + method: 'Typing', + data: { + roomId, + UserName:SessionStore.user.FullName, + userId:SessionStore.user.UserId + }, }) } diff --git a/src/app/module/chat/domain/chat-service.service.ts b/src/app/module/chat/domain/chat-service.service.ts index 43a728c2b..99cd51903 100644 --- a/src/app/module/chat/domain/chat-service.service.ts +++ b/src/app/module/chat/domain/chat-service.service.ts @@ -27,6 +27,7 @@ import { AddMemberUseCaseService } from './use-case/member-add-use-case.service' import { UpdateRoomByIdUseCaseService } from './use-case/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 { GetMessageAttachmentLocallyUseCaseService } from 'src/app/module/chat/domain/use-case/message-get-attachment-localy-use-case.service'; import { GetRoomListUseCaseService } from 'src/app/module/chat/domain/use-case/room-get-list-use-case.service'; import { filter } from 'rxjs/operators'; @@ -78,7 +79,8 @@ export class ChatServiceService { private MessageReadAtByIdUseCaseService: MessageReadAtByIdUseCaseService, private SendLocalMessagesUseCaseService: SendLocalMessagesUseCaseService, private MessageMarkAsReadUseCaseService: MessageMarkAsReadUseCaseService, - private SocketConnectUseCaseService: SocketConnectUseCaseService + private SocketConnectUseCaseService: SocketConnectUseCaseService, + private MessageMarkAllMessageAsReadByRoomIdService: MessageMarkAllMessageAsReadByRoomIdService ) { this.messageLiveSignalRDataSourceService.getMessageDelete() .pipe() @@ -182,6 +184,7 @@ export class ChatServiceService { } + getRoomList() { return this.GetRoomListUseCaseService.execute() } @@ -226,6 +229,10 @@ export class ChatServiceService { return this.MessageMarkAsReadUseCaseService.execute(sendReadAt) } + markAllMessagesAsRead(input: MessageMarkAllMessageAsReadByRoomIdInputSchema) { + return this.MessageMarkAllMessageAsReadByRoomIdService.execute(input) + } + listenToIncomingMessage(roomId:string) { return this.ListenMessageByRoomIdNewUseCase.execute({roomId}) } diff --git a/src/app/module/chat/domain/service/room-expiration.service.ts b/src/app/module/chat/domain/service/room-expiration.service.ts deleted file mode 100644 index 14fcbf1d4..000000000 --- a/src/app/module/chat/domain/service/room-expiration.service.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Injectable } from '@angular/core'; - -@Injectable({ - providedIn: 'root' -}) -export class RoomExpirationService { - - constructor() { } -} diff --git a/src/app/module/chat/domain/service/room.service.spec.ts b/src/app/module/chat/domain/service/room.service.spec.ts new file mode 100644 index 000000000..34729ebbf --- /dev/null +++ b/src/app/module/chat/domain/service/room.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { RoomService } from './room.service'; + +describe('RoomService', () => { + let service: RoomService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(RoomService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/module/chat/domain/service/room.service.ts b/src/app/module/chat/domain/service/room.service.ts new file mode 100644 index 000000000..92ce38eee --- /dev/null +++ b/src/app/module/chat/domain/service/room.service.ts @@ -0,0 +1,31 @@ +import { Injectable } from '@angular/core'; +import { RoomSocketRepositoryService } from 'src/app/module/chat/data/repository/room/room-socket-repository.service' +@Injectable({ + providedIn: 'root' +}) +export class RoomService { + + constructor( + private RoomSocketRepositoryService: RoomSocketRepositoryService + ) { + + } + + init() { + this.OnReceiveCreateRoom() + this.OnDeleteCreateRoom() + } + + + OnReceiveCreateRoom() { + this.RoomSocketRepositoryService.listenToCreateRoom().subscribe((data)=> { + console.log('OnReceiveCreateRoom', data) + }) + } + + OnDeleteCreateRoom() { + this.RoomSocketRepositoryService.listenToCreateRoom().subscribe((data)=> { + console.log('OnDeleteCreateRoom7', data) + }) + } +} diff --git a/src/app/module/chat/domain/use-case/member-add-use-case.service.ts b/src/app/module/chat/domain/use-case/member-add-use-case.service.ts index 319d37809..b7c3c527d 100644 --- a/src/app/module/chat/domain/use-case/member-add-use-case.service.ts +++ b/src/app/module/chat/domain/use-case/member-add-use-case.service.ts @@ -1,7 +1,7 @@ import { Injectable } from '@angular/core'; import { captureAndReraiseAsync } from 'src/app/services/decorators/captureAndReraiseAsync'; import { AddMemberToRoomInputDTO } from '../../data/dto/room/addMemberToRoomInputDto'; -import { RoomRemoteDataSourceService } from '../../data/repository/room-remote-repository.service'; +import { RoomRemoteDataSourceService } from '../../data/repository/room/room-remote-repository.service'; @Injectable({ providedIn: 'root' diff --git a/src/app/module/chat/domain/use-case/member-admin-use-case.service.ts b/src/app/module/chat/domain/use-case/member-admin-use-case.service.ts index 4f810fc62..d1610962d 100644 --- a/src/app/module/chat/domain/use-case/member-admin-use-case.service.ts +++ b/src/app/module/chat/domain/use-case/member-admin-use-case.service.ts @@ -1,7 +1,7 @@ import { Injectable } from '@angular/core'; import { z } from "zod"; import { ValidateSchema } from 'src/app/services/decorators/validate-schema.decorator'; -import { RoomRemoteDataSourceService } from '../../data/repository/room-remote-repository.service'; +import { RoomRemoteDataSourceService } from '../../data/repository/room/room-remote-repository.service'; // Define the schema for the entire response const MemberSetAdminDTOSchema = z.object({ diff --git a/src/app/module/chat/domain/use-case/member/-use-case.service.ts b/src/app/module/chat/domain/use-case/member/-use-case.service.ts index 864742f6b..6e1f4a7a2 100644 --- a/src/app/module/chat/domain/use-case/member/-use-case.service.ts +++ b/src/app/module/chat/domain/use-case/member/-use-case.service.ts @@ -1,7 +1,7 @@ import { Injectable } from '@angular/core'; import { captureAndReraiseAsync } from 'src/app/services/decorators/captureAndReraiseAsync'; import { UserRemoveListInputDTO } from '../../../data/dto/room/userRemoveListInputDTO'; -import { RoomRemoteDataSourceService } from '../../../data/repository/room-remote-repository.service'; +import { RoomRemoteDataSourceService } from '../../../data/repository/room/room-remote-repository.service'; @Injectable({ providedIn: 'root' diff --git a/src/app/module/chat/domain/use-case/message-create-use-case.service.ts b/src/app/module/chat/domain/use-case/message-create-use-case.service.ts index 845c59406..f00f9a39a 100644 --- a/src/app/module/chat/domain/use-case/message-create-use-case.service.ts +++ b/src/app/module/chat/domain/use-case/message-create-use-case.service.ts @@ -18,6 +18,7 @@ import { RoomType } from "src/app/module/chat/domain/entity/group"; import { TracingType, XTracerAsync } from 'src/app/services/monitoring/opentelemetry/tracer'; import { MemberListLocalRepository } from 'src/app/module/chat/data/repository/member-list-local-repository.service' import { SessionStore } from 'src/app/store/session.service'; + const MessageInputUseCaseSchema = z.object({ memberId: z.number(), roomId: z.string(), @@ -39,7 +40,7 @@ export class MessageCreateUseCaseService { constructor( private AttachmentLocalRepositoryService: AttachmentLocalDataSource, private messageLocalDataSourceService: MessageLocalDataSourceService, - private messageLiveSignalRDataSourceService: SignalRService, + private MessageSocketRepositoryService: MessageSocketRepositoryService, private messageSocketRepositoryService: MessageSocketRepositoryService, private MemberListLocalRepository: MemberListLocalRepository ) { } @@ -99,7 +100,7 @@ export class MessageCreateUseCaseService { let sendMessageResult: Result if(messageEnum == RoomType.Group) { const DTO = MessageMapper.fromDomain(message, message.requestId) - sendMessageResult = await this.messageLiveSignalRDataSourceService.sendMessage(DTO) + sendMessageResult = await this.MessageSocketRepositoryService.sendGroupMessage(DTO) } else { if(message.receiverId) { @@ -113,7 +114,7 @@ export class MessageCreateUseCaseService { if(getRoomMembers.isOk()) { message.receiverId = getRoomMembers.value.wxUserId const DTO = MessageMapper.fromDomain(message, message.requestId) - sendMessageResult = await this.messageSocketRepositoryService.sendDirectMessage(DTO) + sendMessageResult = await this.messageSocketRepositoryService.sendGroupMessage(DTO) } else { console.log('not found direct users', getRoomMembers.error) } diff --git a/src/app/module/chat/domain/use-case/message/message-mark-all-message-as-read-by-room-id.service.ts b/src/app/module/chat/domain/use-case/message/message-mark-all-message-as-read-by-room-id.service.ts new file mode 100644 index 000000000..d851ba046 --- /dev/null +++ b/src/app/module/chat/domain/use-case/message/message-mark-all-message-as-read-by-room-id.service.ts @@ -0,0 +1,43 @@ +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 + + +/** + * @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' + }); + } + } + + } +} diff --git a/src/app/module/chat/domain/use-case/messages-send-offline-use-case.service.ts b/src/app/module/chat/domain/use-case/messages-send-offline-use-case.service.ts index 340a1eaf6..16e6ab471 100644 --- a/src/app/module/chat/domain/use-case/messages-send-offline-use-case.service.ts +++ b/src/app/module/chat/domain/use-case/messages-send-offline-use-case.service.ts @@ -1,5 +1,6 @@ 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 { MessageOutPutDataDTO } from '../../data/dto/message/messageOutputDTO'; import { MessageTable } from '../../infra/database/dexie/schema/message'; import { SignalRService } from '../../infra/socket/signal-r.service'; @@ -14,7 +15,7 @@ import { AttachmentLocalDataSource } from '../../data/repository/attachment-loca export class SendLocalMessagesUseCaseService { constructor( - private messageLiveSignalRDataSourceService: SignalRService, + private MessageSocketRepositoryService: MessageSocketRepositoryService, private messageLocalDataSourceService: MessageLocalDataSourceService, private AttachmentRepositoryService: AttachmentLocalDataSource, ) { } @@ -47,7 +48,7 @@ export class SendLocalMessagesUseCaseService { const DTO = MessageMapper.fromDomain(message, requestId) await this.messageLocalDataSourceService.update(message.$id, { sending: true }) - const sendMessageResult = await this.messageLiveSignalRDataSourceService.sendMessage(DTO) + const sendMessageResult = await this.MessageSocketRepositoryService.sendGroupMessage(DTO) if(sendMessageResult.isOk()) { diff --git a/src/app/module/chat/domain/use-case/room-create-use-case.service.ts b/src/app/module/chat/domain/use-case/room-create-use-case.service.ts index 5c00a5686..e4c99793d 100644 --- a/src/app/module/chat/domain/use-case/room-create-use-case.service.ts +++ b/src/app/module/chat/domain/use-case/room-create-use-case.service.ts @@ -1,10 +1,10 @@ import { Injectable } from '@angular/core'; import { create } from 'domain'; import { SessionStore } from 'src/app/store/session.service'; -import { RoomRemoteDataSourceService } from '../../data/repository/room-remote-repository.service'; +import { RoomRemoteDataSourceService } from '../../data/repository/room/room-remote-repository.service'; import { captureAndReraiseAsync } from 'src/app/services/decorators/captureAndReraiseAsync'; import { RoomInputDTO } from '../../data/dto/room/roomInputDTO'; -import { RoomLocalRepository } from '../../data/repository/room-local-repository.service'; +import { RoomLocalRepository } from '../../data/repository/room/room-local-repository.service'; @Injectable({ providedIn: 'root' diff --git a/src/app/module/chat/domain/use-case/room-delete-by-id-use-case.service.ts b/src/app/module/chat/domain/use-case/room-delete-by-id-use-case.service.ts index 2d419d797..671056f27 100644 --- a/src/app/module/chat/domain/use-case/room-delete-by-id-use-case.service.ts +++ b/src/app/module/chat/domain/use-case/room-delete-by-id-use-case.service.ts @@ -2,8 +2,8 @@ import { Injectable } from '@angular/core'; import { captureAndReraiseAsync } from 'src/app/services/decorators/captureAndReraiseAsync'; import { isHttpResponse } from 'src/app/services/http.service'; import { RoomByIdInputDTO } from '../../data/dto/room/roomByIdInputDTO'; -import { RoomRemoteDataSourceService } from '../../data/repository/room-remote-repository.service'; -import { RoomLocalRepository } from '../../data/repository/room-local-repository.service'; +import { RoomRemoteDataSourceService } from '../../data/repository/room/room-remote-repository.service'; +import { RoomLocalRepository } from '../../data/repository/room/room-local-repository.service'; @Injectable({ providedIn: 'root' diff --git a/src/app/module/chat/domain/use-case/room-get-by-id-use-case.service.ts b/src/app/module/chat/domain/use-case/room-get-by-id-use-case.service.ts index 162904ab7..3fe01b1ff 100644 --- a/src/app/module/chat/domain/use-case/room-get-by-id-use-case.service.ts +++ b/src/app/module/chat/domain/use-case/room-get-by-id-use-case.service.ts @@ -3,8 +3,8 @@ import { id } from 'date-fns/locale'; import { isHttpResponse } from 'src/app/services/http.service'; import { roomListDetermineChanges } from '../../data/async/list/rooms/roomListChangeDetector'; import { roomMemberListDetermineChanges } from '../../data/async/list/rooms/roomMembersChangeDetector'; -import { RoomRemoteDataSourceService } from '../../data/repository/room-remote-repository.service'; -import { RoomLocalRepository } from '../../data/repository/room-local-repository.service'; +import { RoomRemoteDataSourceService } from '../../data/repository/room/room-remote-repository.service'; +import { RoomLocalRepository } from '../../data/repository/room/room-local-repository.service'; import { MemberListLocalRepository } from '../../data/repository/member-list-local-repository.service'; import { MemberListMapper } from '../mapper/memberLIstMapper'; import { captureAndReraiseAsync } from 'src/app/services/decorators/captureAndReraiseAsync'; diff --git a/src/app/module/chat/domain/use-case/room-get-list-use-case.service.ts b/src/app/module/chat/domain/use-case/room-get-list-use-case.service.ts index 8afd7eeed..7571b788f 100644 --- a/src/app/module/chat/domain/use-case/room-get-list-use-case.service.ts +++ b/src/app/module/chat/domain/use-case/room-get-list-use-case.service.ts @@ -1,7 +1,7 @@ import { Injectable } from '@angular/core'; import { roomListDetermineChanges } from '../../data/async/list/rooms/roomListChangeDetector'; -import { RoomRemoteDataSourceService } from '../../data/repository/room-remote-repository.service'; -import { RoomLocalRepository } from '../../data/repository/room-local-repository.service'; +import { RoomRemoteDataSourceService } from '../../data/repository/room/room-remote-repository.service'; +import { RoomLocalRepository } from '../../data/repository/room/room-local-repository.service'; import { captureAndReraiseAsync } from 'src/app/services/decorators/captureAndReraiseAsync'; import { isHttpResponse } from 'src/app/services/http.service'; import { CronJobService } from 'src/app/utils/task-scheduler' diff --git a/src/app/module/chat/domain/use-case/room-leave-by-id-use-case.service.ts b/src/app/module/chat/domain/use-case/room-leave-by-id-use-case.service.ts index deef734c5..5d01cfb74 100644 --- a/src/app/module/chat/domain/use-case/room-leave-by-id-use-case.service.ts +++ b/src/app/module/chat/domain/use-case/room-leave-by-id-use-case.service.ts @@ -1,8 +1,8 @@ import { Injectable } from '@angular/core'; import { UserRemoveListInputDTO } from '../../data/dto/room/userRemoveListInputDTO'; import { isHttpResponse } from 'src/app/services/http.service'; -import { RoomRemoteDataSourceService } from '../../data/repository/room-remote-repository.service'; -import { RoomLocalRepository } from '../../data/repository/room-local-repository.service'; +import { RoomRemoteDataSourceService } from '../../data/repository/room/room-remote-repository.service'; +import { RoomLocalRepository } from '../../data/repository/room/room-local-repository.service'; @Injectable({ providedIn: 'root' diff --git a/src/app/module/chat/domain/use-case/room-update-by-id-use-case.service.ts b/src/app/module/chat/domain/use-case/room-update-by-id-use-case.service.ts index b68a93dac..caa173171 100644 --- a/src/app/module/chat/domain/use-case/room-update-by-id-use-case.service.ts +++ b/src/app/module/chat/domain/use-case/room-update-by-id-use-case.service.ts @@ -1,8 +1,8 @@ import { Injectable } from '@angular/core'; import { captureAndReraiseAsync } from 'src/app/services/decorators/captureAndReraiseAsync'; import { RoomUpdateInputDTO } from '../../data/dto/room/roomUpdateInputDTO'; -import { RoomRemoteDataSourceService } from '../../data/repository/room-remote-repository.service'; -import { RoomLocalRepository } from '../../data/repository/room-local-repository.service'; +import { RoomRemoteDataSourceService } from '../../data/repository/room/room-remote-repository.service'; +import { RoomLocalRepository } from '../../data/repository/room/room-local-repository.service'; @Injectable({ providedIn: 'root' diff --git a/src/app/module/chat/domain/use-case/socket-connect-use-case.service.ts b/src/app/module/chat/domain/use-case/socket-connect-use-case.service.ts index cf0ece40e..1e33628b9 100644 --- a/src/app/module/chat/domain/use-case/socket-connect-use-case.service.ts +++ b/src/app/module/chat/domain/use-case/socket-connect-use-case.service.ts @@ -1,5 +1,6 @@ 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' @@ -10,8 +11,9 @@ export class SocketConnectUseCaseService { private MessageSocketRepositoryService: MessageSocketRepositoryService ) { } - execute() { - return this.MessageSocketRepositoryService.connect() + @XTracerAsync({name:'SocketConnectUseCaseService', module:'chat', bugPrint: true}) + async execute() { + return await this.MessageSocketRepositoryService.connect() } diff --git a/src/app/module/chat/domain/use-case/socket-join-use-case.service.ts b/src/app/module/chat/domain/use-case/socket-join-use-case.service.ts new file mode 100644 index 000000000..6af5ddd29 --- /dev/null +++ b/src/app/module/chat/domain/use-case/socket-join-use-case.service.ts @@ -0,0 +1,16 @@ +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() {} +} diff --git a/src/app/module/chat/domain/use-case/sync-all-room-messages.service.ts b/src/app/module/chat/domain/use-case/sync-all-room-messages.service.ts index f4b3ad8a1..ce7b2b33d 100644 --- a/src/app/module/chat/domain/use-case/sync-all-room-messages.service.ts +++ b/src/app/module/chat/domain/use-case/sync-all-room-messages.service.ts @@ -5,7 +5,7 @@ import { MessageTable } from '../../infra/database/dexie/schema/message'; 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-local-repository.service'; +import { RoomLocalRepository } from '../../data/repository/room/room-local-repository.service'; import { SessionStore } from 'src/app/store/session.service'; import { Logger } from 'src/app/services/logger/main/service'; import { XTracerAsync, TracingType } from 'src/app/services/monitoring/opentelemetry/tracer'; diff --git a/src/app/module/chat/domain/use-case/typing-send-use-case.service.ts b/src/app/module/chat/domain/use-case/typing-send-use-case.service.ts index 45c8ebd0e..f72f0fcc3 100644 --- a/src/app/module/chat/domain/use-case/typing-send-use-case.service.ts +++ b/src/app/module/chat/domain/use-case/typing-send-use-case.service.ts @@ -1,6 +1,7 @@ import { Injectable } from '@angular/core'; import { SignalRService } from '../../infra/socket/signal-r.service'; import { SessionStore } from 'src/app/store/session.service'; +import { UserTypingRemoteRepositoryService } from '../../data/repository/user-typing-live-data-source.service'; @Injectable({ providedIn: 'root' @@ -8,15 +9,11 @@ import { SessionStore } from 'src/app/store/session.service'; export class SendTypingUseCaseService { constructor( - private messageLiveSignalRDataSourceService: SignalRService, + private UserTypingRemoteRepositoryService: UserTypingRemoteRepositoryService, ) { } execute(roomId) { - return this.messageLiveSignalRDataSourceService.sendTyping({ - roomId, - UserName:SessionStore.user.FullName, - userId: SessionStore.user.UserId - }) + return this.UserTypingRemoteRepositoryService.sendTyping(roomId) } } diff --git a/src/app/module/chat/infra/socket/signal-r.service.ts b/src/app/module/chat/infra/socket/signal-r.service.ts index d690f70f7..310b77c14 100644 --- a/src/app/module/chat/infra/socket/signal-r.service.ts +++ b/src/app/module/chat/infra/socket/signal-r.service.ts @@ -9,6 +9,7 @@ import { MessageDeleteInputDTO } from '../../data/dto/message/messageDeleteInput import { z } from 'zod'; import { switchMap } from 'rxjs/operators'; import { Result } from 'neverthrow'; +import { HubConnection } from '@microsoft/signalr'; const { App } = Plugins; @@ -68,7 +69,7 @@ export class SignalRService { // this.establishConnection() } - async establishConnection() { + async establishConnection(): Promise> { // const connection = new SignalRConnection({url:'https://41e3-41-63-166-54.ngrok-free.app/api/v2/chathub'}) const connection = new SignalRConnection({url:'https://gdapi-dev.dyndns.info/stage/api/v2/chathub'}) @@ -106,11 +107,15 @@ export class SignalRService { this.connection.getConnectionState().subscribe((data) => { this.connectingSubject.next(data) }) + + return attempConnection } else { - setTimeout(() => { - this.establishConnection() - }, 2000) + return new Promise((resolve) => { + setTimeout(() => { + resolve(this.establishConnection()) + }, 2000) + }) } @@ -138,37 +143,25 @@ export class SignalRService { return this.connection.sendData(input) } - getData() { - return this.sendDataSubject.asObservable() + join() { + return this.connection.join() + } + + getData() { + return this.sendDataSubject.asObservable() as BehaviorSubject<{method: string, data: T}> } public getConnectionState(): Observable { return this.connectingSubject.asObservable(); } - - async sendMessage(data: Object): Promise> { - return await this.connection.sendMessage(data as any) - } - + newConnection() { this.establishConnection() } - async sendTyping({roomId, UserName, userId}) { - return await this.connection.typing({ roomId, UserName, userId}) - } async sendReadAt({ roomId, memberId, chatMessageId}) { return await this.connection.sendReadAt({ roomId, memberId, chatMessageId}) } - async sendMessageDelete(data: MessageDeleteInputDTO) { - return await this.connection.deleteMessage(data) - } - - - async sendReactToMessage(data) { - return await this.connection.sendReactMessage(data) - } - } diff --git a/src/app/module/chat/infra/socket/signalR.ts b/src/app/module/chat/infra/socket/signalR.ts index 70d4dc299..a6be6322c 100644 --- a/src/app/module/chat/infra/socket/signalR.ts +++ b/src/app/module/chat/infra/socket/signalR.ts @@ -10,6 +10,12 @@ import { MessageDeleteInputDTO } from '../../data/dto/message/messageDeleteInput import { MessageReactionInput } from '../../domain/use-case/message-reaction-by-id-use-case.service'; import { ISignalRInput } from './signal-r.service'; + +export interface SocketMessage { + method: string, + data: T +} + export class SignalRConnection { private hubConnection: signalR.HubConnection; @@ -96,8 +102,6 @@ export class SignalRConnection { public join() { if(this.connectionStateSubject.value == true) { - - console.log('join=================') this.hubConnection.invoke("Join", SessionStore.user.UserId, SessionStore.user.FullName); //this.hubConnection.invoke("Join", 105, "UserFirefox"); } else { @@ -106,81 +110,6 @@ export class SignalRConnection { } - public async sendMessage(data: Object & { requestId}):Promise> { - return new Promise((resolve, reject) => { - - if(this.connectionStateSubject.value == true) { - console.log('sendMessage', data) - this.hubConnection.invoke("SendMessage", data) - - // - this.pendingRequests.set(data.requestId, { resolve, reject: (data) => resolve(data) }); - - this.messageSubject.pipe( - filter((message: any) => data.requestId == message?.requestId), - first() - ).subscribe(value => { - resolve(ok(value)) - console.log('Received valid value:', value); - // - this.pendingRequests.delete(data.requestId); - }); - - } else { - this.sendLaterSubject.next({method: 'SendMessage', args: data}) - return reject(err(false)) - } - - - }) - } - - public async deleteMessage(data: MessageDeleteInputDTO) { - return new Promise((resolve, reject) => { - if(this.connectionStateSubject.value == true) { - console.log('delete message', data) - this.hubConnection.invoke("DeleteMessage", data) - - this.messageSubject.pipe( - filter((message: any) => data.requestId == message?.requestId), - first() - ).subscribe((value) => { - resolve(ok(value)) - }) - } - - }) - } - - public async typing(data: Object & { roomId, UserName, userId }):Promise> { - return new Promise((resolve, reject) => { - - const requestId = uuidv4() - if(this.connectionStateSubject.value == true) { - // console.log('send typing', data) - - try { - this.hubConnection.invoke("Typing", data) - - } catch (error) {} - - this.typingSubject.pipe( - filter((message: any) => { - return requestId == message?.requestId - }), - first() - ).subscribe(value => { - resolve(ok(value)); - }); - - } else { - this.sendLaterSubject.next({method: 'SendMessage', args: data}) - return reject(err(false)) - } - - - }) - } public async sendReadAt(data: Object & { roomId, memberId, chatMessageId}):Promise> { return new Promise((resolve, reject) => { @@ -212,57 +141,6 @@ export class SignalRConnection { } - public async sendReactMessage(data: MessageReactionInput):Promise> { - return new Promise((resolve, reject) => { - - const requestId = uuidv4() - if(this.connectionStateSubject.value == true) { - - try { - this.hubConnection.invoke("ReactMessage", { roomId: data.roomId, memberId: data.memberId, requestId, messageId: data.messageId} as any) - - } catch (error) {} - - this.messageUPdateSubject.pipe( - filter((message: any) => { - return requestId == message?.requestId - }), - first() - ).subscribe(value => { - resolve(ok(value)); - }); - - // // Create an observable for the timeout (8 seconds) - // const timeout$ = timer(8000); - - // // Create an observable for the message - // const message$ = this.messageUPdateSubject.pipe( - // filter((message: MessageOutPutDataDTO) => requestId === message?.requestId), - // first() - // ); - - // // Use race to choose whichever completes first (either the message or the timeout) - // race(message$, timeout$).subscribe({ - // next: (value) => { - // if (typeof value === 'number') { - // // If the value is a number, it means the timeout fired - // reject(err('No response, timeout')); - // } else { - // resolve(ok(value)); - // } - // }, - // error: (error) => reject(err('Error: ' + error)) - // }); - - } else { - this.sendLaterSubject.next({method: 'SendMessage', args: data}) - return reject(err(false)) - } - - }) - } - - sendData(input: ISignalRInput): Promise> { return new Promise((resolve, reject) => { diff --git a/src/app/services/monitoring/opentelemetry/tracer.ts b/src/app/services/monitoring/opentelemetry/tracer.ts index a2e1b1857..1a71da1c0 100644 --- a/src/app/services/monitoring/opentelemetry/tracer.ts +++ b/src/app/services/monitoring/opentelemetry/tracer.ts @@ -38,7 +38,7 @@ function convertAttributesToString(obj) { } -const createTracingInstance = ({bugPrint, name, module, autoFinish, waitNThrow}): TracingType => { +const createTracingInstance = ({bugPrint, name, module, autoFinish, waitNThrow = 0}): TracingType => { const startTime = Date.now(); const requestId = uuidv4() @@ -52,7 +52,7 @@ const createTracingInstance = ({bugPrint, name, module, autoFinish, waitNThrow}) _tracerInstance = tracerInstance } - let waitNThrowFunction: NodeJS.Timeout + let waitNThrowFunction: NodeJS.Timeout | undefined const span = _tracerInstance.startSpan(name); let finish = false @@ -136,7 +136,6 @@ const createTracingInstance = ({bugPrint, name, module, autoFinish, waitNThrow}) if(waitNThrowFunction) { clearTimeout(waitNThrowFunction); - returnObject.hasError('waitNThrowFunction') } if(environment.apiURL != 'https://gdqas-api.oapr.gov.ao/api/') { @@ -151,6 +150,7 @@ const createTracingInstance = ({bugPrint, name, module, autoFinish, waitNThrow}) const duration = Date.now() - (startTime as unknown as number); useCaseDurationHistogram.record(duration, { use_case: name }); + useCaseDurationHistogram.record(duration, { use_case: name, user: SessionStore.user.UserName }); finish = true }, @@ -164,8 +164,11 @@ const createTracingInstance = ({bugPrint, name, module, autoFinish, waitNThrow}) } } - if(waitNThrow) { - waitNThrowFunction = setTimeout(returnObject.finish, waitNThrow) + if(waitNThrow > 0) { + waitNThrowFunction = setTimeout(()=> { + returnObject.hasError('waitNThrowFunction') + returnObject.finish() + }, waitNThrow) } return returnObject diff --git a/src/app/ui/chat/chat.page.ts b/src/app/ui/chat/chat.page.ts index a5ca0ba95..4bf84b96a 100644 --- a/src/app/ui/chat/chat.page.ts +++ b/src/app/ui/chat/chat.page.ts @@ -19,7 +19,7 @@ import { RoomListOutPutDTO } from 'src/app/module/chat/data/dto/room/roomListOut import { Observable as DexieObservable } from 'Dexie'; import { EditGroupPage } from './modal/edit-group/edit-group.page'; import { ChatServiceService } from 'src/app/module/chat/domain/chat-service.service' -import { RoomLocalRepository } from 'src/app/module/chat/data/repository/room-local-repository.service' +import { RoomLocalRepository } from 'src/app/module/chat/data/repository/room/room-local-repository.service' import { RoomTable } from 'src/app/module/chat/infra/database/dexie/schema/room'; import { map, tap } from 'rxjs/operators'; import { interval, Subscription } from 'rxjs'; @@ -71,6 +71,7 @@ export class ChatPage implements OnInit { public RouteService: RouteService, private ChatServiceService: ChatServiceService, private roomLocalDataSourceService: RoomLocalRepository, + private chatServiceService: ChatServiceService ) { @@ -284,7 +285,6 @@ export class ChatPage implements OnInit { openMessagesPage(rid) { - // this.chatService.refreshtoken(); this.roomId = rid; diff --git a/src/app/ui/chat/component/contacts/contacts.page.ts b/src/app/ui/chat/component/contacts/contacts.page.ts index f60877ccb..7d1bb942d 100644 --- a/src/app/ui/chat/component/contacts/contacts.page.ts +++ b/src/app/ui/chat/component/contacts/contacts.page.ts @@ -121,7 +121,33 @@ export class ContactsPage implements OnInit { } onChange(event) { + const textSearch = event.detail.value; + const filteredUserList: (UserContacts & {isChecked: boolean})[] = this.FilterUserListedByTextSearch(textSearch) as any + + const userContainer = {} + for(const user of filteredUserList) { + const firstLetter = user.wxFullName.charAt(0) + if(!userContainer[firstLetter]) { + userContainer[firstLetter] = [user] + } else { + userContainer[firstLetter].push(user) + } + } + this.userContainer = userContainer + } + + + FilterUserListedByTextSearch(textSearch: string) { + return this.allChatUsers.filter( e => e.wxFullName.toLowerCase().includes(textSearch.toLowerCase())).sort((a,b) => { + if(a.wxFullName < b.wxFullName) { + return -1; + } + if(a.wxFullName > b.wxFullName) { + return 1; + } + return 0; + }); } clicked() {} diff --git a/src/app/ui/chat/component/messages/messages.page.ts b/src/app/ui/chat/component/messages/messages.page.ts index 271726042..25a6fc9d5 100644 --- a/src/app/ui/chat/component/messages/messages.page.ts +++ b/src/app/ui/chat/component/messages/messages.page.ts @@ -22,7 +22,7 @@ import { ViewMediaPage } from 'src/app/modals/view-media/view-media.page'; import { PermissionService } from 'src/app/services/permission.service'; import { Observable as DexieObservable } from 'Dexie'; import { Observable, Subscription } from 'rxjs'; -import { RoomLocalRepository } from 'src/app/module/chat/data/repository/room-local-repository.service' +import { RoomLocalRepository } from 'src/app/module/chat/data/repository/room/room-local-repository.service' import { MemberListLocalRepository } from 'src/app/module/chat/data/repository/member-list-local-repository.service' import { MessageTable } from 'src/app/module/chat/infra/database/dexie/schema/message'; import { ChatServiceService } from 'src/app/module/chat/domain/chat-service.service'; @@ -243,6 +243,9 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy this.messages1[this.roomId].push(LastMessage) this.loadAttachment() + setTimeout(() => { + this.sendReadMessage() + }, 1000) } diff --git a/src/app/ui/chat/modal/messages/messages.page.html b/src/app/ui/chat/modal/messages/messages.page.html index 6540f9fe2..97ba438e8 100644 --- a/src/app/ui/chat/modal/messages/messages.page.html +++ b/src/app/ui/chat/modal/messages/messages.page.html @@ -76,6 +76,9 @@
+
+ +
diff --git a/src/app/ui/chat/modal/messages/messages.page.ts b/src/app/ui/chat/modal/messages/messages.page.ts index e866722d1..2f00d5772 100644 --- a/src/app/ui/chat/modal/messages/messages.page.ts +++ b/src/app/ui/chat/modal/messages/messages.page.ts @@ -40,7 +40,7 @@ import { FilePickerMobileService } from 'src/app/infra/file-picker/mobile/file-p import { FilePickerWebService } from 'src/app/infra/file-picker/web/file-picker-web.service' import { allowedDocExtension } from 'src/app/utils/allowedDocExtension'; import { JSFileToDataUrl } from 'src/app/utils/ToBase64'; -import { RoomLocalRepository } from 'src/app/module/chat/data/repository/room-local-repository.service' +import { RoomLocalRepository } from 'src/app/module/chat/data/repository/room/room-local-repository.service' import { MemberListLocalRepository } from 'src/app/module/chat/data/repository/member-list-local-repository.service' import { UserTypingLocalRepository } from 'src/app/module/chat/data/repository/user-typing-local-data-source.service'; import { UserTypingRemoteRepositoryService } from 'src/app/module/chat/data/repository/user-typing-live-data-source.service'; @@ -276,7 +276,7 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy { listenToIncomingMessage() { this.messageReceiveSubject?.unsubscribe(); this.messageReceiveSubject = this.chatServiceService.listenToIncomingMessage(this.roomId).subscribe(async (message) => { - this.messages1[this.roomId].unshift(message as MessageEntity) + this.messages1[this.roomId].push(message as MessageEntity) if(message.hasAttachment) { @@ -557,6 +557,7 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy { this.audioRecorded = `data:${recordData.value.mimeType};base64,${recordData?.value?.recordDataBase64}`; } + const audioMimeType: string = recordData.value.mimeType //Converting base64 to blob const encodedData = btoa(this.audioRecorded); @@ -572,7 +573,7 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy { } message.attachments = [{ - file: encodedData, + file: this.audioRecorded.split(',')[1], fileName: "audio", source: MessageAttachmentSource.Device, fileType: MessageAttachmentFileType.Audio, diff --git a/src/app/utils/zod.ts b/src/app/utils/zod.ts index 82ba25dee..6f269ed30 100644 --- a/src/app/utils/zod.ts +++ b/src/app/utils/zod.ts @@ -35,10 +35,7 @@ export const zodDataUrlSchema = z.string().refine(value => value.startsWith('dat * ``` */ export const base64Schema = z.string().refine(value => { - // Regular expression for Base64 validation - const isBase64 = /^[A-Za-z0-9+/=]*$/.test(value) && (value.length % 4 === 0); - // Check if the first 20 characters do not contain a comma - return isBase64 && !value.substring(0, 20).includes(','); + return !value.slice(0, 20).includes(','); }, { message: 'Invalid Base64 string or comma found in the first 20 characters' });