Files
SkillMate/frontend/electron/main.js
Claude Project Manager 6b9b6d4f20 Initial commit
2025-09-20 21:31:04 +02:00

210 Zeilen
5.0 KiB
JavaScript

const { app, BrowserWindow, ipcMain, Menu, Tray } = require('electron')
const path = require('path')
const { spawn } = require('child_process')
const isDev = process.env.NODE_ENV === 'development' || (!app.isPackaged && !process.env.NODE_ENV)
let mainWindow
let tray
let backendProcess
function createWindow() {
mainWindow = new BrowserWindow({
width: 1400,
height: 900,
minWidth: 1200,
minHeight: 700,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
preload: path.join(__dirname, 'preload.js')
},
icon: path.join(__dirname, '../public/icon.png'),
titleBarStyle: 'hiddenInset',
frame: process.platform !== 'win32',
backgroundColor: '#F8FAFC'
})
if (isDev) {
mainWindow.loadURL('http://localhost:5173')
mainWindow.webContents.openDevTools()
} else {
// In production, load the built files
const indexPath = path.join(__dirname, '../dist/index.html')
console.log('Loading:', indexPath)
mainWindow.loadFile(indexPath)
// DevTools nur öffnen wenn explizit gewünscht
// mainWindow.webContents.openDevTools()
// Log any errors
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('Console:', message)
})
// Warte bis Seite geladen ist
mainWindow.webContents.on('did-finish-load', () => {
console.log('Page loaded successfully')
})
}
mainWindow.on('closed', () => {
mainWindow = null
})
// Custom window controls for Windows
if (process.platform === 'win32') {
mainWindow.on('maximize', () => {
mainWindow.webContents.send('window-maximized')
})
mainWindow.on('unmaximize', () => {
mainWindow.webContents.send('window-unmaximized')
})
}
}
function createTray() {
// Tray-Funktion vorerst deaktiviert, da Icon fehlt
// TODO: Tray-Icon hinzufügen
return
tray = new Tray(path.join(__dirname, '../public/tray-icon.png'))
const contextMenu = Menu.buildFromTemplate([
{
label: 'SkillMate öffnen',
click: () => {
if (mainWindow) {
mainWindow.show()
} else {
createWindow()
}
}
},
{ type: 'separator' },
{
label: 'Beenden',
click: () => {
app.quit()
}
}
])
tray.setToolTip('SkillMate')
tray.setContextMenu(contextMenu)
tray.on('click', () => {
if (mainWindow) {
mainWindow.isVisible() ? mainWindow.hide() : mainWindow.show()
} else {
createWindow()
}
})
}
function startBackend() {
// Backend nur im Development-Modus automatisch starten
// In Production wird es extern gestartet
return
if (!isDev) {
// In production, backend is bundled with the app
const backendPath = app.isPackaged
? path.join(process.resourcesPath, 'backend', 'index.js')
: path.join(__dirname, '../../backend/dist/index.js')
console.log('Starting backend from:', backendPath)
// Check if backend exists
const fs = require('fs')
if (!fs.existsSync(backendPath)) {
console.error('Backend not found at:', backendPath)
// Try alternative path
const altPath = path.join(__dirname, '../backend/index.js')
console.log('Trying alternative path:', altPath)
if (fs.existsSync(altPath)) {
backendPath = altPath
}
}
backendProcess = spawn('node', [backendPath], {
env: {
...process.env,
NODE_ENV: 'production',
PORT: '3001',
DATABASE_PATH: path.join(app.getPath('userData'), 'skillmate.db'),
LOG_PATH: path.join(app.getPath('userData'), 'logs')
},
stdio: ['pipe', 'pipe', 'pipe']
})
backendProcess.stdout.on('data', (data) => {
console.log(`Backend: ${data}`)
})
backendProcess.stderr.on('data', (data) => {
console.error(`Backend Error: ${data}`)
})
backendProcess.on('error', (error) => {
console.error('Failed to start backend:', error)
})
backendProcess.on('exit', (code) => {
console.log(`Backend exited with code ${code}`)
})
}
}
app.whenReady().then(() => {
createWindow()
createTray()
startBackend()
})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('before-quit', () => {
if (backendProcess) {
backendProcess.kill()
}
})
app.on('activate', () => {
if (mainWindow === null) {
createWindow()
}
})
// IPC handlers
ipcMain.handle('app:minimize', () => {
mainWindow.minimize()
})
ipcMain.handle('app:maximize', () => {
if (mainWindow.isMaximized()) {
mainWindow.unmaximize()
} else {
mainWindow.maximize()
}
})
ipcMain.handle('app:close', () => {
mainWindow.close()
})
ipcMain.handle('app:getVersion', () => {
return app.getVersion()
})
ipcMain.handle('app:getPath', (event, name) => {
return app.getPath(name)
})