[eric] shortcuts: Cmd+L works again (stale isActive closures fixed) and now fires from inside focused browser pages too

This commit is contained in:
ciregenz
2026-08-05 16:06:40 -07:00
parent 73f564574f
commit e266d1ea38
4 changed files with 24 additions and 5 deletions
+9
View File
@@ -2252,6 +2252,14 @@ function routeReloadShortcut(event, input) {
// guest never reach the host renderer, so we catch them here and forward the intent + the guest's
// webContents id so the renderer can target that exact browser. Attached to guests ONLY: on the host
// the renderer's own keydown handles canvas-vs-browser, and intercepting there would eat canvas zoom.
// The renderer registers the user's new-agent combo so it still fires while a guest webview holds focus (host keydown never sees those).
let newAgentCombo = { primary: true, shift: false, key: 'l' };
ipcMain.on('set-new-agent-shortcut', (_e, combo) => {
if (combo && typeof combo.key === 'string' && combo.key) {
newAgentCombo = { primary: !!combo.primary, shift: !!combo.shift, key: combo.key.toLowerCase() };
}
});
function routeBrowserShortcut(event, input, webContentsId) {
if (input.type !== 'keyDown' || input.alt) return;
const mod = input.meta || input.control;
@@ -2263,6 +2271,7 @@ function routeBrowserShortcut(event, input, webContentsId) {
else if (mod && !input.shift && key === 'f') action = 'find';
else if (mod && input.shift && key === 't') action = 'reopen-closed';
else if (input.control && !input.meta && key === 'tab') action = input.shift ? 'tab-prev' : 'tab-next';
else if (mod === newAgentCombo.primary && input.shift === newAgentCombo.shift && key === newAgentCombo.key) action = 'new-agent';
if (!action) return;
event.preventDefault();
try {
+1
View File
@@ -43,6 +43,7 @@ contextBridge.exposeInMainWorld('openswarm', {
setWindowButtonsVisible: (visible) => ipcRenderer.invoke('set-window-buttons-visible', visible),
// Native window bg tracks the theme so a live resize never paints the boot-dark color behind a light UI.
setWindowBackground: (color) => ipcRenderer.invoke('set-window-background', color),
setNewAgentShortcut: (combo) => ipcRenderer.send('set-new-agent-shortcut', combo),
// Phase 2 provenance: { sha, shortSha, builtAt, channel } for the About panel.
getBuildInfo: () => ipcRenderer.invoke('get-build-info'),
@@ -281,6 +281,7 @@ const AppShell: React.FC = () => {
return w.openswarm.onBrowserShortcut((payload: { action: string; webContentsId: number }) => {
// Reopen-last-closed is global (no target browser), so handle it before the per-browser id guard.
if (payload.action === 'reopen-closed') { dispatch(reopenLastClosed()); return; }
if (payload.action === 'new-agent') { window.dispatchEvent(new CustomEvent('openswarm:new-agent')); return; }
const id = findBrowserByWebContentsId(payload.webContentsId) ?? getLastInteractedBrowser();
if (!id) return;
switch (payload.action) {
@@ -37,6 +37,9 @@ export function useDashboardShortcuts({
const needsShift = parts.includes('shift');
const needsAlt = parts.includes('alt');
// Main matches this combo inside focused webviews (host keydown never fires there) and echoes it back as openswarm:new-agent.
(window as unknown as { openswarm?: { setNewAgentShortcut?: (c: { primary: boolean; shift: boolean; key: string }) => void } }).openswarm?.setNewAgentShortcut?.({ primary: needsPrimary, shift: needsShift, key });
const handleShortcut = (e: KeyboardEvent) => {
if (!isActive) return; // Don't fire shortcuts when dashboard is hidden
if (e.key.toLowerCase() !== key) return;
@@ -46,9 +49,14 @@ export function useDashboardShortcuts({
e.preventDefault();
setToolbarOpen(true);
};
const handleForwarded = (): void => { if (isActive) setToolbarOpen(true); };
window.addEventListener('keydown', handleShortcut);
return () => window.removeEventListener('keydown', handleShortcut);
}, [newAgentShortcut]);
window.addEventListener('openswarm:new-agent', handleForwarded);
return () => {
window.removeEventListener('keydown', handleShortcut);
window.removeEventListener('openswarm:new-agent', handleForwarded);
};
}, [newAgentShortcut, isActive, setToolbarOpen]);
useEffect(() => {
const handleEnter = (e: KeyboardEvent) => {
@@ -64,7 +72,7 @@ export function useDashboardShortcuts({
};
window.addEventListener('keydown', handleEnter);
return () => window.removeEventListener('keydown', handleEnter);
}, [selection.selectedIds, dispatch]);
}, [selection.selectedIds, dispatch, isActive]);
useEffect(() => {
const handleDelete = (e: KeyboardEvent) => {
@@ -79,7 +87,7 @@ export function useDashboardShortcuts({
};
window.addEventListener('keydown', handleDelete);
return () => window.removeEventListener('keydown', handleDelete);
}, [selection, dispatch]);
}, [selection, dispatch, isActive]);
// Cmd/Ctrl+Shift+T reopens the most recently closed card (browser, agent, note, app, workflow, or browser tab), like a browser's reopen-closed-tab. The guest-focused case routes through main -> AppShell.
useEffect(() => {
@@ -123,5 +131,5 @@ export function useDashboardShortcuts({
};
window.addEventListener('keydown', handleSearch);
return () => window.removeEventListener('keydown', handleSearch);
}, []);
}, [isActive, setSearchPaletteOpen]);
}