shortcut moved
This commit is contained in:
parent
6d708d6dcd
commit
73a6e1345e
2
aec
2
aec
@ -1 +1 @@
|
||||
Subproject commit 9e11f4f95707714464194bdfc9db0222ec5c6163
|
||||
Subproject commit f00bb1fb948053c752b916adfee19f90644a0b2f
|
19
docs/refactor-plan.md
Normal file
19
docs/refactor-plan.md
Normal file
@ -0,0 +1,19 @@
|
||||
# Refactor Plan: Non-Window Logic Migration from windowManager.js
|
||||
|
||||
## Goal
|
||||
`windowManager.js`를 순수 창 관리 모듈로 만들기 위해 비즈니스 로직을 해당 서비스와 `featureBridge.js`로 이전.
|
||||
|
||||
## Steps (based on initial plan)
|
||||
1. **Shortcuts**: Completed. Logic moved to `shortcutsService.js` and IPC to `featureBridge.js`. Used `internalBridge` for coordination.
|
||||
|
||||
2. **Screenshot**: Next. Move `captureScreenshot` function and related IPC handlers from `windowManager.js` to `askService.js` (since it's primarily used there). Update `askService.js` to use its own screenshot method. Add IPC handlers to `featureBridge.js` if needed.
|
||||
|
||||
3. **System Permissions**: Create new `permissionService.js` in `src/features/common/services/`. Move all permission-related logic (check, request, open preferences, mark completed, etc.) and IPC handlers from `windowManager.js` to the new service and `featureBridge.js`.
|
||||
|
||||
4. **API Key / Model State**: Completely remove from `windowManager.js` (e.g., `setupApiKeyIPC` and helpers). Ensure all usages (e.g., in `askService.js`) directly require and use `modelStateService.js` instead.
|
||||
|
||||
## Notes
|
||||
- Maintain original logic without changes.
|
||||
- Break circular dependencies if found.
|
||||
- Use `internalBridge` for inter-module communication where appropriate.
|
||||
- After each step, verify no errors and test functionality.
|
@ -5,6 +5,7 @@ const authService = require('../features/common/services/authService');
|
||||
const whisperService = require('../features/common/services/whisperService');
|
||||
const ollamaService = require('../features/common/services/ollamaService');
|
||||
const modelStateService = require('../features/common/services/modelStateService');
|
||||
const shortcutsService = require('../features/shortcuts/shortcutsService');
|
||||
|
||||
const askService = require('../features/ask/askService');
|
||||
const listenService = require('../features/listen/listenService');
|
||||
@ -26,6 +27,12 @@ module.exports = {
|
||||
ipcMain.handle('settings:ensure-ollama-ready', async () => await settingsService.ensureOllamaReady());
|
||||
ipcMain.handle('settings:shutdown-ollama', async () => await settingsService.shutdownOllama());
|
||||
|
||||
// Shortcuts
|
||||
ipcMain.handle('get-current-shortcuts', async () => await shortcutsService.loadKeybinds());
|
||||
ipcMain.handle('get-default-shortcuts', async () => await shortcutsService.handleRestoreDefaults());
|
||||
ipcMain.handle('save-shortcuts', async (event, newKeybinds) => await shortcutsService.handleSaveShortcuts(newKeybinds));
|
||||
|
||||
|
||||
// User/Auth
|
||||
ipcMain.handle('get-current-user', () => authService.getCurrentUser());
|
||||
ipcMain.handle('start-firebase-auth', async () => await authService.startFirebaseAuthFlow());
|
||||
|
@ -2,9 +2,10 @@
|
||||
const { EventEmitter } = require('events');
|
||||
|
||||
// FeatureCore와 WindowCore를 잇는 내부 이벤트 버스
|
||||
module.exports = new EventEmitter();
|
||||
const internalBridge = new EventEmitter();
|
||||
module.exports = internalBridge;
|
||||
|
||||
// 예시 이벤트
|
||||
internalBridge.on('content-protection-changed', (enabled) => {
|
||||
// windowManager에서 처리
|
||||
});
|
||||
// internalBridge.on('content-protection-changed', (enabled) => {
|
||||
// // windowManager에서 처리
|
||||
// });
|
@ -1,159 +1,23 @@
|
||||
// src/bridge/windowBridge.js
|
||||
const { ipcMain, BrowserWindow, globalShortcut } = require('electron');
|
||||
const { ipcMain } = require('electron');
|
||||
const windowManager = require('../window/windowManager');
|
||||
|
||||
module.exports = {
|
||||
// windowManager에서 필요한 변수들을 매개변수로 받도록 수정
|
||||
initialize(windowPool, app, shell, getCurrentDisplay, createFeatureWindows, movementManager, getContentProtectionStatus, setContentProtection, updateLayout) {
|
||||
let settingsHideTimer = null;
|
||||
initialize() {
|
||||
ipcMain.handle('toggle-content-protection', () => windowManager.toggleContentProtection());
|
||||
ipcMain.handle('resize-header-window', (event, args) => windowManager.resizeHeaderWindow(args));
|
||||
ipcMain.handle('get-content-protection-status', () => windowManager.getContentProtectionStatus());
|
||||
ipcMain.handle('open-shortcut-editor', () => windowManager.openShortcutEditor());
|
||||
ipcMain.on('show-settings-window', (event, bounds) => windowManager.showSettingsWindow(bounds));
|
||||
ipcMain.on('hide-settings-window', () => windowManager.hideSettingsWindow());
|
||||
ipcMain.on('cancel-hide-settings-window', () => windowManager.cancelHideSettingsWindow());
|
||||
ipcMain.handle('open-login-page', () => windowManager.openLoginPage());
|
||||
ipcMain.handle('move-window-step', (event, direction) => windowManager.moveWindowStep(direction));
|
||||
ipcMain.on('close-shortcut-editor', () => windowManager.closeWindow('shortcut-settings'));
|
||||
|
||||
// 기존
|
||||
ipcMain.on('window:hide', (e) => BrowserWindow.fromWebContents(e.sender)?.hide());
|
||||
|
||||
// windowManager 관련 추가
|
||||
ipcMain.handle('toggle-content-protection', () => {
|
||||
// windowManager의 toggle-content-protection 로직
|
||||
const newStatus = !getContentProtectionStatus();
|
||||
setContentProtection(newStatus);
|
||||
return newStatus;
|
||||
});
|
||||
|
||||
|
||||
ipcMain.handle('resize-header-window', (event, { width, height }) => {
|
||||
const header = windowPool.get('header');
|
||||
if (header) {
|
||||
console.log(`[WindowBridge] Resize request: ${width}x${height}`);
|
||||
|
||||
// Prevent resizing during animations or if already at target size
|
||||
if (movementManager && movementManager.isAnimating) {
|
||||
console.log('[WindowBridge] Skipping resize during animation');
|
||||
return { success: false, error: 'Cannot resize during animation' };
|
||||
}
|
||||
|
||||
const currentBounds = header.getBounds();
|
||||
console.log(`[WindowBridge] Current bounds: ${currentBounds.width}x${currentBounds.height} at (${currentBounds.x}, ${currentBounds.y})`);
|
||||
|
||||
// Skip if already at target size to prevent unnecessary operations
|
||||
if (currentBounds.width === width && currentBounds.height === height) {
|
||||
console.log('[WindowBridge] Already at target size, skipping resize');
|
||||
return { success: true };
|
||||
}
|
||||
|
||||
const wasResizable = header.isResizable();
|
||||
if (!wasResizable) {
|
||||
header.setResizable(true);
|
||||
}
|
||||
|
||||
// Calculate the center point of the current window
|
||||
const centerX = currentBounds.x + currentBounds.width / 2;
|
||||
// Calculate new X position to keep the window centered
|
||||
const newX = Math.round(centerX - width / 2);
|
||||
|
||||
// Get the current display to ensure we stay within bounds
|
||||
const display = getCurrentDisplay(header);
|
||||
const { x: workAreaX, width: workAreaWidth } = display.workArea;
|
||||
|
||||
// Clamp the new position to stay within display bounds
|
||||
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);
|
||||
}
|
||||
|
||||
// Update layout after resize
|
||||
if (updateLayout) {
|
||||
updateLayout();
|
||||
}
|
||||
|
||||
return { success: true };
|
||||
}
|
||||
return { success: false, error: 'Header window not found' };
|
||||
});
|
||||
|
||||
ipcMain.handle('get-content-protection-status', () => {
|
||||
return getContentProtectionStatus();
|
||||
});
|
||||
|
||||
ipcMain.handle('open-shortcut-editor', () => {
|
||||
// open-shortcut-editor 로직
|
||||
const header = windowPool.get('header');
|
||||
if (!header) return;
|
||||
globalShortcut.unregisterAll();
|
||||
createFeatureWindows(header, 'shortcut-settings');
|
||||
});
|
||||
|
||||
|
||||
// 추가: show-settings-window
|
||||
ipcMain.on('show-settings-window', (event, bounds) => {
|
||||
if (!bounds) return;
|
||||
const win = windowPool.get('settings');
|
||||
if (win && !win.isDestroyed()) {
|
||||
if (settingsHideTimer) {
|
||||
clearTimeout(settingsHideTimer);
|
||||
settingsHideTimer = null;
|
||||
}
|
||||
// 위치 조정 로직
|
||||
const header = windowPool.get('header');
|
||||
const headerBounds = header?.getBounds() ?? { x: 0, y: 0 };
|
||||
const settingsBounds = win.getBounds();
|
||||
const disp = getCurrentDisplay(header);
|
||||
const { x: waX, y: waY, width: waW, height: waH } = disp.workArea;
|
||||
let x = Math.round(headerBounds.x + (bounds?.x ?? 0) + (bounds?.width ?? 0) / 2 - settingsBounds.width / 2);
|
||||
let y = Math.round(headerBounds.y + (bounds?.y ?? 0) + (bounds?.height ?? 0) + 31);
|
||||
x = Math.max(waX + 10, Math.min(waX + waW - settingsBounds.width - 10, x));
|
||||
y = Math.max(waY + 10, Math.min(waY + waH - settingsBounds.height - 10, y));
|
||||
win.setBounds({ x, y });
|
||||
win.__lockedByButton = true;
|
||||
win.show();
|
||||
win.moveTop();
|
||||
win.setAlwaysOnTop(true);
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.on('hide-settings-window', (event) => {
|
||||
const window = windowPool.get("settings");
|
||||
if (window && !window.isDestroyed()) {
|
||||
if (settingsHideTimer) {
|
||||
clearTimeout(settingsHideTimer);
|
||||
}
|
||||
settingsHideTimer = setTimeout(() => {
|
||||
if (window && !window.isDestroyed()) {
|
||||
window.setAlwaysOnTop(false);
|
||||
window.hide();
|
||||
}
|
||||
settingsHideTimer = null;
|
||||
}, 200);
|
||||
|
||||
window.__lockedByButton = false;
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.on('cancel-hide-settings-window', (event) => {
|
||||
if (settingsHideTimer) {
|
||||
clearTimeout(settingsHideTimer);
|
||||
settingsHideTimer = null;
|
||||
}
|
||||
});
|
||||
|
||||
// 로그인 페이지 열기
|
||||
ipcMain.handle('open-personalize-page', () => {
|
||||
const webUrl = process.env.pickleglass_WEB_URL || 'http://localhost:3000';
|
||||
const personalizeUrl = `${webUrl}/personalize?desktop=true`;
|
||||
shell.openExternal(personalizeUrl);
|
||||
console.log('Opening personalization page:', personalizeUrl);
|
||||
});
|
||||
|
||||
// 윈도우 이동
|
||||
ipcMain.handle('move-window-step', (event, direction) => {
|
||||
if (movementManager) {
|
||||
movementManager.moveStep(direction);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// Renderer로 상태를 전송
|
||||
notifyFocusChange(win, isFocused) {
|
||||
win.webContents.send('window:focus-change', isFocused);
|
||||
},
|
||||
}
|
||||
};
|
@ -1,11 +1,24 @@
|
||||
const { globalShortcut, screen } = require('electron');
|
||||
const shortcutsRepository = require('./repositories');
|
||||
const internalBridge = require('../../bridge/internalBridge');
|
||||
|
||||
|
||||
class ShortcutsService {
|
||||
constructor() {
|
||||
this.lastVisibleWindows = new Set(['header']);
|
||||
this.mouseEventsIgnored = false;
|
||||
this.movementManager = null;
|
||||
this.windowPool = null;
|
||||
}
|
||||
|
||||
initialize(movementManager, windowPool) {
|
||||
this.movementManager = movementManager;
|
||||
this.windowPool = windowPool;
|
||||
internalBridge.on('reregister-shortcuts', () => {
|
||||
console.log('[ShortcutsService] Reregistering shortcuts due to header state change.');
|
||||
this.registerShortcuts();
|
||||
});
|
||||
console.log('[ShortcutsService] Initialized with dependencies and event listener.');
|
||||
}
|
||||
|
||||
getDefaultKeybinds() {
|
||||
@ -58,6 +71,32 @@ class ShortcutsService {
|
||||
return keybinds;
|
||||
}
|
||||
|
||||
async handleSaveShortcuts(newKeybinds) {
|
||||
try {
|
||||
await this.saveKeybinds(newKeybinds);
|
||||
const shortcutEditor = this.windowPool.get('shortcut-settings');
|
||||
if (shortcutEditor && !shortcutEditor.isDestroyed()) {
|
||||
shortcutEditor.close(); // This will trigger re-registration on 'closed' event in windowManager
|
||||
} else {
|
||||
// If editor wasn't open, re-register immediately
|
||||
await this.registerShortcuts();
|
||||
}
|
||||
return { success: true };
|
||||
} catch (error) {
|
||||
console.error("Failed to save shortcuts:", error);
|
||||
// On failure, re-register old shortcuts to be safe
|
||||
await this.registerShortcuts();
|
||||
return { success: false, error: error.message };
|
||||
}
|
||||
}
|
||||
|
||||
async handleRestoreDefaults() {
|
||||
const defaults = this.getDefaultKeybinds();
|
||||
await this.saveKeybinds(defaults);
|
||||
await this.registerShortcuts();
|
||||
return defaults;
|
||||
}
|
||||
|
||||
async saveKeybinds(newKeybinds) {
|
||||
const keybindsToSave = [];
|
||||
for (const action in newKeybinds) {
|
||||
@ -103,15 +142,19 @@ class ShortcutsService {
|
||||
});
|
||||
}
|
||||
|
||||
async registerShortcuts(movementManager, windowPool) {
|
||||
async registerShortcuts() {
|
||||
if (!this.movementManager || !this.windowPool) {
|
||||
console.error('[Shortcuts] Service not initialized. Cannot register shortcuts.');
|
||||
return;
|
||||
}
|
||||
const keybinds = await this.loadKeybinds();
|
||||
globalShortcut.unregisterAll();
|
||||
|
||||
const header = windowPool.get('header');
|
||||
const header = this.windowPool.get('header');
|
||||
const mainWindow = header;
|
||||
|
||||
const sendToRenderer = (channel, ...args) => {
|
||||
windowPool.forEach(win => {
|
||||
this.windowPool.forEach(win => {
|
||||
if (win && !win.isDestroyed()) {
|
||||
try {
|
||||
win.webContents.send(channel, ...args);
|
||||
@ -133,7 +176,7 @@ class ShortcutsService {
|
||||
if (displays.length > 1) {
|
||||
displays.forEach((display, index) => {
|
||||
const key = `${modifier}+Shift+${index + 1}`;
|
||||
globalShortcut.register(key, () => movementManager.moveToDisplay(display.id));
|
||||
globalShortcut.register(key, () => this.movementManager.moveToDisplay(display.id));
|
||||
});
|
||||
}
|
||||
|
||||
@ -144,14 +187,14 @@ class ShortcutsService {
|
||||
];
|
||||
edgeDirections.forEach(({ key, direction }) => {
|
||||
globalShortcut.register(key, () => {
|
||||
if (header && header.isVisible()) movementManager.moveToEdge(direction);
|
||||
if (header && header.isVisible()) this.movementManager.moveToEdge(direction);
|
||||
});
|
||||
});
|
||||
|
||||
// --- User-configurable shortcuts ---
|
||||
if (header?.currentHeaderState === 'apikey') {
|
||||
if (keybinds.toggleVisibility) {
|
||||
globalShortcut.register(keybinds.toggleVisibility, () => this.toggleAllWindowsVisibility(windowPool));
|
||||
globalShortcut.register(keybinds.toggleVisibility, () => this.toggleAllWindowsVisibility(this.windowPool));
|
||||
}
|
||||
console.log('[Shortcuts] ApiKeyHeader is active, only toggleVisibility shortcut is registered.');
|
||||
return;
|
||||
@ -164,7 +207,7 @@ class ShortcutsService {
|
||||
let callback;
|
||||
switch(action) {
|
||||
case 'toggleVisibility':
|
||||
callback = () => this.toggleAllWindowsVisibility(windowPool);
|
||||
callback = () => this.toggleAllWindowsVisibility(this.windowPool);
|
||||
break;
|
||||
case 'nextStep':
|
||||
// Late require to prevent circular dependency
|
||||
@ -172,7 +215,7 @@ class ShortcutsService {
|
||||
break;
|
||||
case 'scrollUp':
|
||||
callback = () => {
|
||||
const askWindow = windowPool.get('ask');
|
||||
const askWindow = this.windowPool.get('ask');
|
||||
if (askWindow && !askWindow.isDestroyed() && askWindow.isVisible()) {
|
||||
askWindow.webContents.send('scroll-response-up');
|
||||
}
|
||||
@ -180,23 +223,23 @@ class ShortcutsService {
|
||||
break;
|
||||
case 'scrollDown':
|
||||
callback = () => {
|
||||
const askWindow = windowPool.get('ask');
|
||||
const askWindow = this.windowPool.get('ask');
|
||||
if (askWindow && !askWindow.isDestroyed() && askWindow.isVisible()) {
|
||||
askWindow.webContents.send('scroll-response-down');
|
||||
}
|
||||
};
|
||||
break;
|
||||
case 'moveUp':
|
||||
callback = () => { if (header && header.isVisible()) movementManager.moveStep('up'); };
|
||||
callback = () => { if (header && header.isVisible()) this.movementManager.moveStep('up'); };
|
||||
break;
|
||||
case 'moveDown':
|
||||
callback = () => { if (header && header.isVisible()) movementManager.moveStep('down'); };
|
||||
callback = () => { if (header && header.isVisible()) this.movementManager.moveStep('down'); };
|
||||
break;
|
||||
case 'moveLeft':
|
||||
callback = () => { if (header && header.isVisible()) movementManager.moveStep('left'); };
|
||||
callback = () => { if (header && header.isVisible()) this.movementManager.moveStep('left'); };
|
||||
break;
|
||||
case 'moveRight':
|
||||
callback = () => { if (header && header.isVisible()) movementManager.moveStep('right'); };
|
||||
callback = () => { if (header && header.isVisible()) this.movementManager.moveStep('right'); };
|
||||
break;
|
||||
case 'toggleClickThrough':
|
||||
callback = () => {
|
||||
|
@ -27,6 +27,7 @@ const settingsService = require('./features/settings/settingsService');
|
||||
const sessionRepository = require('./features/common/repositories/session');
|
||||
const modelStateService = require('./features/common/services/modelStateService');
|
||||
const featureBridge = require('./bridge/featureBridge');
|
||||
const windowBridge = require('./bridge/windowBridge');
|
||||
|
||||
// Global variables
|
||||
const eventBridge = new EventEmitter();
|
||||
@ -198,6 +199,7 @@ app.whenReady().then(async () => {
|
||||
//////// after_modelStateService ////////
|
||||
|
||||
featureBridge.initialize(); // 추가: featureBridge 초기화
|
||||
windowBridge.initialize();
|
||||
setupWebDataHandlers();
|
||||
|
||||
// Initialize Ollama models in database
|
||||
|
@ -7,6 +7,7 @@ const os = require('os');
|
||||
const util = require('util');
|
||||
const execFile = util.promisify(require('child_process').execFile);
|
||||
const shortcutsService = require('../features/shortcuts/shortcutsService');
|
||||
const internalBridge = require('../bridge/internalBridge');
|
||||
|
||||
// Try to load sharp, but don't fail if it's not available
|
||||
let sharp;
|
||||
@ -67,8 +68,140 @@ function updateLayout() {
|
||||
}
|
||||
|
||||
let movementManager = null;
|
||||
const windowBridge = require('../bridge/windowBridge');
|
||||
|
||||
const setContentProtection = (status) => {
|
||||
isContentProtectionOn = status;
|
||||
console.log(`[Protection] Content protection toggled to: ${isContentProtectionOn}`);
|
||||
windowPool.forEach(win => {
|
||||
if (win && !win.isDestroyed()) {
|
||||
win.setContentProtection(isContentProtectionOn);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const getContentProtectionStatus = () => isContentProtectionOn;
|
||||
|
||||
const toggleContentProtection = () => {
|
||||
const newStatus = !getContentProtectionStatus();
|
||||
setContentProtection(newStatus);
|
||||
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 openShortcutEditor = () => {
|
||||
const header = windowPool.get('header');
|
||||
if (!header) return;
|
||||
globalShortcut.unregisterAll();
|
||||
createFeatureWindows(header, 'shortcut-settings');
|
||||
};
|
||||
|
||||
const showSettingsWindow = (bounds) => {
|
||||
if (!bounds) return;
|
||||
const win = windowPool.get('settings');
|
||||
if (win && !win.isDestroyed()) {
|
||||
if (settingsHideTimer) {
|
||||
clearTimeout(settingsHideTimer);
|
||||
settingsHideTimer = null;
|
||||
}
|
||||
const header = windowPool.get('header');
|
||||
const headerBounds = header?.getBounds() ?? { x: 0, y: 0 };
|
||||
const settingsBounds = win.getBounds();
|
||||
const disp = getCurrentDisplay(header);
|
||||
const { x: waX, y: waY, width: waW, height: waH } = disp.workArea;
|
||||
let x = Math.round(headerBounds.x + (bounds?.x ?? 0) + (bounds?.width ?? 0) / 2 - settingsBounds.width / 2);
|
||||
let y = Math.round(headerBounds.y + (bounds?.y ?? 0) + (bounds?.height ?? 0) + 31);
|
||||
x = Math.max(waX + 10, Math.min(waX + waW - settingsBounds.width - 10, x));
|
||||
y = Math.max(waY + 10, Math.min(waY + waH - settingsBounds.height - 10, y));
|
||||
win.setBounds({ x, y });
|
||||
win.__lockedByButton = true;
|
||||
win.show();
|
||||
win.moveTop();
|
||||
win.setAlwaysOnTop(true);
|
||||
}
|
||||
};
|
||||
|
||||
const hideSettingsWindow = () => {
|
||||
const window = windowPool.get("settings");
|
||||
if (window && !window.isDestroyed()) {
|
||||
if (settingsHideTimer) {
|
||||
clearTimeout(settingsHideTimer);
|
||||
}
|
||||
settingsHideTimer = setTimeout(() => {
|
||||
if (window && !window.isDestroyed()) {
|
||||
window.setAlwaysOnTop(false);
|
||||
window.hide();
|
||||
}
|
||||
settingsHideTimer = null;
|
||||
}, 200);
|
||||
|
||||
window.__lockedByButton = false;
|
||||
}
|
||||
};
|
||||
|
||||
const cancelHideSettingsWindow = () => {
|
||||
if (settingsHideTimer) {
|
||||
clearTimeout(settingsHideTimer);
|
||||
settingsHideTimer = null;
|
||||
}
|
||||
};
|
||||
|
||||
const openLoginPage = () => {
|
||||
const webUrl = process.env.pickleglass_WEB_URL || 'http://localhost:3000';
|
||||
const personalizeUrl = `${webUrl}/personalize?desktop=true`;
|
||||
shell.openExternal(personalizeUrl);
|
||||
console.log('Opening personalization page:', personalizeUrl);
|
||||
};
|
||||
|
||||
const moveWindowStep = (direction) => {
|
||||
if (movementManager) {
|
||||
movementManager.moveStep(direction);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
function createFeatureWindows(header, namesToCreate) {
|
||||
@ -255,7 +388,7 @@ function createFeatureWindows(header, namesToCreate) {
|
||||
restoreClicks();
|
||||
windowPool.delete('shortcut-settings');
|
||||
console.log('[Shortcuts] Re-enabled after editing.');
|
||||
shortcutsService.registerShortcuts(movementManager, windowPool);
|
||||
shortcutsService.registerShortcuts();
|
||||
});
|
||||
|
||||
shortcutEditor.webContents.once('dom-ready', async () => {
|
||||
@ -408,25 +541,11 @@ function createWindows() {
|
||||
layoutManager = new WindowLayoutManager(windowPool);
|
||||
|
||||
header.webContents.once('dom-ready', () => {
|
||||
shortcutsService.registerShortcuts(movementManager, windowPool);
|
||||
shortcutsService.initialize(movementManager, windowPool);
|
||||
shortcutsService.registerShortcuts();
|
||||
});
|
||||
|
||||
setupIpcHandlers(movementManager);
|
||||
|
||||
// Content protection helper functions
|
||||
const getContentProtectionStatus = () => isContentProtectionOn;
|
||||
const setContentProtection = (status) => {
|
||||
isContentProtectionOn = status;
|
||||
console.log(`[Protection] Content protection toggled to: ${isContentProtectionOn}`);
|
||||
windowPool.forEach(win => {
|
||||
if (win && !win.isDestroyed()) {
|
||||
win.setContentProtection(isContentProtectionOn);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Initialize windowBridge with required dependencies
|
||||
windowBridge.initialize(windowPool, require('electron').app, require('electron').shell, getCurrentDisplay, createFeatureWindows, movementManager, getContentProtectionStatus, setContentProtection, updateLayout);
|
||||
|
||||
if (currentHeaderState === 'main') {
|
||||
createFeatureWindows(header, ['listen', 'ask', 'settings', 'shortcut-settings']);
|
||||
@ -499,46 +618,7 @@ function setupIpcHandlers(movementManager) {
|
||||
} else { // 'apikey' | 'permission'
|
||||
destroyFeatureWindows();
|
||||
}
|
||||
shortcutsService.registerShortcuts(movementManager, windowPool);
|
||||
});
|
||||
|
||||
ipcMain.handle('get-current-shortcuts', async () => {
|
||||
return await shortcutsService.loadKeybinds();
|
||||
});
|
||||
|
||||
ipcMain.handle('get-default-shortcuts', async () => {
|
||||
const defaults = shortcutsService.getDefaultKeybinds();
|
||||
await shortcutsService.saveKeybinds(defaults);
|
||||
// Reregister shortcuts with new defaults
|
||||
await shortcutsService.registerShortcuts(movementManager, windowPool);
|
||||
return defaults;
|
||||
});
|
||||
|
||||
ipcMain.handle('save-shortcuts', async (event, newKeybinds) => {
|
||||
try {
|
||||
await shortcutsService.saveKeybinds(newKeybinds);
|
||||
|
||||
const editor = windowPool.get('shortcut-settings');
|
||||
if (editor && !editor.isDestroyed()) {
|
||||
editor.close(); // This will trigger re-registration on 'closed' event
|
||||
} else {
|
||||
// If editor wasn't open, re-register immediately
|
||||
await shortcutsService.registerShortcuts(movementManager, windowPool);
|
||||
}
|
||||
return { success: true };
|
||||
} catch (error) {
|
||||
console.error("Failed to save shortcuts:", error);
|
||||
// On failure, re-register old shortcuts to be safe
|
||||
await shortcutsService.registerShortcuts(movementManager, windowPool);
|
||||
return { success: false, error: error.message };
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.on('close-shortcut-editor', () => {
|
||||
const editor = windowPool.get('shortcut-settings');
|
||||
if (editor && !editor.isDestroyed()) {
|
||||
editor.close();
|
||||
}
|
||||
internalBridge.emit('reregister-shortcuts');
|
||||
});
|
||||
|
||||
// resize-header-window handler moved to windowBridge.js to avoid duplication
|
||||
@ -1063,6 +1143,13 @@ async function captureScreenshot(options = {}) {
|
||||
}
|
||||
}
|
||||
|
||||
const closeWindow = (windowName) => {
|
||||
const win = windowPool.get(windowName);
|
||||
if (win && !win.isDestroyed()) {
|
||||
win.close();
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
updateLayout,
|
||||
createWindows,
|
||||
@ -1073,4 +1160,14 @@ module.exports = {
|
||||
getCurrentModelInfo,
|
||||
captureScreenshot,
|
||||
toggleFeature, // Export toggleFeature so shortcutsService can use it
|
||||
toggleContentProtection,
|
||||
resizeHeaderWindow,
|
||||
getContentProtectionStatus,
|
||||
openShortcutEditor,
|
||||
showSettingsWindow,
|
||||
hideSettingsWindow,
|
||||
cancelHideSettingsWindow,
|
||||
openLoginPage,
|
||||
moveWindowStep,
|
||||
closeWindow,
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user