diff --git a/typescript-version/package-lock.json b/typescript-version/package-lock.json
index 89827e5..e4b6f2e 100644
--- a/typescript-version/package-lock.json
+++ b/typescript-version/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "twitch-vod-manager",
- "version": "4.1.7",
+ "version": "4.1.8",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "twitch-vod-manager",
- "version": "4.1.7",
+ "version": "4.1.8",
"license": "MIT",
"dependencies": {
"axios": "^1.6.0",
diff --git a/typescript-version/package.json b/typescript-version/package.json
index 62ab971..3ffe8d6 100644
--- a/typescript-version/package.json
+++ b/typescript-version/package.json
@@ -1,6 +1,6 @@
{
"name": "twitch-vod-manager",
- "version": "4.1.7",
+ "version": "4.1.8",
"description": "Twitch VOD Manager - Download Twitch VODs easily",
"main": "dist/main.js",
"author": "xRangerDE",
diff --git a/typescript-version/src/index.html b/typescript-version/src/index.html
index fa4a751..a50e466 100644
--- a/typescript-version/src/index.html
+++ b/typescript-version/src/index.html
@@ -457,7 +457,7 @@
Updates
-
Version: v4.1.7
+
Version: v4.1.8
@@ -502,7 +502,7 @@
Nicht verbunden
- v4.1.7
+ v4.1.8
diff --git a/typescript-version/src/main.ts b/typescript-version/src/main.ts
index aade707..cd38aea 100644
--- a/typescript-version/src/main.ts
+++ b/typescript-version/src/main.ts
@@ -8,7 +8,7 @@ import { autoUpdater } from 'electron-updater';
// ==========================================
// CONFIG & CONSTANTS
// ==========================================
-const APP_VERSION = '4.1.7';
+const APP_VERSION = '4.1.8';
const UPDATE_CHECK_URL = 'http://24-music.de/version.json';
// Paths
@@ -396,6 +396,7 @@ let autoUpdateStartupTimer: NodeJS.Timeout | null = null;
let autoUpdateCheckInProgress = false;
let autoUpdateReadyToInstall = false;
let lastAutoUpdateCheckAt = 0;
+let twitchLoginInFlight: Promise | null = null;
// ==========================================
// TOOL PATHS
@@ -1447,6 +1448,10 @@ function emitQueueUpdated(force = false): void {
mainWindow?.webContents.send('queue-updated', downloadQueue);
}
+function hasQueueItemId(id: string): boolean {
+ return downloadQueue.some((item) => item.id === id);
+}
+
function getRuntimeMetricsSnapshot(): RuntimeMetricsSnapshot {
return {
...runtimeMetrics,
@@ -1644,6 +1649,22 @@ async function twitchLogin(): Promise {
}
}
+function requestTwitchLogin(): Promise {
+ if (twitchLoginInFlight) {
+ return twitchLoginInFlight;
+ }
+
+ let loginPromise: Promise;
+ loginPromise = twitchLogin().finally(() => {
+ if (twitchLoginInFlight === loginPromise) {
+ twitchLoginInFlight = null;
+ }
+ });
+
+ twitchLoginInFlight = loginPromise;
+ return loginPromise;
+}
+
async function ensureTwitchAuth(forceRefresh = false): Promise {
if (!config.client_id || !config.client_secret) {
accessToken = null;
@@ -1654,7 +1675,7 @@ async function ensureTwitchAuth(forceRefresh = false): Promise {
return true;
}
- return await twitchLogin();
+ return await requestTwitchLogin();
}
function normalizeLogin(input: string): string {
@@ -2749,6 +2770,14 @@ async function processQueue(): Promise {
}
}
+ if (!hasQueueItemId(item.id)) {
+ appendDebugLog('queue-item-finished-removed', { itemId: item.id });
+ runtimeMetrics.activeItemId = null;
+ runtimeMetrics.activeItemTitle = null;
+ activeQueueItemId = null;
+ continue;
+ }
+
const wasPaused = pauseRequested || (finalResult.error || '').includes('pausiert');
item.status = finalResult.success ? 'completed' : (wasPaused ? 'paused' : 'error');
item.progress = finalResult.success ? 100 : item.progress;
@@ -2813,6 +2842,13 @@ function createWindow(): void {
mainWindow.loadFile(path.join(__dirname, '../src/index.html'));
+ mainWindow.webContents.on('did-finish-load', () => {
+ emitQueueUpdated(true);
+ if (isDownloading) {
+ mainWindow?.webContents.send('download-started');
+ }
+ });
+
mainWindow.on('closed', () => {
mainWindow = null;
});
@@ -2961,6 +2997,7 @@ ipcMain.handle('save-config', (_, newConfig: Partial) => {
if (config.client_id !== previousClientId || config.client_secret !== previousClientSecret) {
accessToken = null;
+ twitchLoginInFlight = null;
}
if (config.metadata_cache_minutes !== previousCacheMinutes) {
@@ -3021,6 +3058,9 @@ ipcMain.handle('remove-from-queue', (_, id: string) => {
if (currentProcess) {
currentProcess.kill();
}
+ activeQueueItemId = null;
+ runtimeMetrics.activeItemId = null;
+ runtimeMetrics.activeItemTitle = null;
appendDebugLog('queue-item-removed-active-cancelled', { id });
}
diff --git a/typescript-version/src/renderer-globals.d.ts b/typescript-version/src/renderer-globals.d.ts
index 64e22b3..23e9cf6 100644
--- a/typescript-version/src/renderer-globals.d.ts
+++ b/typescript-version/src/renderer-globals.d.ts
@@ -178,7 +178,7 @@ interface ApiBridge {
cutVideo(inputFile: string, startTime: number, endTime: number): Promise<{ success: boolean; outputFile: string | null }>;
mergeVideos(inputFiles: string[], outputFile: string): Promise<{ success: boolean; outputFile: string | null }>;
getVersion(): Promise;
- checkUpdate(): Promise<{ checking?: boolean; error?: boolean }>;
+ checkUpdate(): Promise<{ checking?: boolean; error?: boolean; skipped?: 'ready-to-install' | 'in-progress' | 'throttled' | 'error' | string }>;
downloadUpdate(): Promise<{ downloading?: boolean; error?: boolean }>;
installUpdate(): Promise;
openExternal(url: string): Promise;
diff --git a/typescript-version/src/renderer-updates.ts b/typescript-version/src/renderer-updates.ts
index 3a77c22..375bec4 100644
--- a/typescript-version/src/renderer-updates.ts
+++ b/typescript-version/src/renderer-updates.ts
@@ -3,7 +3,16 @@ async function checkUpdateSilent(): Promise {
}
async function checkUpdate(): Promise {
- await window.api.checkUpdate();
+ const result = await window.api.checkUpdate();
+
+ if (result?.error) {
+ return;
+ }
+
+ const skippedReason = result?.skipped;
+ if (skippedReason === 'in-progress' || skippedReason === 'ready-to-install' || skippedReason === 'throttled') {
+ return;
+ }
setTimeout(() => {
if (byId('updateBanner').style.display !== 'flex') {
diff --git a/typescript-version/src/renderer.ts b/typescript-version/src/renderer.ts
index 11d0b03..9abd095 100644
--- a/typescript-version/src/renderer.ts
+++ b/typescript-version/src/renderer.ts
@@ -10,6 +10,8 @@ async function init(): Promise {
config.language = language;
const initialQueue = await window.api.getQueue();
queue = Array.isArray(initialQueue) ? initialQueue : [];
+ downloading = await window.api.isDownloading();
+ markQueueActivity();
const version = await window.api.getVersion();
byId('versionText').textContent = `v${version}`;