diff --git a/src/bridge/featureBridge.js b/src/bridge/featureBridge.js index 3cce84b..a00675e 100644 --- a/src/bridge/featureBridge.js +++ b/src/bridge/featureBridge.js @@ -1,6 +1,8 @@ // src/bridge/featureBridge.js const { ipcMain } = require('electron'); const settingsService = require('../features/settings/settingsService'); +const askService = require('../features/ask/askService'); +const listenService = require('../features/listen/listenService'); module.exports = { // Renderer로부터의 요청을 수신 diff --git a/src/features/listen/stt/sttService.js b/src/features/listen/stt/sttService.js index 144bcfa..c6dcf45 100644 --- a/src/features/listen/stt/sttService.js +++ b/src/features/listen/stt/sttService.js @@ -1,7 +1,7 @@ const { BrowserWindow } = require('electron'); const { spawn } = require('child_process'); const { createSTT } = require('../../common/ai/factory'); -const { getStoredApiKey, getStoredProvider, getCurrentModelInfo } = require('../../../window/windowManager'); +// const { getStoredApiKey, getStoredProvider, getCurrentModelInfo } = require('../../../window/windowManager'); const COMPLETION_DEBOUNCE_MS = 2000; @@ -120,6 +120,7 @@ class SttService { async initializeSttSessions(language = 'en') { const effectiveLanguage = process.env.OPENAI_TRANSCRIBE_LANG || language || 'en'; + const { getCurrentModelInfo } = require('../../../window/windowManager'); const modelInfo = await getCurrentModelInfo(null, { type: 'stt' }); if (!modelInfo || !modelInfo.apiKey) { throw new Error('AI model or API key is not configured.'); @@ -399,6 +400,7 @@ class SttService { let modelInfo = this.modelInfo; if (!modelInfo) { console.warn('[SttService] modelInfo not found, fetching on-the-fly as a fallback...'); + const { getCurrentModelInfo } = require('../../../window/windowManager'); modelInfo = await getCurrentModelInfo(null, { type: 'stt' }); } if (!modelInfo) { @@ -420,6 +422,7 @@ class SttService { let modelInfo = this.modelInfo; if (!modelInfo) { console.warn('[SttService] modelInfo not found, fetching on-the-fly as a fallback...'); + const { getCurrentModelInfo } = require('../../../window/windowManager'); modelInfo = await getCurrentModelInfo(null, { type: 'stt' }); } if (!modelInfo) { @@ -501,6 +504,7 @@ class SttService { let modelInfo = this.modelInfo; if (!modelInfo) { console.warn('[SttService] modelInfo not found, fetching on-the-fly as a fallback...'); + const { getCurrentModelInfo } = require('../../../window/windowManager'); modelInfo = await getCurrentModelInfo(null, { type: 'stt' }); } if (!modelInfo) { diff --git a/src/features/listen/summary/summaryService.js b/src/features/listen/summary/summaryService.js index 518d39d..d0aae05 100644 --- a/src/features/listen/summary/summaryService.js +++ b/src/features/listen/summary/summaryService.js @@ -3,7 +3,7 @@ const { getSystemPrompt } = require('../../common/prompts/promptBuilder.js'); const { createLLM } = require('../../common/ai/factory'); const sessionRepository = require('../../common/repositories/session'); const summaryRepository = require('./repositories'); -const { getStoredApiKey, getStoredProvider, getCurrentModelInfo } = require('../../../window/windowManager.js'); +// const { getStoredApiKey, getStoredProvider, getCurrentModelInfo } = require('../../../window/windowManager.js'); class SummaryService { constructor() { @@ -97,6 +97,7 @@ Please build upon this context while analyzing the new conversation segments. await sessionRepository.touch(this.currentSessionId); } + const { getCurrentModelInfo } = require('../../../window/windowManager'); const modelInfo = await getCurrentModelInfo(null, { type: 'llm' }); if (!modelInfo || !modelInfo.apiKey) { throw new Error('AI model or API key is not configured.'); diff --git a/src/window/windowManager.js b/src/window/windowManager.js index 1d4fa08..bc91ce9 100644 --- a/src/window/windowManager.js +++ b/src/window/windowManager.js @@ -77,110 +77,6 @@ function updateLayout() { let movementManager = null; const windowBridge = require('../bridge/windowBridge'); -/** - * - * @param {'listen'|'ask'|'settings'} featureName - * @param {{ -* listen?: { targetVisibility?: 'show'|'hide' }, -* ask?: { targetVisibility?: 'show'|'hide', questionText?: string }, -* settings?: { targetVisibility?: 'show'|'hide' } -* }} [options={}] -*/ -async function toggleFeature(featureName, options = {}) { - if (!windowPool.get(featureName) && currentHeaderState === 'main') { - createFeatureWindows(windowPool.get('header')); - } - - const header = windowPool.get('header'); - if (featureName === 'listen') { - console.log(`[WindowManager] Toggling feature: ${featureName}`); - const listenWindow = windowPool.get(featureName); - // const listenService = global.listenService; - if (listenService && listenService.isSessionActive()) { - console.log('[WindowManager] Listen session is active, closing it via toggle.'); - await listenService.closeSession(); - listenWindow.webContents.send('session-state-changed', { isActive: false }); - header.webContents.send('session-state-text', 'Done'); - // return; - } else { - if (listenWindow.isVisible()) { - listenWindow.webContents.send('window-hide-animation'); - listenWindow.webContents.send('session-state-changed', { isActive: false }); - header.webContents.send('session-state-text', 'Listen'); - } else { - listenWindow.show(); - updateLayout(); - listenWindow.webContents.send('window-show-animation'); - await listenService.initializeSession(); - listenWindow.webContents.send('session-state-changed', { isActive: true }); - header.webContents.send('session-state-text', 'Stop'); - } - } - } - - if (featureName === 'ask') { - let askWindow = windowPool.get('ask'); - - if (!askWindow || askWindow.isDestroyed()) { - console.log('[WindowManager] Ask window not found, creating new one'); - return; - } - - const questionText = options?.ask?.questionText ?? null; - const targetVisibility = options?.ask?.targetVisibility ?? null; - if (askWindow.isVisible()) { - if (questionText) { - askWindow.webContents.send('ask:sendQuestionToRenderer', questionText); - } else { - updateLayout(); - if (targetVisibility === 'show') { - askWindow.webContents.send('ask:showTextInput'); - } else { - askWindow.webContents.send('window-hide-animation'); - } - } - } else { - console.log('[WindowManager] Showing hidden Ask window'); - askWindow.show(); - updateLayout(); - if (questionText) { - askWindow.webContents.send('ask:sendQuestionToRenderer', questionText); - } - askWindow.webContents.send('window-show-animation'); - } - } - - if (featureName === 'settings') { - const settingsWindow = windowPool.get(featureName); - - if (settingsWindow) { - if (settingsWindow.isDestroyed()) { - console.error(`Window ${featureName} is destroyed, cannot toggle`); - return; - } - - if (settingsWindow.isVisible()) { - if (featureName === 'settings') { - settingsWindow.webContents.send('settings-window-hide-animation'); - } else { - settingsWindow.webContents.send('window-hide-animation'); - } - } else { - try { - settingsWindow.show(); - updateLayout(); - - settingsWindow.webContents.send('window-show-animation'); - } catch (e) { - console.error('Error showing window:', e); - } - } - } else { - console.error(`Window not found for feature: ${featureName}`); - console.error('Available windows:', Array.from(windowPool.keys())); - } - } -} function createFeatureWindows(header, namesToCreate) { @@ -1124,6 +1020,112 @@ function setupIpcHandlers(movementManager) { } +/** + * + * @param {'listen'|'ask'|'settings'} featureName + * @param {{ +* listen?: { targetVisibility?: 'show'|'hide' }, +* ask?: { targetVisibility?: 'show'|'hide', questionText?: string }, +* settings?: { targetVisibility?: 'show'|'hide' } +* }} [options={}] +*/ +async function toggleFeature(featureName, options = {}) { + if (!windowPool.get(featureName) && currentHeaderState === 'main') { + createFeatureWindows(windowPool.get('header')); + } + + const header = windowPool.get('header'); + if (featureName === 'listen') { + console.log(`[WindowManager] Toggling feature: ${featureName}`); + const listenWindow = windowPool.get(featureName); + // const listenService = global.listenService; + if (listenService && listenService.isSessionActive()) { + console.log('[WindowManager] Listen session is active, closing it via toggle.'); + await listenService.closeSession(); + listenWindow.webContents.send('session-state-changed', { isActive: false }); + header.webContents.send('session-state-text', 'Done'); + // return; + } else { + if (listenWindow.isVisible()) { + listenWindow.webContents.send('window-hide-animation'); + listenWindow.webContents.send('session-state-changed', { isActive: false }); + header.webContents.send('session-state-text', 'Listen'); + } else { + listenWindow.show(); + updateLayout(); + listenWindow.webContents.send('window-show-animation'); + await listenService.initializeSession(); + listenWindow.webContents.send('session-state-changed', { isActive: true }); + header.webContents.send('session-state-text', 'Stop'); + } + } + } + + if (featureName === 'ask') { + let askWindow = windowPool.get('ask'); + + if (!askWindow || askWindow.isDestroyed()) { + console.log('[WindowManager] Ask window not found, creating new one'); + return; + } + + const questionText = options?.ask?.questionText ?? null; + const targetVisibility = options?.ask?.targetVisibility ?? null; + if (askWindow.isVisible()) { + if (questionText) { + askWindow.webContents.send('ask:sendQuestionToRenderer', questionText); + } else { + updateLayout(); + if (targetVisibility === 'show') { + askWindow.webContents.send('ask:showTextInput'); + } else { + askWindow.webContents.send('window-hide-animation'); + } + } + } else { + console.log('[WindowManager] Showing hidden Ask window'); + askWindow.show(); + updateLayout(); + if (questionText) { + askWindow.webContents.send('ask:sendQuestionToRenderer', questionText); + } + askWindow.webContents.send('window-show-animation'); + } + } + + if (featureName === 'settings') { + const settingsWindow = windowPool.get(featureName); + + if (settingsWindow) { + if (settingsWindow.isDestroyed()) { + console.error(`Window ${featureName} is destroyed, cannot toggle`); + return; + } + + if (settingsWindow.isVisible()) { + if (featureName === 'settings') { + settingsWindow.webContents.send('settings-window-hide-animation'); + } else { + settingsWindow.webContents.send('window-hide-animation'); + } + } else { + try { + settingsWindow.show(); + updateLayout(); + + settingsWindow.webContents.send('window-show-animation'); + } catch (e) { + console.error('Error showing window:', e); + } + } + } else { + console.error(`Window not found for feature: ${featureName}`); + console.error('Available windows:', Array.from(windowPool.keys())); + } + } +} + + //////// after_modelStateService //////// async function getStoredApiKey() {