/** * Session Panel — 세션 목록 UI 관리 */ class SessionPanel { constructor() { this.sessions = []; this.activeSessionId = null; this.onSessionSelect = null; // callback(sessionId) this.onSessionRemove = null; // callback(sessionId) this.listEl = document.getElementById('sessionList'); } /** * 세션 목록 업데이트 */ update(sessions) { this.sessions = sessions; this.render(); } /** * 활성 세션 설정 */ setActive(sessionId) { this.activeSessionId = sessionId; this.render(); } /** * 세션 목록 렌더링 */ render() { if (!this.listEl) return; if (this.sessions.length === 0) { this.listEl.innerHTML = `
세션이 없습니다
+ 버튼으로 추가하세요
`; return; } this.listEl.innerHTML = this.sessions.map(s => `
${this._escapeHtml(s.name)}
${s.host}:${s.cdpPort} · ${this._statusText(s.status)}
`).join(''); // 이벤트 바인딩 this.listEl.querySelectorAll('.session-card').forEach(card => { card.addEventListener('click', (e) => { if (e.target.closest('.session-remove')) return; const id = card.dataset.sessionId; if (this.onSessionSelect) this.onSessionSelect(id); }); }); this.listEl.querySelectorAll('.session-remove').forEach(btn => { btn.addEventListener('click', (e) => { e.stopPropagation(); const id = btn.dataset.removeId; if (this.onSessionRemove) this.onSessionRemove(id); }); }); } _statusText(status) { const map = { connected: '연결됨', connecting: '연결 중...', disconnected: '연결 끊김', error: '오류', }; return map[status] || status; } _escapeHtml(str) { const div = document.createElement('div'); div.textContent = str; return div.innerHTML; } }