d3ro-voice/src/renderer/popups/result-popup/script.js
Yun Chan 517210af2f Phase 3 구현: 텍스트 삽입 + RecordingTip/ResultPopup + Settings
- TextInsertService: clipboard save→set→Ctrl+V→restore (@nut-tree-fork/nut-js)
- RecordingTip 팝업: 9개 웨이브바 cos분포, thinking 점근수렴, 2-phase 리사이즈
- ResultPopup 팝업: 복사 버튼, auto-close, 마우스 호버 유지, 다크모드
- WindowManager: 팝업 프리로딩, 커서 위치 표시, 멀티모니터 보정
- Settings 모달: General/Audio/STT/LLM 탭
- VoiceModeService: 전사 완료 시 자동 텍스트 삽입 + 팝업 연동
- electron-vite: 팝업 HTML 멀티 엔트리 + popup preload 빌드
2026-04-05 02:11:58 +09:00

95 lines
3.1 KiB
JavaScript

// ResultPopup 팝업 스크립트
// 설계서 03: 2-phase 리사이즈, auto-close, 마우스 호버 시 유지
;(function () {
'use strict'
var container = document.getElementById('container')
var resultText = document.getElementById('result-text')
var copyBtn = document.getElementById('copy-btn')
var copyIcon = document.getElementById('copy-icon')
var checkIcon = document.getElementById('check-icon')
var autoCloseTimer = null
var remainingTime = 0
var lastTick = 0
// ── Auto-close 제어 ─────────────────────────────────
function startAutoCloseTimer(ms) {
remainingTime = ms
lastTick = Date.now()
clearInterval(autoCloseTimer)
autoCloseTimer = setInterval(function () {
remainingTime -= (Date.now() - lastTick)
lastTick = Date.now()
if (remainingTime <= 0) {
clearInterval(autoCloseTimer)
autoCloseTimer = null
window.popupAPI.send('window:hideResultPopup')
}
}, 100)
}
function pauseAutoClose() {
clearInterval(autoCloseTimer)
autoCloseTimer = null
}
function resumeAutoClose() {
startAutoCloseTimer(remainingTime > 0 ? remainingTime : 2000)
}
// ── 복사 버튼 ───────────────────────────────────────
copyBtn.addEventListener('click', function () {
// navigator.clipboard는 팝업에서 작동 안 할 수 있으므로 IPC 사용
window.popupAPI.send('clipboard:copy', resultText.textContent)
copyBtn.classList.add('copied')
copyIcon.classList.add('hidden')
checkIcon.classList.remove('hidden')
setTimeout(function () {
copyBtn.classList.remove('copied')
copyIcon.classList.remove('hidden')
checkIcon.classList.add('hidden')
}, 2000)
})
// ── 마우스 호버 시 auto-close 일시정지 ──────────────
container.addEventListener('mouseenter', pauseAutoClose)
container.addEventListener('mouseleave', resumeAutoClose)
// ── IPC 리스너 ───────────────────────────────────────
// Phase 1: prepare — 결과 텍스트 세팅 + 크기 측정
window.popupAPI.on('result:prepare', function (data) {
resultText.textContent = data.text || ''
container.classList.remove('visible')
requestAnimationFrame(function () {
requestAnimationFrame(function () {
var rect = container.getBoundingClientRect()
window.popupAPI.send('result:measured', {
width: Math.ceil(rect.width) + 4,
height: Math.ceil(rect.height) + 4
})
})
})
})
// Phase 2: show — 리사이즈 완료 후 표시
window.popupAPI.on('result:show', function (data) {
container.classList.add('visible')
var autoHideMs = (data && data.autoHideMs) || 5000
if (autoHideMs > 0) {
startAutoCloseTimer(autoHideMs)
}
})
// hide
window.popupAPI.on('result:hide', function () {
container.classList.remove('visible')
clearInterval(autoCloseTimer)
autoCloseTimer = null
})
})()