feat: instant draft-first worktree creation and multi-run launcher redesign (#741)
## Summary - **Instant worktree creation from chat draft**: selecting "+ New worktree" in the draft branch selector immediately creates a session draft and bootstraps the worktree in the background — no modal interruption - **Redesigned multi-run launcher**: compact 2-column grid layout in a right-sized dialog with scroll shadow, sticky footer, tooltips replacing verbose descriptions, and project icons in the selector - **Branch selector aligned across surfaces**: multi-run and agent manager branch pickers now use the shared git store and match NewWorktreeDialog behavior (same default resolution cascade, no synthetic HEAD option, all branches shown) - **Opaque model multi-select dropdown**: fixes text bleed-through on translucent backgrounds by compositing `--surface-elevated` over `--surface-background` - **"+ New" inline button in sidebar worktree headers** for faster worktree creation ## Why Worktree creation was behind modal flow that interrupted the user's train of thought. The draft-first approach lets users start typing immediately while the worktree bootstraps. The multi-run launcher had an oversized form layout with redundant explanations, and its branch picker behaved differently from the main worktree dialog - causing confusion about which branches were available and what the default was.
This commit is contained in:
committed by
GitHub
parent
c66d480782
commit
53c2a0d919
@@ -12529,6 +12529,46 @@ async function main(options = {}) {
|
||||
}
|
||||
});
|
||||
|
||||
app.post('/api/git/worktrees/preview', async (req, res) => {
|
||||
const { previewWorktreeCreate } = await getGitLibraries();
|
||||
if (typeof previewWorktreeCreate !== 'function') {
|
||||
return res.status(501).json({ error: 'Worktree preview is not available' });
|
||||
}
|
||||
|
||||
try {
|
||||
const directory = req.query.directory;
|
||||
if (!directory || typeof directory !== 'string') {
|
||||
return res.status(400).json({ error: 'directory parameter is required' });
|
||||
}
|
||||
|
||||
const preview = await previewWorktreeCreate(directory, req.body || {});
|
||||
res.json(preview);
|
||||
} catch (error) {
|
||||
console.error('Failed to preview worktree:', error);
|
||||
res.status(500).json({ error: error.message || 'Failed to preview worktree' });
|
||||
}
|
||||
});
|
||||
|
||||
app.get('/api/git/worktrees/bootstrap-status', async (req, res) => {
|
||||
const { getWorktreeBootstrapStatus } = await getGitLibraries();
|
||||
if (typeof getWorktreeBootstrapStatus !== 'function') {
|
||||
return res.status(501).json({ error: 'Worktree bootstrap status is not available' });
|
||||
}
|
||||
|
||||
try {
|
||||
const directory = req.query.directory;
|
||||
if (!directory || typeof directory !== 'string') {
|
||||
return res.status(400).json({ error: 'directory parameter is required' });
|
||||
}
|
||||
|
||||
const status = await getWorktreeBootstrapStatus(directory);
|
||||
res.json(status);
|
||||
} catch (error) {
|
||||
console.error('Failed to get worktree bootstrap status:', error);
|
||||
res.status(500).json({ error: error.message || 'Failed to get worktree bootstrap status' });
|
||||
}
|
||||
});
|
||||
|
||||
app.delete('/api/git/worktrees', async (req, res) => {
|
||||
const { removeWorktree } = await getGitLibraries();
|
||||
if (typeof removeWorktree !== 'function') {
|
||||
|
||||
Reference in New Issue
Block a user