diff --git a/src/features/ask/askService.js b/src/features/ask/askService.js index ceb347d..ee0af0c 100644 --- a/src/features/ask/askService.js +++ b/src/features/ask/askService.js @@ -22,11 +22,6 @@ async function sendMessage(userPrompt) { console.warn('[AskService] Cannot process empty message'); return { success: false, error: 'Empty message' }; } - - const askWindow = windowPool.get('ask'); - if (askWindow && !askWindow.isDestroyed()) { - askWindow.webContents.send('hide-text-input'); - } let sessionId; diff --git a/src/features/listen/listenService.js b/src/features/listen/listenService.js index 3c229d2..54e6e71 100644 --- a/src/features/listen/listenService.js +++ b/src/features/listen/listenService.js @@ -193,8 +193,6 @@ class ListenService { this.currentSessionId = null; this.summaryService.resetConversationHistory(); - this.sendToRenderer('session-did-close'); - console.log('Listen service session closed.'); return { success: true }; } catch (error) { diff --git a/src/ui/ask/AskView.js b/src/ui/ask/AskView.js index 39270ba..6250d38 100644 --- a/src/ui/ask/AskView.js +++ b/src/ui/ask/AskView.js @@ -729,17 +729,13 @@ export class AskView extends LitElement { this.handleStreamChunk = this.handleStreamChunk.bind(this); this.handleStreamEnd = this.handleStreamEnd.bind(this); this.handleSendText = this.handleSendText.bind(this); - this.handleGlobalSendRequest = this.handleGlobalSendRequest.bind(this); this.handleTextKeydown = this.handleTextKeydown.bind(this); - this.closeResponsePanel = this.closeResponsePanel.bind(this); this.handleCopy = this.handleCopy.bind(this); this.clearResponseContent = this.clearResponseContent.bind(this); - this.processAssistantQuestion = this.processAssistantQuestion.bind(this); this.handleEscKey = this.handleEscKey.bind(this); - this.handleDocumentClick = this.handleDocumentClick.bind(this); - this.handleWindowBlur = this.handleWindowBlur.bind(this); - this.handleScroll = this.handleScroll.bind(this); + this.handleCloseAskWindow = this.handleCloseAskWindow.bind(this); + this.handleCloseIfNoContent = this.handleCloseIfNoContent.bind(this); this.loadLibraries(); @@ -747,6 +743,94 @@ export class AskView extends LitElement { this.isThrottled = false; } + connectedCallback() { + super.connectedCallback(); + + console.log('๐Ÿ“ฑ AskView connectedCallback - IPC ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ ์„ค์ •'); + + document.addEventListener('keydown', this.handleEscKey); + + this.resizeObserver = new ResizeObserver(entries => { + for (const entry of entries) { + const needed = entry.contentRect.height; + const current = window.innerHeight; + + if (needed > current - 4) { + this.requestWindowResize(Math.ceil(needed)); + } + } + }); + + const container = this.shadowRoot?.querySelector('.ask-container'); + if (container) this.resizeObserver.observe(container); + + this.handleQuestionFromAssistant = (event, question) => { + console.log('๐Ÿ“จ AskView: Received question from ListenView:', question); + this.handleSendText(null, question); + }; + + if (window.require) { + const { ipcRenderer } = window.require('electron'); + ipcRenderer.on('ask:sendQuestionToRenderer', this.handleQuestionFromAssistant); + ipcRenderer.on('hide-text-input', () => { + console.log('๐Ÿ“ค Hide text input signal received'); + this.showTextInput = false; + this.requestUpdate(); + }); + ipcRenderer.on('ask:showTextInput', () => { + console.log('๐Ÿ“ค Show text input signal received'); + if (!this.showTextInput) { + this.showTextInput = true; + this.requestUpdate(); + } + }); + + ipcRenderer.on('ask-response-chunk', this.handleStreamChunk); + ipcRenderer.on('ask-response-stream-end', this.handleStreamEnd); + + ipcRenderer.on('scroll-response-up', () => this.handleScroll('up')); + ipcRenderer.on('scroll-response-down', () => this.handleScroll('down')); + console.log('โœ… AskView: IPC ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ ๋“ฑ๋ก ์™„๋ฃŒ'); + } + } + + disconnectedCallback() { + super.disconnectedCallback(); + this.resizeObserver?.disconnect(); + + console.log('๐Ÿ“ฑ AskView disconnectedCallback - IPC ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ ์ œ๊ฑฐ'); + + document.removeEventListener('keydown', this.handleEscKey); + + if (this.copyTimeout) { + clearTimeout(this.copyTimeout); + } + + if (this.headerAnimationTimeout) { + clearTimeout(this.headerAnimationTimeout); + } + + if (this.streamingTimeout) { + clearTimeout(this.streamingTimeout); + } + + Object.values(this.lineCopyTimeouts).forEach(timeout => clearTimeout(timeout)); + + if (window.require) { + const { ipcRenderer } = window.require('electron'); + ipcRenderer.removeListener('hide-text-input', () => { }); + ipcRenderer.removeListener('ask:showTextInput', () => { }); + + ipcRenderer.removeListener('ask-response-chunk', this.handleStreamChunk); + ipcRenderer.removeListener('ask-response-stream-end', this.handleStreamEnd); + + ipcRenderer.removeListener('scroll-response-up', () => this.handleScroll('up')); + ipcRenderer.removeListener('scroll-response-down', () => this.handleScroll('down')); + console.log('โœ… AskView: IPC ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ ์ œ๊ฑฐ ์™„๋ฃŒ'); + } + } + + async loadLibraries() { try { if (!window.marked) { @@ -803,38 +887,49 @@ export class AskView extends LitElement { } } - handleDocumentClick(e) { + handleCloseAskWindow() { + this.clearResponseContent(); + ipcRenderer.invoke('ask:closeAskWindow'); + } + + handleCloseIfNoContent() { if (!this.currentResponse && !this.isLoading && !this.isStreaming) { - const askContainer = this.shadowRoot?.querySelector('.ask-container'); - if (askContainer && !e.composedPath().includes(askContainer)) { - this.closeIfNoContent(); - } + this.handleCloseAskWindow(); } } handleEscKey(e) { if (e.key === 'Escape') { e.preventDefault(); - this.closeResponsePanel(); + this.handleCloseIfNoContent(); } } - handleWindowBlur() { - if (!this.currentResponse && !this.isLoading && !this.isStreaming) { - // If there's no active content, ask the main process to close this window. - if (window.require) { - const { ipcRenderer } = window.require('electron'); - ipcRenderer.invoke('close-ask-window-if-empty'); + clearResponseContent() { + this.currentResponse = ''; + this.currentQuestion = ''; + this.isLoading = false; + this.isStreaming = false; + this.headerText = 'AI Response'; + this.showTextInput = true; + this.accumulatedResponse = ''; + this.requestUpdate(); + this.renderContent(); + } + + handleInputFocus() { + this.isInputFocused = true; + } + + focusTextInput() { + requestAnimationFrame(() => { + const textInput = this.shadowRoot?.getElementById('textInput'); + if (textInput) { + textInput.focus(); } - } + }); } - closeIfNoContent() { - if (window.require) { - const { ipcRenderer } = window.require('electron'); - ipcRenderer.invoke('force-close-window', 'ask'); - } - } loadScript(src) { return new Promise((resolve, reject) => { @@ -874,114 +969,6 @@ export class AskView extends LitElement { return text; } - connectedCallback() { - super.connectedCallback(); - - console.log('๐Ÿ“ฑ AskView connectedCallback - IPC ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ ์„ค์ •'); - - document.addEventListener('click', this.handleDocumentClick, true); - document.addEventListener('keydown', this.handleEscKey); - - this.resizeObserver = new ResizeObserver(entries => { - for (const entry of entries) { - const needed = entry.contentRect.height; - const current = window.innerHeight; - - if (needed > current - 4) { - this.requestWindowResize(Math.ceil(needed)); - } - } - }); - - const container = this.shadowRoot?.querySelector('.ask-container'); - if (container) this.resizeObserver.observe(container); - - this.handleQuestionFromAssistant = (event, question) => { - console.log('๐Ÿ“จ AskView: Received question from ListenView:', question); - this.currentResponse = ''; - this.isStreaming = false; - this.requestUpdate(); - - this.currentQuestion = question; - this.isLoading = true; - this.showTextInput = false; - this.headerText = 'analyzing screen...'; - this.startHeaderAnimation(); - this.requestUpdate(); - - this.processAssistantQuestion(question); - }; - - if (window.require) { - const { ipcRenderer } = window.require('electron'); - ipcRenderer.on('ask-global-send', this.handleGlobalSendRequest); - ipcRenderer.on('receive-question-from-assistant', this.handleQuestionFromAssistant); - ipcRenderer.on('hide-text-input', () => { - console.log('๐Ÿ“ค Hide text input signal received'); - this.showTextInput = false; - this.requestUpdate(); - }); - ipcRenderer.on('window-hide-animation', () => { - console.log('๐Ÿ“ค Ask window hiding - clearing response content'); - setTimeout(() => { - this.clearResponseContent(); - }, 250); - }); - ipcRenderer.on('window-blur', this.handleWindowBlur); - ipcRenderer.on('window-did-show', () => { - if (!this.currentResponse && !this.isLoading && !this.isStreaming) { - this.focusTextInput(); - } - }); - - ipcRenderer.on('ask-response-chunk', this.handleStreamChunk); - ipcRenderer.on('ask-response-stream-end', this.handleStreamEnd); - - ipcRenderer.on('scroll-response-up', () => this.handleScroll('up')); - ipcRenderer.on('scroll-response-down', () => this.handleScroll('down')); - console.log('โœ… AskView: IPC ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ ๋“ฑ๋ก ์™„๋ฃŒ'); - } - } - - disconnectedCallback() { - super.disconnectedCallback(); - this.resizeObserver?.disconnect(); - - console.log('๐Ÿ“ฑ AskView disconnectedCallback - IPC ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ ์ œ๊ฑฐ'); - - document.removeEventListener('click', this.handleDocumentClick, true); - document.removeEventListener('keydown', this.handleEscKey); - - if (this.copyTimeout) { - clearTimeout(this.copyTimeout); - } - - if (this.headerAnimationTimeout) { - clearTimeout(this.headerAnimationTimeout); - } - - if (this.streamingTimeout) { - clearTimeout(this.streamingTimeout); - } - - Object.values(this.lineCopyTimeouts).forEach(timeout => clearTimeout(timeout)); - - if (window.require) { - const { ipcRenderer } = window.require('electron'); - ipcRenderer.removeListener('ask-global-send', this.handleGlobalSendRequest); - ipcRenderer.removeListener('hide-text-input', () => { }); - ipcRenderer.removeListener('window-hide-animation', () => { }); - ipcRenderer.removeListener('window-blur', this.handleWindowBlur); - - ipcRenderer.removeListener('ask-response-chunk', this.handleStreamChunk); - ipcRenderer.removeListener('ask-response-stream-end', this.handleStreamEnd); - - ipcRenderer.removeListener('scroll-response-up', () => this.handleScroll('up')); - ipcRenderer.removeListener('scroll-response-down', () => this.handleScroll('down')); - console.log('โœ… AskView: IPC ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ ์ œ๊ฑฐ ์™„๋ฃŒ'); - } - } - handleScroll(direction) { const scrollableElement = this.shadowRoot.querySelector('#responseContainer'); if (scrollableElement) { @@ -1124,18 +1111,6 @@ export class AskView extends LitElement { this.adjustWindowHeightThrottled(); } - clearResponseContent() { - this.currentResponse = ''; - this.currentQuestion = ''; - this.isLoading = false; - this.isStreaming = false; - this.headerText = 'AI Response'; - this.showTextInput = true; - this.accumulatedResponse = ''; - this.requestUpdate(); - this.renderContent(); // ๐Ÿ‘ˆ updateResponseContent() ๋Œ€์‹  renderContent() ํ˜ธ์ถœ - } - requestWindowResize(targetHeight) { if (window.require) { @@ -1180,13 +1155,6 @@ export class AskView extends LitElement { .replace(/`(.*?)`/g, '$1'); } - closeResponsePanel() { - if (window.require) { - const { ipcRenderer } = window.require('electron'); - ipcRenderer.invoke('force-close-window', 'ask'); - } - } - fixIncompleteMarkdown(text) { if (!text) return text; @@ -1224,29 +1192,6 @@ export class AskView extends LitElement { return text; } - // โœจ processAssistantQuestion ์ˆ˜์ • - async processAssistantQuestion(question) { - this.currentQuestion = question; - this.showTextInput = false; - this.isLoading = true; - this.isStreaming = false; - this.currentResponse = ''; - this.accumulatedResponse = ''; - this.startHeaderAnimation(); - this.requestUpdate(); - this.renderContent(); - - if (window.require) { - const { ipcRenderer } = window.require('electron'); - ipcRenderer.invoke('ask:sendMessage', question).catch(error => { - console.error('Error processing assistant question:', error); - this.isLoading = false; - this.isStreaming = false; - this.currentResponse = `Error: ${error.message}`; - this.renderContent(); - }); - } - } async handleCopy() { if (this.copyState === 'copied') return; @@ -1316,10 +1261,9 @@ export class AskView extends LitElement { } } - async handleSendText() { + async handleSendText(e, overridingText = '') { const textInput = this.shadowRoot?.getElementById('textInput'); - if (!textInput) return; - const text = textInput.value.trim(); + const text = (overridingText || textInput?.value || '').trim(); if (!text) return; textInput.value = ''; @@ -1377,37 +1321,10 @@ export class AskView extends LitElement { } } - focusTextInput() { - requestAnimationFrame(() => { - const textInput = this.shadowRoot?.getElementById('textInput'); - if (textInput) { - textInput.focus(); - } - }); - } - firstUpdated() { setTimeout(() => this.adjustWindowHeight(), 200); } - handleGlobalSendRequest() { - const textInput = this.shadowRoot?.getElementById('textInput'); - - if (!this.showTextInput) { - this.showTextInput = true; - this.requestUpdate(); - this.focusTextInput(); - return; - } - - if (!textInput) return; - - textInput.focus(); - - if (!textInput.value.trim()) return; - - this.handleSendText(); - } getTruncatedQuestion(question, maxLength = 30) { if (!question) return ''; @@ -1415,24 +1332,7 @@ export class AskView extends LitElement { return question.substring(0, maxLength) + '...'; } - handleInputFocus() { - this.isInputFocused = true; - } - handleInputBlur(e) { - this.isInputFocused = false; - - // ์ž ์‹œ ํ›„ ํฌ์ปค์Šค๊ฐ€ ๋‹ค๋ฅธ ๊ณณ์œผ๋กœ ๊ฐ”๋Š”์ง€ ํ™•์ธ - setTimeout(() => { - const activeElement = this.shadowRoot?.activeElement || document.activeElement; - const textInput = this.shadowRoot?.getElementById('textInput'); - - // ํฌ์ปค์Šค๊ฐ€ AskView ๋‚ด๋ถ€๊ฐ€ ์•„๋‹ˆ๊ณ , ์‘๋‹ต์ด ์—†๋Š” ๊ฒฝ์šฐ - if (!this.currentResponse && !this.isLoading && !this.isStreaming && activeElement !== textInput && !this.isInputFocused) { - this.closeIfNoContent(); - } - }, 200); - } render() { const hasResponse = this.isLoading || this.currentResponse || this.isStreaming; @@ -1470,7 +1370,7 @@ export class AskView extends LitElement { -