From 561502ec36787e71cf5c768662bda5768b59fd68 Mon Sep 17 00:00:00 2001 From: Yun Chan Date: Sun, 5 Apr 2026 13:43:33 +0900 Subject: [PATCH] =?UTF-8?q?Settings=20=EC=97=B4=EA=B8=B0=20=EC=86=8D?= =?UTF-8?q?=EB=8F=84=20=EA=B0=9C=EC=84=A0:=20=EB=94=94=EB=B0=94=EC=9D=B4?= =?UTF-8?q?=EC=8A=A4=20=EB=B9=84=EB=8F=99=EA=B8=B0=20=EB=A1=9C=EB=93=9C=20?= =?UTF-8?q?+=20=EB=B6=80=ED=8C=85=20=EC=8B=9C=20=ED=94=84=EB=A6=AC?= =?UTF-8?q?=EC=BA=90=EC=8B=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - SettingsModal: 설정+핫키 먼저 로드 → 즉시 표시, 디바이스는 백그라운드 - bootstrap: 앱 부팅 시 getDevices() 미리 호출 → 캐싱 - 첫 번째 Settings 열기도 빠르게 (캐시 히트) --- src/main/bootstrap.ts | 4 ++++ src/renderer/components/SettingsModal.tsx | 16 +++++++++++----- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/main/bootstrap.ts b/src/main/bootstrap.ts index 46b9257..7f1c4d1 100644 --- a/src/main/bootstrap.ts +++ b/src/main/bootstrap.ts @@ -12,6 +12,7 @@ import { getTextInsertService } from './services/TextInsertService' import { getCustomInstructionService } from './services/CustomInstructionService' import { getSoundEffectService } from './services/SoundEffectService' import { getAutoLaunchService } from './services/AutoLaunchService' +import { getAudioCaptureService } from './services/AudioCaptureService' import { initDatabase } from './db' import { createMainWindow, @@ -118,6 +119,9 @@ async function initPopupWindows(): Promise { preloadPopupWindows() setupHistoryPopupIPC() + // 오디오 디바이스 미리 캐싱 (Settings 열 때 즉시 반환) + getAudioCaptureService().getDevices().catch(() => { /* 실패해도 무시 */ }) + // Ctrl+Shift+V → 히스토리 팝업 토글 globalShortcut.register('Ctrl+Shift+V', () => { if (isHistoryPopupVisible()) { diff --git a/src/renderer/components/SettingsModal.tsx b/src/renderer/components/SettingsModal.tsx index 94bf087..ca98b1f 100644 --- a/src/renderer/components/SettingsModal.tsx +++ b/src/renderer/components/SettingsModal.tsx @@ -199,15 +199,14 @@ export function SettingsModal({ open, onClose }: SettingsModalProps): React.Reac if (!open) return setLoading(true) + // 빠른 로드: 설정+핫키 먼저 (즉시 표시) Promise.all([ window.electronAPI.config.getAll(), window.electronAPI.hotkey.getDictationShortcut(), window.electronAPI.hotkey.getHandsFreeShortcut(), window.electronAPI.hotkey.isEnabled(), - window.electronAPI.audio.getDevices(), - window.electronAPI.audio.getSelectedDevice(), ]) - .then(([configResult, dictResult, hfResult, enabledResult, devicesResult, selectedResult]) => { + .then(([configResult, dictResult, hfResult, enabledResult]) => { if (configResult.success) setConfig(configResult.data) if (dictResult.success && dictResult.data) setDictationBinding(dictResult.data) if (hfResult.success && hfResult.data) setHandsFreeBinding(hfResult.data) @@ -215,10 +214,17 @@ export function SettingsModal({ open, onClose }: SettingsModalProps): React.Reac setHotkeyGlobalEnabled(enabledResult.data) setDictationEnabled(enabledResult.data) } - if (devicesResult.success) setAudioDevices(devicesResult.data) - if (selectedResult.success && selectedResult.data) setSelectedDeviceId(selectedResult.data) }) .finally(() => setLoading(false)) + + // 느린 로드: 오디오 디바이스 (백그라운드, UI 블로킹 안 함) + Promise.all([ + window.electronAPI.audio.getDevices(), + window.electronAPI.audio.getSelectedDevice(), + ]).then(([devicesResult, selectedResult]) => { + if (devicesResult.success) setAudioDevices(devicesResult.data) + if (selectedResult.success && selectedResult.data) setSelectedDeviceId(selectedResult.data) + }) }, [open]) const updateConfig = useCallback((key: keyof AppConfig, value: AppConfig[keyof AppConfig]) => {