119 lines
3.5 KiB
TypeScript
119 lines
3.5 KiB
TypeScript
import { store } from '@/store/store'
|
||
import * as signalR from '@microsoft/signalr'
|
||
import { MessengerAttachmentDto, MessengerMessageDeletedDto, MessengerMessageDto } from './messenger.service'
|
||
|
||
export interface MessengerSendMessageDto {
|
||
conversationId?: string
|
||
recipientIds: string[]
|
||
text?: string
|
||
attachments: MessengerAttachmentDto[]
|
||
}
|
||
|
||
type MessageHandler = (message: MessengerMessageDto) => void
|
||
type MessageDeletedHandler = (message: MessengerMessageDeletedDto) => void
|
||
type StateHandler = (connected: boolean) => void
|
||
|
||
class MessengerSignalRService {
|
||
private connection?: signalR.HubConnection
|
||
private messageHandlers = new Set<MessageHandler>()
|
||
private messageDeletedHandlers = new Set<MessageDeletedHandler>()
|
||
private stateHandlers = new Set<StateHandler>()
|
||
|
||
private createConnection() {
|
||
const { auth } = store.getState()
|
||
|
||
this.connection = new signalR.HubConnectionBuilder()
|
||
.withUrl(`${import.meta.env.VITE_API_URL}/messengerhub`, {
|
||
accessTokenFactory: () => store.getState().auth.session.token || auth.session.token || '',
|
||
})
|
||
.withAutomaticReconnect()
|
||
.configureLogging(signalR.LogLevel.Warning)
|
||
.build()
|
||
|
||
this.connection.on('MessengerMessageReceived', (message: MessengerMessageDto) => {
|
||
this.messageHandlers.forEach((handler) => handler(message))
|
||
})
|
||
|
||
this.connection.on('MessengerMessageDeleted', (message: MessengerMessageDeletedDto) => {
|
||
this.messageDeletedHandlers.forEach((handler) => handler(message))
|
||
})
|
||
|
||
this.connection.onreconnected(() => this.emitState(true))
|
||
this.connection.onreconnecting(() => this.emitState(false))
|
||
this.connection.onclose(() => this.emitState(false))
|
||
}
|
||
|
||
async start() {
|
||
if (!store.getState().auth.session.signedIn) return
|
||
|
||
if (!this.connection) {
|
||
this.createConnection()
|
||
}
|
||
|
||
if (this.connection?.state === signalR.HubConnectionState.Connected) {
|
||
this.emitState(true)
|
||
return
|
||
}
|
||
|
||
if (this.connection?.state === signalR.HubConnectionState.Connecting) return
|
||
|
||
try {
|
||
await this.connection?.start()
|
||
this.emitState(true)
|
||
} catch {
|
||
this.emitState(false)
|
||
}
|
||
}
|
||
|
||
async stop() {
|
||
if (!this.connection) return
|
||
|
||
await this.connection.stop()
|
||
this.connection = undefined
|
||
this.emitState(false)
|
||
}
|
||
|
||
async sendMessage(input: MessengerSendMessageDto) {
|
||
await this.start()
|
||
if (this.connection?.state !== signalR.HubConnectionState.Connected) {
|
||
throw new Error('Messenger bağlantısı yok')
|
||
}
|
||
|
||
await this.connection.invoke('SendMessage', input)
|
||
}
|
||
|
||
async deleteMessage(messageId: string) {
|
||
await this.start()
|
||
if (this.connection?.state !== signalR.HubConnectionState.Connected) {
|
||
throw new Error('Messenger bağlantısı yok')
|
||
}
|
||
|
||
await this.connection.invoke('DeleteMessage', messageId)
|
||
}
|
||
|
||
onMessage(handler: MessageHandler) {
|
||
this.messageHandlers.add(handler)
|
||
return () => this.messageHandlers.delete(handler)
|
||
}
|
||
|
||
onMessageDeleted(handler: MessageDeletedHandler) {
|
||
this.messageDeletedHandlers.add(handler)
|
||
return () => this.messageDeletedHandlers.delete(handler)
|
||
}
|
||
|
||
onStateChange(handler: StateHandler) {
|
||
this.stateHandlers.add(handler)
|
||
handler(this.getConnectionState())
|
||
return () => this.stateHandlers.delete(handler)
|
||
}
|
||
|
||
getConnectionState() {
|
||
return this.connection?.state === signalR.HubConnectionState.Connected
|
||
}
|
||
|
||
private emitState(connected: boolean) {
|
||
this.stateHandlers.forEach((handler) => handler(connected))
|
||
}
|
||
}
|
||
|
||
export const messengerSignalR = new MessengerSignalRService()
|