46 lines
1.3 KiB
TypeScript
46 lines
1.3 KiB
TypeScript
|
|
import { Client, type IMessage } from '@stomp/stompjs'
|
||
|
|
import { tokenStore } from '@/lib/token'
|
||
|
|
import type { ChatMessage } from '@/api/chat'
|
||
|
|
|
||
|
|
function wsUrl(): string {
|
||
|
|
const base = import.meta.env.VITE_API_BASE_URL ?? 'http://localhost:8080'
|
||
|
|
// http(s) -> ws(s)
|
||
|
|
return base.replace(/^http/, 'ws') + '/ws'
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 스팟 채팅용 STOMP 클라이언트.
|
||
|
|
* connect 후 스팟 토픽을 구독하고, send 로 메시지를 전송한다.
|
||
|
|
*/
|
||
|
|
export function createSpotChat(
|
||
|
|
spotId: number,
|
||
|
|
onMessage: (m: ChatMessage) => void,
|
||
|
|
onStatus?: (connected: boolean) => void,
|
||
|
|
) {
|
||
|
|
const client = new Client({
|
||
|
|
brokerURL: wsUrl(),
|
||
|
|
connectHeaders: { Authorization: `Bearer ${tokenStore.get() ?? ''}` },
|
||
|
|
reconnectDelay: 3000,
|
||
|
|
onConnect: () => {
|
||
|
|
onStatus?.(true)
|
||
|
|
client.subscribe(`/topic/spots/${spotId}`, (msg: IMessage) => {
|
||
|
|
onMessage(JSON.parse(msg.body) as ChatMessage)
|
||
|
|
})
|
||
|
|
},
|
||
|
|
onDisconnect: () => onStatus?.(false),
|
||
|
|
onWebSocketClose: () => onStatus?.(false),
|
||
|
|
})
|
||
|
|
|
||
|
|
return {
|
||
|
|
activate: () => client.activate(),
|
||
|
|
deactivate: () => client.deactivate(),
|
||
|
|
send: (content: string) => {
|
||
|
|
client.publish({
|
||
|
|
destination: `/app/spots/${spotId}/chat`,
|
||
|
|
body: JSON.stringify({ content }),
|
||
|
|
})
|
||
|
|
},
|
||
|
|
isConnected: () => client.connected,
|
||
|
|
}
|
||
|
|
}
|