mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-03 08:53:36 +00:00
feat: update terminal shortcut and improve code formatting
- Added a hasInstallScript property to package-lock.json. - Refactored the app-store.ts file for improved readability by formatting function parameters and object properties. - Updated the default terminal shortcut from "Cmd+`" to "T" and implemented migration logic for state persistence. - Incremented version number in the terminal state management to reflect breaking changes.
This commit is contained in:
@@ -49,7 +49,9 @@ export interface ShortcutKey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Helper to parse shortcut string to ShortcutKey object
|
// Helper to parse shortcut string to ShortcutKey object
|
||||||
export function parseShortcut(shortcut: string | undefined | null): ShortcutKey {
|
export function parseShortcut(
|
||||||
|
shortcut: string | undefined | null
|
||||||
|
): ShortcutKey {
|
||||||
if (!shortcut) return { key: "" };
|
if (!shortcut) return { key: "" };
|
||||||
const parts = shortcut.split("+").map((p) => p.trim());
|
const parts = shortcut.split("+").map((p) => p.trim());
|
||||||
const result: ShortcutKey = { key: parts[parts.length - 1] };
|
const result: ShortcutKey = { key: parts[parts.length - 1] };
|
||||||
@@ -82,7 +84,10 @@ export function parseShortcut(shortcut: string | undefined | null): ShortcutKey
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Helper to format ShortcutKey to display string
|
// Helper to format ShortcutKey to display string
|
||||||
export function formatShortcut(shortcut: string | undefined | null, forDisplay = false): string {
|
export function formatShortcut(
|
||||||
|
shortcut: string | undefined | null,
|
||||||
|
forDisplay = false
|
||||||
|
): string {
|
||||||
if (!shortcut) return "";
|
if (!shortcut) return "";
|
||||||
const parsed = parseShortcut(shortcut);
|
const parsed = parseShortcut(shortcut);
|
||||||
const parts: string[] = [];
|
const parts: string[] = [];
|
||||||
@@ -179,7 +184,7 @@ export const DEFAULT_KEYBOARD_SHORTCUTS: KeyboardShortcuts = {
|
|||||||
context: "C",
|
context: "C",
|
||||||
settings: "S",
|
settings: "S",
|
||||||
profiles: "M",
|
profiles: "M",
|
||||||
terminal: "Cmd+`",
|
terminal: "T",
|
||||||
|
|
||||||
// UI
|
// UI
|
||||||
toggleSidebar: "`",
|
toggleSidebar: "`",
|
||||||
@@ -308,7 +313,12 @@ export interface ProjectAnalysis {
|
|||||||
// Terminal panel layout types (recursive for splits)
|
// Terminal panel layout types (recursive for splits)
|
||||||
export type TerminalPanelContent =
|
export type TerminalPanelContent =
|
||||||
| { type: "terminal"; sessionId: string; size?: number; fontSize?: number }
|
| { type: "terminal"; sessionId: string; size?: number; fontSize?: number }
|
||||||
| { type: "split"; direction: "horizontal" | "vertical"; panels: TerminalPanelContent[]; size?: number };
|
| {
|
||||||
|
type: "split";
|
||||||
|
direction: "horizontal" | "vertical";
|
||||||
|
panels: TerminalPanelContent[];
|
||||||
|
size?: number;
|
||||||
|
};
|
||||||
|
|
||||||
// Terminal tab - each tab has its own layout
|
// Terminal tab - each tab has its own layout
|
||||||
export interface TerminalTab {
|
export interface TerminalTab {
|
||||||
@@ -600,7 +610,11 @@ 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", targetSessionId?: string) => 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;
|
||||||
@@ -610,7 +624,11 @@ export interface AppActions {
|
|||||||
setActiveTerminalTab: (tabId: string) => void;
|
setActiveTerminalTab: (tabId: string) => void;
|
||||||
renameTerminalTab: (tabId: string, name: string) => void;
|
renameTerminalTab: (tabId: string, name: string) => void;
|
||||||
moveTerminalToTab: (sessionId: string, targetTabId: string | "new") => void;
|
moveTerminalToTab: (sessionId: string, targetTabId: string | "new") => void;
|
||||||
addTerminalToTab: (sessionId: string, tabId: string, direction?: "horizontal" | "vertical") => void;
|
addTerminalToTab: (
|
||||||
|
sessionId: string,
|
||||||
|
tabId: string,
|
||||||
|
direction?: "horizontal" | "vertical"
|
||||||
|
) => void;
|
||||||
|
|
||||||
// Reset
|
// Reset
|
||||||
reset: () => void;
|
reset: () => void;
|
||||||
@@ -1331,8 +1349,10 @@ export const useAppStore = create<AppState & AppActions>()(
|
|||||||
|
|
||||||
resetAIProfiles: () => {
|
resetAIProfiles: () => {
|
||||||
// Merge: keep user-created profiles, but refresh all built-in profiles to latest defaults
|
// Merge: keep user-created profiles, but refresh all built-in profiles to latest defaults
|
||||||
const defaultProfileIds = new Set(DEFAULT_AI_PROFILES.map(p => p.id));
|
const defaultProfileIds = new Set(DEFAULT_AI_PROFILES.map((p) => p.id));
|
||||||
const userProfiles = get().aiProfiles.filter(p => !p.isBuiltIn && !defaultProfileIds.has(p.id));
|
const userProfiles = get().aiProfiles.filter(
|
||||||
|
(p) => !p.isBuiltIn && !defaultProfileIds.has(p.id)
|
||||||
|
);
|
||||||
set({ aiProfiles: [...DEFAULT_AI_PROFILES, ...userProfiles] });
|
set({ aiProfiles: [...DEFAULT_AI_PROFILES, ...userProfiles] });
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -1528,9 +1548,17 @@ export const useAppStore = create<AppState & AppActions>()(
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
addTerminalToLayout: (sessionId, direction = "horizontal", targetSessionId) => {
|
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,
|
||||||
|
};
|
||||||
|
|
||||||
// If no tabs, create first tab
|
// If no tabs, create first tab
|
||||||
if (current.tabs.length === 0) {
|
if (current.tabs.length === 0) {
|
||||||
@@ -1538,7 +1566,13 @@ export const useAppStore = create<AppState & AppActions>()(
|
|||||||
set({
|
set({
|
||||||
terminalState: {
|
terminalState: {
|
||||||
...current,
|
...current,
|
||||||
tabs: [{ id: newTabId, name: "Terminal 1", layout: { type: "terminal", sessionId, size: 100 } }],
|
tabs: [
|
||||||
|
{
|
||||||
|
id: newTabId,
|
||||||
|
name: "Terminal 1",
|
||||||
|
layout: { type: "terminal", sessionId, size: 100 },
|
||||||
|
},
|
||||||
|
],
|
||||||
activeTabId: newTabId,
|
activeTabId: newTabId,
|
||||||
activeSessionId: sessionId,
|
activeSessionId: sessionId,
|
||||||
},
|
},
|
||||||
@@ -1547,7 +1581,9 @@ export const useAppStore = create<AppState & AppActions>()(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add to active tab's layout
|
// Add to active tab's layout
|
||||||
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;
|
||||||
|
|
||||||
// If targetSessionId is provided, find and split that specific terminal
|
// If targetSessionId is provided, find and split that specific terminal
|
||||||
@@ -1571,7 +1607,9 @@ export const useAppStore = create<AppState & AppActions>()(
|
|||||||
// It's a split - recurse into panels
|
// It's a split - recurse into panels
|
||||||
return {
|
return {
|
||||||
...node,
|
...node,
|
||||||
panels: node.panels.map(p => splitTargetTerminal(p, targetId, targetDirection)),
|
panels: node.panels.map((p) =>
|
||||||
|
splitTargetTerminal(p, targetId, targetDirection)
|
||||||
|
),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1592,7 +1630,10 @@ export const useAppStore = create<AppState & AppActions>()(
|
|||||||
const newSize = 100 / (node.panels.length + 1);
|
const newSize = 100 / (node.panels.length + 1);
|
||||||
return {
|
return {
|
||||||
...node,
|
...node,
|
||||||
panels: [...node.panels.map(p => ({ ...p, size: newSize })), { ...newTerminal, size: newSize }],
|
panels: [
|
||||||
|
...node.panels.map((p) => ({ ...p, size: newSize })),
|
||||||
|
{ ...newTerminal, size: newSize },
|
||||||
|
],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
// Different direction, wrap in new split
|
// Different direction, wrap in new split
|
||||||
@@ -1607,12 +1648,16 @@ export const useAppStore = create<AppState & AppActions>()(
|
|||||||
if (!activeTab.layout) {
|
if (!activeTab.layout) {
|
||||||
newLayout = { type: "terminal", sessionId, size: 100 };
|
newLayout = { type: "terminal", sessionId, size: 100 };
|
||||||
} else if (targetSessionId) {
|
} else if (targetSessionId) {
|
||||||
newLayout = splitTargetTerminal(activeTab.layout, targetSessionId, direction);
|
newLayout = splitTargetTerminal(
|
||||||
|
activeTab.layout,
|
||||||
|
targetSessionId,
|
||||||
|
direction
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
newLayout = addToRootLayout(activeTab.layout, direction);
|
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
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -1630,7 +1675,9 @@ export const useAppStore = create<AppState & AppActions>()(
|
|||||||
if (current.tabs.length === 0) return;
|
if (current.tabs.length === 0) return;
|
||||||
|
|
||||||
// Find which tab contains this session
|
// Find which tab contains this session
|
||||||
const findFirstTerminal = (node: TerminalPanelContent | null): string | null => {
|
const findFirstTerminal = (
|
||||||
|
node: TerminalPanelContent | null
|
||||||
|
): string | null => {
|
||||||
if (!node) return null;
|
if (!node) return null;
|
||||||
if (node.type === "terminal") return node.sessionId;
|
if (node.type === "terminal") return node.sessionId;
|
||||||
for (const panel of node.panels) {
|
for (const panel of node.panels) {
|
||||||
@@ -1640,7 +1687,9 @@ export const useAppStore = create<AppState & AppActions>()(
|
|||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
const removeAndCollapse = (node: TerminalPanelContent): TerminalPanelContent | null => {
|
const removeAndCollapse = (
|
||||||
|
node: TerminalPanelContent
|
||||||
|
): TerminalPanelContent | null => {
|
||||||
if (node.type === "terminal") {
|
if (node.type === "terminal") {
|
||||||
return node.sessionId === sessionId ? null : node;
|
return node.sessionId === sessionId ? null : node;
|
||||||
}
|
}
|
||||||
@@ -1654,19 +1703,27 @@ export const useAppStore = create<AppState & AppActions>()(
|
|||||||
return { ...node, panels: newPanels };
|
return { ...node, panels: newPanels };
|
||||||
};
|
};
|
||||||
|
|
||||||
let newTabs = current.tabs.map(tab => {
|
let newTabs = current.tabs.map((tab) => {
|
||||||
if (!tab.layout) return tab;
|
if (!tab.layout) return tab;
|
||||||
const newLayout = removeAndCollapse(tab.layout);
|
const newLayout = removeAndCollapse(tab.layout);
|
||||||
return { ...tab, layout: newLayout };
|
return { ...tab, layout: newLayout };
|
||||||
});
|
});
|
||||||
|
|
||||||
// Remove empty tabs
|
// Remove empty tabs
|
||||||
newTabs = newTabs.filter(tab => tab.layout !== null);
|
newTabs = newTabs.filter((tab) => tab.layout !== null);
|
||||||
|
|
||||||
// Determine new active session
|
// Determine new active session
|
||||||
const newActiveTabId = newTabs.length > 0 ? (current.activeTabId && newTabs.find(t => t.id === current.activeTabId) ? current.activeTabId : newTabs[0].id) : null;
|
const newActiveTabId =
|
||||||
|
newTabs.length > 0
|
||||||
|
? current.activeTabId &&
|
||||||
|
newTabs.find((t) => t.id === current.activeTabId)
|
||||||
|
? current.activeTabId
|
||||||
|
: newTabs[0].id
|
||||||
|
: null;
|
||||||
const newActiveSessionId = newActiveTabId
|
const newActiveSessionId = newActiveTabId
|
||||||
? findFirstTerminal(newTabs.find(t => t.id === newActiveTabId)?.layout || null)
|
? findFirstTerminal(
|
||||||
|
newTabs.find((t) => t.id === newActiveTabId)?.layout || null
|
||||||
|
)
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
set({
|
set({
|
||||||
@@ -1683,16 +1740,20 @@ export const useAppStore = create<AppState & AppActions>()(
|
|||||||
const current = get().terminalState;
|
const current = get().terminalState;
|
||||||
if (current.tabs.length === 0) return;
|
if (current.tabs.length === 0) return;
|
||||||
|
|
||||||
const swapInLayout = (node: TerminalPanelContent): TerminalPanelContent => {
|
const swapInLayout = (
|
||||||
|
node: TerminalPanelContent
|
||||||
|
): TerminalPanelContent => {
|
||||||
if (node.type === "terminal") {
|
if (node.type === "terminal") {
|
||||||
if (node.sessionId === sessionId1) return { ...node, sessionId: sessionId2 };
|
if (node.sessionId === sessionId1)
|
||||||
if (node.sessionId === sessionId2) return { ...node, sessionId: sessionId1 };
|
return { ...node, sessionId: sessionId2 };
|
||||||
|
if (node.sessionId === sessionId2)
|
||||||
|
return { ...node, sessionId: sessionId1 };
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
return { ...node, panels: node.panels.map(swapInLayout) };
|
return { ...node, panels: node.panels.map(swapInLayout) };
|
||||||
};
|
};
|
||||||
|
|
||||||
const newTabs = current.tabs.map(tab => ({
|
const newTabs = current.tabs.map((tab) => ({
|
||||||
...tab,
|
...tab,
|
||||||
layout: tab.layout ? swapInLayout(tab.layout) : null,
|
layout: tab.layout ? swapInLayout(tab.layout) : null,
|
||||||
}));
|
}));
|
||||||
@@ -1719,7 +1780,9 @@ export const useAppStore = create<AppState & AppActions>()(
|
|||||||
const current = get().terminalState;
|
const current = get().terminalState;
|
||||||
const clampedSize = Math.max(8, Math.min(32, fontSize));
|
const clampedSize = Math.max(8, Math.min(32, fontSize));
|
||||||
|
|
||||||
const updateFontSize = (node: TerminalPanelContent): TerminalPanelContent => {
|
const updateFontSize = (
|
||||||
|
node: TerminalPanelContent
|
||||||
|
): TerminalPanelContent => {
|
||||||
if (node.type === "terminal") {
|
if (node.type === "terminal") {
|
||||||
if (node.sessionId === sessionId) {
|
if (node.sessionId === sessionId) {
|
||||||
return { ...node, fontSize: clampedSize };
|
return { ...node, fontSize: clampedSize };
|
||||||
@@ -1729,7 +1792,7 @@ export const useAppStore = create<AppState & AppActions>()(
|
|||||||
return { ...node, panels: node.panels.map(updateFontSize) };
|
return { ...node, panels: node.panels.map(updateFontSize) };
|
||||||
};
|
};
|
||||||
|
|
||||||
const newTabs = current.tabs.map(tab => {
|
const newTabs = current.tabs.map((tab) => {
|
||||||
if (!tab.layout) return tab;
|
if (!tab.layout) return tab;
|
||||||
return { ...tab, layout: updateFontSize(tab.layout) };
|
return { ...tab, layout: updateFontSize(tab.layout) };
|
||||||
});
|
});
|
||||||
@@ -1743,7 +1806,11 @@ export const useAppStore = create<AppState & AppActions>()(
|
|||||||
const current = get().terminalState;
|
const current = get().terminalState;
|
||||||
const newTabId = `tab-${Date.now()}`;
|
const newTabId = `tab-${Date.now()}`;
|
||||||
const tabNumber = current.tabs.length + 1;
|
const tabNumber = current.tabs.length + 1;
|
||||||
const newTab: TerminalTab = { id: newTabId, name: name || `Terminal ${tabNumber}`, layout: null };
|
const newTab: TerminalTab = {
|
||||||
|
id: newTabId,
|
||||||
|
name: name || `Terminal ${tabNumber}`,
|
||||||
|
layout: null,
|
||||||
|
};
|
||||||
set({
|
set({
|
||||||
terminalState: {
|
terminalState: {
|
||||||
...current,
|
...current,
|
||||||
@@ -1756,14 +1823,14 @@ export const useAppStore = create<AppState & AppActions>()(
|
|||||||
|
|
||||||
removeTerminalTab: (tabId) => {
|
removeTerminalTab: (tabId) => {
|
||||||
const current = get().terminalState;
|
const current = get().terminalState;
|
||||||
const newTabs = current.tabs.filter(t => t.id !== tabId);
|
const newTabs = current.tabs.filter((t) => t.id !== tabId);
|
||||||
let newActiveTabId = current.activeTabId;
|
let newActiveTabId = current.activeTabId;
|
||||||
let newActiveSessionId = current.activeSessionId;
|
let newActiveSessionId = current.activeSessionId;
|
||||||
|
|
||||||
if (current.activeTabId === tabId) {
|
if (current.activeTabId === tabId) {
|
||||||
newActiveTabId = newTabs.length > 0 ? newTabs[0].id : null;
|
newActiveTabId = newTabs.length > 0 ? newTabs[0].id : null;
|
||||||
if (newActiveTabId) {
|
if (newActiveTabId) {
|
||||||
const newActiveTab = newTabs.find(t => t.id === newActiveTabId);
|
const newActiveTab = newTabs.find((t) => t.id === newActiveTabId);
|
||||||
const findFirst = (node: TerminalPanelContent): string | null => {
|
const findFirst = (node: TerminalPanelContent): string | null => {
|
||||||
if (node.type === "terminal") return node.sessionId;
|
if (node.type === "terminal") return node.sessionId;
|
||||||
for (const p of node.panels) {
|
for (const p of node.panels) {
|
||||||
@@ -1772,20 +1839,27 @@ export const useAppStore = create<AppState & AppActions>()(
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
newActiveSessionId = newActiveTab?.layout ? findFirst(newActiveTab.layout) : null;
|
newActiveSessionId = newActiveTab?.layout
|
||||||
|
? findFirst(newActiveTab.layout)
|
||||||
|
: null;
|
||||||
} else {
|
} else {
|
||||||
newActiveSessionId = null;
|
newActiveSessionId = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
set({
|
set({
|
||||||
terminalState: { ...current, tabs: newTabs, activeTabId: newActiveTabId, activeSessionId: newActiveSessionId },
|
terminalState: {
|
||||||
|
...current,
|
||||||
|
tabs: newTabs,
|
||||||
|
activeTabId: newActiveTabId,
|
||||||
|
activeSessionId: newActiveSessionId,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
setActiveTerminalTab: (tabId) => {
|
setActiveTerminalTab: (tabId) => {
|
||||||
const current = get().terminalState;
|
const current = get().terminalState;
|
||||||
const tab = current.tabs.find(t => t.id === tabId);
|
const tab = current.tabs.find((t) => t.id === tabId);
|
||||||
if (!tab) return;
|
if (!tab) return;
|
||||||
|
|
||||||
let newActiveSessionId = current.activeSessionId;
|
let newActiveSessionId = current.activeSessionId;
|
||||||
@@ -1802,13 +1876,19 @@ export const useAppStore = create<AppState & AppActions>()(
|
|||||||
}
|
}
|
||||||
|
|
||||||
set({
|
set({
|
||||||
terminalState: { ...current, activeTabId: tabId, activeSessionId: newActiveSessionId },
|
terminalState: {
|
||||||
|
...current,
|
||||||
|
activeTabId: tabId,
|
||||||
|
activeSessionId: newActiveSessionId,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
renameTerminalTab: (tabId, name) => {
|
renameTerminalTab: (tabId, name) => {
|
||||||
const current = get().terminalState;
|
const current = get().terminalState;
|
||||||
const newTabs = current.tabs.map(t => t.id === tabId ? { ...t, name } : t);
|
const newTabs = current.tabs.map((t) =>
|
||||||
|
t.id === tabId ? { ...t, name } : t
|
||||||
|
);
|
||||||
set({
|
set({
|
||||||
terminalState: { ...current, tabs: newTabs },
|
terminalState: { ...current, tabs: newTabs },
|
||||||
});
|
});
|
||||||
@@ -1818,9 +1898,13 @@ export const useAppStore = create<AppState & AppActions>()(
|
|||||||
const current = get().terminalState;
|
const current = get().terminalState;
|
||||||
|
|
||||||
let sourceTabId: string | null = null;
|
let sourceTabId: string | null = null;
|
||||||
let originalTerminalNode: (TerminalPanelContent & { type: "terminal" }) | null = null;
|
let originalTerminalNode:
|
||||||
|
| (TerminalPanelContent & { type: "terminal" })
|
||||||
|
| null = null;
|
||||||
|
|
||||||
const findTerminal = (node: TerminalPanelContent): (TerminalPanelContent & { type: "terminal" }) | null => {
|
const findTerminal = (
|
||||||
|
node: TerminalPanelContent
|
||||||
|
): (TerminalPanelContent & { type: "terminal" }) | null => {
|
||||||
if (node.type === "terminal") {
|
if (node.type === "terminal") {
|
||||||
return node.sessionId === sessionId ? node : null;
|
return node.sessionId === sessionId ? node : null;
|
||||||
}
|
}
|
||||||
@@ -1844,10 +1928,12 @@ export const useAppStore = create<AppState & AppActions>()(
|
|||||||
if (!sourceTabId || !originalTerminalNode) return;
|
if (!sourceTabId || !originalTerminalNode) return;
|
||||||
if (sourceTabId === targetTabId) return;
|
if (sourceTabId === targetTabId) return;
|
||||||
|
|
||||||
const sourceTab = current.tabs.find(t => t.id === sourceTabId);
|
const sourceTab = current.tabs.find((t) => t.id === sourceTabId);
|
||||||
if (!sourceTab?.layout) return;
|
if (!sourceTab?.layout) return;
|
||||||
|
|
||||||
const removeAndCollapse = (node: TerminalPanelContent): TerminalPanelContent | null => {
|
const removeAndCollapse = (
|
||||||
|
node: TerminalPanelContent
|
||||||
|
): TerminalPanelContent | null => {
|
||||||
if (node.type === "terminal") {
|
if (node.type === "terminal") {
|
||||||
return node.sessionId === sessionId ? null : node;
|
return node.sessionId === sessionId ? null : node;
|
||||||
}
|
}
|
||||||
@@ -1869,21 +1955,42 @@ export const useAppStore = create<AppState & AppActions>()(
|
|||||||
if (targetTabId === "new") {
|
if (targetTabId === "new") {
|
||||||
const newTabId = `tab-${Date.now()}`;
|
const newTabId = `tab-${Date.now()}`;
|
||||||
const sourceWillBeRemoved = !newSourceLayout;
|
const sourceWillBeRemoved = !newSourceLayout;
|
||||||
const tabName = sourceWillBeRemoved ? sourceTab.name : `Terminal ${current.tabs.length + 1}`;
|
const tabName = sourceWillBeRemoved
|
||||||
|
? sourceTab.name
|
||||||
|
: `Terminal ${current.tabs.length + 1}`;
|
||||||
newTabs = [
|
newTabs = [
|
||||||
...current.tabs,
|
...current.tabs,
|
||||||
{ id: newTabId, name: tabName, layout: { type: "terminal", sessionId, size: 100, fontSize: originalTerminalNode.fontSize } },
|
{
|
||||||
|
id: newTabId,
|
||||||
|
name: tabName,
|
||||||
|
layout: {
|
||||||
|
type: "terminal",
|
||||||
|
sessionId,
|
||||||
|
size: 100,
|
||||||
|
fontSize: originalTerminalNode.fontSize,
|
||||||
|
},
|
||||||
|
},
|
||||||
];
|
];
|
||||||
finalTargetTabId = newTabId;
|
finalTargetTabId = newTabId;
|
||||||
} else {
|
} else {
|
||||||
const targetTab = current.tabs.find(t => t.id === targetTabId);
|
const targetTab = current.tabs.find((t) => t.id === targetTabId);
|
||||||
if (!targetTab) return;
|
if (!targetTab) return;
|
||||||
|
|
||||||
const terminalNode: TerminalPanelContent = { type: "terminal", sessionId, size: 50, fontSize: originalTerminalNode.fontSize };
|
const terminalNode: TerminalPanelContent = {
|
||||||
|
type: "terminal",
|
||||||
|
sessionId,
|
||||||
|
size: 50,
|
||||||
|
fontSize: originalTerminalNode.fontSize,
|
||||||
|
};
|
||||||
let newTargetLayout: TerminalPanelContent;
|
let newTargetLayout: TerminalPanelContent;
|
||||||
|
|
||||||
if (!targetTab.layout) {
|
if (!targetTab.layout) {
|
||||||
newTargetLayout = { type: "terminal", sessionId, size: 100, fontSize: originalTerminalNode.fontSize };
|
newTargetLayout = {
|
||||||
|
type: "terminal",
|
||||||
|
sessionId,
|
||||||
|
size: 100,
|
||||||
|
fontSize: originalTerminalNode.fontSize,
|
||||||
|
};
|
||||||
} else if (targetTab.layout.type === "terminal") {
|
} else if (targetTab.layout.type === "terminal") {
|
||||||
newTargetLayout = {
|
newTargetLayout = {
|
||||||
type: "split",
|
type: "split",
|
||||||
@@ -1897,15 +2004,15 @@ export const useAppStore = create<AppState & AppActions>()(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
newTabs = current.tabs.map(t =>
|
newTabs = current.tabs.map((t) =>
|
||||||
t.id === targetTabId ? { ...t, layout: newTargetLayout } : t
|
t.id === targetTabId ? { ...t, layout: newTargetLayout } : t
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!newSourceLayout) {
|
if (!newSourceLayout) {
|
||||||
newTabs = newTabs.filter(t => t.id !== sourceTabId);
|
newTabs = newTabs.filter((t) => t.id !== sourceTabId);
|
||||||
} else {
|
} else {
|
||||||
newTabs = newTabs.map(t =>
|
newTabs = newTabs.map((t) =>
|
||||||
t.id === sourceTabId ? { ...t, layout: newSourceLayout } : t
|
t.id === sourceTabId ? { ...t, layout: newSourceLayout } : t
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1922,10 +2029,14 @@ export const useAppStore = create<AppState & AppActions>()(
|
|||||||
|
|
||||||
addTerminalToTab: (sessionId, tabId, direction = "horizontal") => {
|
addTerminalToTab: (sessionId, tabId, direction = "horizontal") => {
|
||||||
const current = get().terminalState;
|
const current = get().terminalState;
|
||||||
const tab = current.tabs.find(t => t.id === tabId);
|
const tab = current.tabs.find((t) => t.id === tabId);
|
||||||
if (!tab) return;
|
if (!tab) return;
|
||||||
|
|
||||||
const terminalNode: TerminalPanelContent = { type: "terminal", sessionId, size: 50 };
|
const terminalNode: TerminalPanelContent = {
|
||||||
|
type: "terminal",
|
||||||
|
sessionId,
|
||||||
|
size: 50,
|
||||||
|
};
|
||||||
let newLayout: TerminalPanelContent;
|
let newLayout: TerminalPanelContent;
|
||||||
|
|
||||||
if (!tab.layout) {
|
if (!tab.layout) {
|
||||||
@@ -1941,7 +2052,10 @@ export const useAppStore = create<AppState & AppActions>()(
|
|||||||
const newSize = 100 / (tab.layout.panels.length + 1);
|
const newSize = 100 / (tab.layout.panels.length + 1);
|
||||||
newLayout = {
|
newLayout = {
|
||||||
...tab.layout,
|
...tab.layout,
|
||||||
panels: [...tab.layout.panels.map(p => ({ ...p, size: newSize })), { ...terminalNode, size: newSize }],
|
panels: [
|
||||||
|
...tab.layout.panels.map((p) => ({ ...p, size: newSize })),
|
||||||
|
{ ...terminalNode, size: newSize },
|
||||||
|
],
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
newLayout = {
|
newLayout = {
|
||||||
@@ -1952,7 +2066,7 @@ export const useAppStore = create<AppState & AppActions>()(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const newTabs = current.tabs.map(t =>
|
const newTabs = current.tabs.map((t) =>
|
||||||
t.id === tabId ? { ...t, layout: newLayout } : t
|
t.id === tabId ? { ...t, layout: newLayout } : t
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -1971,7 +2085,7 @@ export const useAppStore = create<AppState & AppActions>()(
|
|||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
name: "automaker-storage",
|
name: "automaker-storage",
|
||||||
version: 1, // Increment when making breaking changes to persisted state
|
version: 2, // Increment when making breaking changes to persisted state
|
||||||
migrate: (persistedState: unknown, version: number) => {
|
migrate: (persistedState: unknown, version: number) => {
|
||||||
const state = persistedState as Partial<AppState>;
|
const state = persistedState as Partial<AppState>;
|
||||||
|
|
||||||
@@ -1983,6 +2097,21 @@ export const useAppStore = create<AppState & AppActions>()(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Migration from version 1 to version 2:
|
||||||
|
// - Change terminal shortcut from "Cmd+`" to "T"
|
||||||
|
if (version <= 1) {
|
||||||
|
if (
|
||||||
|
state.keyboardShortcuts?.terminal === "Cmd+`" ||
|
||||||
|
state.keyboardShortcuts?.terminal === undefined
|
||||||
|
) {
|
||||||
|
state.keyboardShortcuts = {
|
||||||
|
...DEFAULT_KEYBOARD_SHORTCUTS,
|
||||||
|
...state.keyboardShortcuts,
|
||||||
|
terminal: "T",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return state as AppState;
|
return state as AppState;
|
||||||
},
|
},
|
||||||
partialize: (state) => ({
|
partialize: (state) => ({
|
||||||
|
|||||||
1
package-lock.json
generated
1
package-lock.json
generated
@@ -7,6 +7,7 @@
|
|||||||
"": {
|
"": {
|
||||||
"name": "automaker",
|
"name": "automaker",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
|
"hasInstallScript": true,
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"apps/*",
|
"apps/*",
|
||||||
"libs/*"
|
"libs/*"
|
||||||
|
|||||||
Reference in New Issue
Block a user