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(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, } }