Initial commit
Dieser Commit ist enthalten in:
210
frontend/electron/main.js
Normale Datei
210
frontend/electron/main.js
Normale Datei
@ -0,0 +1,210 @@
|
||||
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)
|
||||
})
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren