send and receive message

This commit is contained in:
Peter Maquiran
2024-07-11 10:28:21 +01:00
parent 386ca67315
commit b0325a5558
50 changed files with 720 additions and 372 deletions
+3 -4
View File
@@ -4,15 +4,13 @@ import { Platform } from '@ionic/angular';
import { StatusBar } from '@ionic-native/status-bar/ngx';
import { NgxMatDateFormats } from '@angular-material-components/datetime-picker';
import { NGX_MAT_DATE_FORMATS } from '@angular-material-components/datetime-picker';
import { InativityService } from "src/app/services/inativity.service";
import { ThemeService } from 'src/app/services/theme.service';
import { environment } from 'src/environments/environment';
import { Storage } from '@ionic/storage';
import { ChatController } from './controller/chat';
import { register } from 'swiper/element/bundle';
import { DomSanitizer } from '@angular/platform-browser';
import {ScreenOrientation} from "@ionic-native/screen-orientation/ngx";
import { ChatServiceService } from 'src/app/module/chat/chat-service.service'
const CUSTOM_DATE_FORMATS: NgxMatDateFormats = {
parse: {
dateInput: "YYYY-MMMM-DD HH:mm"
@@ -41,7 +39,8 @@ export class AppComponent {
public ThemeService: ThemeService,
private storage: Storage,
private sanitizer: DomSanitizer,
private screenOrientation: ScreenOrientation
private screenOrientation: ScreenOrientation,
private ChatServiceService: ChatServiceService
) {
window["sanitizer"] = this.sanitizer
-2
View File
@@ -96,7 +96,6 @@ import { DeplomaOptionsPageModule } from './shared/popover/deploma-options/deplo
import { DiplomaOptionsPage } from './shared/popover/deploma-options/deploma-options.page';
import { ImageCropperModule } from 'ngx-image-cropper';
import { createAction, createReducer, on, StoreModule } from '@ngrx/store';
import { chatReducer } from './services/Repositorys/chat/data-source/room/room-memory-data-source';
// import { ServiceWorkerModule } from '@angular/service-worker';
// import { AngularFireModule } from '@angular/fire';
// import { AngularFireMessagingModule } from '@angular/fire/messaging';
@@ -145,7 +144,6 @@ export function counterReducer(state, action) {
@NgModule({
declarations: [AppComponent, PopupQuestionPipe, InputFilterDirective],
imports: [BrowserModule,
StoreModule.forRoot({ count: counterReducer, chat: chatReducer }),
CommonModule,
FormsModule,
CalendarModule.forRoot({
+229 -229
View File
@@ -78,206 +78,206 @@ const routes: Routes = [
],
},
{
path: 'agenda',
children: [
{
path:'',
loadChildren: () => AgendaPageModule
},
{
path:':eventId/:caller',
loadChildren: () => import('../pages/agenda/view-event/view-event.module').then( m => m.ViewEventPageModule),
},
{
path: 'eventId/:caller',
loadChildren: () => import('../pages/agenda/view-event/view-event.module').then( m => m.ViewEventPageModule),
},
{
path: 'edit-event',
loadChildren: () => import('../pages/agenda/edit-event/edit-event.module').then( m => m.EditEventPageModule)
},
{
path: 'emend-message-modal',
loadChildren: () => import('../pages/gabinete-digital/event-list/approve-event-modal/approve-event-modal.module').then( m => m.ApproveEventModalPageModule)
},
{
path: 'view-event',
loadChildren: () => import('../pages/agenda/view-event/view-event.module').then( m => m.ViewEventPageModule)
},
{
path:'event-list',
children: [
{
path:'',
loadChildren: ()=> import('../pages/gabinete-digital/event-list/event-list.module').then(m => m.EventListPageModule)
},
{
path:'approve-event',
children : [
{
path:':serialNumber/:caller',
loadChildren: ()=> import('../pages/gabinete-digital/event-list/approve-event/approve-event.module').then(m => m.ApproveEventPageModule)
},
]
}
]
},
],
// {
// path: 'agenda',
// children: [
// {
// path:'',
// loadChildren: () => AgendaPageModule
// },
// {
// path:':eventId/:caller',
// loadChildren: () => import('../pages/agenda/view-event/view-event.module').then( m => m.ViewEventPageModule),
// },
// {
// path: 'eventId/:caller',
// loadChildren: () => import('../pages/agenda/view-event/view-event.module').then( m => m.ViewEventPageModule),
// },
// {
// path: 'edit-event',
// loadChildren: () => import('../pages/agenda/edit-event/edit-event.module').then( m => m.EditEventPageModule)
// },
// {
// path: 'emend-message-modal',
// loadChildren: () => import('../pages/gabinete-digital/event-list/approve-event-modal/approve-event-modal.module').then( m => m.ApproveEventModalPageModule)
// },
// {
// path: 'view-event',
// loadChildren: () => import('../pages/agenda/view-event/view-event.module').then( m => m.ViewEventPageModule)
// },
// {
// path:'event-list',
// children: [
// {
// path:'',
// loadChildren: ()=> import('../pages/gabinete-digital/event-list/event-list.module').then(m => m.EventListPageModule)
// },
// {
// path:'approve-event',
// children : [
// {
// path:':serialNumber/:caller',
// loadChildren: ()=> import('../pages/gabinete-digital/event-list/approve-event/approve-event.module').then(m => m.ApproveEventPageModule)
// },
// ]
// }
// ]
// },
// ],
},
{
path: 'gabinete-digital',
children: [
{
path:'',
loadChildren: ()=> GabineteDigitalPageModule
},
{
path:'expediente',
children: [
{
path:'',
loadChildren: ()=> import('../pages/gabinete-digital/expediente/expediente.module').then(m => m.ExpedientePageModule)
},
{
path:':SerialNumber',
loadChildren: ()=> import('../pages/gabinete-digital/expediente/expediente-detail/expediente-detail.module').then(m => m.ExpedienteDetailPageModule)
},
{
path:':SerialNumber/:caller',
loadChildren: ()=> import('../pages/gabinete-digital/expediente/expediente-detail/expediente-detail.module').then(m => m.ExpedienteDetailPageModule)
},
{
path:'events/:eventId/:caller',
loadChildren: ()=> import('../pages/events/event-detail/event-detail.module').then(m => m.EventDetailPageModule),
},
{
path:'expediente-task-modal',
loadChildren: ()=> import('../pages/gabinete-digital/expediente/expedient-task-modal/expedient-task-modal.module').then(m => m.ExpedientTaskModalPageModule),
},
]
},
{
path: 'expedientes-pr',
children: [
{
path: '',
loadChildren: ()=> import('../pages/gabinete-digital/expedientes-pr/expedientes-pr.module').then(m => m.ExpedientesPrPageModule),
},
{
path:':SerialNumber/:caller',
loadChildren: ()=> import('../pages/gabinete-digital/expedientes-pr/expediente-pr/expediente-pr.module').then(m => m.ExpedientePrPageModule),
},
]
},
{
path: 'despachos',
children: [
{
path: '',
loadChildren: ()=> import('../pages/gabinete-digital/despachos/despachos.module').then(m => m.DespachosPageModule),
},
{
path:':SerialNumber/:caller',
loadChildren: ()=> import('../pages/gabinete-digital/despachos/despacho/despacho.module').then(m => m.DespachoPageModule),
},
]
},
{
path: 'despachos-pr',
children: [
{
path: '',
loadChildren: ()=> import('../pages/gabinete-digital/despachos-pr/despachos-pr.module').then(m => m.DespachosPrPageModule),
},
{
path:':SerialNumber/:caller',
loadChildren: ()=> import('../pages/gabinete-digital/despachos-pr/despacho-pr/despacho-pr.module').then(m => m.DespachoPrPageModule),
},
]
},
{
path: 'pedidos',
children: [
{
path: '',
loadChildren: ()=> import('../pages/gabinete-digital/pedidos/pedidos.module').then(m => m.PedidosPageModule),
},
{
path:':SerialNumber/:caller',
loadChildren: ()=> import('../pages/gabinete-digital/pedidos/pedido/pedido.module').then(m => m.PedidoPageModule),
},
]
},
{
path: 'diplomas',
children: [
{
path: '',
loadChildren: ()=> import('../pages/gabinete-digital/diplomas/diplomas.module').then(m => m.DiplomasPageModule),
},
{
path:':SerialNumber/:caller',
loadChildren: ()=> import('../pages/gabinete-digital/diplomas/diploma/diploma.module').then(m => m.DiplomaPageModule),
},
]
},
{
path: 'diplomas-assinar',
children: [
{
path: '',
loadChildren: ()=> import('../pages/gabinete-digital/diplomas-assinar/diplomas-assinar.module').then(m => m.DiplomasAssinarPageModule),
},
{
path:':SerialNumber/:caller',
loadChildren: ()=> import('../pages/gabinete-digital/diplomas-assinar/diploma-assinar/diploma-assinar.module').then(m => m.DiplomaAssinarPageModule),
},
]
},
{
path: 'diplomas-gerar',
children: [
{
path: '',
loadChildren: ()=> import('../pages/gabinete-digital/diplomas-gerar/diplomas-gerar.module').then(m => m.DiplomasGerarPageModule),
},
{
path:':SerialNumber/:caller',
loadChildren: ()=> import('../pages/gabinete-digital/diplomas-gerar/diplomas-gerar/diplomas-gerar-routing.module').then(m => m.DiplomasGerarPageRoutingModule),
},
]
},
{
path:'event-list',
children: [
{
path:'',
loadChildren: ()=> import('../pages/gabinete-digital/event-list/event-list.module').then(m => m.EventListPageModule)
},
{
path:'approve-event',
children : [
{
path:':serialNumber/:caller',
loadChildren: ()=> import('../pages/gabinete-digital/event-list/approve-event/approve-event.module').then(m => m.ApproveEventPageModule)
},
]
}
]
},
{
path: 'events-to-approve',
children: [
{
path: '',
loadChildren: ()=> import('../shared/gabinete-digital/edit-event-to-approve/edit-event.module')
}
]
}
],
},
// },
// {
// path: 'gabinete-digital',
// children: [
// {
// path:'',
// loadChildren: ()=> GabineteDigitalPageModule
// },
// {
// path:'expediente',
// children: [
// {
// path:'',
// loadChildren: ()=> import('../pages/gabinete-digital/expediente/expediente.module').then(m => m.ExpedientePageModule)
// },
// {
// path:':SerialNumber',
// loadChildren: ()=> import('../pages/gabinete-digital/expediente/expediente-detail/expediente-detail.module').then(m => m.ExpedienteDetailPageModule)
// },
// {
// path:':SerialNumber/:caller',
// loadChildren: ()=> import('../pages/gabinete-digital/expediente/expediente-detail/expediente-detail.module').then(m => m.ExpedienteDetailPageModule)
// },
// {
// path:'events/:eventId/:caller',
// loadChildren: ()=> import('../pages/events/event-detail/event-detail.module').then(m => m.EventDetailPageModule),
// },
// {
// path:'expediente-task-modal',
// loadChildren: ()=> import('../pages/gabinete-digital/expediente/expedient-task-modal/expedient-task-modal.module').then(m => m.ExpedientTaskModalPageModule),
// },
// ]
// },
// {
// path: 'expedientes-pr',
// children: [
// {
// path: '',
// loadChildren: ()=> import('../pages/gabinete-digital/expedientes-pr/expedientes-pr.module').then(m => m.ExpedientesPrPageModule),
// },
// {
// path:':SerialNumber/:caller',
// loadChildren: ()=> import('../pages/gabinete-digital/expedientes-pr/expediente-pr/expediente-pr.module').then(m => m.ExpedientePrPageModule),
// },
// ]
// },
// {
// path: 'despachos',
// children: [
// {
// path: '',
// loadChildren: ()=> import('../pages/gabinete-digital/despachos/despachos.module').then(m => m.DespachosPageModule),
// },
// {
// path:':SerialNumber/:caller',
// loadChildren: ()=> import('../pages/gabinete-digital/despachos/despacho/despacho.module').then(m => m.DespachoPageModule),
// },
// ]
// },
// {
// path: 'despachos-pr',
// children: [
// {
// path: '',
// loadChildren: ()=> import('../pages/gabinete-digital/despachos-pr/despachos-pr.module').then(m => m.DespachosPrPageModule),
// },
// {
// path:':SerialNumber/:caller',
// loadChildren: ()=> import('../pages/gabinete-digital/despachos-pr/despacho-pr/despacho-pr.module').then(m => m.DespachoPrPageModule),
// },
// ]
// },
// {
// path: 'pedidos',
// children: [
// {
// path: '',
// loadChildren: ()=> import('../pages/gabinete-digital/pedidos/pedidos.module').then(m => m.PedidosPageModule),
// },
// {
// path:':SerialNumber/:caller',
// loadChildren: ()=> import('../pages/gabinete-digital/pedidos/pedido/pedido.module').then(m => m.PedidoPageModule),
// },
// ]
// },
// {
// path: 'diplomas',
// children: [
// {
// path: '',
// loadChildren: ()=> import('../pages/gabinete-digital/diplomas/diplomas.module').then(m => m.DiplomasPageModule),
// },
// {
// path:':SerialNumber/:caller',
// loadChildren: ()=> import('../pages/gabinete-digital/diplomas/diploma/diploma.module').then(m => m.DiplomaPageModule),
// },
// ]
// },
// {
// path: 'diplomas-assinar',
// children: [
// {
// path: '',
// loadChildren: ()=> import('../pages/gabinete-digital/diplomas-assinar/diplomas-assinar.module').then(m => m.DiplomasAssinarPageModule),
// },
// {
// path:':SerialNumber/:caller',
// loadChildren: ()=> import('../pages/gabinete-digital/diplomas-assinar/diploma-assinar/diploma-assinar.module').then(m => m.DiplomaAssinarPageModule),
// },
// ]
// },
// {
// path: 'diplomas-gerar',
// children: [
// {
// path: '',
// loadChildren: ()=> import('../pages/gabinete-digital/diplomas-gerar/diplomas-gerar.module').then(m => m.DiplomasGerarPageModule),
// },
// {
// path:':SerialNumber/:caller',
// loadChildren: ()=> import('../pages/gabinete-digital/diplomas-gerar/diplomas-gerar/diplomas-gerar-routing.module').then(m => m.DiplomasGerarPageRoutingModule),
// },
// ]
// },
// {
// path:'event-list',
// children: [
// {
// path:'',
// loadChildren: ()=> import('../pages/gabinete-digital/event-list/event-list.module').then(m => m.EventListPageModule)
// },
// {
// path:'approve-event',
// children : [
// {
// path:':serialNumber/:caller',
// loadChildren: ()=> import('../pages/gabinete-digital/event-list/approve-event/approve-event.module').then(m => m.ApproveEventPageModule)
// },
// ]
// }
// ]
// },
// {
// path: 'events-to-approve',
// children: [
// {
// path: '',
// loadChildren: ()=> import('../shared/gabinete-digital/edit-event-to-approve/edit-event.module')
// }
// ]
// }
// ],
// },
{
path: 'search',
children: [
@@ -288,37 +288,37 @@ const routes: Routes = [
],
},
{
path: 'publications',
children: [
{
path:'',
loadChildren: ()=> PublicationsPageModule
},
{
path:':folderId',
loadChildren: ()=> import('../pages/publications/view-publications/view-publications.module').then(m => m.ViewPublicationsPageModule)
},
{
path:'view-publications',
children: [
{
path:':folderId/:publicationId',
loadChildren: ()=> import('../pages/publications/view-publications/publication-detail/publication-detail.module').then(m => m.PublicationDetailPageModule)
},
]
},
{
path:'new-publication',
loadChildren: ()=> import('../shared/publication/new-publication/new-publication.module').then(m => m.NewPublicationPageModule)
},
{
path: 'request-options',
loadChildren: () => import('../shared/popover/request-options/request-options.module').then( m => m.RequestOptionsPageModule)
},
],
// {
// path: 'publications',
// children: [
// {
// path:'',
// loadChildren: ()=> PublicationsPageModule
// },
// {
// path:':folderId',
// loadChildren: ()=> import('../pages/publications/view-publications/view-publications.module').then(m => m.ViewPublicationsPageModule)
// },
// {
// path:'view-publications',
// children: [
// {
// path:':folderId/:publicationId',
// loadChildren: ()=> import('../pages/publications/view-publications/publication-detail/publication-detail.module').then(m => m.PublicationDetailPageModule)
// },
// ]
// },
// {
// path:'new-publication',
// loadChildren: ()=> import('../shared/publication/new-publication/new-publication.module').then(m => m.NewPublicationPageModule)
// },
// {
// path: 'request-options',
// loadChildren: () => import('../shared/popover/request-options/request-options.module').then( m => m.RequestOptionsPageModule)
// },
// ],
},
// },
{
path: 'chat',
children: [
@@ -0,0 +1,12 @@
import { Injectable } from '@angular/core';
import { MessageAsyncService } from 'src/app/module/chat/data/async/socket/message-async.service'
@Injectable({
providedIn: 'root'
})
export class ChatServiceService {
constructor(
private MessageAsyncService: MessageAsyncService
) { }
}
@@ -1,5 +1,5 @@
import { TableRoom } from "../../data-source/room/rooom-local-data-source.service";
import { RoomListItemOutPutDTO, RoomListOutPutDTO } from "../../dto/room/roomListOutputDTO";
import { TableRoom } from "../../../data-source/room/rooom-local-data-source.service";
import { RoomListItemOutPutDTO, RoomListOutPutDTO } from "../../../dto/room/roomListOutputDTO";
export function roomListDetermineChanges(serverRooms: RoomListItemOutPutDTO[], localRooms: TableRoom[]) {
const serverRoomMap = new Map(serverRooms.map(room => [room.id, room]));
@@ -1,5 +1,5 @@
import { TableMemberList } from "../../data-source/room/rooom-local-data-source.service";
import { RoomByIdMemberItemOutputDTO } from "../../dto/room/roomByIdOutputDTO";
import { TableMemberList } from "../../../data-source/room/rooom-local-data-source.service";
import { RoomByIdMemberItemOutputDTO } from "../../../dto/room/roomByIdOutputDTO";
export function roomMemberListDetermineChanges(____serverRooms: RoomByIdMemberItemOutputDTO[], localRooms: TableMemberList[], roomId: string) {
@@ -0,0 +1,49 @@
import { Injectable } from '@angular/core';
import { MessageLiveDataSourceService } from '../../data-source/message/message-live-data-source.service';
import { MessageLocalDataSourceService } from '../../data-source/message/message-local-data-source.service';
import { MessageRemoteDataSourceService } from '../../data-source/message/message-remote-data-source.service';
import { SignalRService } from '../../../infra/socket/signal-r.service';
import { filter } from 'rxjs/operators';
import { InstanceId } from '../../repository/message-respository.service';
@Injectable({
providedIn: 'root'
})
export class MessageAsyncService {
constructor(
private messageRemoteDataSourceService: MessageRemoteDataSourceService,
private messageLiveDataSourceService: MessageLiveDataSourceService,
private messageLiveSignalRDataSourceService: SignalRService,
private messageLocalDataSourceService: MessageLocalDataSourceService
) {
this.messageLiveSignalRDataSourceService.getMessage().pipe(
filter((message: any) => {
return !message?.requestId?.startsWith(InstanceId) && message?.requestId
})
).subscribe(async (message: any) => {
console.log('message async ', message)
const id = message.id
delete message.id;
// const result = await this.messageLocalDataSourceService.createMessage({
// messageId: id,
// sending: false,
// ...message
// })
// if(result.isOk()) {
// console.log(result.value)
// } else {
// console.log(result.error)
// }
})
}
}
@@ -1,17 +1,20 @@
import { Injectable } from '@angular/core';
import { err, ok } from 'neverthrow';
import { WebSocketMessage, WebSocketService } from '../../infra/socket/socket';
import { WebSocketMessage, WebSocketService } from '../../../infra/socket/socket';
import { SignalRService } from '../../../infra/socket/signal-r.service';
@Injectable({
providedIn: 'root'
})
export class MessageLiveDataSourceService {
constructor(public socket: WebSocketService) {}
constructor(
public socket: WebSocketService,
private signalR: SignalRService) {}
async sendMessage(data: WebSocketMessage) {
try {
const result = await this.socket.sendMessage(data).toPromise()
return ok(result)
@@ -21,4 +24,4 @@ export class MessageLiveDataSourceService {
}
}
}
@@ -0,0 +1,38 @@
import { Injectable } from '@angular/core';
import { err, ok } from 'neverthrow';
import { SignalRService } from '../../../infra/socket/signal-r.service';
interface msgObj {
roomId: string;
senderId: string;
message:string;
messageType:1;
canEdit:Boolean;
oneShot:Boolean;
requestId: string;
}
@Injectable({
providedIn: 'root'
})
export class MessageLiveDataSourceService {
constructor(
private messageLiveSignalRDataSourceService: SignalRService
) {}
async sendMessage(data: msgObj) {
try {
const result = await this.messageLiveSignalRDataSourceService.sendMessage(data)
return ok(result)
} catch (e) {
return err(e)
}
}
}
@@ -1,11 +1,11 @@
import { Injectable } from '@angular/core';
import { HttpService } from 'src/app/services/http.service';
import { DataSourceReturn } from '../../../type';
import { MessageInputDTO, MessageInputDTOSchema } from '../../dto/message/messageInputDtO';
import { ValidateSchema } from 'src/app/services/decorators/validate-schema.decorator';
import { APIReturn } from 'src/app/services/decorators/api-validate-schema.decorator';
import { MessageOutPutDTO, MessageOutPutDTOSchema } from '../../dto/message/messageOutputDTO';
import { MessageListOutput } from '../../dto/message/messageListOutputDTO';
import { DataSourceReturn } from 'src/app/services/Repositorys/type';
@Injectable({
providedIn: 'root'
@@ -1,5 +1,5 @@
import { Injectable } from '@angular/core';
import { WebSocketMessage, WebSocketService } from '../../infra/socket/socket';
import { WebSocketMessage, WebSocketService } from '../../../infra/socket/socket';
import { err, ok } from 'neverthrow';
@Injectable({
@@ -12,7 +12,7 @@ export class RoomLiveDataSourceService {
async getRoomById(data: WebSocketMessage) {
try {
const result = await this.socket.sendMessage(data).toPromise()
console.log({result})
@@ -24,4 +24,4 @@ export class RoomLiveDataSourceService {
}
}
}
@@ -6,13 +6,13 @@ 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 { DataSourceReturn } from '../../../type';
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 { DataSourceReturn } from 'src/app/services/Repositorys/type';
@Injectable({
providedIn: 'root'
@@ -4,6 +4,10 @@ import { MessageLiveDataSourceService } from '../data-source/message/message-liv
import { MessageInputDTO } from '../dto/message/messageInputDtO';
import { MessageLocalDataSourceService, TableMessage } from '../data-source/message/message-local-data-source.service';
import { SessionStore } from 'src/app/store/session.service';
import { SignalRService } from '../../infra/socket/signal-r.service';
import { v4 as uuidv4 } from 'uuid'
export const InstanceId = uuidv4();
@Injectable({
providedIn: 'root'
@@ -13,30 +17,11 @@ export class MessageRepositoryService {
constructor(
private messageRemoteDataSourceService: MessageRemoteDataSourceService,
private messageLiveDataSourceService: MessageLiveDataSourceService,
private messageLiveSignalRDataSourceService: SignalRService,
private messageLocalDataSourceService: MessageLocalDataSourceService
) {
this.messageLiveDataSourceService.socket.messages$.subscribe(({payload, requestId, type}) => {
if(payload.sender == null) {
delete payload.sender
}
if(type == 'sendMessage') {
let clone: TableMessage = {
...payload,
messageId: payload.id,
}
delete clone.id
try {
this.messageLocalDataSourceService.createMessage(clone)
} catch (e) {
//console.log('error', {payload})
}
} else if (type == 'deleteMessage') {
}
@@ -53,6 +38,8 @@ export class MessageRepositoryService {
wxUserId: SessionStore.user.UserId
}
data['requestId'] = InstanceId +'@'+ uuidv4();
const localActionResult = await this.messageLocalDataSourceService.sendMessage(data)
this.messageLiveDataSourceService.sendMessage({
@@ -61,17 +48,22 @@ export class MessageRepositoryService {
})
if(localActionResult.isOk()) {
const sendMessageResult = await this.messageRemoteDataSourceService.sendMessage(data)
const sendMessageResult = await this.messageLiveSignalRDataSourceService.sendMessage(data)
//const sendMessageResult = await this.messageRemoteDataSourceService.sendMessage(data)
if(sendMessageResult.isOk()) {
if(sendMessageResult.value.data.sender == null) {
delete sendMessageResult.value.data.sender
if(sendMessageResult.value.sender == undefined || sendMessageResult.value.sender == null) {
console.log({sendMessageResult})
delete sendMessageResult.value.sender
}
let clone: TableMessage = {
...sendMessageResult.value.data,
messageId: sendMessageResult.value.data.id,
...sendMessageResult.value,
messageId: sendMessageResult.value.id,
id : localActionResult.value
}
@@ -1,20 +1,17 @@
import { Injectable } from '@angular/core';
import { RoomRemoteDataSourceService } from '../data-source/room/room-remote-data-source.service'
import { RoomInputDTO } from '../dto/room/roomInputDTO';
import { addRoom, RoomRemoteDataSourceState } from '../data-source/room/room-memory-data-source';
import { Store } from '@ngrx/store';
import { AddMemberToRoomInputDTO } from '../dto/room/addMemberToRoomInputDto';
import { RoomLocalDataSourceService } from '../data-source/room/rooom-local-data-source.service';
import { RoomByIdInputDTO } from '../dto/room/roomByIdInputDTO';
import { roomListDetermineChanges } from '../async/rooms/roomListChangeDetector';
import { roomListDetermineChanges } from '../async/list/rooms/roomListChangeDetector';
import { UserRemoveListInputDTO } from '../dto/room/userRemoveListInputDTO';
import { roomMemberListDetermineChanges } from '../async/rooms/roomMembersChangeDetector';
import { roomMemberListDetermineChanges } from '../async/list/rooms/roomMembersChangeDetector';
import { captureAndReraiseAsync } from 'src/app/services/decorators/captureAndReraiseAsync';
import { RoomUpdateInputDTO } from '../dto/room/roomUpdateInputDTO';
import { SessionStore } from 'src/app/store/session.service';
import { RoomLiveDataSourceService } from '../data-source/room/room-live-data-source.service';
import { isHttpResponse } from 'src/app/services/http.service';
import { TableMessage } from '../data-source/message/message-local-data-source.service';
import { MessageLiveDataSourceService } from '../data-source/message/message-live-data-source.service';
@@ -41,7 +38,7 @@ export class RoomRepositoryService {
constructor(
private roomRemoteDataSourceService: RoomRemoteDataSourceService,
private roomMemoryDataSourceService: Store<RoomRemoteDataSourceState>,
// private roomMemoryDataSourceService: Store<RoomRemoteDataSourceState>,
private roomLocalDataSourceService: RoomLocalDataSourceService,
private roomLiveDataSourceService: RoomLiveDataSourceService,
private messageLiveDataSourceService: MessageLiveDataSourceService,
@@ -235,7 +232,7 @@ export class RoomRepositoryService {
}
}
this.roomMemoryDataSourceService.dispatch(addRoom(result.value))
// this.roomMemoryDataSourceService.dispatch(addRoom(result.value))
const localResult = await this.roomLocalDataSourceService.createRoom(result.value.data)
this.messageLiveDataSourceService.sendMessage({
@@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';
import { SignalRService } from './signal-r.service';
describe('SignalRService', () => {
let service: SignalRService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(SignalRService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
@@ -0,0 +1,78 @@
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
import { Platform } from '@ionic/angular';
import { SignalRConnection } from './signalR';
import { Plugins } from '@capacitor/core';
const { App } = Plugins;
@Injectable({
providedIn: 'root'
})
export class SignalRService {
private connection: SignalRConnection;
private messageSubject: BehaviorSubject<string> = new BehaviorSubject<any>(null);
private connectingSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(null);
constructor(
private platform: Platform,) {
// this.startConnection();
// this.addMessageListener();
try {
if (!this.platform.is('desktop')) {
App.addListener('appStateChange', ({ isActive }) => {
if (isActive) {
// The app is in the foreground.
console.log('App is in the foreground');
this.newConnection()
} else {
// The app is in the background.
console.log('App is in the background');
// You can perform actions specific to the background state here.
}
});
}
} catch(error) {}
this.establishConnection()
}
private async establishConnection() {
const connection = new SignalRConnection({url:'https://gdapi-dev.dyndns.info/stage/chathub'})
const attempConnection = await connection.establishConnection()
if(attempConnection.isOk()) {
this.connection?.closeConnection()
this.connection = connection
this.connection.getSendLater().subscribe(data => {
})
this.connection.getMessages().subscribe((data) => {
this.messageSubject.next(data)
})
}
}
getMessage() {
return this.messageSubject.asObservable()
}
async sendMessage(data: Object) {
return await this.connection.sendMessage(data as any)
}
newConnection() {
this.establishConnection()
}
}
+140
View File
@@ -0,0 +1,140 @@
import * as signalR from '@microsoft/signalr';
import { BehaviorSubject, Observable } from 'rxjs';
import { ok, Result, err } from 'neverthrow';
import { SessionStore } from 'src/app/store/session.service';
import { filter, first } from 'rxjs/operators';
export class SignalRConnection {
private hubConnection: signalR.HubConnection;
private messageSubject: BehaviorSubject<string> = new BehaviorSubject<any>(null);
private connectionStateSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
private disconnectSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
private reconnectSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
private sendLaterSubject: BehaviorSubject<Object> = new BehaviorSubject<Object>(false);
private reconnect = true
url: string
constructor({url}) {
this.url = url
}
establishConnection(): Promise<Result<signalR.HubConnection, false>> {
return new Promise((resolve, reject) => {
const hubConnection = new signalR.HubConnectionBuilder()
.withUrl(this.url)
.build();
this.hubConnection = hubConnection
this.join()
hubConnection
.start()
.then(() => {
console.log('Connection started');
this.connectionStateSubject.next(true);
this.hubConnection = hubConnection
this.addMessageListener()
this.join()
resolve(ok(hubConnection))
})
.catch(error => {
console.log('Error while starting connection: ' + error);
this.connectionStateSubject.next(false);
reject(err(false))
});
hubConnection.onclose(() => {
console.log('Connection closed');
this.connectionStateSubject.next(false);
this.disconnectSubject.next(true)
if(this.reconnect) {
this.attempReconnect();
}
});
})
}
async attempReconnect() {
const attempConnection = await this.establishConnection()
if(attempConnection.isOk()) {
this.reconnectSubject.next(true)
}
}
public join() {
if(this.connectionStateSubject.value == true) {
console.log('join=============')
this.hubConnection.invoke("Join", 105, "UserFirefox");
} else {
this.sendLaterSubject.next({method: 'SendMessage', args:["Join", 312, "Daniel"]})
}
}
public async sendMessage(data: Object & { requestId}):Promise<Result<any, any>> {
return new Promise((resolve, reject) => {
if(this.connectionStateSubject.value == true) {
console.log('sendMessage')
this.hubConnection.invoke("SendMessage", data)
this.messageSubject.pipe(
filter((message: any) => data.requestId == message?.requestId),
first()
).subscribe(value => {
resolve(ok(value))
console.log('Received valid value:', value);
});
} else {
this.sendLaterSubject.next({method: 'SendMessage', args: data})
return reject(err(false))
}
})
}
private addMessageListener(): void {
this.hubConnection.on('ReceiveMessage', (message) => {
console.log('ReceiveMessage', message)
this.messageSubject.next(message);
});
}
public getMessages(): Observable<string> {
return this.messageSubject.asObservable()
}
public getConnectionState(): Observable<boolean> {
return this.connectionStateSubject.asObservable();
}
public getDisconnectTrigger(): Observable<boolean> {
return this.disconnectSubject.asObservable();
}
public getSendLater() {
return this.sendLaterSubject.asObservable();
}
public closeConnection(): void {
this.reconnect = false
if (this.hubConnection) {
this.hubConnection
.stop()
.then(() => {
console.log('Connection closed by user');
this.connectionStateSubject.next(false);
})
.catch(err => console.log('Error while closing connection: ' + err));
}
}
}
@@ -0,0 +1,50 @@
<!DOCTYPE html>
<html>
<head>
<title>SignalR Client</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/8.0.0/signalr.min.js"></script>
</head>
<body>
<h1>SignalR Client</h1>
<div id="messages"></div>
<input id="chatbox">
<script>
var msgObj = {
roomId: "882fcb86-4028-4242-bb47-fca0170dcc65",
senderId:105,
message:"message enviada",
messageType:1,
canEdit:true,
oneShot:false,
};
const connection = new signalR.HubConnectionBuilder()
.withAutomaticReconnect()
.withUrl("https://gdapi-dev.dyndns.info/stage/chathub")
.build();
connection.start().then(function () {
connection.invoke("Join", 105, "UserFirefox");
document.getElementById("chatbox").addEventListener("keyup", function (event) {
if (event.key === "Enter") {
msgObj.Message = chatbox.value;
connection.invoke("SendMessage", msgObj);
event.target.value = "";
}
});
}).catch(function (err) {
return console.error(err.toString());
});
connection.on("ReceiveMessage", function (message) {
console.log(message);
const messages = document.getElementById("messages");
messages.innerHTML += `<p>${message.message}</p>`;
});
</script>
</body>
</html>
+1 -1
View File
@@ -8,7 +8,7 @@
<!-- Aside left -->
<div class="aside-wrapper d-flex flex-column flex-grow-1">
<!-- <p class="text-center mt-0 aside-title px-20">Chat</p> -->
<ion-progress-bar type="indeterminate" *ngIf="ChatSystemService.loadingWholeList"></ion-progress-bar>
<!-- <ion-progress-bar type="indeterminate" ></ion-progress-bar> -->
<div class="title-content">
<div class="div-title">
<ion-label class="title font-25-em">Chat</ion-label>
+5 -13
View File
@@ -24,18 +24,13 @@ import { environment } from 'src/environments/environment';
import { TimeService } from 'src/app/services/functions/time.service';
import { ThemeService } from 'src/app/services/theme.service'
import { DataService } from 'src/app/services/data.service';
import { StorageService } from 'src/app/services/storage.service';
import { SessionStore } from 'src/app/store/session.service';
import { ChatDebuggingPage } from 'src/app/shared/popover/chat-debugging/chat-debugging.page';
import { RouteService } from 'src/app/services/route.service';
import { Plugins } from '@capacitor/core';
import { Store } from '@ngrx/store';
import { RoomRemoteDataSourceState } from 'src/app/services/Repositorys/chat/data-source/room/room-memory-data-source';
import { RoomRepositoryService } from 'src/app/services/Repositorys/chat/repository/room-repository.service'
import { RoomListOutPutDTO } from 'src/app/services/Repositorys/chat/dto/room/roomListOutputDTO';
import { MessageLiveDataSourceService } from 'src/app/module/chat/data/data-source/message/message-live-data-source.service';
import { RoomRemoteDataSourceState } from 'src/app/module/chat/data/data-source/room/room-memory-data-source';
import { RoomListOutPutDTO } from 'src/app/module/chat/data/dto/room/roomListOutputDTO';
import { MessageRepositoryService } from 'src/app/module/chat/data/repository/message-respository.service'
import { RoomRepositoryService } from 'src/app/module/chat/data/repository/room-repository.service'
import { Observable as DexieObservable } from 'Dexie';
import { MessageLiveDataSourceService } from 'src/app/services/Repositorys/chat/data-source/message/message-live-data-source.service';
@Component({
selector: 'app-chat',
@@ -124,7 +119,6 @@ export class ChatPage implements OnInit {
private router: Router,
public ChatSystemService: ChatSystemService,
public RouteService: RouteService,
private store: Store<{ chat: RoomRemoteDataSourceState }>,
private RoomRepositoryService: RoomRepositoryService,
private messageLiveDataSourceService: MessageLiveDataSourceService,
) {
@@ -141,8 +135,6 @@ export class ChatPage implements OnInit {
})
this.count$ = store.select('chat');
this.headers = new HttpHeaders();
window.onresize = (event) => {
if (window.innerWidth > 701) {
-10
View File
@@ -16,9 +16,7 @@ import { ViewEventPage } from 'src/app/modals/view-event/view-event.page';
import { ChangeProfileService } from 'src/app/services/change-profile.service';
import { SessionStore } from 'src/app/store/session.service';
import { TaskService } from 'src/app/services/task.service';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs';
import { increment } from 'src/app/app.module';
@Component({
selector: 'app-events',
@@ -95,16 +93,8 @@ export class EventsPage implements OnInit {
public p: PermissionService,
private changeProfileService: ChangeProfileService,
public TaskService: TaskService,
private store: Store<{ count: number }>
) {
this.count$ = store.select('count');
setInterval(() => {
this.store.dispatch(increment());
}, 5000)
window['zipPhoneCallback'] = function (zipphone) {
var frame = document.getElementById('home-iframe');
if(frame) {
-2
View File
@@ -77,8 +77,6 @@ export class EventsPage implements OnInit {
private router: Router,
public activatedRoute: ActivatedRoute,
private processes:ProcessesService,
/* private gabineteService: GabineteDigitalPage, */
private modalController:ModalController,
private screenOrientation: ScreenOrientation,
public platform: Platform,
public ThemeService: ThemeService,
+42 -42
View File
@@ -1,53 +1,53 @@
import { DateTime } from 'luxon';
// import { DateTime } from 'luxon';
type GetDateWithFormatFormatInput = {
date?: Date;
format?: string;
};
// type GetDateWithFormatFormatInput = {
// date?: Date;
// format?: string;
// };
export class DateUtils {
static getDateStringWithFormat(
input: Partial<GetDateWithFormatFormatInput> = {},
): string {
if (!input?.date) {
Object.assign(input, { date: DateUtils.getJSDate() });
}
// export class DateUtils {
// static getDateStringWithFormat(
// input: Partial<GetDateWithFormatFormatInput> = {},
// ): string {
// if (!input?.date) {
// Object.assign(input, { date: DateUtils.getJSDate() });
// }
if (!input?.format) {
Object.assign(input, { format: process.env.DATE_FORMAT });
}
// if (!input?.format) {
// Object.assign(input, { format: process.env.DATE_FORMAT });
// }
return DateTime.fromJSDate(input.date, { zone: 'utc' })
.setZone(process.env.TZ)
.toFormat(input.format);
}
// return DateTime.fromJSDate(input.date, { zone: 'utc' })
// .setZone(process.env.TZ)
// .toFormat(input.format);
// }
static getISODateString(): string {
return DateTime.fromJSDate(DateUtils.getJSDate(), { zone: 'utc' })
.setZone(process.env.TZ)
.toJSON();
}
// static getISODateString(): string {
// return DateTime.fromJSDate(DateUtils.getJSDate(), { zone: 'utc' })
// .setZone(process.env.TZ)
// .toJSON();
// }
static getISODateJSDateObject(dateObject: Date): string {
// Convert the JavaScript Date object to Luxon DateTime
const luxonDateTime = DateTime.fromJSDate(dateObject, { zone: 'utc' });
// static getISODateJSDateObject(dateObject: Date): string {
// // Convert the JavaScript Date object to Luxon DateTime
// const luxonDateTime = DateTime.fromJSDate(dateObject, { zone: 'utc' });
// Get the ISO 8601 formatted string in UTC
const isoDateString = luxonDateTime.toISO();
// // Get the ISO 8601 formatted string in UTC
// const isoDateString = luxonDateTime.toISO();
return isoDateString;
}
// return isoDateString;
// }
static getJSDate(): Date {
return DateTime.fromJSDate(DateTime.now().toJSDate(), { zone: 'utc' })
.setZone(process.env.TZ)
.toJSDate();
}
// static getJSDate(): Date {
// return DateTime.fromJSDate(DateTime.now().toJSDate(), { zone: 'utc' })
// .setZone(process.env.TZ)
// .toJSDate();
// }
static getDate(): DateTime {
return DateTime.fromJSDate(DateUtils.getJSDate(), { zone: 'utc' }).setZone(
process.env.TZ,
);
}
}
// static getDate(): DateTime {
// return DateTime.fromJSDate(DateUtils.getJSDate(), { zone: 'utc' }).setZone(
// process.env.TZ,
// );
// }
// }
+4 -6
View File
@@ -1,6 +1,4 @@
import { DateUtils } from './date';
// import { DateUtils } from './date';
export type MessageType = {
message: string;
@@ -33,7 +31,7 @@ export class ColoredLoggerService {
console.info(
`[${getCurrentTime()}] %cINFO : `, // Console Message
'color: #039BE5', // CSS Style
Object.assign(obj, { context, createdAt: DateUtils.getISODateString(), message })
Object.assign(obj, { context, createdAt: getCurrentTime(), message })
);
}
@@ -41,7 +39,7 @@ export class ColoredLoggerService {
console.info(
`[${getCurrentTime()}] %cINFO : `, // Console Message
'color: #039BE5', // CSS Style
Object.assign(obj, { context, createdAt: DateUtils.getISODateString(), message })
Object.assign(obj, { context, createdAt: getCurrentTime(), message })
);
}
@@ -49,7 +47,7 @@ export class ColoredLoggerService {
console.warn(
`[${getCurrentTime()}] %cWARN : `, // Console Message
'color: #FB8C00', // CSS Style
Object.assign(obj, { context, createdAt: DateUtils.getISODateString(), message })
Object.assign(obj, { context, createdAt: getCurrentTime(), message })
);
}
@@ -1,5 +1,4 @@
import { Injectable } from '@angular/core';
import { RoomRepositoryService } from '../Repositorys/chat/repository/room-repository.service';
@Injectable({
providedIn: 'root'
@@ -7,6 +6,6 @@ import { RoomRepositoryService } from '../Repositorys/chat/repository/room-repos
export class NewChatSystemService {
constructor(
private roomRepositoryService: RoomRepositoryService
) { }
}
@@ -4,11 +4,13 @@ import { ModalController, PickerController } from '@ionic/angular';
import { ChatService } from 'src/app/services/chat.service';
import { ThemeService } from 'src/app/services/theme.service'
import { SessionStore } from 'src/app/store/session.service';
import { RoomRepositoryService } from 'src/app/services/Repositorys/chat/repository/room-repository.service'
import { HttpResponse } from '@microsoft/signalr';
import { HttpErrorHandle } from 'src/app/services/http-error-handle.service';
import { ToastService } from 'src/app/services/toast.service';
import { ZodError } from 'zod';
import { RoomRepositoryService } from 'src/app/module/chat/data/repository/room-repository.service'
@Component({
selector: 'app-edit-group',
templateUrl: './edit-group.page.html',
@@ -3,7 +3,7 @@ import { ThemeService } from 'src/app/services/theme.service'
import { ChatSystemService } from 'src/app/services/chat/chat-system.service';
import { ContactRepositoryService } from 'src/app/services/Repositorys/contacts/repository/contacts-repository.service';
import { UserContacts } from 'src/app/services/Repositorys/contacts/data-source/contacts-data-source.service';
import { RoomRepositoryService } from 'src/app/services/Repositorys/chat/repository/room-repository.service'
import { RoomRepositoryService } from 'src/app/module/chat/data/repository/room-repository.service'
import { HttpErrorHandle } from 'src/app/services/http-error-handle.service';
import { SessionStore } from 'src/app/store/session.service';
@@ -1,14 +1,13 @@
import { HttpHeaders } from '@angular/common/http';
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { ModalController } from '@ionic/angular';
import { ChatService } from 'src/app/services/chat.service';
import { MessagesPage } from '../messages.page';
import { ThemeService } from 'src/app/services/theme.service'
import { ChatSystemService } from 'src/app/services/chat/chat-system.service'
import { SessionStore } from 'src/app/store/session.service';
import { ContactRepositoryService } from 'src/app/services/Repositorys/contacts/repository/contacts-repository.service';
import { UserContacts } from 'src/app/services/Repositorys/contacts/data-source/contacts-data-source.service';
import { RoomRepositoryService } from 'src/app/services/Repositorys/chat/repository/room-repository.service';
import { RoomRepositoryService } from 'src/app/module/chat/data/repository/room-repository.service'
import { HttpErrorResponse } from '@angular/common/http';
import { HttpErrorHandle } from 'src/app/services/http-error-handle.service';
import { ToastService } from 'src/app/services/toast.service';
@@ -33,15 +33,16 @@ import { ViewMediaPage } from 'src/app/modals/view-media/view-media.page';
import { ChatMessageDebuggingPage } from 'src/app/shared/popover/chat-message-debugging/chat-message-debugging.page';
import { PermissionService } from 'src/app/services/permission.service';
import { FileValidatorService } from "src/app/services/file/file-validator.service"
import { RoomRepositoryService } from 'src/app/services/Repositorys/chat/repository/room-repository.service';
import { RoomListItemOutPutDTO } from 'src/app/services/Repositorys/chat/dto/room/roomListOutputDTO';
import { MessageRepositoryService } from 'src/app/services/Repositorys/chat/repository/message-respository.service';
import { MessageInputDTO } from 'src/app/services/Repositorys/chat/dto/message/messageInputDtO';
import { TableMemberList } from 'src/app/services/Repositorys/chat/data-source/room/rooom-local-data-source.service';
import { TableMessage } from 'src/app/services/Repositorys/chat/data-source/message/message-local-data-source.service';
import { ChatPopoverPage } from '../../popover/chat-popover/chat-popover.page';
import { Observable as DexieObservable } from 'Dexie';
import { Subscription } from 'rxjs';
import { MessageRepositoryService } from 'src/app/module/chat/data/repository/message-respository.service'
import { RoomRepositoryService } from 'src/app/module/chat/data/repository/room-repository.service'
import { TableMessage } from 'src/app/module/chat/data/data-source/message/message-local-data-source.service';
import { TableMemberList } from 'src/app/module/chat/data/data-source/room/rooom-local-data-source.service';
import { MessageInputDTO } from 'src/app/module/chat/data/dto/message/messageInputDtO';
import { RoomListItemOutPutDTO } from 'src/app/module/chat/data/dto/room/roomListOutputDTO';
const IMAGE_DIR = 'stored-images';
@Component({
@@ -7,7 +7,7 @@ import { SessionStore } from 'src/app/store/session.service';
import { ThemeService } from 'src/app/services/theme.service';
import { RouteService } from 'src/app/services/route.service';
import { HttpErrorResponse } from '@angular/common/http';
import { RoomRepositoryService } from 'src/app/services/Repositorys/chat/repository/room-repository.service';
import { RoomRepositoryService } from 'src/app/module/chat/data/repository/room-repository.service'
import { HttpErrorHandle } from 'src/app/services/http-error-handle.service'
@Component({
@@ -4,14 +4,11 @@ import { ChatService } from 'src/app/services/chat.service';
import { ToastService } from 'src/app/services/toast.service';
import { ThemeService } from 'src/app/services/theme.service'
import { SetRoomOwnerPage } from 'src/app/modals/set-room-owner/set-room-owner.page';
import { RoomRepositoryService } from 'src/app/services/Repositorys/chat/repository/room-repository.service'
import { ChatSystemService } from 'src/app/services/chat/chat-system.service';
import { HttpErrorResponse, HttpResponse } from '@angular/common/http';
import { SessionStore } from 'src/app/store/session.service';
import { GroupContactsPage } from '../../chat/group-messages/group-contacts/group-contacts.page';
import { ZodError } from 'zod';
import { isHttpResponse } from 'src/app/services/http.service';
import { MessageRepositoryService } from 'src/app/module/chat/data/repository/message-respository.service'
import { RoomRepositoryService } from 'src/app/module/chat/data/repository/room-repository.service'
@Component({
selector: 'app-chat-popover',