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;