31 lines
1.6 KiB
TypeScript
31 lines
1.6 KiB
TypeScript
import { io, type Socket } from 'socket.io-client';
|
|
import type { GameSessionAuth } from '../shared/p2p-types.js';
|
|
import { PRESENCE_RETRY_MS } from '../../constants/presence.js';
|
|
|
|
export function createPresence(counter: HTMLElement) {
|
|
let socket: Socket | undefined, sessionId = '';
|
|
let retry: ReturnType<typeof setTimeout> | undefined;
|
|
const unknown = () => { counter.textContent = '접속 확인 중'; };
|
|
window.addEventListener('pagehide', () => { clearTimeout(retry); socket?.disconnect(); unknown(); });
|
|
window.addEventListener('pageshow', () => { socket?.connect(); });
|
|
return {
|
|
connect(auth: GameSessionAuth) {
|
|
if (socket && sessionId === auth.gameSessionId) { socket.connect(); return; }
|
|
clearTimeout(retry); socket?.removeAllListeners(); socket?.disconnect(); unknown();
|
|
sessionId = auth.gameSessionId;
|
|
socket = io('/presence', { auth: { gameSessionId: auth.gameSessionId, token: auth.token }, forceNew: true, autoConnect: false });
|
|
socket.on('presence:count', (count: unknown) => {
|
|
if (Number.isSafeInteger(count) && (count as number) >= 0) counter.textContent = `현재 ${count}명 접속 중`;
|
|
});
|
|
socket.on('connect', () => clearTimeout(retry));
|
|
socket.on('disconnect', unknown);
|
|
socket.on('connect_error', error => {
|
|
unknown(); clearTimeout(retry);
|
|
// Middleware errors do not trigger Socket.IO's transport reconnection loop.
|
|
if (error.message !== 'INVALID_SESSION') retry = setTimeout(() => socket?.connect(), PRESENCE_RETRY_MS);
|
|
});
|
|
socket.connect();
|
|
},
|
|
};
|
|
}
|