107 lines
2.7 KiB
TypeScript
107 lines
2.7 KiB
TypeScript
import { onUnmounted, ref } from 'vue'
|
|
import type { BotStatus } from '@/types/status'
|
|
import { getGuildId, setGuildId } from '@/api/client'
|
|
|
|
const RECONNECT_DELAY_MS = 3000
|
|
|
|
const status = ref<BotStatus | null>(null)
|
|
const connected = ref(false)
|
|
/** Wstrzymuje przyjmowanie aktualizacji, gdy użytkownik przeciąga utwory. */
|
|
const paused = ref(false)
|
|
const pendingTracks = ref<{ id: string; guildId: string; title: string }[]>([])
|
|
|
|
let socket: WebSocket | null = null
|
|
let reconnectTimer: number | null = null
|
|
let subscribers = 0
|
|
|
|
/** Jedno połączenie WebSocket na aplikację, niezależnie od liczby komponentów. */
|
|
export function useBotStatus() {
|
|
function open() {
|
|
const scheme = window.location.protocol === 'https:' ? 'wss:' : 'ws:'
|
|
const guild = getGuildId()
|
|
const currentSocket = new WebSocket(
|
|
`${scheme}//${window.location.host}/ws${guild ? `?guild_id=${guild}` : ''}`,
|
|
)
|
|
socket = currentSocket
|
|
|
|
currentSocket.onopen = () => {
|
|
connected.value = true
|
|
}
|
|
|
|
currentSocket.onmessage = (event) => {
|
|
if (socket !== currentSocket) return
|
|
if (paused.value) return
|
|
try {
|
|
status.value = JSON.parse(event.data) as BotStatus
|
|
} catch (error) {
|
|
console.error('Błąd parsowania danych z WS:', error)
|
|
}
|
|
}
|
|
|
|
currentSocket.onclose = () => {
|
|
if (socket !== currentSocket) return
|
|
connected.value = false
|
|
socket = null
|
|
if (subscribers > 0) {
|
|
reconnectTimer = window.setTimeout(open, RECONNECT_DELAY_MS)
|
|
}
|
|
}
|
|
|
|
currentSocket.onerror = () => currentSocket.close()
|
|
}
|
|
|
|
function connect() {
|
|
subscribers += 1
|
|
if (!socket) open()
|
|
}
|
|
|
|
function disconnect() {
|
|
subscribers = Math.max(0, subscribers - 1)
|
|
if (subscribers > 0) return
|
|
if (reconnectTimer !== null) {
|
|
window.clearTimeout(reconnectTimer)
|
|
reconnectTimer = null
|
|
}
|
|
socket?.close()
|
|
socket = null
|
|
}
|
|
|
|
function selectGuild(guildId: string) {
|
|
setGuildId(guildId)
|
|
if (reconnectTimer !== null) {
|
|
window.clearTimeout(reconnectTimer)
|
|
reconnectTimer = null
|
|
}
|
|
if (socket) {
|
|
const previousSocket = socket
|
|
socket = null
|
|
previousSocket.close()
|
|
open()
|
|
}
|
|
}
|
|
|
|
function addPendingTrack(guildId: string, title: string) {
|
|
const id = `pending-${Date.now()}-${Math.random().toString(36).slice(2)}`
|
|
pendingTracks.value.push({ id, guildId, title })
|
|
return id
|
|
}
|
|
|
|
function removePendingTrack(id: string) {
|
|
pendingTracks.value = pendingTracks.value.filter((track) => track.id !== id)
|
|
}
|
|
|
|
onUnmounted(disconnect)
|
|
|
|
return {
|
|
status,
|
|
connected,
|
|
paused,
|
|
pendingTracks,
|
|
connect,
|
|
disconnect,
|
|
selectGuild,
|
|
addPendingTrack,
|
|
removePendingTrack,
|
|
}
|
|
}
|