feat(v0.3): M3 themes/font settings + M7 session dashboard
- M3: settings.ts (⚙ panel: dark/light/solarized theme + font size A-/A+), persisted to localStorage; terminal-session.applyTheme; TabApp.applySettings applies to all + new tabs - M7: dashboard.ts (▦ overlay listing every tab with connection dot + folder + Claude status; click a row to focus; live re-render while open); TabApp.snapshot()/focusTab() - Browser-verified: light theme renders + persists; dashboard lists tabs and focuses on click. 208 tests green, typechecks + build ok.
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
|
||||
import { TerminalSession } from './terminal-session.js'
|
||||
import { THEMES, DEFAULT_SETTINGS, type Settings } from './settings.js'
|
||||
|
||||
const TABS_KEY = 'web-terminal:tabs'
|
||||
const ACTIVE_KEY = 'web-terminal:active'
|
||||
@@ -41,6 +42,7 @@ export class TabApp {
|
||||
private editingIndex = -1
|
||||
private dragIndex = -1
|
||||
private notifyAsked = false
|
||||
private settings: Settings = DEFAULT_SETTINGS
|
||||
private readonly paneHost: HTMLElement
|
||||
private readonly tabBar: HTMLElement
|
||||
private readonly approvalBar: HTMLDivElement
|
||||
@@ -181,6 +183,7 @@ export class TabApp {
|
||||
})
|
||||
this.paneHost.appendChild(entry.session.el)
|
||||
this.tabs.push(entry)
|
||||
entry.session.applyTheme(THEMES[this.settings.theme] ?? THEMES['dark']!, this.settings.fontSize)
|
||||
entry.session.connect()
|
||||
return entry
|
||||
}
|
||||
@@ -251,6 +254,36 @@ export class TabApp {
|
||||
this.tabs[this.activeIndex]?.session.send(data)
|
||||
}
|
||||
|
||||
/** Apply theme + font settings to every terminal (M3). */
|
||||
applySettings(s: Settings): void {
|
||||
this.settings = s
|
||||
const theme = THEMES[s.theme] ?? THEMES['dark']!
|
||||
for (const t of this.tabs) t.session.applyTheme(theme, s.fontSize)
|
||||
}
|
||||
|
||||
/** A read-only view of all tabs for the dashboard (M7). */
|
||||
snapshot(): Array<{
|
||||
idx: number
|
||||
title: string
|
||||
conn: string
|
||||
claude: string
|
||||
active: boolean
|
||||
pending: boolean
|
||||
}> {
|
||||
return this.tabs.map((t, idx) => ({
|
||||
idx,
|
||||
title: this.displayTitle(t, idx),
|
||||
conn: t.session.status,
|
||||
claude: t.session.claudeStatus,
|
||||
active: idx === this.activeIndex,
|
||||
pending: t.session.pendingApproval,
|
||||
}))
|
||||
}
|
||||
|
||||
focusTab(idx: number): void {
|
||||
this.activate(idx)
|
||||
}
|
||||
|
||||
/** Scrollback search in the active tab (M1). */
|
||||
findInActive(query: string, dir: 'next' | 'prev'): void {
|
||||
const s = this.tabs[this.activeIndex]?.session
|
||||
|
||||
Reference in New Issue
Block a user