diff --git a/electron/main.ts b/electron/main.ts index b3c58fe..4a36b14 100644 --- a/electron/main.ts +++ b/electron/main.ts @@ -491,6 +491,45 @@ ipcMain.handle('create-window', async (_event, tabData: { route: string; title: } }); +ipcMain.handle('window-minimize', async (event) => { + const win = BrowserWindow.fromWebContents(event.sender); + if (win) { + win.minimize(); + return { success: true }; + } + return { success: false }; +}); + +ipcMain.handle('window-maximize', async (event) => { + const win = BrowserWindow.fromWebContents(event.sender); + if (win) { + if (win.isMaximized()) { + win.unmaximize(); + } else { + win.maximize(); + } + return { success: true, isMaximized: win.isMaximized() }; + } + return { success: false }; +}); + +ipcMain.handle('window-close', async (event) => { + const win = BrowserWindow.fromWebContents(event.sender); + if (win) { + win.close(); + return { success: true }; + } + return { success: false }; +}); + +ipcMain.handle('window-is-maximized', async (event) => { + const win = BrowserWindow.fromWebContents(event.sender); + if (win) { + return { success: true, isMaximized: win.isMaximized() }; + } + return { success: false, isMaximized: false }; +}); + async function startServer() { if (electronState.isDevelopment()) { log.info('In dev mode, assuming external servers are running.'); diff --git a/electron/preload.ts b/electron/preload.ts index 2988c7e..57f0541 100644 --- a/electron/preload.ts +++ b/electron/preload.ts @@ -54,4 +54,8 @@ contextBridge.exposeInMainWorld('electronAPI', { terminalGetStatus: () => ipcRenderer.invoke('terminal-get-status'), terminalGetPort: () => ipcRenderer.invoke('terminal-get-port'), createWindow: (tabData: { route: string; title: string }) => ipcRenderer.invoke('create-window', tabData), + windowMinimize: () => ipcRenderer.invoke('window-minimize'), + windowMaximize: () => ipcRenderer.invoke('window-maximize'), + windowClose: () => ipcRenderer.invoke('window-close'), + windowIsMaximized: () => ipcRenderer.invoke('window-is-maximized'), }) diff --git a/src/pages/PopoutPage.tsx b/src/pages/PopoutPage.tsx index 23bd7e6..36bfd97 100644 --- a/src/pages/PopoutPage.tsx +++ b/src/pages/PopoutPage.tsx @@ -5,11 +5,13 @@ import { matchModule } from '@/lib/module-registry' import { MarkdownTabPage } from '@/components/tabs/MarkdownTabPage' import { RemoteTabPage } from '@/modules/remote/RemoteTabPage' import { FileTransferPage } from '@/modules/remote/components/file-transfer/FileTransferPage' +import { Minus, Square, X, Maximize2 } from 'lucide-react' export const PopoutPage = () => { const [searchParams] = useSearchParams() const [file, setFile] = useState(null) const [error, setError] = useState(null) + const [isMaximized, setIsMaximized] = useState(false) useEffect(() => { const path = searchParams.get('path') @@ -27,8 +29,29 @@ export const PopoutPage = () => { size: 0, modified: new Date().toISOString(), }) + + window.electronAPI?.windowIsMaximized().then((result) => { + if (result.success) { + setIsMaximized(result.isMaximized) + } + }) }, [searchParams]) + const handleMinimize = () => { + window.electronAPI?.windowMinimize() + } + + const handleMaximize = async () => { + const result = await window.electronAPI?.windowMaximize() + if (result?.success && result.isMaximized !== undefined) { + setIsMaximized(result.isMaximized) + } + } + + const handleClose = () => { + window.electronAPI?.windowClose() + } + if (error) { return (
@@ -79,8 +102,37 @@ export const PopoutPage = () => { } return ( -
- {renderContent()} +
+
+ {file.name} +
+ + + +
+
+
+ {renderContent()} +
) } diff --git a/src/types/electron.d.ts b/src/types/electron.d.ts index c6a3c27..49c3ade 100644 --- a/src/types/electron.d.ts +++ b/src/types/electron.d.ts @@ -54,6 +54,10 @@ export interface ElectronAPI { terminalGetStatus: () => Promise<{ running: boolean; port: number }> terminalGetPort: () => Promise<{ port: number }> createWindow: (tabData: { route: string; title: string }) => Promise<{ success: boolean; windowId?: number; error?: string }> + windowMinimize: () => Promise<{ success: boolean }> + windowMaximize: () => Promise<{ success: boolean; isMaximized?: boolean }> + windowClose: () => Promise<{ success: boolean }> + windowIsMaximized: () => Promise<{ success: boolean; isMaximized: boolean }> } declare global {