커맨드 선택 팝업 (Ctrl+Shift+C): 커서 위치에서 빠른 명령어 전환
- command-popup: Vanilla JS 팝업 (히스토리 팝업과 동일 패턴) Arrow↑↓ 선택, Enter 적용, 1-5 직접 선택, ESC 닫기 - WindowManager: showCommandPopup/hideCommandPopup/sendKeyToCommandPopup - bootstrap: Ctrl+Shift+C 단축키 등록 + command:selected IPC - electron.vite.config: command-popup HTML 빌드 엔트리 추가 - 선택한 명령어가 즉시 activeInstructionId로 설정 → 다음 녹음에 적용
This commit is contained in:
parent
fea923d302
commit
1361b95a4d
6 changed files with 419 additions and 4 deletions
|
|
@ -17,6 +17,7 @@ let mainWindow: BrowserWindow | null = null
|
|||
let recordingTipWindow: BrowserWindow | null = null
|
||||
let resultPopupWindow: BrowserWindow | null = null
|
||||
let historyPopupWindow: BrowserWindow | null = null
|
||||
let commandPopupWindow: BrowserWindow | null = null
|
||||
|
||||
// ── 메인 윈도우 ───────────────────────────────────────
|
||||
|
||||
|
|
@ -355,12 +356,93 @@ export function isHistoryPopupVisible(): boolean {
|
|||
return !!(historyPopupWindow && !historyPopupWindow.isDestroyed() && historyPopupWindow.isVisible())
|
||||
}
|
||||
|
||||
// ── CommandPopup 팝업 ─────────────────────────────────
|
||||
|
||||
function createCommandPopupWindow(): BrowserWindow {
|
||||
const win = new BrowserWindow({
|
||||
width: 340,
|
||||
height: 300,
|
||||
show: false,
|
||||
frame: false,
|
||||
transparent: true,
|
||||
resizable: false,
|
||||
alwaysOnTop: true,
|
||||
skipTaskbar: true,
|
||||
focusable: false,
|
||||
webPreferences: {
|
||||
preload: join(__dirname, '../preload/popup.js'),
|
||||
sandbox: false,
|
||||
contextIsolation: true,
|
||||
nodeIntegration: false
|
||||
}
|
||||
})
|
||||
|
||||
if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
|
||||
win.loadURL(`${process.env['ELECTRON_RENDERER_URL']}/popups/command-popup/index.html`)
|
||||
} else {
|
||||
win.loadFile(join(__dirname, '../renderer/popups/command-popup/index.html'))
|
||||
}
|
||||
|
||||
win.on('closed', () => { commandPopupWindow = null })
|
||||
return win
|
||||
}
|
||||
|
||||
export function getCommandPopupWindow(): BrowserWindow {
|
||||
if (!commandPopupWindow || commandPopupWindow.isDestroyed()) {
|
||||
commandPopupWindow = createCommandPopupWindow()
|
||||
}
|
||||
return commandPopupWindow
|
||||
}
|
||||
|
||||
export function showCommandPopup(commands: Array<Record<string, unknown>>, activeId: string | null): void {
|
||||
const win = getCommandPopupWindow()
|
||||
const cursorPos = screen.getCursorScreenPoint()
|
||||
const display = screen.getDisplayNearestPoint(cursorPos)
|
||||
|
||||
const popupWidth = 340
|
||||
const popupHeight = Math.min(80 + commands.length * 48, 400)
|
||||
|
||||
let x = cursorPos.x - Math.round(popupWidth / 2)
|
||||
let y = cursorPos.y - popupHeight - 20
|
||||
|
||||
x = Math.max(display.workArea.x, Math.min(x, display.workArea.x + display.workArea.width - popupWidth))
|
||||
if (y < display.workArea.y) { y = cursorPos.y + 20 }
|
||||
|
||||
win.setBounds({ x, y, width: popupWidth, height: popupHeight })
|
||||
win.webContents.send('command:showItems', { commands, activeId })
|
||||
|
||||
if (!win.isVisible()) { win.showInactive() }
|
||||
win.webContents.send('command:show', {})
|
||||
}
|
||||
|
||||
export function hideCommandPopup(): void {
|
||||
if (commandPopupWindow && !commandPopupWindow.isDestroyed()) {
|
||||
commandPopupWindow.webContents.send('command:hide', {})
|
||||
setTimeout(() => {
|
||||
if (commandPopupWindow && !commandPopupWindow.isDestroyed()) {
|
||||
commandPopupWindow.hide()
|
||||
}
|
||||
}, 150)
|
||||
}
|
||||
}
|
||||
|
||||
export function sendKeyToCommandPopup(key: string): void {
|
||||
if (commandPopupWindow && !commandPopupWindow.isDestroyed() && commandPopupWindow.isVisible()) {
|
||||
commandPopupWindow.webContents.send('command:keyEvent', { key })
|
||||
}
|
||||
}
|
||||
|
||||
export function isCommandPopupVisible(): boolean {
|
||||
return !!(commandPopupWindow && !commandPopupWindow.isDestroyed() && commandPopupWindow.isVisible())
|
||||
}
|
||||
|
||||
// ── 프리로딩 ──────────────────────────────────────────
|
||||
|
||||
export function preloadPopupWindows(): void {
|
||||
getRecordingTipWindow()
|
||||
getResultPopupWindow()
|
||||
getHistoryPopupWindow()
|
||||
getCommandPopupWindow()
|
||||
logger.info('Popup windows preloaded')
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue