119 lines
2.9 KiB
TypeScript
119 lines
2.9 KiB
TypeScript
import { app, BrowserWindow, ipcMain } from 'electron';
|
|
import path from 'path';
|
|
import os from 'os';
|
|
import { store as electronStore } from './store';
|
|
import { setupIpcHandlers } from './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,
|
|
},
|
|
show: false,
|
|
});
|
|
|
|
// 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
|
|
mainWindow.loadFile(path.join(__dirname, '../dist/index.html'));
|
|
}
|
|
|
|
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();
|
|
});
|
|
|
|
export default app;
|