176 lines
4.5 KiB
TypeScript
176 lines
4.5 KiB
TypeScript
import { app, BrowserWindow, Tray, Menu, nativeImage } from 'electron';
|
|
import * as path from 'path';
|
|
import { fileURLToPath } from 'url';
|
|
import * as dotenv from 'dotenv';
|
|
import { setupIpcHandlers, cleanupIpcHandlers } from './ipc-handlers.js';
|
|
import { initDatabase, closeDatabase } from './database.js';
|
|
|
|
// ES module equivalent of __dirname
|
|
const __filename = fileURLToPath(import.meta.url);
|
|
const __dirname = path.dirname(__filename);
|
|
|
|
// Load environment variables from .env file
|
|
// In dev: __dirname = dist/main, so go up to electron-app root
|
|
// In prod: __dirname = resources/app.asar/dist/main, .env should be in resources
|
|
const envPath = process.env.NODE_ENV === 'development'
|
|
? path.join(__dirname, '../../.env')
|
|
: path.join(process.resourcesPath, '.env');
|
|
dotenv.config({ path: envPath });
|
|
|
|
console.log('Loading .env from:', envPath);
|
|
console.log('WS_URL:', process.env.WS_URL);
|
|
console.log('API_URL:', process.env.API_URL);
|
|
|
|
let mainWindow: BrowserWindow | null = null;
|
|
let tray: Tray | null = null;
|
|
const isDev = process.env.NODE_ENV === 'development';
|
|
|
|
function getIconPath(): string {
|
|
if (isDev) {
|
|
return process.platform === 'win32'
|
|
? path.join(__dirname, '../../resources/icons/icon.ico')
|
|
: path.join(__dirname, '../../resources/icons/logo.png');
|
|
}
|
|
|
|
return process.platform === 'win32'
|
|
? path.join(process.resourcesPath, 'icons', 'icon.ico')
|
|
: path.join(process.resourcesPath, 'icons', 'logo.png');
|
|
}
|
|
|
|
function createWindow(): void {
|
|
const iconPath = getIconPath();
|
|
|
|
console.log('Window icon path:', iconPath);
|
|
|
|
mainWindow = new BrowserWindow({
|
|
width: 1400,
|
|
height: 900,
|
|
minWidth: 1000,
|
|
minHeight: 700,
|
|
frame: false,
|
|
backgroundColor: '#0a0e27',
|
|
icon: iconPath,
|
|
show: false, // Don't show until loaded
|
|
webPreferences: {
|
|
preload: path.join(__dirname, 'preload.js'),
|
|
nodeIntegration: false,
|
|
contextIsolation: true,
|
|
sandbox: true,
|
|
devTools: true, // Enable dev tools in production for debugging
|
|
},
|
|
title: 'rmtPocketWatcher',
|
|
});
|
|
|
|
// Setup IPC handlers for WebSocket communication
|
|
setupIpcHandlers(mainWindow);
|
|
|
|
// Load the app
|
|
if (isDev) {
|
|
mainWindow.loadURL('http://localhost:5173');
|
|
mainWindow.webContents.openDevTools();
|
|
} else {
|
|
const rendererPath = path.join(__dirname, '../renderer/index.html');
|
|
console.log('Loading renderer from:', rendererPath);
|
|
mainWindow.loadFile(rendererPath).catch(err => {
|
|
console.error('Failed to load renderer:', err);
|
|
});
|
|
}
|
|
|
|
// Show window and open dev tools to see errors
|
|
mainWindow.webContents.on('did-fail-load', (_event, errorCode, errorDescription) => {
|
|
console.error('Failed to load:', errorCode, errorDescription);
|
|
});
|
|
|
|
mainWindow.webContents.on('did-finish-load', () => {
|
|
console.log('Window loaded successfully');
|
|
mainWindow?.show();
|
|
});
|
|
|
|
mainWindow.on('closed', () => {
|
|
cleanupIpcHandlers();
|
|
mainWindow = null;
|
|
});
|
|
}
|
|
|
|
function createTray(): void {
|
|
// In dev: __dirname = dist/main, logo is at root
|
|
// In prod: __dirname = resources/app.asar/dist/main
|
|
const iconPath = getIconPath();
|
|
|
|
console.log('Tray icon path:', iconPath);
|
|
|
|
let icon = nativeImage.createFromPath(iconPath);
|
|
if (process.platform !== 'win32') {
|
|
icon = icon.resize({ width: 16, height: 16 });
|
|
}
|
|
|
|
tray = new Tray(icon);
|
|
|
|
const contextMenu = Menu.buildFromTemplate([
|
|
{
|
|
label: 'Show rmtPocketWatcher',
|
|
click: () => {
|
|
if (mainWindow) {
|
|
mainWindow.show();
|
|
mainWindow.focus();
|
|
}
|
|
}
|
|
},
|
|
{
|
|
label: 'Open DevTools',
|
|
click: () => {
|
|
if (mainWindow) {
|
|
mainWindow.webContents.openDevTools();
|
|
}
|
|
}
|
|
},
|
|
{
|
|
label: 'Reload',
|
|
click: () => {
|
|
if (mainWindow) {
|
|
mainWindow.reload();
|
|
}
|
|
}
|
|
},
|
|
{
|
|
label: 'Quit',
|
|
click: () => {
|
|
app.quit();
|
|
}
|
|
}
|
|
]);
|
|
|
|
tray.setToolTip('rmtPocketWatcher');
|
|
tray.setContextMenu(contextMenu);
|
|
|
|
// Double-click to show window
|
|
tray.on('double-click', () => {
|
|
if (mainWindow) {
|
|
mainWindow.show();
|
|
mainWindow.focus();
|
|
}
|
|
});
|
|
}
|
|
|
|
app.whenReady().then(() => {
|
|
initDatabase();
|
|
createTray();
|
|
createWindow();
|
|
});
|
|
|
|
app.on('window-all-closed', () => {
|
|
// Quit the app when all windows are closed
|
|
app.quit();
|
|
});
|
|
|
|
app.on('activate', () => {
|
|
if (BrowserWindow.getAllWindows().length === 0) {
|
|
createWindow();
|
|
}
|
|
});
|
|
|
|
app.on('before-quit', () => {
|
|
cleanupIpcHandlers();
|
|
closeDatabase();
|
|
});
|