Show authenticated unique online player count on home screen
This commit is contained in:
@@ -175,3 +175,4 @@ body.player-app:is([data-screen=home], [data-screen=join]) #reconnect { position
|
||||
body.player-app .home-actions > .primary { min-height: 68px; font-size: 28px; }
|
||||
body.player-app .home .stat-mode > div { gap: 16px; }
|
||||
}
|
||||
.online-count { position: absolute; top: max(16px, env(safe-area-inset-top)); right: max(20px, env(safe-area-inset-right)); z-index: 5; color: #45534a; font-size: 13px; font-variant-numeric: tabular-nums; }
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
<div class="app">
|
||||
<main id="main">
|
||||
<section id="home" class="home">
|
||||
<span id="online-count" class="online-count" role="status">접속 확인 중</span>
|
||||
<div class="home-stage"><h1 aria-label="쎄쎄쎄:기공대전"><span>쎄쎄쎄</span><span>:기공대전</span></h1><div id="home-fighters" aria-hidden="true"></div></div>
|
||||
<div class="home-menu">
|
||||
<div class="home-actions"><button id="bot-start" class="primary" disabled><span>봇과 대전</span><svg viewBox="0 0 24 24" fill="none" aria-hidden="true"><path d="M4 12h15m-6-6 6 6-6 6" stroke="currentColor" stroke-width="3" stroke-linecap="square" stroke-linejoin="miter"/></svg></button><div class="split"><button id="room-create" disabled><span>방 만들기</span><svg viewBox="0 0 24 24" fill="none" aria-hidden="true"><path d="M12 4v16M4 12h16" stroke="currentColor" stroke-width="2"/></svg></button><button id="join-open" disabled><span>방 참가</span><svg viewBox="0 0 24 24" fill="none" aria-hidden="true"><path d="M13 4h7v16h-7M3 12h12m-5-5 5 5-5 5" stroke="currentColor" stroke-width="2"/></svg></button></div></div>
|
||||
|
||||
@@ -18,6 +18,7 @@ import { createLobbyFeatures } from './lobby-features.js';
|
||||
import { createGlobalSettingsCache } from './global-settings.js';
|
||||
import { createAppFooter } from './app-footer.js';
|
||||
import { installSoundControls } from './sound.js';
|
||||
import { createPresence } from './presence.js';
|
||||
import './game.css';
|
||||
import './match.css';
|
||||
import './home.css';
|
||||
@@ -30,6 +31,7 @@ const footer = createAppFooter(el('app-footer'), {
|
||||
rules: el<HTMLDialogElement>('rules-dialog'), privacy: el<HTMLDialogElement>('privacy-dialog'), contact: el<HTMLDialogElement>('contact-dialog'),
|
||||
});
|
||||
installSoundControls();
|
||||
const presence = createPresence(el('online-count'));
|
||||
const globalSettings = createGlobalSettingsCache({
|
||||
getItem: key => localStorage.getItem(key), setItem: (key, value) => localStorage.setItem(key, value),
|
||||
});
|
||||
@@ -244,6 +246,7 @@ async function boot() {
|
||||
let token: string | undefined;
|
||||
try { token = localStorage.getItem(GUEST_TOKEN_KEY) ?? undefined; } catch { storageAvailable = false; }
|
||||
const [session] = await Promise.all([api.ensureSession(token), globalSettings.refresh()]);
|
||||
presence.connect(session);
|
||||
if (session.guestToken) try { localStorage.setItem(GUEST_TOKEN_KEY, session.guestToken); } catch { storageAvailable = false; }
|
||||
reporter?.destroy(); reporter = createResultReporter({ gameSessionId: session.gameSessionId, record: value => api.record(value) }, storage);
|
||||
analytics.ready(); stats(session.stats); connection('접속됨', true); el('reconnect').hidden = true;
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import { io, type Socket } from 'socket.io-client';
|
||||
import type { GameSessionAuth } from '../shared/p2p-types.js';
|
||||
|
||||
export function createPresence(counter: HTMLElement) {
|
||||
let socket: Socket | undefined, sessionId = '';
|
||||
const unknown = () => { counter.textContent = '접속 확인 중'; };
|
||||
window.addEventListener('pagehide', () => { socket?.disconnect(); unknown(); });
|
||||
window.addEventListener('pageshow', () => { socket?.connect(); });
|
||||
return {
|
||||
connect(auth: GameSessionAuth) {
|
||||
if (socket && sessionId === auth.gameSessionId) { socket.connect(); return; }
|
||||
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('disconnect', unknown); socket.on('connect_error', unknown);
|
||||
socket.connect();
|
||||
},
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user