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}`;