fix: split terminal inside current panel instead of at root

When clicking split on a terminal, the new terminal is now added
as a sibling of that specific terminal rather than at the root
of the layout tree.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
SuperComboGamer
2025-12-13 01:07:33 -05:00
parent 18494547bc
commit be4a0b292c
2 changed files with 42 additions and 10 deletions

View File

@@ -257,7 +257,8 @@ export function TerminalView() {
}; };
// Create a new terminal session // Create a new terminal session
const createTerminal = async (direction?: "horizontal" | "vertical") => { // targetSessionId: the terminal to split (if splitting an existing terminal)
const createTerminal = async (direction?: "horizontal" | "vertical", targetSessionId?: string) => {
try { try {
const headers: Record<string, string> = { const headers: Record<string, string> = {
"Content-Type": "application/json", "Content-Type": "application/json",
@@ -278,7 +279,7 @@ export function TerminalView() {
const data = await response.json(); const data = await response.json();
if (data.success) { if (data.success) {
addTerminalToLayout(data.data.id, direction); addTerminalToLayout(data.data.id, direction, targetSessionId);
} else { } else {
console.error("[Terminal] Failed to create session:", data.error); console.error("[Terminal] Failed to create session:", data.error);
} }
@@ -358,8 +359,8 @@ export function TerminalView() {
isActive={terminalState.activeSessionId === content.sessionId} isActive={terminalState.activeSessionId === content.sessionId}
onFocus={() => setActiveTerminalSession(content.sessionId)} onFocus={() => setActiveTerminalSession(content.sessionId)}
onClose={() => killTerminal(content.sessionId)} onClose={() => killTerminal(content.sessionId)}
onSplitHorizontal={() => createTerminal("horizontal")} onSplitHorizontal={() => createTerminal("horizontal", content.sessionId)}
onSplitVertical={() => createTerminal("vertical")} onSplitVertical={() => createTerminal("vertical", content.sessionId)}
isDragging={activeDragId === content.sessionId} isDragging={activeDragId === content.sessionId}
isDropTarget={activeDragId !== null && activeDragId !== content.sessionId} isDropTarget={activeDragId !== null && activeDragId !== content.sessionId}
fontSize={terminalFontSize} fontSize={terminalFontSize}

View File

@@ -593,7 +593,7 @@ export interface AppActions {
// Terminal actions // Terminal actions
setTerminalUnlocked: (unlocked: boolean, token?: string) => void; setTerminalUnlocked: (unlocked: boolean, token?: string) => void;
setActiveTerminalSession: (sessionId: string | null) => void; setActiveTerminalSession: (sessionId: string | null) => void;
addTerminalToLayout: (sessionId: string, direction?: "horizontal" | "vertical") => void; addTerminalToLayout: (sessionId: string, direction?: "horizontal" | "vertical", targetSessionId?: string) => void;
removeTerminalFromLayout: (sessionId: string) => void; removeTerminalFromLayout: (sessionId: string) => void;
swapTerminals: (sessionId1: string, sessionId2: string) => void; swapTerminals: (sessionId1: string, sessionId2: string) => void;
clearTerminalState: () => void; clearTerminalState: () => void;
@@ -1534,7 +1534,7 @@ export const useAppStore = create<AppState & AppActions>()(
}); });
}, },
addTerminalToLayout: (sessionId, direction = "horizontal") => { addTerminalToLayout: (sessionId, direction = "horizontal", targetSessionId) => {
const current = get().terminalState; const current = get().terminalState;
const newTerminal: TerminalPanelContent = { type: "terminal", sessionId, size: 50 }; const newTerminal: TerminalPanelContent = { type: "terminal", sessionId, size: 50 };
@@ -1556,7 +1556,33 @@ export const useAppStore = create<AppState & AppActions>()(
const activeTab = current.tabs.find(t => t.id === current.activeTabId); const activeTab = current.tabs.find(t => t.id === current.activeTabId);
if (!activeTab) return; if (!activeTab) return;
const addToLayout = ( // If targetSessionId is provided, find and split that specific terminal
const splitTargetTerminal = (
node: TerminalPanelContent,
targetId: string,
targetDirection: "horizontal" | "vertical"
): TerminalPanelContent => {
if (node.type === "terminal") {
if (node.sessionId === targetId) {
// Found the target - split it
return {
type: "split",
direction: targetDirection,
panels: [{ ...node, size: 50 }, newTerminal],
};
}
// Not the target, return unchanged
return node;
}
// It's a split - recurse into panels
return {
...node,
panels: node.panels.map(p => splitTargetTerminal(p, targetId, targetDirection)),
};
};
// Legacy behavior: add to root layout (when no targetSessionId)
const addToRootLayout = (
node: TerminalPanelContent, node: TerminalPanelContent,
targetDirection: "horizontal" | "vertical" targetDirection: "horizontal" | "vertical"
): TerminalPanelContent => { ): TerminalPanelContent => {
@@ -1583,9 +1609,14 @@ export const useAppStore = create<AppState & AppActions>()(
}; };
}; };
const newLayout = activeTab.layout let newLayout: TerminalPanelContent;
? addToLayout(activeTab.layout, direction) if (!activeTab.layout) {
: { type: "terminal" as const, sessionId, size: 100 }; newLayout = { type: "terminal", sessionId, size: 100 };
} else if (targetSessionId) {
newLayout = splitTargetTerminal(activeTab.layout, targetSessionId, direction);
} else {
newLayout = addToRootLayout(activeTab.layout, direction);
}
const newTabs = current.tabs.map(t => const newTabs = current.tabs.map(t =>
t.id === current.activeTabId ? { ...t, layout: newLayout } : t t.id === current.activeTabId ? { ...t, layout: newLayout } : t