diff --git a/gabinete-digital-fo.code-workspace b/gabinete-digital-fo.code-workspace index 3ed675959..d56f8f3c5 100644 --- a/gabinete-digital-fo.code-workspace +++ b/gabinete-digital-fo.code-workspace @@ -23,6 +23,9 @@ { "name": "equilibriumito-gabinete-digital-fo-23cf0fc4cbaa", "path": "../../../Downloads/equilibriumito-gabinete-digital-fo-23cf0fc4cbaa/equilibriumito-gabinete-digital-fo-23cf0fc4cbaa" + }, + { + "path": "../../../Downloads/nestjs-microservice-boilerplate-api-master" } ], "settings": { diff --git a/src/app/app.component.ts b/src/app/app.component.ts index e39173c84..a67b8e8aa 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,5 +1,4 @@ import { Component } from '@angular/core'; - import { Platform } from '@ionic/angular'; import { StatusBar } from '@ionic-native/status-bar/ngx'; import { NgxMatDateFormats } from '@angular-material-components/datetime-picker'; @@ -9,7 +8,7 @@ import { environment } from 'src/environments/environment'; import { Storage } from '@ionic/storage'; import { register } from 'swiper/element/bundle'; import { DomSanitizer } from '@angular/platform-browser'; -import {ScreenOrientation} from "@ionic-native/screen-orientation/ngx"; +import { ScreenOrientation } from "@ionic-native/screen-orientation/ngx"; import { ChatServiceService } from 'src/app/module/chat/chat-service.service' const CUSTOM_DATE_FORMATS: NgxMatDateFormats = { parse: { diff --git a/src/app/module/chat/data/async/socket/message-async.service.ts b/src/app/module/chat/data/async/socket/message-async.service.ts index 6c8a25b20..846d3d91c 100644 --- a/src/app/module/chat/data/async/socket/message-async.service.ts +++ b/src/app/module/chat/data/async/socket/message-async.service.ts @@ -6,6 +6,7 @@ import { SignalRService } from '../../../infra/socket/signal-r.service'; import { filter } from 'rxjs/operators'; import { InstanceId } from '../../repository/message-respository.service'; import { SafeValidateSchema } from 'src/app/services/decorators/validate-schema.decorator'; +import { MessageOutPutDataDTO } from '../../dto/message/messageOutputDTO'; @Injectable({ providedIn: 'root' @@ -20,27 +21,67 @@ export class MessageAsyncService { ) { this.messageLiveSignalRDataSourceService.getMessage().pipe( - filter((message: any) => { - return !message?.requestId?.startsWith(InstanceId) && message?.requestId + filter((message) => { + return !message?.requestId?.startsWith(InstanceId) }) ).subscribe(async (message) => { - console.log('message async ', message) + if(message?.id) { - const id = message.id + '' - delete message.id; + console.log('message async ', message) - const incomingMessage = { - ...message, - messageId: id, - sending: false, - roomId:message.chatRoomId + const id = message.id + '' + delete message.id; + + const incomingMessage = { + ...message, + messageId: id, + sending: false, + roomId:message.chatRoomId + } + + this.incomingMessage(incomingMessage) } - this.incomingMessage(incomingMessage) }) + + this.messageLiveSignalRDataSourceService.getMessageUpdate().pipe( + filter((message) => { + return !message?.requestId?.startsWith(InstanceId) + }) + ).subscribe(async (message) => { + + if(message?.id) { + + console.log('message async ', message) + + const id = message.id + '' + delete message.id; + + const incomingMessage = { + ...message, + messageId: id, + sending: false, + roomId:message.chatRoomId + } + + this.incomingMessage(incomingMessage) + } + + + }) + + this.messageLiveSignalRDataSourceService.getMessageDelete() + .pipe() + .subscribe(async (message) => { + if(message.id) { + this.incomingDeleted(message) + } + + }) + } @SafeValidateSchema(IncomingMessageSchema, 'socket/incomingMessage') @@ -54,4 +95,15 @@ export class MessageAsyncService { console.log(result.error) } } + + + async incomingDeleted(data: MessageOutPutDataDTO) { + const result = await this.messageLocalDataSourceService.deleteByMessageId(data.id) + + if(result.isOk()) { + + } else { + console.log(result.error) + } + } } diff --git a/src/app/module/chat/data/data-source/message/message-local-data-source.service.ts b/src/app/module/chat/data/data-source/message/message-local-data-source.service.ts index 841d7c6bd..44cd478c5 100644 --- a/src/app/module/chat/data/data-source/message/message-local-data-source.service.ts +++ b/src/app/module/chat/data/data-source/message/message-local-data-source.service.ts @@ -88,6 +88,19 @@ export class MessageLocalDataSourceService { } } + async deleteByMessageId(messageId: string): Promise> { + try { + console.log(messageId) + const lastMessage = await messageDataSource.message + .where('messageId') + .equals(messageId).delete() + + return ok(lastMessage[0]); // Get the last message + } catch (error) { + return err(error); + } + } + async sendMessage(data: MessageInputDTO) { @@ -121,6 +134,25 @@ export class MessageLocalDataSourceService { } + async messageExist({messageId}) { + try { + const existingMessage = await messageDataSource.message + .where('messageId') + .equals(messageId) + .first(); + + if (existingMessage) { + return ok(true) + } else { + return err(false) + } + + } catch (error) { + return err(false); + } + + } + async update(data: TableMessage ) { try { diff --git a/src/app/module/chat/data/dto/message/messageDeleteInputDTO.ts b/src/app/module/chat/data/dto/message/messageDeleteInputDTO.ts new file mode 100644 index 000000000..77cc1e899 --- /dev/null +++ b/src/app/module/chat/data/dto/message/messageDeleteInputDTO.ts @@ -0,0 +1,10 @@ +import { z } from "zod"; + +export const MessageDeleteInputDTOSchema = z.object({ + requestId: z.string(), + roomId: z.string(), + messageId: z.string(), + senderId: z.number(), +}); + +export type MessageDeleteInputDTO = z.infer diff --git a/src/app/module/chat/data/dto/message/messageOutputDTO.ts b/src/app/module/chat/data/dto/message/messageOutputDTO.ts index 411b82117..4c4edfe0f 100644 --- a/src/app/module/chat/data/dto/message/messageOutputDTO.ts +++ b/src/app/module/chat/data/dto/message/messageOutputDTO.ts @@ -16,7 +16,8 @@ const DataSchema = z.object({ deliverAt: z.string().datetime().nullable(), canEdit: z.boolean(), oneShot: z.boolean(), - requireUnlock: z.boolean() + requireUnlock: z.boolean(), + requestId: z.string() }); diff --git a/src/app/module/chat/data/repository/message-respository.service.ts b/src/app/module/chat/data/repository/message-respository.service.ts index dd1e30dc0..0bd760147 100644 --- a/src/app/module/chat/data/repository/message-respository.service.ts +++ b/src/app/module/chat/data/repository/message-respository.service.ts @@ -8,6 +8,7 @@ import { SignalRService } from '../../infra/socket/signal-r.service'; import { v4 as uuidv4 } from 'uuid' import { filter } from 'rxjs/operators'; import { err, ok } from 'neverthrow'; +import { MessageDeleteInputDTO } from '../../domain/use-case/message-delete-live-use-case.service'; export const InstanceId = uuidv4(); @@ -81,12 +82,20 @@ export class MessageRepositoryService { } } + + sendMessageDelete(data: MessageDeleteInputDTO) { + + data['requestId'] = InstanceId +'@'+ uuidv4(); + + return this.messageLiveSignalRDataSourceService.sendMessageDelete(data) + } + async sendReadAt({roomId}) { const result = await this.messageLocalDataSourceService.getLastMessageByRoomId(roomId) if(result.isOk()) { if(result.value) { - - // return await this.messageLiveSignalRDataSourceService.sendReadAt({roomId, memberId: SessionStore.user.UserId, chatMessageId: result.value.messageId}) + + return await this.messageLiveSignalRDataSourceService.sendReadAt({roomId, memberId: SessionStore.user.UserId, chatMessageId: result.value.messageId}) } return ok(true) } diff --git a/src/app/module/chat/domain/chat-service.service.ts b/src/app/module/chat/domain/chat-service.service.ts new file mode 100644 index 000000000..0aee17a61 --- /dev/null +++ b/src/app/module/chat/domain/chat-service.service.ts @@ -0,0 +1,23 @@ +import { Injectable } from '@angular/core'; +import { MessageDeleteLiveUseCaseService, MessageDeleteInputDTO } from 'src/app/module/chat/domain/use-case/message-delete-live-use-case.service' +import { SessionStore } from 'src/app/store/session.service'; + +@Injectable({ + providedIn: 'root' +}) +export class ChatServiceService { + + constructor( + private MessageDeleteLiveUseCaseService: MessageDeleteLiveUseCaseService + ) { } + + messageDelete(data: {roomId, messageId}) { + + const params = { + ...data, + senderId: SessionStore.user.UserId, + } + + return this.MessageDeleteLiveUseCaseService.execute(params) + } +} diff --git a/src/app/module/chat/domain/use-case/message-delete-live-use-case.service.ts b/src/app/module/chat/domain/use-case/message-delete-live-use-case.service.ts new file mode 100644 index 000000000..a992d3a24 --- /dev/null +++ b/src/app/module/chat/domain/use-case/message-delete-live-use-case.service.ts @@ -0,0 +1,25 @@ +import { Injectable } from '@angular/core'; +import { z } from 'zod'; +import { MessageRepositoryService } from '../../data/repository/message-respository.service'; + +export const MessageDeleteInputDTOSchema = z.object({ + requestId: z.string(), + roomId: z.string(), + messageId: z.string(), + senderId: z.number(), +}); +export type MessageDeleteInputDTO = z.infer + + +@Injectable({ + providedIn: 'root' +}) +export class MessageDeleteLiveUseCaseService { + constructor( + public repository: MessageRepositoryService + ) { } + + async execute(data: MessageDeleteInputDTO) { + return this.repository.sendMessageDelete(data) + } +} 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 ef4453cd0..45ef02bba 100644 --- a/src/app/module/chat/infra/socket/signal-r.service.ts +++ b/src/app/module/chat/infra/socket/signal-r.service.ts @@ -6,6 +6,7 @@ import { Plugins } from '@capacitor/core'; import { z } from 'zod'; import { UserTypingDTO } from '../../data/dto/typing/typingInputDTO'; import { MessageOutPutDataDTO } from '../../data/dto/message/messageOutputDTO'; +import { MessageDeleteInputDTO } from '../../data/dto/message/messageDeleteInputDTO'; const { App } = Plugins; @@ -19,6 +20,8 @@ export class SignalRService { private messageSubject: BehaviorSubject = new BehaviorSubject(null); private typingSubject: BehaviorSubject = new BehaviorSubject(null); private connectingSubject: BehaviorSubject = new BehaviorSubject(null); + private messageDelete: BehaviorSubject = new BehaviorSubject(null); + private messageUpdateSubject: BehaviorSubject = new BehaviorSubject(null); constructor( private platform: Platform) { @@ -48,7 +51,8 @@ export class SignalRService { private async establishConnection() { - const connection = new SignalRConnection({url:'https://41e3-41-63-166-54.ngrok-free.app/api/v2/chathub'}) + // 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'}) const attempConnection = await connection.establishConnection() if(attempConnection.isOk()) { @@ -66,6 +70,14 @@ export class SignalRService { this.connection.getTyping().subscribe((data) => { this.typingSubject.next(data) }) + + this.connection.getMessageDelete().subscribe((data) => { + this.messageDelete.next(data) + }) + + this.connection.getMessageUpdateSubject().subscribe((data) => { + this.messageUpdateSubject.next(data) + }) } } @@ -80,6 +92,14 @@ export class SignalRService { return this.typingSubject.asObservable().pipe() } + getMessageDelete() { + return this.messageDelete.asObservable() + } + + getMessageUpdate() { + return this.messageUpdateSubject.asObservable() + } + async sendMessage(data: Object) { return await this.connection.sendMessage(data as any) } @@ -95,4 +115,10 @@ export class SignalRService { async sendReadAt({ roomId, memberId, chatMessageId}) { return await this.connection.sendReadAt({ roomId, memberId, chatMessageId}) } + + + async sendMessageDelete(data: MessageDeleteInputDTO) { + return await this.connection.deleteMessage(data) + } + } diff --git a/src/app/module/chat/infra/socket/signalR.ts b/src/app/module/chat/infra/socket/signalR.ts index d9f96c901..9b6efcb75 100644 --- a/src/app/module/chat/infra/socket/signalR.ts +++ b/src/app/module/chat/infra/socket/signalR.ts @@ -6,41 +6,14 @@ import { filter, first } from 'rxjs/operators'; import { v4 as uuidv4 } from 'uuid' import { UserTypingDTO } from '../../data/dto/typing/typingInputDTO'; import { MessageOutPutDataDTO } from '../../data/dto/message/messageOutputDTO'; - - -var msgObj = { - roomId: "53bc6471-c28e-42d0-aa72-f4e52221f16f", - senderId:312, - message:"message enviada", - messageType:312, - canEdit:true, - oneShot:false, - requestId:"testing" - }; - // var deletObj = { - // roomId: "53bc6471-c28e-42d0-aa72-f4e52221f16f", - // senderId:312, - // messageId:"message enviada", - // requestId:"testing" - // }; - // var reactObj = { - // roomId: "53bc6471-c28e-42d0-aa72-f4e52221f16f", - // memberId:2, - // messageId:"e7074c10-4f92-458c-adb2-774ec2d42992", - // reaction:"reacted", - // requestId:"testingReaction" - // }; - const typingObj = { - roomId: "53bc6471-c28e-42d0-aa72-f4e52221f16f", - userId: 312, - userName:"usertyping", - requestId:"testing" - }; +import { MessageDeleteInputDTO } from '../../data/dto/message/messageDeleteInputDTO'; export class SignalRConnection { private hubConnection: signalR.HubConnection; private messageSubject: BehaviorSubject = new BehaviorSubject(null); + private messageDelete: BehaviorSubject = new BehaviorSubject(null); + private messageUPdateSubject: BehaviorSubject = new BehaviorSubject(null); private typingSubject: BehaviorSubject = new BehaviorSubject(null); private readAtSubject: BehaviorSubject = new BehaviorSubject(null); private connectionStateSubject: BehaviorSubject = new BehaviorSubject(false); @@ -57,7 +30,6 @@ export class SignalRConnection { establishConnection(): Promise> { return new Promise((resolve, reject) => { - console.log('try to connect'); const hubConnection = new signalR.HubConnectionBuilder() .withUrl(this.url) .build(); @@ -106,7 +78,7 @@ export class SignalRConnection { if(this.connectionStateSubject.value == true) { console.log('join=================') - this.hubConnection.invoke("Join", 312, SessionStore.user.FullName); + this.hubConnection.invoke("Join", SessionStore.user.UserId, SessionStore.user.FullName); //this.hubConnection.invoke("Join", 105, "UserFirefox"); } else { this.sendLaterSubject.next({method: 'SendMessage', args:["Join", 312, "Daniel"]}) @@ -119,7 +91,7 @@ export class SignalRConnection { if(this.connectionStateSubject.value == true) { console.log('sendMessage', data) - this.hubConnection.invoke("SendMessage", msgObj) + this.hubConnection.invoke("SendMessage", data) this.messageSubject.pipe( filter((message: any) => data.requestId == message?.requestId), @@ -138,6 +110,23 @@ export class SignalRConnection { }) } + 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) => { @@ -146,7 +135,7 @@ export class SignalRConnection { console.log('send typing', data) try { - this.hubConnection.invoke("Typing", typingObj) + this.hubConnection.invoke("Typing", data) } catch (error) {} @@ -176,7 +165,7 @@ export class SignalRConnection { if(this.connectionStateSubject.value == true) { try { - this.hubConnection.invoke("ReadAt", { roomId: data.roomId, memberId: data.memberId, requestId } as any) + this.hubConnection.invoke("ReadAt", { roomId: data.roomId, memberId: data.memberId, requestId, messageId: data.chatMessageId} as any) } catch (error) {} @@ -215,6 +204,20 @@ export class SignalRConnection { this.readAtSubject.next(_message); }); + this.hubConnection.on('DeleteMessage', (_message) => { + console.log('DeleteMessage', _message) + this.messageDelete.next(_message); + }); + + this.hubConnection.on('UpdateMessage', (_message) => { + console.log('UpdateMessage', _message) + this.messageUPdateSubject.next(_message); + }) + + } + + public getMessageUpdateSubject() { + return this.messageUPdateSubject.asObservable() } public getMessages() { @@ -237,6 +240,10 @@ export class SignalRConnection { return this.sendLaterSubject.asObservable(); } + public getMessageDelete() { + return this.messageDelete.asObservable() + } + public closeConnection(): void { this.reconnect = false if (this.hubConnection) { diff --git a/src/app/shared/chat/messages/messages.page.html b/src/app/shared/chat/messages/messages.page.html index 7855ffadd..b2206d2fe 100644 --- a/src/app/shared/chat/messages/messages.page.html +++ b/src/app/shared/chat/messages/messages.page.html @@ -46,14 +46,14 @@
-
- {{ message.message }} == {{ message.id }} +
+ {{ message.message }} .== {{ message.id }}
- +
@@ -151,7 +151,7 @@
- +