diff --git a/com.burnttoasters.rosi.metainfo.xml b/com.burnttoasters.rosi.metainfo.xml index 17ff00c..46ef13b 100644 --- a/com.burnttoasters.rosi.metainfo.xml +++ b/com.burnttoasters.rosi.metainfo.xml @@ -33,7 +33,7 @@ - + diff --git a/package-lock.json b/package-lock.json index 2f2a581..d785824 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "rosi", - "version": "4.0.0", + "version": "4.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "rosi", - "version": "4.0.0", + "version": "4.0.1", "license": "MPL-2.0", "dependencies": { "electron-log": "^5.3.4", diff --git a/package.json b/package.json index 73765ed..34685b3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rosi", - "version": "4.0.0", + "version": "4.0.1", "private": true, "description": "Electron GUI for yt-dlp", "keywords": [ diff --git a/src/main/main.ts b/src/main/main.ts index b76a842..ac6c45f 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -48,6 +48,9 @@ process.on('uncaughtException', (error) => { try { killAllProcesses(); } catch {} + try { + cancelFormats(); + } catch {} try { dialog.showErrorBox( 'Fatal Error', @@ -75,6 +78,7 @@ let mainWindow: BrowserWindow | null = null; let splashWindow: BrowserWindow | null = null; let mainWindowCloseInProgress = false; let mainWindowCloseTimer: NodeJS.Timeout | null = null; +let appQuitting = false; function getMainWindow() { return mainWindow; @@ -278,6 +282,7 @@ function createWindow() { mainWindowCloseTimer = setTimeout(() => { log.warn('Timed out waiting for renderer settings flush. Closing window.'); + mainWindowCloseInProgress = false; if (mainWindow && !mainWindow.isDestroyed()) { mainWindow.destroy(); } @@ -391,7 +396,7 @@ void app.whenReady().then(() => { }); app.on('window-all-closed', () => { - if (process.platform !== 'darwin') app.quit(); + if (process.platform !== 'darwin' || appQuitting) app.quit(); }); app.on('activate', () => { @@ -399,6 +404,7 @@ app.on('activate', () => { }); app.on('before-quit', () => { + appQuitting = true; try { killAllProcesses(); } catch (error) { @@ -461,7 +467,10 @@ ipcMain.handle('save-settings', (_, data) => { ipcMain.handle('detect-gpu', () => detectGpu()); -ipcMain.on('reset-settings', () => { +ipcMain.on('reset-settings', (event) => { + if (mainWindow && !mainWindow.isDestroyed() && event.sender?.id !== mainWindow.webContents.id) { + return; + } try { const saved = saveSettings(getDefaultSettings(), mainWindow); if (!saved) { @@ -531,9 +540,17 @@ ipcMain.handle('getFormats', async (_, url) => { return errorResult('INTERNAL_ERROR', message); } }); -ipcMain.on('cancel-formats', () => cancelFormats()); +ipcMain.on('cancel-formats', (event) => { + if (mainWindow && !mainWindow.isDestroyed() && event.sender?.id !== mainWindow.webContents.id) { + return; + } + cancelFormats(); +}); ipcMain.handle('download-video', (event, options) => { + if (mainWindow && !mainWindow.isDestroyed() && event.sender?.id !== mainWindow.webContents.id) { + return errorResult('VALIDATION_ERROR', 'Unauthorized sender.'); + } const validation = validateDownloadRequestPayload(options); if (!validation.ok) { return errorResult(validation.error.code, validation.error.message, validation.error.details); @@ -548,7 +565,10 @@ ipcMain.handle('download-video', (event, options) => { } }); -ipcMain.on('cancel-download', () => { +ipcMain.on('cancel-download', (event) => { + if (mainWindow && !mainWindow.isDestroyed() && event.sender?.id !== mainWindow.webContents.id) { + return; + } try { cancelActiveSession(true); } catch (error) { @@ -609,9 +629,10 @@ ipcMain.handle('show-notification', (_, options) => { notification.on('click', () => { try { - if (mainWindow && !mainWindow.isDestroyed()) { - if (mainWindow.isMinimized()) mainWindow.restore(); - mainWindow.focus(); + const win = getMainWindow(); + if (win && !win.isDestroyed()) { + if (win.isMinimized()) win.restore(); + win.focus(); } if (validation.data.filePath) { shell.showItemInFolder(validation.data.filePath); diff --git a/src/renderer/rosiEngine.js b/src/renderer/rosiEngine.js index e5ea607..454520e 100644 --- a/src/renderer/rosiEngine.js +++ b/src/renderer/rosiEngine.js @@ -595,9 +595,10 @@ function updateProgressBar(percent, statusText = null, detailsText = null) { const bar = document.getElementById('progress-bar'); const details = document.getElementById('progress-details'); - if (percentEl) percentEl.textContent = `${Math.round(percent)}%`; + const clamped = Math.max(0, Math.min(100, percent)); + if (percentEl) percentEl.textContent = `${Math.round(clamped)}%`; if (bar) { - bar.style.width = `${percent}%`; + bar.style.width = `${clamped}%`; bar.classList.remove('indeterminate'); } if (statusText && statusEl) statusEl.textContent = statusText;