mirror of
https://github.com/davidkaya/aryx.git
synced 2026-08-04 02:48:44 +02:00
feat: add Quick Prompt global hotkey popup for one-off AI questions
Add a system-wide global hotkey (Win+Shift+A / Cmd+Shift+A) that summons a floating, frameless popup window for quick AI interactions from any app. Main process: - GlobalHotkeyService for registering/unregistering system-wide shortcuts - Frameless, transparent, always-on-top BrowserWindow factory - IPC handlers for send, discard, close, continue-in-aryx, cancel - Session event routing from sidecar to quick prompt window - Settings persistence for default model, hotkey, and reasoning effort Renderer (separate lightweight entry): - QuickPromptApp with session state, streaming, keyboard shortcuts - QuickPromptInput with model selector trigger and cancel support - QuickPromptResponse with streamed markdown and thinking blocks - QuickPromptActions (Discard / Close / Continue in Aryx) - ModelSelector dropdown with tier badges and reasoning effort - Glass Command Bar aesthetic with animated gradient border Settings: - Quick Prompt section in SettingsPanel with enable toggle, hotkey display, default model selector, and reasoning effort picker Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
import electron from 'electron';
|
||||
import type { BrowserWindow as BrowserWindowType } from 'electron';
|
||||
import { join } from 'node:path';
|
||||
|
||||
import { resolveWindowIconPath } from '@main/windows/appIcon';
|
||||
|
||||
const { app, BrowserWindow, screen } = electron;
|
||||
|
||||
export function createQuickPromptWindow(): BrowserWindowType {
|
||||
const window = new BrowserWindow({
|
||||
width: 680,
|
||||
height: 72,
|
||||
show: false,
|
||||
frame: false,
|
||||
transparent: true,
|
||||
resizable: false,
|
||||
skipTaskbar: true,
|
||||
alwaysOnTop: true,
|
||||
maximizable: false,
|
||||
minimizable: false,
|
||||
fullscreenable: false,
|
||||
title: 'Aryx Quick Prompt',
|
||||
icon: resolveWindowIconPath({
|
||||
appPath: app.getAppPath(),
|
||||
platform: process.platform,
|
||||
}),
|
||||
webPreferences: {
|
||||
preload: join(__dirname, '../preload/quickprompt.js'),
|
||||
contextIsolation: true,
|
||||
nodeIntegration: false,
|
||||
},
|
||||
});
|
||||
|
||||
const rendererUrl = process.env.ELECTRON_RENDERER_URL;
|
||||
|
||||
if (rendererUrl) {
|
||||
void window.loadURL(`${rendererUrl}/quickprompt.html`);
|
||||
} else {
|
||||
void window.loadFile(join(__dirname, '../../dist/renderer/quickprompt.html'));
|
||||
}
|
||||
|
||||
window.on('blur', () => {
|
||||
if (window.isVisible()) {
|
||||
window.webContents.send('quick-prompt:hide');
|
||||
window.hide();
|
||||
}
|
||||
});
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
export function toggleQuickPromptWindow(window: BrowserWindowType): void {
|
||||
if (window.isVisible()) {
|
||||
window.webContents.send('quick-prompt:hide');
|
||||
window.hide();
|
||||
return;
|
||||
}
|
||||
|
||||
centerOnActiveDisplay(window);
|
||||
window.webContents.send('quick-prompt:show');
|
||||
window.show();
|
||||
window.focus();
|
||||
}
|
||||
|
||||
export function showQuickPromptWindow(window: BrowserWindowType): void {
|
||||
centerOnActiveDisplay(window);
|
||||
window.webContents.send('quick-prompt:show');
|
||||
window.show();
|
||||
window.focus();
|
||||
}
|
||||
|
||||
export function hideQuickPromptWindow(window: BrowserWindowType): void {
|
||||
if (!window.isVisible()) return;
|
||||
window.webContents.send('quick-prompt:hide');
|
||||
window.hide();
|
||||
}
|
||||
|
||||
function centerOnActiveDisplay(window: BrowserWindowType): void {
|
||||
const cursorPoint = screen.getCursorScreenPoint();
|
||||
const activeDisplay = screen.getDisplayNearestPoint(cursorPoint);
|
||||
const { x, y, width, height } = activeDisplay.workArea;
|
||||
|
||||
const [windowWidth] = window.getSize();
|
||||
const windowX = Math.round(x + (width - windowWidth) / 2);
|
||||
// Position in the upper-third of the screen for command-bar feel
|
||||
const windowY = Math.round(y + height * 0.25);
|
||||
|
||||
window.setPosition(windowX, windowY);
|
||||
}
|
||||
Reference in New Issue
Block a user