build fix

This commit is contained in:
alma 2025-05-05 17:09:36 +02:00
parent 9a7bc49f48
commit 3b782fb11f
5 changed files with 211 additions and 1 deletions

View File

@ -55,7 +55,7 @@ export async function POST() {
secure: true,
auth: {
user: account.email,
pass: account.password,
pass: account.password || undefined,
},
logger: false,
tls: {

View File

@ -0,0 +1,81 @@
'use client';
import { useEffect, useState } from 'react';
import { Minus, Square, X } from 'lucide-react';
// Import types from our electron.d.ts file
declare global {
interface Window {
electron?: {
windowControl: {
minimize: () => Promise<void>;
maximize: () => Promise<void>;
close: () => Promise<void>;
};
windowState: {
onMaximized: (callback: () => void) => void;
onUnmaximized: (callback: () => void) => void;
removeMaximizedListener: () => void;
removeUnmaximizedListener: () => void;
};
appInfo: {
isElectron: boolean;
version: string;
};
};
}
}
export function WindowControls() {
const [isElectron, setIsElectron] = useState(false);
const [isMaximized, setIsMaximized] = useState(false);
useEffect(() => {
// Check if running in Electron
if (typeof window !== 'undefined' && window.electron) {
setIsElectron(true);
// Set up event listeners for window state
const maximizedHandler = () => setIsMaximized(true);
const unmaximizedHandler = () => setIsMaximized(false);
window.electron.windowState.onMaximized(maximizedHandler);
window.electron.windowState.onUnmaximized(unmaximizedHandler);
return () => {
window.electron?.windowState.removeMaximizedListener();
window.electron?.windowState.removeUnmaximizedListener();
};
}
}, []);
if (!isElectron) return null;
return (
<div className="flex -mr-2 items-center">
<button
onClick={() => window.electron?.windowControl.minimize()}
className="px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-700"
aria-label="Minimize"
>
<Minus size={16} />
</button>
<button
onClick={() => window.electron?.windowControl.maximize()}
className="px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-700"
aria-label={isMaximized ? "Restore" : "Maximize"}
>
<Square size={16} />
</button>
<button
onClick={() => window.electron?.windowControl.close()}
className="px-4 py-2 hover:bg-red-500 dark:hover:bg-red-600"
aria-label="Close"
>
<X size={16} className="hover:text-white" />
</button>
</div>
);
}

76
electron/main.js Normal file
View File

@ -0,0 +1,76 @@
const { app, BrowserWindow, ipcMain } = require('electron');
const path = require('path');
const isDev = process.env.NODE_ENV === 'development';
const port = process.env.PORT || 3000;
// Keep a global reference of the window object to prevent garbage collection
let mainWindow;
function createWindow() {
mainWindow = new BrowserWindow({
width: 1200,
height: 800,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
preload: path.join(__dirname, 'preload.js')
},
icon: path.join(__dirname, '../public/favicon.ico')
});
// Load the app
const startUrl = isDev
? `http://localhost:${port}`
: `file://${path.join(__dirname, '../.next/index.html')}`;
mainWindow.loadURL(startUrl);
// Open DevTools in development mode
if (isDev) {
mainWindow.webContents.openDevTools();
}
mainWindow.on('closed', () => {
mainWindow = null;
});
// Handle window maximize/unmaximize
mainWindow.on('maximize', () => {
mainWindow.webContents.send('window-maximized');
});
mainWindow.on('unmaximize', () => {
mainWindow.webContents.send('window-unmaximized');
});
}
app.whenReady().then(createWindow);
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
// IPC handlers for window controls
ipcMain.handle('minimize-window', () => {
mainWindow.minimize();
});
ipcMain.handle('maximize-window', () => {
if (mainWindow.isMaximized()) {
mainWindow.unmaximize();
} else {
mainWindow.maximize();
}
});
ipcMain.handle('close-window', () => {
mainWindow.close();
});

24
electron/preload.js Normal file
View File

@ -0,0 +1,24 @@
const { contextBridge, ipcRenderer } = require('electron');
// Expose protected methods that allow the renderer process to use
// the ipcRenderer without exposing the entire object
contextBridge.exposeInMainWorld('electron', {
// Window control methods
windowControl: {
minimize: () => ipcRenderer.invoke('minimize-window'),
maximize: () => ipcRenderer.invoke('maximize-window'),
close: () => ipcRenderer.invoke('close-window'),
},
// Window state listeners
windowState: {
onMaximized: (callback) => ipcRenderer.on('window-maximized', callback),
onUnmaximized: (callback) => ipcRenderer.on('window-unmaximized', callback),
removeMaximizedListener: () => ipcRenderer.removeAllListeners('window-maximized'),
removeUnmaximizedListener: () => ipcRenderer.removeAllListeners('window-unmaximized'),
},
// App info
appInfo: {
isElectron: true,
version: process.env.npm_package_version,
}
});

29
types/electron.d.ts vendored Normal file
View File

@ -0,0 +1,29 @@
interface ElectronWindowControl {
minimize: () => Promise<void>;
maximize: () => Promise<void>;
close: () => Promise<void>;
}
interface ElectronWindowState {
onMaximized: (callback: () => void) => void;
onUnmaximized: (callback: () => void) => void;
removeMaximizedListener: () => void;
removeUnmaximizedListener: () => void;
}
interface ElectronAppInfo {
isElectron: boolean;
version: string;
}
interface Electron {
windowControl: ElectronWindowControl;
windowState: ElectronWindowState;
appInfo: ElectronAppInfo;
}
declare global {
interface Window {
electron: Electron;
}
}