Governed substrate for autonomous agents: scoped identity (passports), audited actions, MCP workspace. Infra IPs and secrets redacted for public release.
60 lines
1.6 KiB
TypeScript
60 lines
1.6 KiB
TypeScript
import { ipcMain, Menu, BrowserWindow, clipboard, shell } from 'electron';
|
|
|
|
type WindowGetter = () => BrowserWindow | null;
|
|
|
|
interface ContextMenuOptions {
|
|
isEditable?: boolean;
|
|
hasSelection?: boolean;
|
|
selectionText?: string;
|
|
linkHref?: string;
|
|
linkText?: string;
|
|
pageUrl?: string;
|
|
}
|
|
|
|
export function registerContextMenuHandler(getWindow: WindowGetter): void {
|
|
ipcMain.on('app:contextMenu', (event, opts: ContextMenuOptions = {}) => {
|
|
const win = BrowserWindow.fromWebContents(event.sender) ?? getWindow();
|
|
if (!win) return;
|
|
|
|
const items: Electron.MenuItemConstructorOptions[] = [];
|
|
|
|
if (opts.linkHref) {
|
|
items.push(
|
|
{
|
|
label: 'Open Link in New Tab',
|
|
click: () => event.sender.send('app:openInNewTab', opts.linkHref!),
|
|
},
|
|
{
|
|
label: 'Open Link in Browser',
|
|
click: () => shell.openExternal(opts.linkHref!),
|
|
},
|
|
{
|
|
label: 'Copy Link',
|
|
click: () => clipboard.writeText(opts.linkHref!),
|
|
},
|
|
{ type: 'separator' }
|
|
);
|
|
}
|
|
|
|
if (opts.isEditable) {
|
|
items.push(
|
|
{ role: 'undo' },
|
|
{ role: 'redo' },
|
|
{ type: 'separator' },
|
|
{ role: 'cut' },
|
|
{ role: 'copy' },
|
|
{ role: 'paste' },
|
|
{ role: 'selectAll' }
|
|
);
|
|
} else if (opts.hasSelection) {
|
|
items.push({ role: 'copy' }, { role: 'selectAll' });
|
|
} else {
|
|
items.push({ role: 'reload' }, { role: 'toggleDevTools' });
|
|
}
|
|
|
|
if (items.length === 0) return;
|
|
|
|
const menu = Menu.buildFromTemplate(items);
|
|
menu.popup({ window: win });
|
|
});
|
|
}
|