From 3b782fb11f0e5ec9f338b9bd845d6b393f408dbc Mon Sep 17 00:00:00 2001 From: alma Date: Mon, 5 May 2025 17:09:36 +0200 Subject: [PATCH] build fix --- app/api/courrier/fix-folders/route.ts | 2 +- components/electron/window-controls.tsx | 81 +++++++++++++++++++++++++ electron/main.js | 76 +++++++++++++++++++++++ electron/preload.js | 24 ++++++++ types/electron.d.ts | 29 +++++++++ 5 files changed, 211 insertions(+), 1 deletion(-) create mode 100644 components/electron/window-controls.tsx create mode 100644 electron/main.js create mode 100644 electron/preload.js create mode 100644 types/electron.d.ts diff --git a/app/api/courrier/fix-folders/route.ts b/app/api/courrier/fix-folders/route.ts index 36df2f23..ded91d7e 100644 --- a/app/api/courrier/fix-folders/route.ts +++ b/app/api/courrier/fix-folders/route.ts @@ -55,7 +55,7 @@ export async function POST() { secure: true, auth: { user: account.email, - pass: account.password, + pass: account.password || undefined, }, logger: false, tls: { diff --git a/components/electron/window-controls.tsx b/components/electron/window-controls.tsx new file mode 100644 index 00000000..714a8bea --- /dev/null +++ b/components/electron/window-controls.tsx @@ -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; + maximize: () => Promise; + close: () => Promise; + }; + 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 ( +
+ + + + + +
+ ); +} \ No newline at end of file diff --git a/electron/main.js b/electron/main.js new file mode 100644 index 00000000..569a9a57 --- /dev/null +++ b/electron/main.js @@ -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(); +}); \ No newline at end of file diff --git a/electron/preload.js b/electron/preload.js new file mode 100644 index 00000000..1a88afca --- /dev/null +++ b/electron/preload.js @@ -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, + } +}); \ No newline at end of file diff --git a/types/electron.d.ts b/types/electron.d.ts new file mode 100644 index 00000000..f9159317 --- /dev/null +++ b/types/electron.d.ts @@ -0,0 +1,29 @@ +interface ElectronWindowControl { + minimize: () => Promise; + maximize: () => Promise; + close: () => Promise; +} + +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; + } +} \ No newline at end of file