diff --git a/src/app/app.module.ts b/src/app/app.module.ts index cab5111ac..021f4fbaa 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -97,6 +97,7 @@ import { DiplomaOptionsPage } from './shared/popover/deploma-options/deploma-opt import { ImageCropperModule } from 'ngx-image-cropper'; import { createAction, createReducer, on, StoreModule } from '@ngrx/store'; import { typingReducer } from './module/chat/data/data-source/userTyping/user-typing-memory-data-source.service'; +import { ChatModule } from './module/chat/chat.module'; // import { ServiceWorkerModule } from '@angular/service-worker'; // import { AngularFireModule } from '@angular/fire'; // import { AngularFireMessagingModule } from '@angular/fire/messaging'; @@ -210,7 +211,9 @@ export function counterReducer(state, action) { // options DeplomaOptionsPageModule, CreateProcessPageModule, - ImageCropperModule + ImageCropperModule, + // module + ChatModule ], entryComponents: [ DiplomaOptionsPage, diff --git a/src/app/module/chat/chat.module.ts b/src/app/module/chat/chat.module.ts new file mode 100644 index 000000000..d8baf4ea6 --- /dev/null +++ b/src/app/module/chat/chat.module.ts @@ -0,0 +1,36 @@ +import { NgModule } from '@angular/core'; +import { SignalRService } from 'src/app/module/chat/infra/socket/signal-r.service' +import { SyncMessageRepositoryService } from './data/service/sync-repository/sync-message-repository.service'; +@NgModule({ + imports: [ + + ], + providers: [ + SyncMessageRepositoryService + ], + declarations: [], + schemas: [], + entryComponents: [] +}) +export class ChatModule { + + constructor( + private message: SyncMessageRepositoryService, + private SignalRService: SignalRService + ) { + + + this.triggerToSendOfflineMessages() + } + + + triggerToSendOfflineMessages() { + const result = this.SignalRService.getConnectionState() + + result.subscribe((value) => { + if(value) { + this.message.sendLocalMessages() + } + }) + } +} diff --git a/src/app/module/chat/data/async/repository/message-repository-aync.service.spec.ts b/src/app/module/chat/data/async/repository/message-repository-aync.service.spec.ts new file mode 100644 index 000000000..03d1d6ce9 --- /dev/null +++ b/src/app/module/chat/data/async/repository/message-repository-aync.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { MessageRepositoryAyncService } from './message-repository-aync.service'; + +describe('MessageRepositoryAyncService', () => { + let service: MessageRepositoryAyncService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(MessageRepositoryAyncService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/module/chat/data/async/repository/message-repository-aync.service.ts b/src/app/module/chat/data/async/repository/message-repository-aync.service.ts new file mode 100644 index 000000000..52d5122e7 --- /dev/null +++ b/src/app/module/chat/data/async/repository/message-repository-aync.service.ts @@ -0,0 +1,12 @@ +import { Injectable } from '@angular/core'; + +@Injectable({ + providedIn: 'root' +}) +export class MessageRepositoryAyncService { + + constructor() { + + // alert('hellor') + } +} 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 24bfc8b38..9e0305e12 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 @@ -235,5 +235,18 @@ export class MessageLocalDataSourceService { ) ) } + + + async getOfflineMessages () { + try { + const allMessages = await messageDataSource.message + .filter(msg => typeof msg.id !== 'string' && msg.sending == false) + .toArray(); + + return allMessages as MessageEntity[]; + } catch (error) { + console.error('Error fetching messages:', error); + } + } } diff --git a/src/app/module/chat/data/service/sync-repository/sync-message-repository.service.ts b/src/app/module/chat/data/service/sync-repository/sync-message-repository.service.ts new file mode 100644 index 000000000..621cf9b9d --- /dev/null +++ b/src/app/module/chat/data/service/sync-repository/sync-message-repository.service.ts @@ -0,0 +1,51 @@ +import { Injectable } from '@angular/core'; +import { SignalRService } from '../../../infra/socket/signal-r.service'; +import { MessageLiveDataSourceService } from '../../data-source/message/message-live-data-source.service'; +import { MessageLocalDataSourceService, TableMessage } from '../../data-source/message/message-local-data-source.service'; +import { MessageRemoteDataSourceService } from '../../data-source/message/message-remote-data-source.service'; +import { InstanceId } from '../../../domain/chat-service.service'; +import { v4 as uuidv4 } from 'uuid' +import { MessageMapper } from 'src/app/module/chat/domain/mapper/messageMapper' + +@Injectable({ + providedIn: 'root' +}) +export class SyncMessageRepositoryService { + + constructor( + private messageRemoteDataSourceService: MessageRemoteDataSourceService, + private messageLiveDataSourceService: MessageLiveDataSourceService, + private messageLiveSignalRDataSourceService: SignalRService, + private messageLocalDataSourceService: MessageLocalDataSourceService + ) { } + + async sendLocalMessages() { + const messages = await this.messageLocalDataSourceService.getOfflineMessages() + + if(messages.length >= 1) { + console.log('to send '+ messages.length) + for(const message of messages) { + const requestId = InstanceId +'@'+ uuidv4(); + const DTO = MessageMapper.fromDomain(message, requestId) + const sendMessageResult = await this.messageLiveSignalRDataSourceService.sendMessage(DTO) + + if(sendMessageResult.isOk()) { + + if(sendMessageResult.value.sender == undefined || sendMessageResult.value.sender == null) { + + delete sendMessageResult.value.sender + } + + let clone: TableMessage = { + ...sendMessageResult.value, + id: sendMessageResult.value.id, + $id : message.$id + } + + return this.messageLocalDataSourceService.update({...clone, sending: false, roomId: message.roomId}) + } + } + + } + } +} diff --git a/src/app/module/chat/domain/use-case/sync-local-message.service.ts b/src/app/module/chat/domain/use-case/sync-local-message.service.ts new file mode 100644 index 000000000..918a43c7d --- /dev/null +++ b/src/app/module/chat/domain/use-case/sync-local-message.service.ts @@ -0,0 +1,16 @@ +import { Injectable } from '@angular/core'; +import { SyncMessageRepositoryService } from 'src/app/module/chat/data/service/sync-repository/sync-message-repository.service' +@Injectable({ + providedIn: 'root' +}) +export class SyncLocalMessageService { + + constructor( + private SyncMessageRepositoryService: SyncMessageRepositoryService + ) { } + + + async execute() { + return this.SyncMessageRepositoryService.sendLocalMessages() + } +} 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 1bb3efa8a..a0967fc0c 100644 --- a/src/app/module/chat/infra/socket/signal-r.service.ts +++ b/src/app/module/chat/infra/socket/signal-r.service.ts @@ -1,5 +1,5 @@ import { Injectable } from '@angular/core'; -import { BehaviorSubject, Subject, timer } from 'rxjs'; +import { BehaviorSubject, Observable, Subject, timer } from 'rxjs'; import { Platform } from '@ionic/angular'; import { SignalRConnection } from './signalR'; import { Plugins } from '@capacitor/core'; @@ -102,6 +102,16 @@ export class SignalRService { this.sendDataSubject.next(data) this.deadConnectionBackGround.next() }) + + this.connection.getConnectionState().subscribe((data) => { + this.connectingSubject.next(data) + }) + } else { + + setTimeout(() => { + this.establishConnection() + }, 2000) + } } @@ -131,6 +141,9 @@ export class SignalRService { getData() { return this.sendDataSubject.asObservable() } + public getConnectionState(): Observable { + return this.connectingSubject.asObservable(); + } async sendMessage(data: Object) { return await this.connection.sendMessage(data as any) diff --git a/src/app/module/chat/infra/socket/signalR.ts b/src/app/module/chat/infra/socket/signalR.ts index 608ff0115..cbf776680 100644 --- a/src/app/module/chat/infra/socket/signalR.ts +++ b/src/app/module/chat/infra/socket/signalR.ts @@ -27,6 +27,7 @@ export class SignalRConnection { private sendDataSubject: BehaviorSubject<{method: string, data: any}> = new BehaviorSubject<{method: string, data: any}>(null); private pendingRequests: Map = new Map(); url: string + private hasConnectOnce = false constructor({url}) { this.url = url @@ -44,6 +45,7 @@ export class SignalRConnection { hubConnection .start() .then(() => { + this.hasConnectOnce = true console.log('Connection started'); this.connectionStateSubject.next(true); this.hubConnection = hubConnection @@ -54,7 +56,13 @@ export class SignalRConnection { .catch(error => { console.log('Error while starting connection: ' + error); this.connectionStateSubject.next(false); - reject(err(false)) + + if(this.hasConnectOnce) { + setTimeout(()=> { + this.attempReconnect(); + }, 2000) + } + resolve(err(false)) }); hubConnection.onclose(() => { @@ -64,7 +72,7 @@ export class SignalRConnection { this.pendingRequests.forEach((_, requestId) => { const { reject } = this.pendingRequests.get(requestId); - reject(err('Connection closed================!s')); + reject(err(false)); this.pendingRequests.delete(requestId); });