const { app, BrowserWindow, ipcMain } = require('electron'); const path = require('path'); const os = require('os'); const spawn = require('child_process').spawn; const { store: electronStore } = require('./store'); const { setupIpcHandlers } = require('./ipc/handlers'); // Initialize IPC handlers immediately setupIpcHandlers(); function createWindow() { const mainWindow = new BrowserWindow({ width: 1200, height: 800, frame: false, titleBarStyle: 'hidden', webPreferences: { nodeIntegration: false, contextIsolation: true, preload: path.join(__dirname, 'preload.js'), sandbox: false, webSecurity: true, }, }); // Enable logging mainWindow.webContents.on('did-fail-load', (event, errorCode, errorDescription) => { console.error('Failed to load:', errorCode, errorDescription); }); mainWindow.webContents.on('console-message', (event, level, message) => { console.log('Renderer Console:', message); }); // In development, use the Vite dev server if (process.env.VITE_DEV_SERVER_URL) { // Wait for dev server to be ready const pollDevServer = async () => { try { const response = await fetch(process.env.VITE_DEV_SERVER_URL); if (response.ok) { mainWindow.loadURL(process.env.VITE_DEV_SERVER_URL); mainWindow.webContents.openDevTools(); } else { setTimeout(pollDevServer, 500); } } catch { setTimeout(pollDevServer, 500); } }; pollDevServer(); } else { // In production, load the built files const prodPath = path.join(__dirname, '../dist/index.html'); console.log('Production mode detected'); console.log('__dirname:', __dirname); console.log('Attempting to load:', prodPath); // Check if the file exists try { if (require('fs').existsSync(prodPath)) { console.log('Found production build at:', prodPath); mainWindow.loadFile(prodPath).catch(err => { console.error('Failed to load production file:', err); // Try alternative path const altPath = path.join(process.cwd(), 'dist/index.html'); console.log('Trying alternative path:', altPath); if (require('fs').existsSync(altPath)) { mainWindow.loadFile(altPath).catch(err => { console.error('Failed to load alternative path:', err); }); } else { console.error('Alternative path does not exist'); } }); } else { console.error('Production build not found at:', prodPath); // Try alternative path const altPath = path.join(process.cwd(), 'dist/index.html'); console.log('Trying alternative path:', altPath); if (require('fs').existsSync(altPath)) { mainWindow.loadFile(altPath).catch(err => { console.error('Failed to load alternative path:', err); }); } else { console.error('Alternative path does not exist'); } } } catch (err) { console.error('Error checking file existence:', err); } } mainWindow.once('ready-to-show', () => { mainWindow.show(); }); // Handle window state const windowState = electronStore.get('windowState', { width: 1200, height: 800 }); mainWindow.setSize(windowState.width, windowState.height); mainWindow.on('close', () => { const { width, height } = mainWindow.getBounds(); electronStore.set('windowState', { width, height }); }); // Set up security headers mainWindow.webContents.session.webRequest.onHeadersReceived((details, callback) => { callback({ responseHeaders: { ...details.responseHeaders, 'Content-Security-Policy': [ "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data:;" ] } }); }); } app.whenReady().then(() => { createWindow(); app.on('activate', () => { if (BrowserWindow.getAllWindows().length === 0) { createWindow(); } }); }); app.on('window-all-closed', () => { if (process.platform !== 'darwin') { app.quit(); } }); // IPC handlers for file system operations ipcMain.handle('get-app-path', () => { return app.getPath('userData'); }); // Window control handlers ipcMain.handle('window-minimize', (event) => { const window = BrowserWindow.fromWebContents(event.sender); window?.minimize(); }); ipcMain.handle('window-maximize', (event) => { const window = BrowserWindow.fromWebContents(event.sender); if (window?.isMaximized()) { window.unmaximize(); } else { window?.maximize(); } }); ipcMain.handle('window-close', (event) => { const window = BrowserWindow.fromWebContents(event.sender); window?.close(); }); ipcMain.handle('open-external', (_, url) => { return require('electron').shell.openExternal(url); }); module.exports = app;