// CommandPopup 팝업 스크립트 // Ctrl+Shift+C로 커서 위치에 명령어 선택 팝업 // Arrow↑↓ 선택, Enter 적용, 1-5 직접 선택, ESC 닫기 ;(function () { 'use strict' var container = document.getElementById('container') var itemsContainer = document.getElementById('items') var items = [] var selectedIndex = 0 var currentCommands = [] var currentActiveId = null var i18nStrings = {} // ── i18n 적용 (HTML 텍스트) ─────────────────────────── function applyI18nToHtml() { var elements = document.querySelectorAll('[data-i18n]') elements.forEach(function(el) { var key = el.getAttribute('data-i18n') if (i18nStrings[key]) { el.textContent = i18nStrings[key] } }) } // ── 아이템 렌더링 ─────────────────────────────────── function renderItems(commands, activeId) { currentCommands = commands currentActiveId = activeId itemsContainer.innerHTML = '' items = [] if (commands.length === 0) { var empty = document.createElement('div') empty.style.cssText = 'color: var(--d3-overlay-strong); font-size: 13px; text-align: center; padding: 24px 16px;' empty.textContent = i18nStrings.noCommands || 'No commands' itemsContainer.appendChild(empty) return } // ── "선택 해제" 항목 (맨 위) ── var noneDiv = document.createElement('div') noneDiv.className = 'item item-none' + (0 === selectedIndex ? ' selected' : '') + (!activeId ? ' active' : '') noneDiv.dataset.index = '0' var noneNum = document.createElement('span') noneNum.className = 'item-number' noneNum.textContent = '0' var noneName = document.createElement('span') noneName.className = 'item-name' noneName.style.opacity = '0.5' noneName.textContent = i18nStrings.noCommand || 'No command (insert original)' if (!activeId) { var noneBadge = document.createElement('span') noneBadge.className = 'item-active-badge' noneBadge.textContent = '●' noneDiv.appendChild(noneNum) noneDiv.appendChild(noneName) noneDiv.appendChild(noneBadge) } else { noneDiv.appendChild(noneNum) noneDiv.appendChild(noneName) } itemsContainer.appendChild(noneDiv) items.push(noneDiv) noneDiv.addEventListener('click', function () { selectAndApply(-1) }) commands.forEach(function (cmd, index) { var itemIndex = index + 1 var div = document.createElement('div') div.className = 'item' + (itemIndex === selectedIndex ? ' selected' : '') + (cmd.id === activeId ? ' active' : '') div.dataset.index = String(itemIndex) var num = document.createElement('span') num.className = 'item-number' num.textContent = String(itemIndex) var name = document.createElement('span') name.className = 'item-name' name.textContent = cmd.name var desc = document.createElement('span') desc.className = 'item-desc' desc.textContent = cmd.description div.appendChild(num) div.appendChild(name) if (cmd.id === activeId) { var badge = document.createElement('span') badge.className = 'item-active-badge' badge.textContent = '●' div.appendChild(badge) } div.appendChild(desc) itemsContainer.appendChild(div) items.push(div) div.addEventListener('click', function () { selectAndApply(itemIndex) }) }) } // ── 선택 업데이트 ─────────────────────────────────── function updateSelection(newIndex) { var totalItems = currentCommands.length + 1 // +1 for "none" item if (totalItems <= 1) return if (newIndex < 0) newIndex = totalItems - 1 if (newIndex >= totalItems) newIndex = 0 items.forEach(function (item, i) { if (i === newIndex) { item.classList.add('selected') } else { item.classList.remove('selected') } }) selectedIndex = newIndex if (items[selectedIndex]) { items[selectedIndex].scrollIntoView({ block: 'nearest' }) } } // ── 선택 적용 ─────────────────────────────────────── function selectAndApply(index) { // index 0 또는 -1 = "선택 해제" if (index <= 0) { window.popupAPI.send('command:selected', { id: '', name: '' }) return } var cmdIndex = index - 1 if (cmdIndex < 0 || cmdIndex >= currentCommands.length) return var cmd = currentCommands[cmdIndex] window.popupAPI.send('command:selected', { id: cmd.id, name: cmd.name }) } // ── IPC 리스너 ─────────────────────────────────────── window.popupAPI.on('command:showItems', function (data) { selectedIndex = 0 if (data._i18n) i18nStrings = data._i18n applyI18nToHtml() renderItems(data.commands || [], data.activeId || null) container.classList.remove('hiding') }) window.popupAPI.on('command:show', function () { container.classList.add('visible') container.classList.remove('hiding') }) window.popupAPI.on('command:hide', function () { container.classList.add('hiding') container.classList.remove('visible') }) window.popupAPI.on('command:keyEvent', function (data) { var key = data.key if (key === 'ArrowUp') { updateSelection(selectedIndex - 1) } else if (key === 'ArrowDown') { updateSelection(selectedIndex + 1) } else if (key === 'Enter') { selectAndApply(selectedIndex) } else if (key === 'Escape') { window.popupAPI.send('command:dismissed', {}) } else if (key === '0') { selectAndApply(0) } else if (key >= '1' && key <= '9') { var idx = parseInt(key, 10) if (idx <= currentCommands.length) { selectAndApply(idx) } } }) })()