import { ipcMain, desktopCapturer, BrowserWindow, shell, app, dialog } from 'electron' import fs from 'node:fs/promises' import path from 'node:path' import { RECORDINGS_DIR } from '../main' let selectedSource: any = null export function registerIpcHandlers( createEditorWindow: () => void, createSourceSelectorWindow: () => BrowserWindow, getMainWindow: () => BrowserWindow | null, getSourceSelectorWindow: () => BrowserWindow | null, onRecordingStateChange?: (recording: boolean, sourceName: string) => void ) { ipcMain.handle('get-sources', async (_, opts) => { const sources = await desktopCapturer.getSources(opts) return sources.map(source => ({ id: source.id, name: source.name, display_id: source.display_id, thumbnail: source.thumbnail ? source.thumbnail.toDataURL() : null, appIcon: source.appIcon ? source.appIcon.toDataURL() : null })) }) ipcMain.handle('select-source', (_, source) => { selectedSource = source const sourceSelectorWin = getSourceSelectorWindow() if (sourceSelectorWin) { sourceSelectorWin.close() } return selectedSource }) ipcMain.handle('get-selected-source', () => { return selectedSource }) ipcMain.handle('open-source-selector', () => { const sourceSelectorWin = getSourceSelectorWindow() if (sourceSelectorWin) { sourceSelectorWin.focus() return } createSourceSelectorWindow() }) ipcMain.handle('switch-to-editor', () => { const mainWin = getMainWindow() if (mainWin) { mainWin.close() } createEditorWindow() }) ipcMain.handle('store-recorded-video', async (_, videoData: ArrayBuffer, fileName: string) => { try { const videoPath = path.join(RECORDINGS_DIR, fileName) await fs.writeFile(videoPath, Buffer.from(videoData)) currentVideoPath = videoPath; return { success: true, path: videoPath, message: 'Video stored successfully' } } catch (error) { console.error('Failed to store video:', error) return { success: false, message: 'Failed to store video', error: String(error) } } }) ipcMain.handle('get-recorded-video-path', async () => { try { const files = await fs.readdir(RECORDINGS_DIR) const videoFiles = files.filter(file => file.endsWith('.webm')) if (videoFiles.length === 0) { return { success: false, message: 'No recorded video found' } } const latestVideo = videoFiles.sort().reverse()[0] const videoPath = path.join(RECORDINGS_DIR, latestVideo) return { success: true, path: videoPath } } catch (error) { console.error('Failed to get video path:', error) return { success: false, message: 'Failed to get video path', error: String(error) } } }) ipcMain.handle('set-recording-state', (_, recording: boolean) => { const source = selectedSource || { name: 'Screen' } if (onRecordingStateChange) { onRecordingStateChange(recording, source.name) } }) ipcMain.handle('open-external-url', async (_, url: string) => { try { await shell.openExternal(url) return { success: true } } catch (error) { console.error('Failed to open URL:', error) return { success: false, error: String(error) } } }) // Return base path for assets so renderer can resolve file:// paths in production ipcMain.handle('get-asset-base-path', () => { try { if (app.isPackaged) { return path.join(process.resourcesPath, 'assets') } return path.join(app.getAppPath(), 'public', 'assets') } catch (err) { console.error('Failed to resolve asset base path:', err) return null } }) ipcMain.handle('save-exported-video', async (_, videoData: ArrayBuffer, fileName: string) => { try { const result = await dialog.showSaveDialog({ title: 'Save Exported Video', defaultPath: path.join(app.getPath('downloads'), fileName), filters: [ { name: 'MP4 Video', extensions: ['mp4'] } ], properties: ['createDirectory', 'showOverwriteConfirmation'] }); if (result.canceled || !result.filePath) { return { success: false, cancelled: true, message: 'Export cancelled' }; } await fs.writeFile(result.filePath, Buffer.from(videoData)); return { success: true, path: result.filePath, message: 'Video exported successfully' }; } catch (error) { console.error('Failed to save exported video:', error) return { success: false, message: 'Failed to save exported video', error: String(error) } } }) ipcMain.handle('open-video-file-picker', async () => { try { const result = await dialog.showOpenDialog({ title: 'Select Video File', defaultPath: RECORDINGS_DIR, filters: [ { name: 'Video Files', extensions: ['webm', 'mp4', 'mov', 'avi', 'mkv'] }, { name: 'All Files', extensions: ['*'] } ], properties: ['openFile'] }); if (result.canceled || result.filePaths.length === 0) { return { success: false, cancelled: true }; } return { success: true, path: result.filePaths[0] }; } catch (error) { console.error('Failed to open file picker:', error); return { success: false, message: 'Failed to open file picker', error: String(error) }; } }); let currentVideoPath: string | null = null; ipcMain.handle('set-current-video-path', (_, path: string) => { currentVideoPath = path; return { success: true }; }); ipcMain.handle('get-current-video-path', () => { return currentVideoPath ? { success: true, path: currentVideoPath } : { success: false }; }); ipcMain.handle('clear-current-video-path', () => { currentVideoPath = null; return { success: true }; }); }