- 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>
166 lines
6.0 KiB
TypeScript
166 lines
6.0 KiB
TypeScript
import { app } from "../lib/state"
|
|
import { updateAll, rebuildDisplayRows } from "../ui/panels"
|
|
import { ensureGridView, createNewGridTab, switchToGridTab } from "../grid/view-switch"
|
|
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) {
|
|
app.selectedProjects.clear()
|
|
app.selectedSessions.clear()
|
|
app.selectedBranches.clear()
|
|
rebuildDisplayRows()
|
|
updateAll()
|
|
return
|
|
}
|
|
|
|
type LaunchItem = { path: string; name: string; tabNum: number; sessionId?: string; targetBranch?: string }
|
|
const items: LaunchItem[] = []
|
|
|
|
for (const [path, tabNum] 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, tabNum, 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
|
|
// Sessions without explicit tab number go to tab 1
|
|
items.push({ path: project.path, name: project.name, tabNum: 1, sessionId: session.id, targetBranch: needsBranch ? targetBranch : undefined })
|
|
}
|
|
}
|
|
}
|
|
|
|
if (items.length === 0) return
|
|
|
|
// Group items by tab number
|
|
const byTab = new Map<number, LaunchItem[]>()
|
|
for (const item of items) {
|
|
if (!byTab.has(item.tabNum)) byTab.set(item.tabNum, [])
|
|
byTab.get(item.tabNum)!.push(item)
|
|
}
|
|
|
|
ensureGridView()
|
|
|
|
// Launch each tab group into its own grid tab
|
|
for (const [tabNum, tabItems] of byTab) {
|
|
// Find existing grid tab for this number, or create one
|
|
let targetTabId: number
|
|
const existingTab = app.gridTabs.find(t => t.name === `Tab ${tabNum}`)
|
|
if (existingTab) {
|
|
targetTabId = existingTab.id
|
|
} else {
|
|
targetTabId = createNewGridTab()
|
|
// Rename to match the picker tab number
|
|
const tab = app.gridTabs.find(t => t.id === targetTabId)
|
|
if (tab) {
|
|
tab.name = `Tab ${tabNum}`
|
|
app.gridTabs.sort((a, b) => {
|
|
const na = parseInt(a.name.replace(/\D/g, "")) || 0
|
|
const nb = parseInt(b.name.replace(/\D/g, "")) || 0
|
|
return na - nb
|
|
})
|
|
}
|
|
}
|
|
|
|
const termW = process.stdout.columns || 120
|
|
const termH = process.stdout.rows || 40
|
|
const totalPanes = tabItems.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 tabItems) {
|
|
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)
|
|
}
|
|
|
|
switchToGridTab(targetTabId)
|
|
}
|
|
|
|
app.selectedProjects.clear()
|
|
app.selectedSessions.clear()
|
|
app.selectedBranches.clear()
|
|
}
|