cleaning dependency in windowmanager
This commit is contained in:
		
							parent
							
								
									698473007a
								
							
						
					
					
						commit
						f755fdb9e3
					
				@ -91,6 +91,7 @@ module.exports = {
 | 
			
		||||
    ipcMain.handle('listen:startMacosSystemAudio', async () => await listenService.handleStartMacosAudio());
 | 
			
		||||
    ipcMain.handle('listen:stopMacosSystemAudio', async () => await listenService.handleStopMacosAudio());
 | 
			
		||||
    ipcMain.handle('update-google-search-setting', async (event, enabled) => await listenService.handleUpdateGoogleSearchSetting(enabled));
 | 
			
		||||
    ipcMain.handle('listen:isSessionActive', async () => await listenService.isSessionActive());
 | 
			
		||||
    ipcMain.handle('listen:changeSession', async (event, listenButtonText) => {
 | 
			
		||||
      console.log('[FeatureBridge] listen:changeSession from mainheader', listenButtonText);
 | 
			
		||||
      try {
 | 
			
		||||
 | 
			
		||||
@ -20,7 +20,6 @@ module.exports = {
 | 
			
		||||
    ipcMain.on('header-state-changed', (event, state) => windowManager.handleHeaderStateChanged(state));
 | 
			
		||||
    ipcMain.on('header-animation-finished', (event, state) => windowManager.handleHeaderAnimationFinished(state));
 | 
			
		||||
    ipcMain.handle('get-header-position', () => windowManager.getHeaderPosition());
 | 
			
		||||
    ipcMain.handle('move-header', (event, newX, newY) => windowManager.moveHeader(newX, newY));
 | 
			
		||||
    ipcMain.handle('move-header-to', (event, newX, newY) => windowManager.moveHeaderTo(newX, newY));
 | 
			
		||||
    ipcMain.handle('adjust-window-height', (event, targetHeight) => windowManager.adjustWindowHeight(event.sender, targetHeight));
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
@ -54,53 +54,7 @@ class ListenService {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async handleListenRequest(listenButtonText) {
 | 
			
		||||
        const { windowPool, updateLayout } = require('../../window/windowManager');
 | 
			
		||||
        const listenWindow = windowPool.get('listen');
 | 
			
		||||
        const header = windowPool.get('header');
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            switch (listenButtonText) {
 | 
			
		||||
                case 'Listen':
 | 
			
		||||
                    console.log('[ListenService] changeSession to "Listen"');
 | 
			
		||||
                    listenWindow.show();
 | 
			
		||||
                    updateLayout();
 | 
			
		||||
                    listenWindow.webContents.send('window-show-animation');
 | 
			
		||||
                    await this.initializeSession();
 | 
			
		||||
                    listenWindow.webContents.send('session-state-changed', { isActive: true });
 | 
			
		||||
                    break;
 | 
			
		||||
        
 | 
			
		||||
                case 'Stop':
 | 
			
		||||
                    console.log('[ListenService] changeSession to "Stop"');
 | 
			
		||||
                    await this.closeSession();
 | 
			
		||||
                    listenWindow.webContents.send('session-state-changed', { isActive: false });
 | 
			
		||||
                    break;
 | 
			
		||||
        
 | 
			
		||||
                case 'Done':
 | 
			
		||||
                    console.log('[ListenService] changeSession to "Done"');
 | 
			
		||||
                    listenWindow.webContents.send('window-hide-animation');
 | 
			
		||||
                    listenWindow.webContents.send('session-state-changed', { isActive: false });
 | 
			
		||||
                    break;
 | 
			
		||||
        
 | 
			
		||||
                default:
 | 
			
		||||
                    throw new Error(`[ListenService] unknown listenButtonText: ${listenButtonText}`);
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            header.webContents.send('listen:changeSessionResult', { success: true });
 | 
			
		||||
 | 
			
		||||
        } catch (error) {
 | 
			
		||||
            console.error('[ListenService] error in handleListenRequest:', error);
 | 
			
		||||
            header.webContents.send('listen:changeSessionResult', { success: false });
 | 
			
		||||
            throw error; 
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    initialize() {
 | 
			
		||||
        this.setupIpcHandlers();
 | 
			
		||||
        console.log('[ListenService] Initialized and ready.');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async handleListenRequest(listenButtonText) {
 | 
			
		||||
        const { windowPool, updateLayout } = require('../../window/windowManager');
 | 
			
		||||
        const { windowPool } = require('../../window/windowManager');
 | 
			
		||||
        const listenWindow = windowPool.get('listen');
 | 
			
		||||
        const header = windowPool.get('header');
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -273,7 +273,7 @@ contextBridge.exposeInMainWorld('api', {
 | 
			
		||||
    stopMacosSystemAudio: () => ipcRenderer.invoke('listen:stopMacosSystemAudio'),
 | 
			
		||||
    
 | 
			
		||||
    // Session Management
 | 
			
		||||
    isSessionActive: () => ipcRenderer.invoke('is-session-active'),
 | 
			
		||||
    isSessionActive: () => ipcRenderer.invoke('listen:isSessionActive'),
 | 
			
		||||
    
 | 
			
		||||
    // Listeners
 | 
			
		||||
    onSystemAudioData: (callback) => ipcRenderer.on('system-audio-data', callback),
 | 
			
		||||
 | 
			
		||||
@ -422,6 +422,12 @@ async function startCapture(screenshotIntervalSeconds = 5, imageQuality = 'mediu
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
        if (isMacOS) {
 | 
			
		||||
 | 
			
		||||
            const sessionActive = await window.api.listenCapture.isSessionActive();
 | 
			
		||||
            if (!sessionActive) {
 | 
			
		||||
                throw new Error('STT sessions not initialized - please wait for initialization to complete');
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // On macOS, use SystemAudioDump for audio and getDisplayMedia for screen
 | 
			
		||||
            console.log('Starting macOS capture with SystemAudioDump...');
 | 
			
		||||
 | 
			
		||||
@ -466,6 +472,12 @@ async function startCapture(screenshotIntervalSeconds = 5, imageQuality = 'mediu
 | 
			
		||||
 | 
			
		||||
            console.log('macOS screen capture started - audio handled by SystemAudioDump');
 | 
			
		||||
        } else if (isLinux) {
 | 
			
		||||
 | 
			
		||||
            const sessionActive = await window.api.listenCapture.isSessionActive();
 | 
			
		||||
            if (!sessionActive) {
 | 
			
		||||
                throw new Error('STT sessions not initialized - please wait for initialization to complete');
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            // Linux - use display media for screen capture and getUserMedia for microphone
 | 
			
		||||
            mediaStream = await navigator.mediaDevices.getDisplayMedia({
 | 
			
		||||
                video: {
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,27 @@
 | 
			
		||||
const { screen } = require('electron');
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function getCurrentDisplay(window) {
 | 
			
		||||
    if (!window || window.isDestroyed()) return screen.getPrimaryDisplay();
 | 
			
		||||
 | 
			
		||||
    const windowBounds = window.getBounds();
 | 
			
		||||
    const windowCenter = {
 | 
			
		||||
        x: windowBounds.x + windowBounds.width / 2,
 | 
			
		||||
        y: windowBounds.y + windowBounds.height / 2,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    return screen.getDisplayNearestPoint(windowCenter);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getDisplayById(displayId) {
 | 
			
		||||
    const displays = screen.getAllDisplays();
 | 
			
		||||
    return displays.find(d => d.id === displayId) || screen.getPrimaryDisplay();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class SmoothMovementManager {
 | 
			
		||||
    constructor(windowPool, getDisplayById, getCurrentDisplay, updateLayout) {
 | 
			
		||||
    constructor(windowPool, layoutManager) {
 | 
			
		||||
        this.windowPool = windowPool;
 | 
			
		||||
        this.getDisplayById = getDisplayById;
 | 
			
		||||
        this.getCurrentDisplay = getCurrentDisplay;
 | 
			
		||||
        this.updateLayout = updateLayout;
 | 
			
		||||
        this.layoutManager = layoutManager;
 | 
			
		||||
        this.stepSize = 80;
 | 
			
		||||
        this.animationDuration = 300;
 | 
			
		||||
        this.headerPosition = { x: 0, y: 0 };
 | 
			
		||||
@ -39,11 +55,11 @@ class SmoothMovementManager {
 | 
			
		||||
        const header = this.windowPool.get('header');
 | 
			
		||||
        if (!this._isWindowValid(header) || !header.isVisible() || this.isAnimating) return;
 | 
			
		||||
 | 
			
		||||
        const targetDisplay = this.getDisplayById(displayId);
 | 
			
		||||
        const targetDisplay = getDisplayById(displayId);
 | 
			
		||||
        if (!targetDisplay) return;
 | 
			
		||||
 | 
			
		||||
        const currentBounds = header.getBounds();
 | 
			
		||||
        const currentDisplay = this.getCurrentDisplay(header);
 | 
			
		||||
        const currentDisplay = getCurrentDisplay(header);
 | 
			
		||||
 | 
			
		||||
        if (currentDisplay.id === targetDisplay.id) return;
 | 
			
		||||
 | 
			
		||||
@ -60,56 +76,6 @@ class SmoothMovementManager {
 | 
			
		||||
        this.currentDisplayId = targetDisplay.id;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    hideToEdge(edge, callback, { instant = false } = {}) {
 | 
			
		||||
        const header = this.windowPool.get('header');
 | 
			
		||||
        if (!header || header.isDestroyed()) {
 | 
			
		||||
            if (typeof callback === 'function') callback();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
      
 | 
			
		||||
        const { x, y } = header.getBounds();
 | 
			
		||||
        this.lastVisiblePosition = { x, y };
 | 
			
		||||
        this.hiddenPosition     = { edge };
 | 
			
		||||
      
 | 
			
		||||
        if (instant) {
 | 
			
		||||
            header.hide();
 | 
			
		||||
            if (typeof callback === 'function') callback();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        header.webContents.send('window-hide-animation');
 | 
			
		||||
      
 | 
			
		||||
        setTimeout(() => {
 | 
			
		||||
            if (!header.isDestroyed()) header.hide();
 | 
			
		||||
            if (typeof callback === 'function') callback();
 | 
			
		||||
        }, 5);
 | 
			
		||||
    }
 | 
			
		||||
      
 | 
			
		||||
    showFromEdge(callback) {
 | 
			
		||||
        const header = this.windowPool.get('header');
 | 
			
		||||
        if (!header || header.isDestroyed()) {
 | 
			
		||||
            if (typeof callback === 'function') callback();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
      
 | 
			
		||||
        // 숨기기 전에 기억해둔 위치 복구
 | 
			
		||||
        if (this.lastVisiblePosition) {
 | 
			
		||||
            header.setPosition(
 | 
			
		||||
                this.lastVisiblePosition.x,
 | 
			
		||||
                this.lastVisiblePosition.y,
 | 
			
		||||
                false   // animate: false
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
      
 | 
			
		||||
        header.show();
 | 
			
		||||
        header.webContents.send('window-show-animation');
 | 
			
		||||
      
 | 
			
		||||
        // 내부 상태 초기화
 | 
			
		||||
        this.hiddenPosition      = null;
 | 
			
		||||
        this.lastVisiblePosition = null;
 | 
			
		||||
      
 | 
			
		||||
        if (typeof callback === 'function') callback();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    moveStep(direction) {
 | 
			
		||||
        const header = this.windowPool.get('header');
 | 
			
		||||
@ -211,7 +177,7 @@ class SmoothMovementManager {
 | 
			
		||||
                setTimeout(step, 8); // requestAnimationFrame 대신 setTimeout으로 간결하게 처리
 | 
			
		||||
            } else {
 | 
			
		||||
                // 애니메이션 종료
 | 
			
		||||
                this.updateLayout(); // 레이아웃 재정렬
 | 
			
		||||
                this.layoutManager.updateLayout(); // 레이아웃 재정렬
 | 
			
		||||
                if (onComplete) {
 | 
			
		||||
                    onComplete(); // 완료 콜백 실행
 | 
			
		||||
                }
 | 
			
		||||
@ -267,7 +233,7 @@ class SmoothMovementManager {
 | 
			
		||||
                    // Update header position to the actual final position
 | 
			
		||||
                    this.headerPosition = { x: Math.round(targetX), y: Math.round(targetY) };
 | 
			
		||||
                }
 | 
			
		||||
                this.updateLayout();
 | 
			
		||||
                this.layoutManager.updateLayout();
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
        animate();
 | 
			
		||||
@ -277,7 +243,7 @@ class SmoothMovementManager {
 | 
			
		||||
        const header = this.windowPool.get('header');
 | 
			
		||||
        if (!this._isWindowValid(header) || !header.isVisible() || this.isAnimating) return;
 | 
			
		||||
 | 
			
		||||
        const display = this.getCurrentDisplay(header);
 | 
			
		||||
        const display = getCurrentDisplay(header);
 | 
			
		||||
        const { width, height } = display.workAreaSize;
 | 
			
		||||
        const { x: workAreaX, y: workAreaY } = display.workArea;
 | 
			
		||||
        const currentBounds = header.getBounds();
 | 
			
		||||
@ -313,7 +279,7 @@ class SmoothMovementManager {
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this.headerPosition = { x: targetX, y: targetY };
 | 
			
		||||
        this.updateLayout();
 | 
			
		||||
        this.layoutManager.updateLayout();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    destroy() {
 | 
			
		||||
 | 
			
		||||
@ -37,6 +37,110 @@ class WindowLayoutManager {
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    getHeaderPosition = () => {
 | 
			
		||||
        const header = this.windowPool.get('header');
 | 
			
		||||
        if (header) {
 | 
			
		||||
            const [x, y] = header.getPosition();
 | 
			
		||||
            return { x, y };
 | 
			
		||||
        }
 | 
			
		||||
        return { x: 0, y: 0 };
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    resizeHeaderWindow = ({ width, height }) => {
 | 
			
		||||
        const header = this.windowPool.get('header');
 | 
			
		||||
        if (header) {
 | 
			
		||||
          console.log(`[WindowManager] Resize request: ${width}x${height}`);
 | 
			
		||||
    
 | 
			
		||||
          const currentBounds = header.getBounds();
 | 
			
		||||
          console.log(`[WindowManager] Current bounds: ${currentBounds.width}x${currentBounds.height} at (${currentBounds.x}, ${currentBounds.y})`);
 | 
			
		||||
          
 | 
			
		||||
          if (currentBounds.width === width && currentBounds.height === height) {
 | 
			
		||||
            console.log('[WindowManager] Already at target size, skipping resize');
 | 
			
		||||
            return { success: true };
 | 
			
		||||
          }
 | 
			
		||||
    
 | 
			
		||||
          const wasResizable = header.isResizable();
 | 
			
		||||
          if (!wasResizable) {
 | 
			
		||||
            header.setResizable(true);
 | 
			
		||||
          }
 | 
			
		||||
    
 | 
			
		||||
          const centerX = currentBounds.x + currentBounds.width / 2;
 | 
			
		||||
          const newX = Math.round(centerX - width / 2);
 | 
			
		||||
    
 | 
			
		||||
          const display = getCurrentDisplay(header);
 | 
			
		||||
          const { x: workAreaX, width: workAreaWidth } = display.workArea;
 | 
			
		||||
          
 | 
			
		||||
          const clampedX = Math.max(workAreaX, Math.min(workAreaX + workAreaWidth - width, newX));
 | 
			
		||||
    
 | 
			
		||||
          header.setBounds({ x: clampedX, y: currentBounds.y, width, height });
 | 
			
		||||
    
 | 
			
		||||
          if (!wasResizable) {
 | 
			
		||||
            header.setResizable(false);
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          this.updateLayout();
 | 
			
		||||
          
 | 
			
		||||
          return { success: true };
 | 
			
		||||
        }
 | 
			
		||||
        return { success: false, error: 'Header window not found' };
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    moveHeaderTo = (newX, newY) => {
 | 
			
		||||
        const header = this.windowPool.get('header');
 | 
			
		||||
        if (header) {
 | 
			
		||||
            const targetDisplay = screen.getDisplayNearestPoint({ x: newX, y: newY });
 | 
			
		||||
            const { x: workAreaX, y: workAreaY, width, height } = targetDisplay.workArea;
 | 
			
		||||
            const headerBounds = header.getBounds();
 | 
			
		||||
    
 | 
			
		||||
            let clampedX = newX;
 | 
			
		||||
            let clampedY = newY;
 | 
			
		||||
            
 | 
			
		||||
            if (newX < workAreaX) {
 | 
			
		||||
                clampedX = workAreaX;
 | 
			
		||||
            } else if (newX + headerBounds.width > workAreaX + width) {
 | 
			
		||||
                clampedX = workAreaX + width - headerBounds.width;
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            if (newY < workAreaY) {
 | 
			
		||||
                clampedY = workAreaY;
 | 
			
		||||
            } else if (newY + headerBounds.height > workAreaY + height) {
 | 
			
		||||
                clampedY = workAreaY + height - headerBounds.height;
 | 
			
		||||
            }
 | 
			
		||||
    
 | 
			
		||||
            header.setPosition(clampedX, clampedY, false);
 | 
			
		||||
            this.updateLayout();
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    adjustWindowHeight = (sender, targetHeight) => {
 | 
			
		||||
        const senderWindow = this.windowPool.get(sender);
 | 
			
		||||
        if (senderWindow) {
 | 
			
		||||
            const wasResizable = senderWindow.isResizable();
 | 
			
		||||
            if (!wasResizable) {
 | 
			
		||||
                senderWindow.setResizable(true);
 | 
			
		||||
            }
 | 
			
		||||
    
 | 
			
		||||
            const currentBounds = senderWindow.getBounds();
 | 
			
		||||
            const minHeight = senderWindow.getMinimumSize()[1];
 | 
			
		||||
            const maxHeight = senderWindow.getMaximumSize()[1];
 | 
			
		||||
            
 | 
			
		||||
            let adjustedHeight;
 | 
			
		||||
            if (maxHeight === 0) {
 | 
			
		||||
                adjustedHeight = Math.max(minHeight, targetHeight);
 | 
			
		||||
            } else {
 | 
			
		||||
                adjustedHeight = Math.max(minHeight, Math.min(maxHeight, targetHeight));
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            senderWindow.setSize(currentBounds.width, adjustedHeight, false);
 | 
			
		||||
    
 | 
			
		||||
            if (!wasResizable) {
 | 
			
		||||
                senderWindow.setResizable(false);
 | 
			
		||||
            }
 | 
			
		||||
    
 | 
			
		||||
            this.updateLayout();
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @param {object} [visibilityOverride] - { listen: true, ask: true }
 | 
			
		||||
 | 
			
		||||
@ -38,11 +38,6 @@ let settingsHideTimer = null;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
let layoutManager = null;
 | 
			
		||||
function updateLayout() {
 | 
			
		||||
    if (layoutManager) {
 | 
			
		||||
        layoutManager.updateLayout();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
let movementManager = null;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@ -92,6 +87,30 @@ const cancelHideSettingsWindow = () => {
 | 
			
		||||
    internalBridge.emit('window:requestVisibility', { name: 'settings', visible: true });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const moveWindowStep = (direction) => {
 | 
			
		||||
    internalBridge.emit('window:moveStep', { direction });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const resizeHeaderWindow = ({ width, height }) => {
 | 
			
		||||
    internalBridge.emit('window:resizeHeaderWindow', { width, height });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const handleHeaderAnimationFinished = (state) => {
 | 
			
		||||
    internalBridge.emit('window:headerAnimationFinished', state);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const getHeaderPosition = () => {
 | 
			
		||||
    internalBridge.emit('window:getHeaderPosition');
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const moveHeaderTo = (newX, newY) => {
 | 
			
		||||
    internalBridge.emit('window:moveHeaderTo', { newX, newY });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const adjustWindowHeight = (sender, targetHeight) => {
 | 
			
		||||
    internalBridge.emit('window:adjustWindowHeight', { sender, targetHeight });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function setupWindowController(windowPool, layoutManager, movementManager) {
 | 
			
		||||
    internalBridge.on('window:requestVisibility', ({ name, visible }) => {
 | 
			
		||||
@ -109,6 +128,21 @@ function setupWindowController(windowPool, layoutManager, movementManager) {
 | 
			
		||||
    internalBridge.on('window:moveStep', ({ direction }) => {
 | 
			
		||||
        movementManager.moveStep(direction);
 | 
			
		||||
    });
 | 
			
		||||
    internalBridge.on('window:resizeHeaderWindow', ({ width, height }) => {
 | 
			
		||||
        resizingHeaderWindow(layoutManager, movementManager, { width, height });
 | 
			
		||||
    });
 | 
			
		||||
    internalBridge.on('window:headerAnimationFinished', (state) => {
 | 
			
		||||
        handlingHeaderAnimationFinished(windowPool, layoutManager, state);
 | 
			
		||||
    });
 | 
			
		||||
    internalBridge.on('window:getHeaderPosition', () => {
 | 
			
		||||
        gettingHeaderPosition(layoutManager);
 | 
			
		||||
    });
 | 
			
		||||
    internalBridge.on('window:moveHeaderTo', ({ newX, newY }) => {
 | 
			
		||||
        movingHeaderTo(layoutManager, newX, newY);
 | 
			
		||||
    });
 | 
			
		||||
    internalBridge.on('window:adjustWindowHeight', ({ sender, targetHeight }) => {
 | 
			
		||||
        adjustingWindowHeight(layoutManager, sender, targetHeight);
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function changeAllWindowsVisibility(windowPool, targetVisibility) {
 | 
			
		||||
@ -249,8 +283,8 @@ async function handleWindowVisibilityRequest(windowPool, layoutManager, movement
 | 
			
		||||
        const otherWin = windowPool.get(otherName);
 | 
			
		||||
        const isOtherWinVisible = otherWin && !otherWin.isDestroyed() && otherWin.isVisible();
 | 
			
		||||
 | 
			
		||||
        const ANIM_OFFSET_X = 100; 
 | 
			
		||||
        const ANIM_OFFSET_Y = 20; 
 | 
			
		||||
        const ANIM_OFFSET_X = 50; 
 | 
			
		||||
        const ANIM_OFFSET_Y = 20;
 | 
			
		||||
 | 
			
		||||
        if (shouldBeVisible) {
 | 
			
		||||
            win.setOpacity(0);
 | 
			
		||||
@ -305,7 +339,7 @@ async function handleWindowVisibilityRequest(windowPool, layoutManager, movement
 | 
			
		||||
        } else {
 | 
			
		||||
            const currentBounds = win.getBounds();
 | 
			
		||||
            fadeWindow(
 | 
			
		||||
                win, 1, 0, undefined,
 | 
			
		||||
                win, 1, 0, 250,
 | 
			
		||||
                () => win.hide()
 | 
			
		||||
            );
 | 
			
		||||
            if (name === 'listen') {
 | 
			
		||||
@ -313,7 +347,7 @@ async function handleWindowVisibilityRequest(windowPool, layoutManager, movement
 | 
			
		||||
                    const targetX = currentBounds.x - ANIM_OFFSET_X;
 | 
			
		||||
                    movementManager.animateWindow(win, targetX, currentBounds.y);
 | 
			
		||||
                } else {
 | 
			
		||||
                    const targetX = currentBounds.x - currentBounds.width;
 | 
			
		||||
                    const targetX = currentBounds.x - ANIM_OFFSET_X;
 | 
			
		||||
                    movementManager.animateWindow(win, targetX, currentBounds.y);
 | 
			
		||||
                }
 | 
			
		||||
            } else if (name === 'ask') {
 | 
			
		||||
@ -353,52 +387,6 @@ const toggleContentProtection = () => {
 | 
			
		||||
    return newStatus;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const resizeHeaderWindow = ({ width, height }) => {
 | 
			
		||||
    const header = windowPool.get('header');
 | 
			
		||||
    if (header) {
 | 
			
		||||
      console.log(`[WindowManager] Resize request: ${width}x${height}`);
 | 
			
		||||
      
 | 
			
		||||
      if (movementManager && movementManager.isAnimating) {
 | 
			
		||||
        console.log('[WindowManager] Skipping resize during animation');
 | 
			
		||||
        return { success: false, error: 'Cannot resize during animation' };
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      const currentBounds = header.getBounds();
 | 
			
		||||
      console.log(`[WindowManager] Current bounds: ${currentBounds.width}x${currentBounds.height} at (${currentBounds.x}, ${currentBounds.y})`);
 | 
			
		||||
      
 | 
			
		||||
      if (currentBounds.width === width && currentBounds.height === height) {
 | 
			
		||||
        console.log('[WindowManager] Already at target size, skipping resize');
 | 
			
		||||
        return { success: true };
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      const wasResizable = header.isResizable();
 | 
			
		||||
      if (!wasResizable) {
 | 
			
		||||
        header.setResizable(true);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      const centerX = currentBounds.x + currentBounds.width / 2;
 | 
			
		||||
      const newX = Math.round(centerX - width / 2);
 | 
			
		||||
 | 
			
		||||
      const display = getCurrentDisplay(header);
 | 
			
		||||
      const { x: workAreaX, width: workAreaWidth } = display.workArea;
 | 
			
		||||
      
 | 
			
		||||
      const clampedX = Math.max(workAreaX, Math.min(workAreaX + workAreaWidth - width, newX));
 | 
			
		||||
 | 
			
		||||
      header.setBounds({ x: clampedX, y: currentBounds.y, width, height });
 | 
			
		||||
 | 
			
		||||
      if (!wasResizable) {
 | 
			
		||||
        header.setResizable(false);
 | 
			
		||||
      }
 | 
			
		||||
      
 | 
			
		||||
      if (updateLayout) {
 | 
			
		||||
        updateLayout();
 | 
			
		||||
      }
 | 
			
		||||
      
 | 
			
		||||
      return { success: true };
 | 
			
		||||
    }
 | 
			
		||||
    return { success: false, error: 'Header window not found' };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const openLoginPage = () => {
 | 
			
		||||
    const webUrl = process.env.pickleglass_WEB_URL || 'http://localhost:3000';
 | 
			
		||||
@ -407,12 +395,6 @@ const openLoginPage = () => {
 | 
			
		||||
    console.log('Opening personalization page:', personalizeUrl);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const moveWindowStep = (direction) => {
 | 
			
		||||
    if (movementManager) {
 | 
			
		||||
        movementManager.moveStep(direction);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function createFeatureWindows(header, namesToCreate) {
 | 
			
		||||
    // if (windowPool.has('listen')) return;
 | 
			
		||||
@ -617,14 +599,6 @@ function getCurrentDisplay(window) {
 | 
			
		||||
    return screen.getDisplayNearestPoint(windowCenter);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getDisplayById(displayId) {
 | 
			
		||||
    const displays = screen.getAllDisplays();
 | 
			
		||||
    return displays.find(d => d.id === displayId) || screen.getPrimaryDisplay();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function createWindows() {
 | 
			
		||||
@ -636,8 +610,7 @@ function createWindows() {
 | 
			
		||||
 | 
			
		||||
    const initialX = Math.round((screenWidth - DEFAULT_WINDOW_WIDTH) / 2);
 | 
			
		||||
    const initialY = workAreaY + 21;
 | 
			
		||||
    movementManager = new SmoothMovementManager(windowPool, getDisplayById, getCurrentDisplay, updateLayout);
 | 
			
		||||
    
 | 
			
		||||
        
 | 
			
		||||
    const header = new BrowserWindow({
 | 
			
		||||
        width: DEFAULT_WINDOW_WIDTH,
 | 
			
		||||
        height: HEADER_HEIGHT,
 | 
			
		||||
@ -687,15 +660,17 @@ function createWindows() {
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    windowPool.set('header', header);
 | 
			
		||||
    header.on('moved', updateLayout);
 | 
			
		||||
    layoutManager = new WindowLayoutManager(windowPool);
 | 
			
		||||
    movementManager = new SmoothMovementManager(windowPool, layoutManager);
 | 
			
		||||
 | 
			
		||||
    header.on('moved', () => layoutManager.updateLayout());
 | 
			
		||||
 | 
			
		||||
    header.webContents.once('dom-ready', () => {
 | 
			
		||||
        shortcutsService.initialize(windowPool);
 | 
			
		||||
        shortcutsService.registerShortcuts();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    setupIpcHandlers(movementManager);
 | 
			
		||||
    setupIpcHandlers(movementManager, layoutManager);
 | 
			
		||||
    setupWindowController(windowPool, layoutManager, movementManager);
 | 
			
		||||
 | 
			
		||||
    if (currentHeaderState === 'main') {
 | 
			
		||||
@ -729,13 +704,13 @@ function createWindows() {
 | 
			
		||||
 | 
			
		||||
    header.on('resize', () => {
 | 
			
		||||
        console.log('[WindowManager] Header resize event triggered');
 | 
			
		||||
        updateLayout();
 | 
			
		||||
        layoutManager.updateLayout();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    return windowPool;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function setupIpcHandlers(movementManager) {
 | 
			
		||||
function setupIpcHandlers(movementManager, layoutManager) {
 | 
			
		||||
    // quit-application handler moved to windowBridge.js to avoid duplication
 | 
			
		||||
    screen.on('display-added', (event, newDisplay) => {
 | 
			
		||||
        console.log('[Display] New display added:', newDisplay.id);
 | 
			
		||||
@ -752,10 +727,11 @@ function setupIpcHandlers(movementManager) {
 | 
			
		||||
 | 
			
		||||
    screen.on('display-metrics-changed', (event, display, changedMetrics) => {
 | 
			
		||||
        // console.log('[Display] Display metrics changed:', display.id, changedMetrics);
 | 
			
		||||
        updateLayout();
 | 
			
		||||
        layoutManager.updateLayout();
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const handleHeaderStateChanged = (state) => {
 | 
			
		||||
    console.log(`[WindowManager] Header state changed to: ${state}`);
 | 
			
		||||
    currentHeaderState = state;
 | 
			
		||||
@ -768,7 +744,17 @@ const handleHeaderStateChanged = (state) => {
 | 
			
		||||
    internalBridge.emit('reregister-shortcuts');
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const handleHeaderAnimationFinished = (state) => {
 | 
			
		||||
 | 
			
		||||
const resizingHeaderWindow = (layoutManager, movementManager, { width, height }) => {
 | 
			
		||||
    if (movementManager.isAnimating) {
 | 
			
		||||
        console.log('[WindowManager] Skipping resize during animation');
 | 
			
		||||
        return { success: false, error: 'Cannot resize during animation' };
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
    return layoutManager.resizeHeaderWindow({ width, height });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const handlingHeaderAnimationFinished = (windowPool, layoutManager, state) => {
 | 
			
		||||
    const header = windowPool.get('header');
 | 
			
		||||
    if (!header || header.isDestroyed()) return;
 | 
			
		||||
 | 
			
		||||
@ -777,87 +763,24 @@ const handleHeaderAnimationFinished = (state) => {
 | 
			
		||||
        console.log('[WindowManager] Header hidden after animation.');
 | 
			
		||||
    } else if (state === 'visible') {
 | 
			
		||||
        console.log('[WindowManager] Header shown after animation.');
 | 
			
		||||
        updateLayout();
 | 
			
		||||
        layoutManager.updateLayout();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const getHeaderPosition = () => {
 | 
			
		||||
    const header = windowPool.get('header');
 | 
			
		||||
    if (header) {
 | 
			
		||||
        const [x, y] = header.getPosition();
 | 
			
		||||
        return { x, y };
 | 
			
		||||
    }
 | 
			
		||||
    return { x: 0, y: 0 };
 | 
			
		||||
const gettingHeaderPosition = (layoutManager) => {
 | 
			
		||||
    return layoutManager.getHeaderPosition();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const moveHeader = (newX, newY) => {
 | 
			
		||||
    const header = windowPool.get('header');
 | 
			
		||||
    if (header) {
 | 
			
		||||
        const currentY = newY !== undefined ? newY : header.getBounds().y;
 | 
			
		||||
        header.setPosition(newX, currentY, false);
 | 
			
		||||
        updateLayout();
 | 
			
		||||
    }
 | 
			
		||||
const movingHeaderTo = (layoutManager, newX, newY) => {
 | 
			
		||||
    layoutManager.moveHeaderTo(newX, newY);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const moveHeaderTo = (newX, newY) => {
 | 
			
		||||
    const header = windowPool.get('header');
 | 
			
		||||
    if (header) {
 | 
			
		||||
        const targetDisplay = screen.getDisplayNearestPoint({ x: newX, y: newY });
 | 
			
		||||
        const { x: workAreaX, y: workAreaY, width, height } = targetDisplay.workArea;
 | 
			
		||||
        const headerBounds = header.getBounds();
 | 
			
		||||
 | 
			
		||||
        let clampedX = newX;
 | 
			
		||||
        let clampedY = newY;
 | 
			
		||||
        
 | 
			
		||||
        if (newX < workAreaX) {
 | 
			
		||||
            clampedX = workAreaX;
 | 
			
		||||
        } else if (newX + headerBounds.width > workAreaX + width) {
 | 
			
		||||
            clampedX = workAreaX + width - headerBounds.width;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        if (newY < workAreaY) {
 | 
			
		||||
            clampedY = workAreaY;
 | 
			
		||||
        } else if (newY + headerBounds.height > workAreaY + height) {
 | 
			
		||||
            clampedY = workAreaY + height - headerBounds.height;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        header.setPosition(clampedX, clampedY, false);
 | 
			
		||||
        updateLayout();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const adjustWindowHeight = (sender, targetHeight) => {
 | 
			
		||||
    const senderWindow = BrowserWindow.fromWebContents(sender);
 | 
			
		||||
    if (senderWindow) {
 | 
			
		||||
        const wasResizable = senderWindow.isResizable();
 | 
			
		||||
        if (!wasResizable) {
 | 
			
		||||
            senderWindow.setResizable(true);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const currentBounds = senderWindow.getBounds();
 | 
			
		||||
        const minHeight = senderWindow.getMinimumSize()[1];
 | 
			
		||||
        const maxHeight = senderWindow.getMaximumSize()[1];
 | 
			
		||||
        
 | 
			
		||||
        let adjustedHeight;
 | 
			
		||||
        if (maxHeight === 0) {
 | 
			
		||||
            adjustedHeight = Math.max(minHeight, targetHeight);
 | 
			
		||||
        } else {
 | 
			
		||||
            adjustedHeight = Math.max(minHeight, Math.min(maxHeight, targetHeight));
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        senderWindow.setSize(currentBounds.width, adjustedHeight, false);
 | 
			
		||||
 | 
			
		||||
        if (!wasResizable) {
 | 
			
		||||
            senderWindow.setResizable(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        updateLayout();
 | 
			
		||||
    }
 | 
			
		||||
const adjustingWindowHeight = (layoutManager, sender, targetHeight) => {
 | 
			
		||||
    layoutManager.adjustWindowHeight(sender, targetHeight);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
    updateLayout,
 | 
			
		||||
    createWindows,
 | 
			
		||||
    windowPool,
 | 
			
		||||
    toggleContentProtection,
 | 
			
		||||
@ -871,7 +794,6 @@ module.exports = {
 | 
			
		||||
    handleHeaderStateChanged,
 | 
			
		||||
    handleHeaderAnimationFinished,
 | 
			
		||||
    getHeaderPosition,
 | 
			
		||||
    moveHeader,
 | 
			
		||||
    moveHeaderTo,
 | 
			
		||||
    adjustWindowHeight,
 | 
			
		||||
};
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user