import { app, desktopCapturer, dialog, ipcMain, shell } from 'electron'; import * as fs from 'fs'; import * as fsp from 'fs/promises'; import { getDesktopSettingsSnapshot, updateDesktopSettings } from '../desktop-settings'; import { activateLinuxScreenShareAudioRouting, deactivateLinuxScreenShareAudioRouting, prepareLinuxScreenShareAudioRouting, startLinuxScreenShareMonitorCapture, stopLinuxScreenShareMonitorCapture } from '../audio/linux-screen-share-routing'; export function setupSystemHandlers(): void { ipcMain.handle('open-external', async (_event, url: string) => { if (typeof url === 'string' && (url.startsWith('http://') || url.startsWith('https://'))) { await shell.openExternal(url); return true; } return false; }); ipcMain.handle('get-sources', async () => { const sources = await desktopCapturer.getSources({ types: ['window', 'screen'], thumbnailSize: { width: 150, height: 150 } }); return sources.map((source) => ({ id: source.id, name: source.name, thumbnail: source.thumbnail.toDataURL() })); }); ipcMain.handle('prepare-linux-screen-share-audio-routing', async () => { return await prepareLinuxScreenShareAudioRouting(); }); ipcMain.handle('activate-linux-screen-share-audio-routing', async () => { return await activateLinuxScreenShareAudioRouting(); }); ipcMain.handle('deactivate-linux-screen-share-audio-routing', async () => { return await deactivateLinuxScreenShareAudioRouting(); }); ipcMain.handle('start-linux-screen-share-monitor-capture', async (event) => { return await startLinuxScreenShareMonitorCapture(event.sender); }); ipcMain.handle('stop-linux-screen-share-monitor-capture', async (_event, captureId?: string) => { return await stopLinuxScreenShareMonitorCapture(captureId); }); ipcMain.handle('get-app-data-path', () => app.getPath('userData')); ipcMain.handle('get-desktop-settings', () => getDesktopSettingsSnapshot()); ipcMain.handle('set-desktop-settings', (_event, patch: { hardwareAcceleration?: boolean }) => { return updateDesktopSettings(patch); }); ipcMain.handle('relaunch-app', () => { app.relaunch(); app.exit(0); return true; }); ipcMain.handle('file-exists', async (_event, filePath: string) => { try { await fsp.access(filePath, fs.constants.F_OK); return true; } catch { return false; } }); ipcMain.handle('read-file', async (_event, filePath: string) => { const data = await fsp.readFile(filePath); return data.toString('base64'); }); ipcMain.handle('write-file', async (_event, filePath: string, base64Data: string) => { const buffer = Buffer.from(base64Data, 'base64'); await fsp.writeFile(filePath, buffer); return true; }); ipcMain.handle('delete-file', async (_event, filePath: string) => { try { await fsp.unlink(filePath); return true; } catch (error) { if ((error as { code?: string }).code === 'ENOENT') { return true; } throw error; } }); ipcMain.handle('save-file-as', async (_event, defaultFileName: string, base64Data: string) => { const result = await dialog.showSaveDialog({ defaultPath: defaultFileName }); if (result.canceled || !result.filePath) { return { saved: false, cancelled: true }; } const buffer = Buffer.from(base64Data, 'base64'); await fsp.writeFile(result.filePath, buffer); return { saved: true, cancelled: false }; }); ipcMain.handle('ensure-dir', async (_event, dirPath: string) => { await fsp.mkdir(dirPath, { recursive: true }); return true; }); }