From 2dc94084ab29168957e07981a9388b797802f891 Mon Sep 17 00:00:00 2001 From: Administrator Date: Sun, 19 Apr 2026 22:08:22 +0200 Subject: [PATCH] fix: vidmoly login verification + retry stale-uploadId + faster account toggle Three fixes bundled: - Vidmoly redesign broke login: the old check required either the 'login' or 'xfsts' cookie, but the new site sets different cookie names. Now we verify by fetching /?op=my_account and looking for logged-in markers (Logout / My Account / My Files) in the body instead of relying on specific cookie names. - retrySelectedJobs left the stale uploadId in _jobIndexByUploadId when resetting a job. A late 'aborted'/'error' event from the original (cancelled) upload could route back to the reset job and overwrite its 'preview' state. Now the old uploadId is removed from the index and marked in _deletedJobIds so those stragglers get dropped. - toggleAccount did two IPC round-trips (saveConfig + getConfig) on every enable/disable click, plus four re-renders (Accounts, HosterSummary, HosterModal, Settings). Rapid clicks felt laggy. The getConfig refetch is redundant since we mutated the flag in place, and HosterModal/Settings don't depend on account enabled state. Click now renders immediately and the save runs async. --- lib/vidmoly-upload.js | 18 ++++++++++++++---- renderer/app.js | 25 +++++++++++++++++++------ 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/lib/vidmoly-upload.js b/lib/vidmoly-upload.js index e4e8d07..f4e70d5 100644 --- a/lib/vidmoly-upload.js +++ b/lib/vidmoly-upload.js @@ -111,12 +111,22 @@ class VidmolyUploader { throw new Error('Vidmoly Login fehlgeschlagen: Falscher Username oder Passwort'); } - // Check for login cookie - const hasSession = this.cookies.has('login') || this.cookies.has('xfsts') || - this.cookies.size > 1; - if (!hasSession) { + // Verify session by fetching a logged-in-only page. Vidmoly redesigned + // the site and changed cookie names, so the old "has cookie 'login' or + // 'xfsts'" heuristic broke. Instead we hit /?op=my_account (or similar) + // and confirm we're not redirected to the login form. + if (this.cookies.size === 0) { throw new Error('Vidmoly Login fehlgeschlagen: Keine Session erhalten'); } + const verifyRes = await this._fetch(`${BASE_URL}/?op=my_account`); + const verifyBody = await verifyRes.text(); + // A logged-out page shows the login form (name="login" + name="password"); + // a logged-in page shows account info ("Logout", "My Account", "My Files"). + const looksLoggedIn = /(?:logout|my[_ ]?account|my[_ ]?files)/i.test(verifyBody) + && !/]*>\s*[\s\S]{0,500}?name=["']password["']/i.test(verifyBody); + if (!looksLoggedIn) { + throw new Error('Vidmoly Login fehlgeschlagen: Session konnte nicht verifiziert werden'); + } } /** diff --git a/renderer/app.js b/renderer/app.js index 795110e..f6f4c76 100644 --- a/renderer/app.js +++ b/renderer/app.js @@ -1886,8 +1886,19 @@ function handleStats(data) { // --- Retry --- async function retrySelectedJobs() { const retryJobs = []; + // Build a Set for O(1) selectedFiles dedup below. + const existingFilePaths = new Set(); + for (const f of selectedFiles) existingFilePaths.add(f.path); + queueJobs.forEach(j => { if (selectedJobIds.has(j.id) && ['error', 'done', 'aborted', 'skipped'].includes(j.status)) { + // Invalidate the old uploadId: retire the index entry and mark it so + // any late progress event from the previous (cancelled/completed) + // upload can't overwrite the freshly-reset state. + if (j.uploadId) { + _jobIndexByUploadId.delete(j.uploadId); + _deletedJobIds.add(j.uploadId); + } j.status = uploading ? 'queued' : 'preview'; j.error = null; j.result = null; @@ -1898,8 +1909,9 @@ async function retrySelectedJobs() { j.progress = 0; j.uploadId = null; retryJobs.push(j); - if (!selectedFiles.find(f => f.path === j.file || f.name === j.fileName)) { + if (!existingFilePaths.has(j.file)) { selectedFiles.push({ path: j.file, name: j.fileName, size: j.bytesTotal }); + existingFilePaths.add(j.file); } } }); @@ -2868,14 +2880,15 @@ function setupAccountDragReorder(container) { async function toggleAccount(accountId) { const found = findAccountById(accountId); if (!found) return; - found.account.enabled = found.account.enabled === false ? true : false; - await window.api.saveConfig({ hosters: config.hosters }); - config = await window.api.getConfig(); + // Flip in place; re-render immediately so the UI responds before the + // disk write completes. The saveConfig is fire-and-forget-ish here because + // we already know the new state locally — a full getConfig round-trip + // after every toggle made rapid enable/disable clicks feel laggy. + found.account.enabled = !found.account.enabled; syncSelectedUploadHosters(); renderAccounts(); renderHosterSummary(); - renderHosterModal(); - renderSettings(); + try { await window.api.saveConfig({ hosters: config.hosters }); } catch {} } async function checkSingleAccount(accountId) {