toggle listen button logic improved
This commit is contained in:
		
							parent
							
								
									3031d0d288
								
							
						
					
					
						commit
						e86c2db464
					
				
							
								
								
									
										35
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										35
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							@ -4172,28 +4172,6 @@
 | 
				
			|||||||
                "node": ">= 8"
 | 
					                "node": ">= 8"
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        "node_modules/fs-temp": {
 | 
					 | 
				
			||||||
            "version": "1.2.1",
 | 
					 | 
				
			||||||
            "dev": true,
 | 
					 | 
				
			||||||
            "license": "MIT",
 | 
					 | 
				
			||||||
            "optional": true,
 | 
					 | 
				
			||||||
            "dependencies": {
 | 
					 | 
				
			||||||
                "random-path": "^0.1.0"
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "node_modules/fs-xattr": {
 | 
					 | 
				
			||||||
            "version": "0.3.1",
 | 
					 | 
				
			||||||
            "dev": true,
 | 
					 | 
				
			||||||
            "hasInstallScript": true,
 | 
					 | 
				
			||||||
            "license": "MIT",
 | 
					 | 
				
			||||||
            "optional": true,
 | 
					 | 
				
			||||||
            "os": [
 | 
					 | 
				
			||||||
                "!win32"
 | 
					 | 
				
			||||||
            ],
 | 
					 | 
				
			||||||
            "engines": {
 | 
					 | 
				
			||||||
                "node": ">=8.6.0"
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "node_modules/fs.realpath": {
 | 
					        "node_modules/fs.realpath": {
 | 
				
			||||||
            "version": "1.0.0",
 | 
					            "version": "1.0.0",
 | 
				
			||||||
            "dev": true,
 | 
					            "dev": true,
 | 
				
			||||||
@ -5158,19 +5136,6 @@
 | 
				
			|||||||
                "lru-cache": "6.0.0"
 | 
					                "lru-cache": "6.0.0"
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        "node_modules/macos-alias": {
 | 
					 | 
				
			||||||
            "version": "0.2.12",
 | 
					 | 
				
			||||||
            "dev": true,
 | 
					 | 
				
			||||||
            "hasInstallScript": true,
 | 
					 | 
				
			||||||
            "license": "MIT",
 | 
					 | 
				
			||||||
            "optional": true,
 | 
					 | 
				
			||||||
            "os": [
 | 
					 | 
				
			||||||
                "darwin"
 | 
					 | 
				
			||||||
            ],
 | 
					 | 
				
			||||||
            "dependencies": {
 | 
					 | 
				
			||||||
                "nan": "^2.4.0"
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "node_modules/make-fetch-happen": {
 | 
					        "node_modules/make-fetch-happen": {
 | 
				
			||||||
            "version": "10.2.1",
 | 
					            "version": "10.2.1",
 | 
				
			||||||
            "dev": true,
 | 
					            "dev": true,
 | 
				
			||||||
 | 
				
			|||||||
@ -68,12 +68,7 @@ export class PickleGlassApp extends LitElement {
 | 
				
			|||||||
        this.selectedScreenshotInterval = localStorage.getItem('selectedScreenshotInterval') || '5';
 | 
					        this.selectedScreenshotInterval = localStorage.getItem('selectedScreenshotInterval') || '5';
 | 
				
			||||||
        this.selectedImageQuality = localStorage.getItem('selectedImageQuality') || 'medium';
 | 
					        this.selectedImageQuality = localStorage.getItem('selectedImageQuality') || 'medium';
 | 
				
			||||||
        this._isClickThrough = false;
 | 
					        this._isClickThrough = false;
 | 
				
			||||||
        this.outlines = [];
 | 
					 | 
				
			||||||
        this.analysisRequests = [];
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        window.pickleGlass.setStructuredData = data => {
 | 
					 | 
				
			||||||
            this.updateStructuredData(data);
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    connectedCallback() {
 | 
					    connectedCallback() {
 | 
				
			||||||
@ -82,14 +77,13 @@ export class PickleGlassApp extends LitElement {
 | 
				
			|||||||
        if (window.require) {
 | 
					        if (window.require) {
 | 
				
			||||||
            const { ipcRenderer } = window.require('electron');
 | 
					            const { ipcRenderer } = window.require('electron');
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            ipcRenderer.on('update-status', (_, status) => this.setStatus(status));
 | 
					 | 
				
			||||||
            ipcRenderer.on('click-through-toggled', (_, isEnabled) => {
 | 
					            ipcRenderer.on('click-through-toggled', (_, isEnabled) => {
 | 
				
			||||||
                this._isClickThrough = isEnabled;
 | 
					                this._isClickThrough = isEnabled;
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
            ipcRenderer.on('start-listening-session', () => {
 | 
					            // ipcRenderer.on('start-listening-session', () => {
 | 
				
			||||||
                console.log('Received start-listening-session command, calling handleListenClick.');
 | 
					            //     console.log('Received start-listening-session command, calling handleListenClick.');
 | 
				
			||||||
                this.handleListenClick();
 | 
					            //     this.handleListenClick();
 | 
				
			||||||
            });
 | 
					            // });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -97,16 +91,15 @@ export class PickleGlassApp extends LitElement {
 | 
				
			|||||||
        super.disconnectedCallback();
 | 
					        super.disconnectedCallback();
 | 
				
			||||||
        if (window.require) {
 | 
					        if (window.require) {
 | 
				
			||||||
            const { ipcRenderer } = window.require('electron');
 | 
					            const { ipcRenderer } = window.require('electron');
 | 
				
			||||||
            ipcRenderer.removeAllListeners('update-status');
 | 
					 | 
				
			||||||
            ipcRenderer.removeAllListeners('click-through-toggled');
 | 
					            ipcRenderer.removeAllListeners('click-through-toggled');
 | 
				
			||||||
            ipcRenderer.removeAllListeners('start-listening-session');
 | 
					            // ipcRenderer.removeAllListeners('start-listening-session');
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    updated(changedProperties) {
 | 
					    updated(changedProperties) {
 | 
				
			||||||
        if (changedProperties.has('isMainViewVisible') || changedProperties.has('currentView')) {
 | 
					        // if (changedProperties.has('isMainViewVisible') || changedProperties.has('currentView')) {
 | 
				
			||||||
            this.requestWindowResize();
 | 
					        //     this.requestWindowResize();
 | 
				
			||||||
        }
 | 
					        // }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (changedProperties.has('currentView')) {
 | 
					        if (changedProperties.has('currentView')) {
 | 
				
			||||||
            const viewContainer = this.shadowRoot?.querySelector('.view-container');
 | 
					            const viewContainer = this.shadowRoot?.querySelector('.view-container');
 | 
				
			||||||
@ -136,57 +129,35 @@ export class PickleGlassApp extends LitElement {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    setStatus(text) {
 | 
					 | 
				
			||||||
        this.statusText = text;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async handleListenClick() {
 | 
					    // async handleListenClick() {
 | 
				
			||||||
        if (window.require) {
 | 
					    //     if (window.require) {
 | 
				
			||||||
            const { ipcRenderer } = window.require('electron');
 | 
					    //         const { ipcRenderer } = window.require('electron');
 | 
				
			||||||
            const isActive = await ipcRenderer.invoke('is-session-active');
 | 
					    //         const isActive = await ipcRenderer.invoke('is-session-active');
 | 
				
			||||||
            if (isActive) {
 | 
					    //         // if (isActive) {
 | 
				
			||||||
                console.log('Session is already active. No action needed.');
 | 
					    //         //     console.log('Session is already active. No action needed.');
 | 
				
			||||||
                return;
 | 
					    //         //     return;
 | 
				
			||||||
            }
 | 
					    //         // }
 | 
				
			||||||
        }
 | 
					    //     }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (window.pickleGlass) {
 | 
					    //     if (window.pickleGlass) {
 | 
				
			||||||
            await window.pickleGlass.initializeopenai(this.selectedProfile, this.selectedLanguage);
 | 
					    //         // await window.pickleGlass.initializeopenai(this.selectedProfile, this.selectedLanguage);
 | 
				
			||||||
            window.pickleGlass.startCapture(this.selectedScreenshotInterval, this.selectedImageQuality);
 | 
					    //         window.pickleGlass.startCapture(this.selectedScreenshotInterval, this.selectedImageQuality);
 | 
				
			||||||
        }
 | 
					    //     }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // 🔄 Clear previous summary/analysis when a new listening session begins
 | 
					    //     // 🔄 Clear previous summary/analysis when a new listening session begins
 | 
				
			||||||
        this.structuredData = {
 | 
					    //     this.structuredData = {
 | 
				
			||||||
            summary: [],
 | 
					    //         summary: [],
 | 
				
			||||||
            topic: { header: '', bullets: [] },
 | 
					    //         topic: { header: '', bullets: [] },
 | 
				
			||||||
            actions: [],
 | 
					    //         actions: [],
 | 
				
			||||||
            followUps: [],
 | 
					    //         followUps: [],
 | 
				
			||||||
        };
 | 
					    //     };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.currentResponseIndex = -1;
 | 
					    //     this.currentResponseIndex = -1;
 | 
				
			||||||
        this.startTime = Date.now();
 | 
					    //     this.startTime = Date.now();
 | 
				
			||||||
        this.currentView = 'listen';
 | 
					    //     this.currentView = 'listen';
 | 
				
			||||||
        this.isMainViewVisible = true;
 | 
					    //     this.isMainViewVisible = true;
 | 
				
			||||||
    }
 | 
					    // }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    handleShowHideClick() {
 | 
					 | 
				
			||||||
        this.isMainViewVisible = !this.isMainViewVisible;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    handleSettingsClick() {
 | 
					 | 
				
			||||||
        this.currentView = 'settings';
 | 
					 | 
				
			||||||
        this.isMainViewVisible = true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    handleHelpClick() {
 | 
					 | 
				
			||||||
        this.currentView = 'help';
 | 
					 | 
				
			||||||
        this.isMainViewVisible = true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    handleHistoryClick() {
 | 
					 | 
				
			||||||
        this.currentView = 'history';
 | 
					 | 
				
			||||||
        this.isMainViewVisible = true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async handleClose() {
 | 
					    async handleClose() {
 | 
				
			||||||
        if (window.require) {
 | 
					        if (window.require) {
 | 
				
			||||||
@ -195,50 +166,8 @@ export class PickleGlassApp extends LitElement {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    handleBackClick() {
 | 
					 | 
				
			||||||
        this.currentView = 'listen';
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async handleSendText(message) {
 | 
					 | 
				
			||||||
        if (window.pickleGlass) {
 | 
					 | 
				
			||||||
            const result = await window.pickleGlass.sendTextMessage(message);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (!result.success) {
 | 
					 | 
				
			||||||
                console.error('Failed to send message:', result.error);
 | 
					 | 
				
			||||||
                this.setStatus('Error sending message: ' + result.error);
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                this.setStatus('Message sent...');
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // updateOutline(outline) {
 | 
					 | 
				
			||||||
    //     console.log('📝 PickleGlassApp updateOutline:', outline);
 | 
					 | 
				
			||||||
    //     this.outlines = [...outline];
 | 
					 | 
				
			||||||
    //     this.requestUpdate();
 | 
					 | 
				
			||||||
    // }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // updateAnalysisRequests(requests) {
 | 
					 | 
				
			||||||
    //     console.log('📝 PickleGlassApp updateAnalysisRequests:', requests);
 | 
					 | 
				
			||||||
    //     this.analysisRequests = [...requests];
 | 
					 | 
				
			||||||
    //     this.requestUpdate();
 | 
					 | 
				
			||||||
    // }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    updateStructuredData(data) {
 | 
					 | 
				
			||||||
        console.log('📝 PickleGlassApp updateStructuredData:', data);
 | 
					 | 
				
			||||||
        this.structuredData = data;
 | 
					 | 
				
			||||||
        this.requestUpdate();
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        const assistantView = this.shadowRoot?.querySelector('assistant-view');
 | 
					 | 
				
			||||||
        if (assistantView) {
 | 
					 | 
				
			||||||
            assistantView.structuredData = data;
 | 
					 | 
				
			||||||
            console.log('✅ Structured data passed to AssistantView');
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    handleResponseIndexChanged(e) {
 | 
					 | 
				
			||||||
        this.currentResponseIndex = e.detail.index;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    render() {
 | 
					    render() {
 | 
				
			||||||
        switch (this.currentView) {
 | 
					        switch (this.currentView) {
 | 
				
			||||||
@ -247,7 +176,6 @@ export class PickleGlassApp extends LitElement {
 | 
				
			|||||||
                    .currentResponseIndex=${this.currentResponseIndex}
 | 
					                    .currentResponseIndex=${this.currentResponseIndex}
 | 
				
			||||||
                    .selectedProfile=${this.selectedProfile}
 | 
					                    .selectedProfile=${this.selectedProfile}
 | 
				
			||||||
                    .structuredData=${this.structuredData}
 | 
					                    .structuredData=${this.structuredData}
 | 
				
			||||||
                    .onSendText=${message => this.handleSendText(message)}
 | 
					 | 
				
			||||||
                    @response-index-changed=${e => (this.currentResponseIndex = e.detail.index)}
 | 
					                    @response-index-changed=${e => (this.currentResponseIndex = e.detail.index)}
 | 
				
			||||||
                ></assistant-view>`;
 | 
					                ></assistant-view>`;
 | 
				
			||||||
            case 'ask':
 | 
					            case 'ask':
 | 
				
			||||||
 | 
				
			|||||||
@ -90,7 +90,7 @@ function createFeatureWindows(header, namesToCreate) {
 | 
				
			|||||||
        hasShadow: false,
 | 
					        hasShadow: false,
 | 
				
			||||||
        skipTaskbar: true,
 | 
					        skipTaskbar: true,
 | 
				
			||||||
        hiddenInMissionControl: true,
 | 
					        hiddenInMissionControl: true,
 | 
				
			||||||
        resizable: false,
 | 
					        resizable: true,
 | 
				
			||||||
        webPreferences: { nodeIntegration: true, contextIsolation: false },
 | 
					        webPreferences: { nodeIntegration: true, contextIsolation: false },
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -100,8 +100,8 @@ function createFeatureWindows(header, namesToCreate) {
 | 
				
			|||||||
        switch (name) {
 | 
					        switch (name) {
 | 
				
			||||||
            case 'listen': {
 | 
					            case 'listen': {
 | 
				
			||||||
                const listen = new BrowserWindow({
 | 
					                const listen = new BrowserWindow({
 | 
				
			||||||
                    ...commonChildOptions, width:400,minWidth:400,maxWidth:400,
 | 
					                    ...commonChildOptions, width:400,minWidth:400,maxWidth:900,
 | 
				
			||||||
                    maxHeight:700,
 | 
					                    maxHeight:900,
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
                listen.setContentProtection(isContentProtectionOn);
 | 
					                listen.setContentProtection(isContentProtectionOn);
 | 
				
			||||||
                listen.setVisibleOnAllWorkspaces(true,{visibleOnFullScreen:true});
 | 
					                listen.setVisibleOnAllWorkspaces(true,{visibleOnFullScreen:true});
 | 
				
			||||||
@ -472,18 +472,27 @@ function createWindows() {
 | 
				
			|||||||
            createFeatureWindows(windowPool.get('header'));
 | 
					            createFeatureWindows(windowPool.get('header'));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const windowToToggle = windowPool.get(featureName);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (windowToToggle) {
 | 
					        if (featureName === 'listen') {
 | 
				
			||||||
            if (featureName === 'listen') {
 | 
					 | 
				
			||||||
                const listenService = global.listenService;
 | 
					 | 
				
			||||||
                if (listenService && listenService.isSessionActive()) {
 | 
					 | 
				
			||||||
                    console.log('[WindowManager] Listen session is active, closing it via toggle.');
 | 
					 | 
				
			||||||
                    await listenService.closeSession();
 | 
					 | 
				
			||||||
                    return;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            console.log(`[WindowManager] Toggling feature: ${featureName}`);
 | 
					            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();
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            if (listenWindow.isVisible()) {
 | 
				
			||||||
 | 
					                listenWindow.webContents.send('window-hide-animation');
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                listenWindow.show();
 | 
				
			||||||
 | 
					                updateLayout();
 | 
				
			||||||
 | 
					                // listenWindow.webContents.send('start-listening-session');
 | 
				
			||||||
 | 
					                listenWindow.webContents.send('window-show-animation');
 | 
				
			||||||
 | 
					                await listenService.initializeSession();
 | 
				
			||||||
 | 
					                // listenWindow.webContents.send('start-listening-session');
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (featureName === 'ask') {
 | 
					        if (featureName === 'ask') {
 | 
				
			||||||
@ -561,31 +570,29 @@ function createWindows() {
 | 
				
			|||||||
                askWindow.webContents.send('window-show-animation');
 | 
					                askWindow.webContents.send('window-show-animation');
 | 
				
			||||||
                askWindow.webContents.send('window-did-show');
 | 
					                askWindow.webContents.send('window-did-show');
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } else {
 | 
					        }
 | 
				
			||||||
            const windowToToggle = windowPool.get(featureName);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (windowToToggle) {
 | 
					        if (featureName === 'settings') {
 | 
				
			||||||
                if (windowToToggle.isDestroyed()) {
 | 
					            const settingsWindow = windowPool.get(featureName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (settingsWindow) {
 | 
				
			||||||
 | 
					                if (settingsWindow.isDestroyed()) {
 | 
				
			||||||
                    console.error(`Window ${featureName} is destroyed, cannot toggle`);
 | 
					                    console.error(`Window ${featureName} is destroyed, cannot toggle`);
 | 
				
			||||||
                    return;
 | 
					                    return;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (windowToToggle.isVisible()) {
 | 
					                if (settingsWindow.isVisible()) {
 | 
				
			||||||
                    if (featureName === 'settings') {
 | 
					                    if (featureName === 'settings') {
 | 
				
			||||||
                        windowToToggle.webContents.send('settings-window-hide-animation');
 | 
					                        settingsWindow.webContents.send('settings-window-hide-animation');
 | 
				
			||||||
                    } else {
 | 
					                    } else {
 | 
				
			||||||
                        windowToToggle.webContents.send('window-hide-animation');
 | 
					                        settingsWindow.webContents.send('window-hide-animation');
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    try {
 | 
					                    try {
 | 
				
			||||||
                        windowToToggle.show();
 | 
					                        settingsWindow.show();
 | 
				
			||||||
                        updateLayout();
 | 
					                        updateLayout();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        if (featureName === 'listen') {
 | 
					                        settingsWindow.webContents.send('window-show-animation');
 | 
				
			||||||
                            windowToToggle.webContents.send('start-listening-session');
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        windowToToggle.webContents.send('window-show-animation');
 | 
					 | 
				
			||||||
                    } catch (e) {
 | 
					                    } catch (e) {
 | 
				
			||||||
                        console.error('Error showing window:', e);
 | 
					                        console.error('Error showing window:', e);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
				
			|||||||
@ -146,6 +146,7 @@ class ListenService {
 | 
				
			|||||||
            
 | 
					            
 | 
				
			||||||
            this.sendToRenderer('session-state-changed', { isActive: true });
 | 
					            this.sendToRenderer('session-state-changed', { isActive: true });
 | 
				
			||||||
            this.sendToRenderer('update-status', 'Connected. Ready to listen.');
 | 
					            this.sendToRenderer('update-status', 'Connected. Ready to listen.');
 | 
				
			||||||
 | 
					            // this.sendToRenderer('change-listen-capture-state', { status: "start" });
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            return true;
 | 
					            return true;
 | 
				
			||||||
        } catch (error) {
 | 
					        } catch (error) {
 | 
				
			||||||
@ -155,6 +156,7 @@ class ListenService {
 | 
				
			|||||||
        } finally {
 | 
					        } finally {
 | 
				
			||||||
            this.isInitializingSession = false;
 | 
					            this.isInitializingSession = false;
 | 
				
			||||||
            this.sendToRenderer('session-initializing', false);
 | 
					            this.sendToRenderer('session-initializing', false);
 | 
				
			||||||
 | 
					            this.sendToRenderer('change-listen-capture-state', { status: "start" });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -194,6 +196,7 @@ class ListenService {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            this.sendToRenderer('session-state-changed', { isActive: false });
 | 
					            this.sendToRenderer('session-state-changed', { isActive: false });
 | 
				
			||||||
            this.sendToRenderer('session-did-close');
 | 
					            this.sendToRenderer('session-did-close');
 | 
				
			||||||
 | 
					            this.sendToRenderer('change-listen-capture-state', { status: "stop" });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            console.log('Listen service session closed.');
 | 
					            console.log('Listen service session closed.');
 | 
				
			||||||
            return { success: true };
 | 
					            return { success: true };
 | 
				
			||||||
 | 
				
			|||||||
@ -7,9 +7,15 @@ let aecPtr        = 0;        // Rust Aec* 1개만 재사용
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/** WASM 모듈 가져오고 1회 초기화 */
 | 
					/** WASM 모듈 가져오고 1회 초기화 */
 | 
				
			||||||
async function getAec () {
 | 
					async function getAec () {
 | 
				
			||||||
  if (aecModPromise) return aecModPromise;   // 캐시
 | 
					    if (aecModPromise) {
 | 
				
			||||||
 | 
					        console.log('[AEC] getAec: 캐시=있음(재사용)');
 | 
				
			||||||
 | 
					        return aecModPromise;                      // 캐시
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					      console.log('[AEC] getAec: 캐시=없음 → 모듈 로드 시작');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    aecModPromise = createAecModule().then((M) => {
 | 
					    aecModPromise = createAecModule().then((M) => {
 | 
				
			||||||
 | 
					        console.log('[AEC] WASM 모듈 로드 완료');
 | 
				
			||||||
        aecMod = M; 
 | 
					        aecMod = M; 
 | 
				
			||||||
        // C 심볼 → JS 래퍼 바인딩 (딱 1번)
 | 
					        // C 심볼 → JS 래퍼 바인딩 (딱 1번)
 | 
				
			||||||
        M.newPtr   = M.cwrap('AecNew',        'number',
 | 
					        M.newPtr   = M.cwrap('AecNew',        'number',
 | 
				
			||||||
@ -18,7 +24,12 @@ async function getAec () {
 | 
				
			|||||||
                            ['number','number','number','number','number']);
 | 
					                            ['number','number','number','number','number']);
 | 
				
			||||||
        M.destroy  = M.cwrap('AecDestroy',    null, ['number']);
 | 
					        M.destroy  = M.cwrap('AecDestroy',    null, ['number']);
 | 
				
			||||||
        return M;
 | 
					        return M;
 | 
				
			||||||
    });
 | 
					    })    
 | 
				
			||||||
 | 
					    .catch(err => {
 | 
				
			||||||
 | 
					        console.error('[AEC] WASM 모듈 로드 실패:', err);
 | 
				
			||||||
 | 
					        throw err;                               // 상위에서도 잡을 수 있게
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return aecModPromise;
 | 
					  return aecModPromise;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -132,6 +143,10 @@ function disposeAec () {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function runAecSync (micF32, sysF32) {
 | 
					function runAecSync (micF32, sysF32) {
 | 
				
			||||||
 | 
					    const modStat  = aecMod?.HEAPU8        ? '있음' : '없음'; // aecMod가 초기화되었고 HEAP 접근 가능?
 | 
				
			||||||
 | 
					    const ptrStat  = aecPtr                ? '있음' : '없음'; // newPtr 호출 여부
 | 
				
			||||||
 | 
					    const heapStat = aecMod?.HEAPU8        ? '있음' : '없음'; // HEAPU8 생성 여부
 | 
				
			||||||
 | 
					    console.log(`[AEC] mod:${modStat} ptr:${ptrStat} heap:${heapStat}`);
 | 
				
			||||||
  if (!aecMod || !aecPtr || !aecMod.HEAPU8) return micF32;          // 아직 모듈 안 뜸 → 패스
 | 
					  if (!aecMod || !aecPtr || !aecMod.HEAPU8) return micF32;          // 아직 모듈 안 뜸 → 패스
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const len  = micF32.length;
 | 
					  const len  = micF32.length;
 | 
				
			||||||
@ -145,6 +160,7 @@ function runAecSync (micF32, sysF32) {
 | 
				
			|||||||
  const outF32  = float32FromInt16View(new Int16Array(heapBuf, out, len));
 | 
					  const outF32  = float32FromInt16View(new Int16Array(heapBuf, out, len));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  aecMod._free(mic.ptr); aecMod._free(echo.ptr); aecMod._free(out);
 | 
					  aecMod._free(mic.ptr); aecMod._free(echo.ptr); aecMod._free(out);
 | 
				
			||||||
 | 
					  console.log(`[AEC] 적용 완료`);
 | 
				
			||||||
  return outF32;
 | 
					  return outF32;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -266,7 +282,7 @@ async function setupMicProcessing(micStream) {
 | 
				
			|||||||
    micProcessor.onaudioprocess = (e) => {
 | 
					    micProcessor.onaudioprocess = (e) => {
 | 
				
			||||||
        const inputData = e.inputBuffer.getChannelData(0);
 | 
					        const inputData = e.inputBuffer.getChannelData(0);
 | 
				
			||||||
        audioBuffer.push(...inputData);
 | 
					        audioBuffer.push(...inputData);
 | 
				
			||||||
        console.log('🎤 micProcessor.onaudioprocess');
 | 
					        // console.log('🎤 micProcessor.onaudioprocess');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // samplesPerChunk(=2400) 만큼 모이면 전송
 | 
					        // samplesPerChunk(=2400) 만큼 모이면 전송
 | 
				
			||||||
        while (audioBuffer.length >= samplesPerChunk) {
 | 
					        while (audioBuffer.length >= samplesPerChunk) {
 | 
				
			||||||
@ -280,7 +296,7 @@ async function setupMicProcessing(micStream) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                // **음성 구간일 때만 런**
 | 
					                // **음성 구간일 때만 런**
 | 
				
			||||||
                processedChunk = runAecSync(new Float32Array(chunk), sysF32);
 | 
					                processedChunk = runAecSync(new Float32Array(chunk), sysF32);
 | 
				
			||||||
                console.log('🔊 Applied WASM-AEC (speex)');
 | 
					                // console.log('🔊 Applied WASM-AEC (speex)');
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                console.log('🔊 No system audio for AEC reference');
 | 
					                console.log('🔊 No system audio for AEC reference');
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
				
			|||||||
@ -1,138 +1,30 @@
 | 
				
			|||||||
// renderer.js
 | 
					// renderer.js
 | 
				
			||||||
const { ipcRenderer } = require('electron');
 | 
					const { ipcRenderer } = require('electron');
 | 
				
			||||||
const listenCapture = require('./listenCapture.js');
 | 
					const listenCapture = require('./listenCapture.js');
 | 
				
			||||||
 | 
					const params        = new URLSearchParams(window.location.search);
 | 
				
			||||||
 | 
					const isListenView  = params.get('view') === 'listen';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let realtimeConversationHistory = [];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
async function queryLoginState() {
 | 
					 | 
				
			||||||
    const userState = await ipcRenderer.invoke('get-current-user');
 | 
					 | 
				
			||||||
    return userState;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function pickleGlassElement() {
 | 
					 | 
				
			||||||
    return document.getElementById('pickle-glass');
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
async function initializeopenai(profile = 'interview', language = 'en') {
 | 
					 | 
				
			||||||
    // The API key is now handled in the main process from .env file.
 | 
					 | 
				
			||||||
    // We just need to trigger the initialization.
 | 
					 | 
				
			||||||
    try {
 | 
					 | 
				
			||||||
        console.log(`Requesting OpenAI initialization with profile: ${profile}, language: ${language}`);
 | 
					 | 
				
			||||||
        const success = await ipcRenderer.invoke('initialize-openai', profile, language);
 | 
					 | 
				
			||||||
        if (success) {
 | 
					 | 
				
			||||||
            // The status will be updated via 'update-status' event from the main process.
 | 
					 | 
				
			||||||
            console.log('OpenAI initialization successful.');
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            console.error('OpenAI initialization failed.');
 | 
					 | 
				
			||||||
            const appElement = pickleGlassElement();
 | 
					 | 
				
			||||||
            if (appElement && typeof appElement.setStatus === 'function') {
 | 
					 | 
				
			||||||
                appElement.setStatus('Initialization Failed');
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    } catch (error) {
 | 
					 | 
				
			||||||
        console.error('Error during OpenAI initialization IPC call:', error);
 | 
					 | 
				
			||||||
        const appElement = pickleGlassElement();
 | 
					 | 
				
			||||||
        if (appElement && typeof appElement.setStatus === 'function') {
 | 
					 | 
				
			||||||
            appElement.setStatus('Error');
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Listen for status updates
 | 
					 | 
				
			||||||
ipcRenderer.on('update-status', (event, status) => {
 | 
					 | 
				
			||||||
    console.log('Status update:', status);
 | 
					 | 
				
			||||||
    pickleGlass.e().setStatus(status);
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Listen for real-time STT updates
 | 
					 | 
				
			||||||
ipcRenderer.on('stt-update', (event, data) => {
 | 
					 | 
				
			||||||
    console.log('Renderer.js stt-update', data);
 | 
					 | 
				
			||||||
    const { speaker, text, isFinal, isPartial, timestamp } = data;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (isPartial) {
 | 
					 | 
				
			||||||
        console.log(`🔄 [${speaker} - partial]: ${text}`);
 | 
					 | 
				
			||||||
    } else if (isFinal) {
 | 
					 | 
				
			||||||
        console.log(`✅ [${speaker} - final]: ${text}`);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        const speakerText = speaker.toLowerCase();
 | 
					 | 
				
			||||||
        const conversationText = `${speakerText}: ${text.trim()}`;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        realtimeConversationHistory.push(conversationText);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (realtimeConversationHistory.length > 30) {
 | 
					 | 
				
			||||||
            realtimeConversationHistory = realtimeConversationHistory.slice(-30);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        console.log(`📝 Updated realtime conversation history: ${realtimeConversationHistory.length} texts`);
 | 
					 | 
				
			||||||
        console.log(`📋 Latest text: ${conversationText}`);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (pickleGlass.e() && typeof pickleGlass.e().updateRealtimeTranscription === 'function') {
 | 
					 | 
				
			||||||
        pickleGlass.e().updateRealtimeTranscription({
 | 
					 | 
				
			||||||
            speaker,
 | 
					 | 
				
			||||||
            text,
 | 
					 | 
				
			||||||
            isFinal,
 | 
					 | 
				
			||||||
            isPartial,
 | 
					 | 
				
			||||||
            timestamp,
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ipcRenderer.on('update-structured-data', (_, structuredData) => {
 | 
					 | 
				
			||||||
    console.log('📥 Received structured data update:', structuredData);
 | 
					 | 
				
			||||||
    window.pickleGlass.structuredData = structuredData;
 | 
					 | 
				
			||||||
    window.pickleGlass.setStructuredData(structuredData);
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
window.pickleGlass.structuredData = {
 | 
					 | 
				
			||||||
    summary: [],
 | 
					 | 
				
			||||||
    topic: { header: '', bullets: [] },
 | 
					 | 
				
			||||||
    actions: [],
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
window.pickleGlass.setStructuredData = data => {
 | 
					 | 
				
			||||||
    window.pickleGlass.structuredData = data;
 | 
					 | 
				
			||||||
    pickleGlass.e()?.updateStructuredData?.(data);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function formatRealtimeConversationHistory() {
 | 
					 | 
				
			||||||
    if (realtimeConversationHistory.length === 0) return 'No conversation history available.';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return realtimeConversationHistory.slice(-30).join('\n');
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
window.pickleGlass = {
 | 
					window.pickleGlass = {
 | 
				
			||||||
    initializeopenai,
 | 
					 | 
				
			||||||
    startCapture: listenCapture.startCapture,
 | 
					    startCapture: listenCapture.startCapture,
 | 
				
			||||||
    stopCapture: listenCapture.stopCapture,
 | 
					    stopCapture: listenCapture.stopCapture,
 | 
				
			||||||
    isLinux: listenCapture.isLinux,
 | 
					    isLinux: listenCapture.isLinux,
 | 
				
			||||||
    isMacOS: listenCapture.isMacOS,
 | 
					    isMacOS: listenCapture.isMacOS,
 | 
				
			||||||
    captureManualScreenshot: listenCapture.captureManualScreenshot,
 | 
					    captureManualScreenshot: listenCapture.captureManualScreenshot,
 | 
				
			||||||
    getCurrentScreenshot: listenCapture.getCurrentScreenshot,
 | 
					    getCurrentScreenshot: listenCapture.getCurrentScreenshot,
 | 
				
			||||||
    e: pickleGlassElement,
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// -------------------------------------------------------
 | 
					
 | 
				
			||||||
// 🔔 React to session state changes from the main process
 | 
					ipcRenderer.on('change-listen-capture-state', (_event, { status }) => {
 | 
				
			||||||
// When the session ends (isActive === false), ensure we stop
 | 
					    if (!isListenView) {
 | 
				
			||||||
// all local capture pipelines (mic, screen, etc.).
 | 
					        console.log('[Renderer] Non-listen view: ignoring capture-state change');
 | 
				
			||||||
// -------------------------------------------------------
 | 
					        return;
 | 
				
			||||||
ipcRenderer.on('session-state-changed', (_event, { isActive }) => {
 | 
					    }
 | 
				
			||||||
    if (!isActive) {
 | 
					    if (status === "stop") {
 | 
				
			||||||
        console.log('[Renderer] Session ended – stopping local capture');
 | 
					        console.log('[Renderer] Session ended – stopping local capture');
 | 
				
			||||||
        listenCapture.stopCapture();
 | 
					        listenCapture.stopCapture();
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        console.log('[Renderer] New session started – clearing in-memory history and summaries');
 | 
					        console.log('[Renderer] Session initialized – starting local capture');
 | 
				
			||||||
 | 
					        listenCapture.startCapture();
 | 
				
			||||||
        // Reset live conversation & analysis caches
 | 
					 | 
				
			||||||
        realtimeConversationHistory = [];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        const blankData = {
 | 
					 | 
				
			||||||
            summary: [],
 | 
					 | 
				
			||||||
            topic: { header: '', bullets: [] },
 | 
					 | 
				
			||||||
            actions: [],
 | 
					 | 
				
			||||||
            followUps: [],
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
        window.pickleGlass.setStructuredData(blankData);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
				
			|||||||
@ -264,7 +264,7 @@ export class SummaryView extends LitElement {
 | 
				
			|||||||
        super.connectedCallback();
 | 
					        super.connectedCallback();
 | 
				
			||||||
        if (window.require) {
 | 
					        if (window.require) {
 | 
				
			||||||
            const { ipcRenderer } = window.require('electron');
 | 
					            const { ipcRenderer } = window.require('electron');
 | 
				
			||||||
            ipcRenderer.on('update-structured-data', (event, data) => {
 | 
					            ipcRenderer.on('summary-update', (event, data) => {
 | 
				
			||||||
                this.structuredData = data;
 | 
					                this.structuredData = data;
 | 
				
			||||||
                this.requestUpdate();
 | 
					                this.requestUpdate();
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
@ -275,7 +275,7 @@ export class SummaryView extends LitElement {
 | 
				
			|||||||
        super.disconnectedCallback();
 | 
					        super.disconnectedCallback();
 | 
				
			||||||
        if (window.require) {
 | 
					        if (window.require) {
 | 
				
			||||||
            const { ipcRenderer } = window.require('electron');
 | 
					            const { ipcRenderer } = window.require('electron');
 | 
				
			||||||
            ipcRenderer.removeAllListeners('update-structured-data');
 | 
					            ipcRenderer.removeAllListeners('summary-update');
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -27,23 +27,6 @@ class SummaryService {
 | 
				
			|||||||
        this.currentSessionId = sessionId;
 | 
					        this.currentSessionId = sessionId;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // async getApiKey() {
 | 
					 | 
				
			||||||
    //     const storedKey = await getStoredApiKey();
 | 
					 | 
				
			||||||
    //     if (storedKey) {
 | 
					 | 
				
			||||||
    //         console.log('[SummaryService] Using stored API key');
 | 
					 | 
				
			||||||
    //         return storedKey;
 | 
					 | 
				
			||||||
    //     }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    //     const envKey = process.env.OPENAI_API_KEY;
 | 
					 | 
				
			||||||
    //     if (envKey) {
 | 
					 | 
				
			||||||
    //         console.log('[SummaryService] Using environment API key');
 | 
					 | 
				
			||||||
    //         return envKey;
 | 
					 | 
				
			||||||
    //     }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    //     console.error('[SummaryService] No API key found in storage or environment');
 | 
					 | 
				
			||||||
    //     return null;
 | 
					 | 
				
			||||||
    // }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    sendToRenderer(channel, data) {
 | 
					    sendToRenderer(channel, data) {
 | 
				
			||||||
        BrowserWindow.getAllWindows().forEach(win => {
 | 
					        BrowserWindow.getAllWindows().forEach(win => {
 | 
				
			||||||
            if (!win.isDestroyed()) {
 | 
					            if (!win.isDestroyed()) {
 | 
				
			||||||
@ -327,7 +310,7 @@ Keep all points concise and build upon previous analysis if provided.`,
 | 
				
			|||||||
                .then(data => {
 | 
					                .then(data => {
 | 
				
			||||||
                    if (data) {
 | 
					                    if (data) {
 | 
				
			||||||
                        console.log('📤 Sending structured data to renderer');
 | 
					                        console.log('📤 Sending structured data to renderer');
 | 
				
			||||||
                        this.sendToRenderer('update-structured-data', data);
 | 
					                        this.sendToRenderer('summary-update', data);
 | 
				
			||||||
                        
 | 
					                        
 | 
				
			||||||
                        // Notify callback
 | 
					                        // Notify callback
 | 
				
			||||||
                        if (this.onAnalysisComplete) {
 | 
					                        if (this.onAnalysisComplete) {
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										15
									
								
								src/index.js
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								src/index.js
									
									
									
									
									
								
							@ -396,21 +396,6 @@ function setupGeneralIpcHandlers() {
 | 
				
			|||||||
    const userRepository = require('./common/repositories/user');
 | 
					    const userRepository = require('./common/repositories/user');
 | 
				
			||||||
    const presetRepository = require('./common/repositories/preset');
 | 
					    const presetRepository = require('./common/repositories/preset');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ipcMain.handle('save-api-key', (event, apiKey) => {
 | 
					 | 
				
			||||||
        try {
 | 
					 | 
				
			||||||
            // The adapter injects the UID and handles local/firebase logic.
 | 
					 | 
				
			||||||
            // Assuming a default provider if not specified.
 | 
					 | 
				
			||||||
            userRepository.saveApiKey(apiKey, 'openai');
 | 
					 | 
				
			||||||
            BrowserWindow.getAllWindows().forEach(win => {
 | 
					 | 
				
			||||||
                win.webContents.send('api-key-updated');
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
            return { success: true };
 | 
					 | 
				
			||||||
        } catch (error) {
 | 
					 | 
				
			||||||
            console.error('IPC: Failed to save API key:', error);
 | 
					 | 
				
			||||||
            return { success: false, error: error.message };
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    ipcMain.handle('get-user-presets', () => {
 | 
					    ipcMain.handle('get-user-presets', () => {
 | 
				
			||||||
        // The adapter injects the UID.
 | 
					        // The adapter injects the UID.
 | 
				
			||||||
        return presetRepository.getPresets();
 | 
					        return presetRepository.getPresets();
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user