sozsoft-platform/ui/src/services/messenger.signalr.ts

120 lines
3.5 KiB
TypeScript
Raw Normal View History

2026-06-12 17:31:41 +00:00
import { store } from '@/store/store'
import * as signalR from '@microsoft/signalr'
2026-06-12 19:35:48 +00:00
import { MessengerAttachmentDto, MessengerMessageDeletedDto, MessengerMessageDto } from './messenger.service'
2026-06-12 17:31:41 +00:00
export interface MessengerSendMessageDto {
2026-06-12 19:35:48 +00:00
conversationId?: string
2026-06-12 17:31:41 +00:00
recipientIds: string[]
text?: string
attachments: MessengerAttachmentDto[]
}
type MessageHandler = (message: MessengerMessageDto) => void
2026-06-12 19:35:48 +00:00
type MessageDeletedHandler = (message: MessengerMessageDeletedDto) => void
2026-06-12 17:31:41 +00:00
type StateHandler = (connected: boolean) => void
class MessengerSignalRService {
private connection?: signalR.HubConnection
private messageHandlers = new Set<MessageHandler>()
2026-06-12 19:35:48 +00:00
private messageDeletedHandlers = new Set<MessageDeletedHandler>()
2026-06-12 17:31:41 +00:00
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))
})
2026-06-12 19:35:48 +00:00
this.connection.on('MessengerMessageDeleted', (message: MessengerMessageDeletedDto) => {
this.messageDeletedHandlers.forEach((handler) => handler(message))
})
2026-06-12 17:31:41 +00:00
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)
}
2026-06-12 19:35:48 +00:00
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)
}
2026-06-12 17:31:41 +00:00
onMessage(handler: MessageHandler) {
this.messageHandlers.add(handler)
return () => this.messageHandlers.delete(handler)
}
2026-06-12 19:35:48 +00:00
onMessageDeleted(handler: MessageDeletedHandler) {
this.messageDeletedHandlers.add(handler)
return () => this.messageDeletedHandlers.delete(handler)
}
2026-06-12 17:31:41 +00:00
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()