From 950a3220222b0820ea60b5c536c11158bb1beb84 Mon Sep 17 00:00:00 2001 From: Administrator Date: Sat, 23 May 2026 01:03:07 +0200 Subject: [PATCH] =?UTF-8?q?ux(accounts):=20hoster-specific=20login=20field?= =?UTF-8?q?=20labels=20=E2=80=94=20VOE=20shows=20"E-Mail"=20only?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Generic "Username / E-Mail" label on every login-type account form sent users down a confusing path on VOE: VOE only accepts an email address (the web form is type=email, name=email), but the app's label suggested either was fine. Logging in with a username silently failed → upload-page fetch returned a login redirect → the "VOE Upload: CSRF-Token nicht gefunden. Bist du eingeloggt?" error, which doesn't point at the actual cause. Add a tiny per-hoster override table. Currently only voe.sx is in it: label "E-Mail", placeholder "E-Mail-Adresse", input type="email" (so the browser's email-format hint kicks in too). All three getCredsFieldsHtml call sites pass the hoster name — edit-mode, add-mode initial render, and the hoster-select change handler. Other hosters keep the existing "Username / E-Mail" wording. 137/137 tests still green. --- renderer/app.js | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/renderer/app.js b/renderer/app.js index 4f0ef31..a993225 100644 --- a/renderer/app.js +++ b/renderer/app.js @@ -3218,13 +3218,24 @@ async function checkSingleAccount(accountId) { updateAccountCard(accountId); } -function getCredsFieldsHtml(authType, account) { +// Per-hoster overrides for the login form. VOE only accepts emails — the +// generic "Username / E-Mail" label sent users down a confusing rabbit hole +// (login fails → upload fetches login redirect → "CSRF token nicht gefunden"). +// Other hosters that genuinely accept either keep the generic wording. +const LOGIN_FIELD_LABELS = { + 'voe.sx': { label: 'E-Mail', placeholder: 'E-Mail-Adresse', inputType: 'email' } +}; + +function getCredsFieldsHtml(authType, account, hoster) { account = account || {}; if (authType === 'login') { + const fld = (hoster && LOGIN_FIELD_LABELS[hoster]) || { + label: 'Username / E-Mail', placeholder: 'Username oder E-Mail', inputType: 'text' + }; return `
- - + +
@@ -3263,7 +3274,7 @@ function openAccountModal(editAccountId) { subtitle.textContent = `Zugangsdaten für ${getAccountDisplayName(found.name, found.account)} bearbeiten.`; hosterRow.style.display = 'none'; saveBtn.textContent = 'Speichern & prüfen'; - credsContainer.innerHTML = getCredsFieldsHtml(found.account.authType || 'login', found.account); + credsContainer.innerHTML = getCredsFieldsHtml(found.account.authType || 'login', found.account, found.name); } else { // Add mode — always show all options (multiple accounts per hoster allowed) title.textContent = 'Account hinzufügen'; @@ -3274,7 +3285,7 @@ function openAccountModal(editAccountId) { `` ).join(''); const firstOpt = HOSTER_ADD_OPTIONS[0]; - credsContainer.innerHTML = getCredsFieldsHtml(firstOpt.authType, {}); + credsContainer.innerHTML = getCredsFieldsHtml(firstOpt.authType, {}, firstOpt.value); } // Toggle visibility buttons @@ -3890,7 +3901,7 @@ function setupListeners() { const opt = HOSTER_ADD_OPTIONS.find(o => o.value === e.target.value); const authType = opt ? opt.authType : 'login'; const credsContainer = document.getElementById('accountCredsFields'); - credsContainer.innerHTML = getCredsFieldsHtml(authType, {}); + credsContainer.innerHTML = getCredsFieldsHtml(authType, {}, e.target.value); credsContainer.querySelectorAll('.toggle-vis').forEach(btn => { btn.addEventListener('click', () => { const input = btn.previousElementSibling;