2025-02-09 03:10:26 -05:00

205 lines
5.8 KiB
TypeScript

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');
const { MeiliSearch } = require('meilisearch');
const slugify = (str: string) => {
return str
.toLowerCase()
.replace(/[^a-z0-9]+/g, '-')
.replace(/^-|-$/g, '');
};
const { platform } = require('os');
import MeilisearchService from './services/meilisearchService';
const meilisearchService = new MeilisearchService();
(global as any).meilisearchService = meilisearchService;
// Initialize IPC handlers immediately
setupIpcHandlers();
function createWindow() {
const mainWindow = new BrowserWindow({
width: 1200,
height: 800,
minWidth: 1200, // Minimum width
minHeight: 800, // Minimum height
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(() => {
meilisearchService.startServer();
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);
});
// Launch the server
if (process.env.NODE_ENV !== 'development') {
const serverProcess = spawn('node', [path.join(__dirname, '../scripts/dev.cjs')], {
stdio: 'inherit',
});
serverProcess.on('close', (code) => {
console.log(`Server process exited with code ${code}`);
});
serverProcess.on('error', (err) => {
console.error('Failed to start server process:', err);
});
}
app.on('will-quit', () => {
meilisearchService.stopServer();
});
module.exports = app;