mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-02 08:33:36 +00:00
feat(ui): display branch name in terminal header with git icon
- Move branch name display from tab name to terminal header - Show full branch name (no truncation) with GitBranch icon - Display branch name for both 'new tab' and 'split' modes - Persist openTerminalMode setting to server and include in import/export - Update settings dropdown to simplified "New Tab" label
This commit is contained in:
@@ -181,7 +181,7 @@ export function TerminalSection() {
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="newTab">New Tab (named after branch)</SelectItem>
|
||||
<SelectItem value="newTab">New Tab</SelectItem>
|
||||
<SelectItem value="split">Split Current Tab</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
|
||||
@@ -596,22 +596,27 @@ export function TerminalView() {
|
||||
pendingTerminalCreatedRef.current = true;
|
||||
|
||||
if (openMode === 'newTab') {
|
||||
// Create a new tab named after the branch
|
||||
const newTabId = addTerminalTab(pending.branchName);
|
||||
// Create a new tab with default naming
|
||||
const newTabId = addTerminalTab();
|
||||
|
||||
// Set the tab's layout to the new terminal
|
||||
// Set the tab's layout to the new terminal with branch name for display in header
|
||||
useAppStore
|
||||
.getState()
|
||||
.setTerminalTabLayout(
|
||||
newTabId,
|
||||
{ type: 'terminal', sessionId: data.data.id, size: 100 },
|
||||
{
|
||||
type: 'terminal',
|
||||
sessionId: data.data.id,
|
||||
size: 100,
|
||||
branchName: pending.branchName,
|
||||
},
|
||||
data.data.id
|
||||
);
|
||||
toast.success(`Opened terminal for ${pending.branchName}`);
|
||||
} else {
|
||||
// Split mode: add to current tab layout
|
||||
addTerminalToLayout(data.data.id);
|
||||
toast.success(`Opened terminal in ${pending.cwd.split('/').pop() || pending.cwd}`);
|
||||
// Split mode: add to current tab layout with branch name
|
||||
addTerminalToLayout(data.data.id, 'horizontal', undefined, pending.branchName);
|
||||
toast.success(`Opened terminal for ${pending.branchName}`);
|
||||
}
|
||||
|
||||
// Mark this session as new for running initial command
|
||||
@@ -789,6 +794,7 @@ export function TerminalView() {
|
||||
sessionId,
|
||||
size: persisted.size,
|
||||
fontSize: persisted.fontSize,
|
||||
branchName: persisted.branchName,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1347,6 +1353,7 @@ export function TerminalView() {
|
||||
onCommandRan={() => handleCommandRan(content.sessionId)}
|
||||
isMaximized={terminalState.maximizedSessionId === content.sessionId}
|
||||
onToggleMaximize={() => toggleTerminalMaximized(content.sessionId)}
|
||||
branchName={content.branchName}
|
||||
/>
|
||||
</TerminalErrorBoundary>
|
||||
);
|
||||
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
Maximize2,
|
||||
Minimize2,
|
||||
ArrowDown,
|
||||
GitBranch,
|
||||
} from 'lucide-react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Spinner } from '@/components/ui/spinner';
|
||||
@@ -94,6 +95,7 @@ interface TerminalPanelProps {
|
||||
onCommandRan?: () => void; // Callback when the initial command has been sent
|
||||
isMaximized?: boolean;
|
||||
onToggleMaximize?: () => void;
|
||||
branchName?: string; // Branch name to display in header (from "Open in Terminal" action)
|
||||
}
|
||||
|
||||
// Type for xterm Terminal - we'll use any since we're dynamically importing
|
||||
@@ -124,6 +126,7 @@ export function TerminalPanel({
|
||||
onCommandRan,
|
||||
isMaximized = false,
|
||||
onToggleMaximize,
|
||||
branchName,
|
||||
}: TerminalPanelProps) {
|
||||
const terminalRef = useRef<HTMLDivElement>(null);
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
@@ -1776,6 +1779,13 @@ export function TerminalPanel({
|
||||
<div className="flex items-center gap-1.5 flex-1 min-w-0">
|
||||
<Terminal className="h-3 w-3 shrink-0 text-muted-foreground" />
|
||||
<span className="text-xs truncate text-foreground">{shellName}</span>
|
||||
{/* Branch name indicator - show when terminal was opened from worktree */}
|
||||
{branchName && (
|
||||
<span className="flex items-center gap-1 text-[10px] px-1.5 py-0.5 rounded bg-brand-500/10 text-brand-500 shrink-0">
|
||||
<GitBranch className="h-2.5 w-2.5 shrink-0" />
|
||||
<span>{branchName}</span>
|
||||
</span>
|
||||
)}
|
||||
{/* Font size indicator - only show when not default */}
|
||||
{fontSize !== DEFAULT_FONT_SIZE && (
|
||||
<button
|
||||
|
||||
@@ -36,6 +36,7 @@ const SETTINGS_FIELDS_TO_SYNC = [
|
||||
'fontFamilySans',
|
||||
'fontFamilyMono',
|
||||
'terminalFontFamily', // Maps to terminalState.fontFamily
|
||||
'openTerminalMode', // Maps to terminalState.openTerminalMode
|
||||
'sidebarOpen',
|
||||
'chatHistoryOpen',
|
||||
'maxConcurrency',
|
||||
@@ -101,6 +102,9 @@ function getSettingsFieldValue(
|
||||
if (field === 'terminalFontFamily') {
|
||||
return appState.terminalState.fontFamily;
|
||||
}
|
||||
if (field === 'openTerminalMode') {
|
||||
return appState.terminalState.openTerminalMode;
|
||||
}
|
||||
return appState[field as keyof typeof appState];
|
||||
}
|
||||
|
||||
@@ -128,6 +132,9 @@ function hasSettingsFieldChanged(
|
||||
if (field === 'terminalFontFamily') {
|
||||
return newState.terminalState.fontFamily !== prevState.terminalState.fontFamily;
|
||||
}
|
||||
if (field === 'openTerminalMode') {
|
||||
return newState.terminalState.openTerminalMode !== prevState.terminalState.openTerminalMode;
|
||||
}
|
||||
const key = field as keyof typeof newState;
|
||||
return newState[key] !== prevState[key];
|
||||
}
|
||||
@@ -571,11 +578,16 @@ export async function refreshSettingsFromServer(): Promise<boolean> {
|
||||
worktreePanelCollapsed: serverSettings.worktreePanelCollapsed ?? false,
|
||||
lastProjectDir: serverSettings.lastProjectDir ?? '',
|
||||
recentFolders: serverSettings.recentFolders ?? [],
|
||||
// Terminal font (nested in terminalState)
|
||||
...(serverSettings.terminalFontFamily && {
|
||||
// Terminal settings (nested in terminalState)
|
||||
...((serverSettings.terminalFontFamily || serverSettings.openTerminalMode) && {
|
||||
terminalState: {
|
||||
...currentAppState.terminalState,
|
||||
fontFamily: serverSettings.terminalFontFamily,
|
||||
...(serverSettings.terminalFontFamily && {
|
||||
fontFamily: serverSettings.terminalFontFamily,
|
||||
}),
|
||||
...(serverSettings.openTerminalMode && {
|
||||
openTerminalMode: serverSettings.openTerminalMode,
|
||||
}),
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -1805,8 +1805,6 @@ export class HttpApiClient implements ElectronAPI {
|
||||
this.post('/api/worktree/switch-branch', { worktreePath, branchName }),
|
||||
openInEditor: (worktreePath: string, editorCommand?: string) =>
|
||||
this.post('/api/worktree/open-in-editor', { worktreePath, editorCommand }),
|
||||
openInTerminal: (worktreePath: string) =>
|
||||
this.post('/api/worktree/open-in-terminal', { worktreePath }),
|
||||
getDefaultEditor: () => this.get('/api/worktree/default-editor'),
|
||||
getAvailableEditors: () => this.get('/api/worktree/available-editors'),
|
||||
refreshEditors: () => this.post('/api/worktree/refresh-editors', {}),
|
||||
|
||||
@@ -500,7 +500,7 @@ export interface ProjectAnalysis {
|
||||
|
||||
// Terminal panel layout types (recursive for splits)
|
||||
export type TerminalPanelContent =
|
||||
| { type: 'terminal'; sessionId: string; size?: number; fontSize?: number }
|
||||
| { type: 'terminal'; sessionId: string; size?: number; fontSize?: number; branchName?: string }
|
||||
| {
|
||||
type: 'split';
|
||||
id: string; // Stable ID for React key stability
|
||||
@@ -538,7 +538,7 @@ export interface TerminalState {
|
||||
// Persisted terminal layout - now includes sessionIds for reconnection
|
||||
// Used to restore terminal layout structure when switching projects
|
||||
export type PersistedTerminalPanel =
|
||||
| { type: 'terminal'; size?: number; fontSize?: number; sessionId?: string }
|
||||
| { type: 'terminal'; size?: number; fontSize?: number; sessionId?: string; branchName?: string }
|
||||
| {
|
||||
type: 'split';
|
||||
id?: string; // Optional for backwards compatibility with older persisted layouts
|
||||
@@ -576,6 +576,7 @@ export interface PersistedTerminalSettings {
|
||||
scrollbackLines: number;
|
||||
lineHeight: number;
|
||||
maxSessions: number;
|
||||
openTerminalMode: 'newTab' | 'split';
|
||||
}
|
||||
|
||||
/** State for worktree init script execution */
|
||||
@@ -1217,7 +1218,8 @@ export interface AppActions {
|
||||
addTerminalToLayout: (
|
||||
sessionId: string,
|
||||
direction?: 'horizontal' | 'vertical',
|
||||
targetSessionId?: string
|
||||
targetSessionId?: string,
|
||||
branchName?: string
|
||||
) => void;
|
||||
removeTerminalFromLayout: (sessionId: string) => void;
|
||||
swapTerminals: (sessionId1: string, sessionId2: string) => void;
|
||||
@@ -2676,12 +2678,13 @@ export const useAppStore = create<AppState & AppActions>()((set, get) => ({
|
||||
});
|
||||
},
|
||||
|
||||
addTerminalToLayout: (sessionId, direction = 'horizontal', targetSessionId) => {
|
||||
addTerminalToLayout: (sessionId, direction = 'horizontal', targetSessionId, branchName) => {
|
||||
const current = get().terminalState;
|
||||
const newTerminal: TerminalPanelContent = {
|
||||
type: 'terminal',
|
||||
sessionId,
|
||||
size: 50,
|
||||
branchName,
|
||||
};
|
||||
|
||||
// If no tabs, create first tab
|
||||
@@ -2694,7 +2697,7 @@ export const useAppStore = create<AppState & AppActions>()((set, get) => ({
|
||||
{
|
||||
id: newTabId,
|
||||
name: 'Terminal 1',
|
||||
layout: { type: 'terminal', sessionId, size: 100 },
|
||||
layout: { type: 'terminal', sessionId, size: 100, branchName },
|
||||
},
|
||||
],
|
||||
activeTabId: newTabId,
|
||||
@@ -3396,6 +3399,7 @@ export const useAppStore = create<AppState & AppActions>()((set, get) => ({
|
||||
size: panel.size,
|
||||
fontSize: panel.fontSize,
|
||||
sessionId: panel.sessionId, // Preserve for reconnection
|
||||
branchName: panel.branchName, // Preserve branch name for display
|
||||
};
|
||||
}
|
||||
return {
|
||||
|
||||
@@ -475,6 +475,10 @@ export interface GlobalSettings {
|
||||
/** Terminal font family (undefined = use default Menlo/Monaco) */
|
||||
terminalFontFamily?: string;
|
||||
|
||||
// Terminal Configuration
|
||||
/** How to open terminals from "Open in Terminal" worktree action */
|
||||
openTerminalMode?: 'newTab' | 'split';
|
||||
|
||||
// UI State Preferences
|
||||
/** Whether sidebar is currently open */
|
||||
sidebarOpen: boolean;
|
||||
|
||||
Reference in New Issue
Block a user