Project actions: run commands from header on web + mobile, with SSH-forward URL opening (#542)
* feat: add project actions in header with reliable terminal run flow - Add per-project Actions settings with icons, platform filters, and default action - Run/stop actions from header using terminal tabs, including Ctrl+C then force-kill fallback - Improve terminal UX with stable selection, resize handling, and smarter URL auto-open for localhost ports * feat: add project actions UI with refined header dropdown behavior * feat: add parent-session back button in chat * fix: make web and desktop dev modes reliable and conflict-free - Separate desktop and web dev ports to avoid collisions - Add robust process-tree shutdown so Ctrl+C cleans sidecars - Add true web HMR mode and keep service worker out of dev * fix: linux safe scripts for dev * feat: run project actions on web and add desktop SSH forward URL opening * feat: add mobile project actions button with terminal tabs and tighter tab UI * revert: remove experimental mobile terminal selection UI * feat: show Add action button in header when empty * fix: make retry countdown human-readable in status row * fix: prevent nav rail actions from firing through overlays
This commit is contained in:
committed by
GitHub
parent
d948aa5557
commit
95c71789c4
@@ -36,6 +36,7 @@ interface TerminalStore {
|
||||
|
||||
createTab: (directory: string) => string;
|
||||
setActiveTab: (directory: string, tabId: string) => void;
|
||||
setTabLabel: (directory: string, tabId: string, label: string) => void;
|
||||
closeTab: (directory: string, tabId: string) => Promise<void>;
|
||||
|
||||
setTabSessionId: (directory: string, tabId: string, sessionId: string | null) => void;
|
||||
@@ -192,6 +193,43 @@ export const useTerminalStore = create<TerminalStore>()(
|
||||
});
|
||||
},
|
||||
|
||||
setTabLabel: (directory: string, tabId: string, label: string) => {
|
||||
const key = normalizeDirectory(directory);
|
||||
const normalizedLabel = label.trim();
|
||||
if (!normalizedLabel) {
|
||||
return;
|
||||
}
|
||||
|
||||
set((state) => {
|
||||
const newSessions = new Map(state.sessions);
|
||||
const existing = newSessions.get(key);
|
||||
if (!existing) {
|
||||
return state;
|
||||
}
|
||||
|
||||
const idx = findTabIndex(existing, tabId);
|
||||
if (idx < 0) {
|
||||
return state;
|
||||
}
|
||||
|
||||
if (existing.tabs[idx]?.label === normalizedLabel) {
|
||||
return state;
|
||||
}
|
||||
|
||||
const nextTabs = [...existing.tabs];
|
||||
nextTabs[idx] = {
|
||||
...nextTabs[idx],
|
||||
label: normalizedLabel,
|
||||
};
|
||||
|
||||
newSessions.set(key, {
|
||||
...existing,
|
||||
tabs: nextTabs,
|
||||
});
|
||||
return { sessions: newSessions };
|
||||
});
|
||||
},
|
||||
|
||||
closeTab: async (directory: string, tabId: string) => {
|
||||
const key = normalizeDirectory(directory);
|
||||
const entry = get().sessions.get(key);
|
||||
@@ -258,7 +296,7 @@ export const useTerminalStore = create<TerminalStore>()(
|
||||
}
|
||||
|
||||
const tab = existing.tabs[idx];
|
||||
const shouldResetBuffer = tab.terminalSessionId !== sessionId;
|
||||
const shouldResetBuffer = sessionId !== null && tab.terminalSessionId !== sessionId;
|
||||
|
||||
const nextTab: TerminalTab = {
|
||||
...tab,
|
||||
|
||||
Reference in New Issue
Block a user