feat(history): establish Telegram SaaS platform foundation
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
import { useEffect } from 'react'
|
||||
import { useLocation } from 'react-router-dom'
|
||||
import { useQueryClient } from '@tanstack/react-query'
|
||||
import { useAuthStore } from '@/app/store/auth'
|
||||
import { toast } from '@/app/store/toast'
|
||||
import type { Customer, Message } from '@/types'
|
||||
import { getWebSocketTicket } from '@/services/api/auth'
|
||||
|
||||
export function GlobalRealtime() {
|
||||
const token = useAuthStore((state) => state.token)
|
||||
const location = useLocation()
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
useEffect(() => {
|
||||
if (!token) return
|
||||
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'
|
||||
let socket: WebSocket | undefined
|
||||
let reconnectTimer: ReturnType<typeof setTimeout> | undefined
|
||||
let stopped = false
|
||||
let retryDelay = 500
|
||||
|
||||
const connect = async () => {
|
||||
if (stopped) return
|
||||
try {
|
||||
const { ticket } = await getWebSocketTicket()
|
||||
if (stopped) return
|
||||
socket = new WebSocket(`${protocol}//${window.location.host}/api/ws?ticket=${encodeURIComponent(ticket)}`)
|
||||
} catch {
|
||||
reconnectTimer = setTimeout(() => { void connect() }, retryDelay)
|
||||
retryDelay = Math.min(retryDelay * 2, 10_000)
|
||||
return
|
||||
}
|
||||
socket.onopen = () => { retryDelay = 500 }
|
||||
socket.onmessage = (raw) => {
|
||||
let event: { type?: string; message?: Message; customer?: Customer; conversationId?: string }
|
||||
try { event = JSON.parse(String(raw.data)) } catch { return }
|
||||
if (event.type !== 'message.created' || event.message?.sender !== 'customer') return
|
||||
void queryClient.invalidateQueries({ queryKey: ['notifications'] })
|
||||
void queryClient.invalidateQueries({ queryKey: ['conversations'] })
|
||||
if (!location.pathname.startsWith('/inbox')) {
|
||||
const preview = event.message.translatedText || event.message.originalText || `[${event.message.type}]`
|
||||
toast.info(`${event.customer?.name || event.message.senderName || 'Telegram 客户'} 发来新消息`, preview.slice(0, 120))
|
||||
}
|
||||
}
|
||||
socket.onerror = () => socket?.close()
|
||||
socket.onclose = () => {
|
||||
if (stopped) return
|
||||
reconnectTimer = setTimeout(() => { void connect() }, retryDelay)
|
||||
retryDelay = Math.min(retryDelay * 2, 10_000)
|
||||
}
|
||||
}
|
||||
void connect()
|
||||
return () => {
|
||||
stopped = true
|
||||
if (reconnectTimer) clearTimeout(reconnectTimer)
|
||||
socket?.close()
|
||||
}
|
||||
}, [token, location.pathname, queryClient])
|
||||
|
||||
return null
|
||||
}
|
||||
Reference in New Issue
Block a user