feat: inline pane tabs, add-pane mode, and grid chrome cleanup

- Tab bar now shows pane names inline with status icons instead of
  generic tab names with counts, eliminating the separate pane list row
- chromeTop reduced from 4 to 3, gaining one extra row of content space
- Add-pane mode (Ctrl+N) lets users add panes to existing tabs from picker
- Picker tab bar updated to match inline pane name format
- Session formatters and launch actions updated for branch switching

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Alejandro Gutiérrez
2026-02-28 18:13:25 +00:00
parent 9cf18f5740
commit e0f1a08098
7 changed files with 246 additions and 116 deletions

View File

@@ -4,6 +4,67 @@ import { ensureGridView, createNewGridTab, switchToGridTab } from "../grid/view-
import { loadSessions } from "../data/sessions"
import { createSession } from "../pty/session-manager"
export async function doAddPane() {
const targetTabId = app.addPaneTargetTabId
if (!targetTabId || !app.directGrid) return
if (app.selectedProjects.size === 0 && app.selectedSessions.size === 0) return
type LaunchItem = { path: string; name: string; sessionId?: string; targetBranch?: string }
const items: LaunchItem[] = []
for (const [path] of app.selectedProjects) {
const project = app.projects.find(p => p.path === path)
if (!project) continue
const targetBranch = app.selectedBranches.get(path)
const needsBranch = targetBranch && targetBranch !== project.branch
if (!project.sessions) {
project.sessions = await loadSessions(project.path)
project.sessionCount = project.sessions.length
}
const lastSessionId = project.sessions[0]?.id
items.push({ path, name: project.name, sessionId: lastSessionId, targetBranch: needsBranch ? targetBranch : undefined })
}
for (const project of app.projects) {
if (!project.sessions) continue
for (const session of project.sessions) {
if (app.selectedSessions.has(session.id)) {
const targetBranch = app.selectedBranches.get(project.path)
const needsBranch = targetBranch && targetBranch !== project.branch
items.push({ path: project.path, name: project.name, sessionId: session.id, targetBranch: needsBranch ? targetBranch : undefined })
}
}
}
if (items.length === 0) return
const termW = process.stdout.columns || 120
const termH = process.stdout.rows || 40
const totalPanes = items.length + (app.directGrid.getTabPaneCount(targetTabId) || 0)
const cols = totalPanes <= 1 ? 1 : totalPanes <= 2 ? 2 : totalPanes <= 4 ? 2 : 3
const rows = Math.ceil(totalPanes / cols)
const paneW = Math.max(Math.floor(termW / cols) - 2, 20)
const paneH = Math.max(Math.floor((termH - 2) / rows) - 4, 6)
for (const item of items) {
const session = await createSession({
projectPath: item.path,
projectName: item.name,
sessionId: item.sessionId,
targetBranch: item.targetBranch,
width: paneW,
height: paneH,
})
await app.directGrid.addPane(session, targetTabId)
}
app.selectedProjects.clear()
app.selectedSessions.clear()
app.selectedBranches.clear()
app.addPaneTargetTabId = null
switchToGridTab(targetTabId)
}
export async function doLaunch() {
if (app.selectedProjects.size === 0 && app.selectedSessions.size === 0) return
if (app.demoMode) {