/** * public/dashboard.ts — all-sessions overview (M7). * * A ▦ toolbar button opens an overlay listing every tab with its connection * dot, folder name, and Claude status; click a row to focus that tab. While * open it re-renders every second so statuses stay live. */ import { ICON_DASHBOARD } from './icons.js' export interface TabInfo { idx: number title: string conn: string // SessionStatus claude: string // ClaudeStatus active: boolean pending: boolean } export interface DashboardHooks { snapshot: () => TabInfo[] focus: (idx: number) => void } function claudeText(claude: string): string { if (claude === 'working') return '⚙ working' if (claude === 'waiting') return '⏳ needs approval' if (claude === 'idle') return '✓ idle' return '' } export function mountDashboard(toolbar: HTMLElement, hooks: DashboardHooks): void { const overlay = document.createElement('div') overlay.id = 'dashboard' overlay.style.display = 'none' const card = document.createElement('div') card.className = 'dash-card' overlay.appendChild(card) document.body.appendChild(overlay) let timer: ReturnType | null = null const render = (): void => { card.replaceChildren() const title = document.createElement('div') title.className = 'dash-title' title.textContent = 'Sessions' card.appendChild(title) for (const t of hooks.snapshot()) { const row = document.createElement('div') row.className = t.active ? 'dash-row active' : 'dash-row' const dot = document.createElement('span') dot.className = `tab-dot dot-${t.conn}` const name = document.createElement('span') name.className = 'dash-name' name.textContent = t.title const claude = document.createElement('span') claude.className = t.pending ? 'dash-claude pending' : 'dash-claude' claude.textContent = claudeText(t.claude) row.append(dot, name, claude) row.addEventListener('click', () => { hooks.focus(t.idx) hide() }) card.appendChild(row) } } const open = (): void => { render() overlay.style.display = 'flex' timer = setInterval(render, 1000) } const hide = (): void => { overlay.style.display = 'none' if (timer !== null) { clearInterval(timer) timer = null } } overlay.addEventListener('click', (e) => { if (e.target === overlay) hide() }) const btn = document.createElement('button') btn.className = 'toolbtn' btn.innerHTML = ICON_DASHBOARD btn.dataset.tip = 'All sessions' btn.setAttribute('aria-label', 'All sessions') btn.setAttribute('aria-label', 'All sessions') btn.addEventListener('click', () => (overlay.style.display === 'none' ? open() : hide())) toolbar.appendChild(btn) }