From 3cab75702a44578ebc5923bbf0403d0b4689bc39 Mon Sep 17 00:00:00 2001 From: Sucukdeluxe <259325684+Sucukdeluxe@users.noreply.github.com> Date: Tue, 22 Sep 2026 05:45:22 +0200 Subject: [PATCH] Align online backup validity controls with settings layout --- PROJECT_MEMORY.md | 2 ++ renderer/styles.css | 24 ++++++++++----- tests/startup-renderer.test.js | 55 +++++++++++++++++++++++++++++++++- 3 files changed, 73 insertions(+), 8 deletions(-) diff --git a/PROJECT_MEMORY.md b/PROJECT_MEMORY.md index ddb7df1..0cf546e 100644 --- a/PROJECT_MEMORY.md +++ b/PROJECT_MEMORY.md @@ -6,6 +6,7 @@ Multi-Hoster-Upload ist eine Electron-Desktopanwendung für Windows, die große ## Aktueller Zustand +- Online-Backup-Gültigkeitsdauer nach `2.1.49`, noch nicht veröffentlicht: Auswahl und Erstellen-Button verwenden 40 px Höhe und 14 px Schrift; Label und Auswahl sind zur Importzeile ausgerichtet. Footer bricht bei Platzmangel um, auf schmalen Fenstern untereinander. Leere Statuszeile belegt keinen Platz; echte Meldungen bleiben sichtbar. Nativer Select und 14 px Pfeil-Innenabstand bleiben erhalten. Electron-Layoutregression bei 1000, 600 und 360 px; Screenshot der breiten Darstellung visuell geprüft. - Nach `2.1.49`, noch nicht veröffentlicht: Backup-Untermenü erhält eine durchgängige Hover-Fläche über den sichtbaren Abstand und 250 ms abbrechbare Schließverzögerung. Hover plus Klick bleibt offen, erneutes Betreten startet keine neue Öffnungsanimation; Tastaturfokus hält das Untermenü offen. Pfeil und Pfeiltasten folgen der linken Öffnungsrichtung, Escape schließt nur die aktuelle Untermenüebene. Fremde `animationend`-Ereignisse schließen kein übergeordnetes Panel mehr. Electron-Regression prüft DOM-Treffertests im Abstand, verzögerte Ein-/Austritte, Klick, Fokus und Escape bei 850 und 600 Pixel Fensterbreite. Kein Release beauftragt. - Release `2.1.49` auf beiden Plattformen veröffentlicht und geprüft: Vidmoly-Sitzungsprüfung, getrennte Upload-Sperrmeldungen, Checkbox-Fokusfix und GB-Dateigrößenlimit. Live-Diagnose am 22.09.2026 bestätigt zuerst gültige Anmeldung mit `UPLOAD_DISABLED` (Upload-Konfiguration HTTP 403), danach erfolgreiche Anmeldung und vollständige Upload-Konfiguration (HTTP 200). Nutzer bestätigt funktionierende Anmeldung und gibt Release frei. Ein tatsächlicher Dateitransfer wurde dadurch nicht nachgewiesen. Ältere Angaben zu unveröffentlichten Änderungen darunter dokumentieren die Vorbereitung; diese Änderungen sind jetzt in `2.1.49` enthalten. - Vidmoly nach `2.1.48`, noch nicht veröffentlicht: Anmeldung wird über `/api/auth/me` statt anhand der Upload-Konfiguration verifiziert. Öffentliches Website-JavaScript am 22.09.2026 bestätigt unveränderte Upload-Felder sowie `DISK_FULL`, `UPLOAD_IP_BLACKLIST` und `UPLOAD_DISABLED`; diese Antworten werden jetzt getrennt und ohne Antwortdaten angezeigt. Upload übernimmt zusätzlich das aktuelle Webfeld `tos=1`, weiterhin ohne API-Key. HTTP-Fehler, fehlende Benutzer, OTP-Anforderung und ungültige Serveradressen werden geprüft. Die konkrete Serverantwort des gemeldeten Accounts war in den lokalen Logs nicht vorhanden; erfolgreicher Live-Login/Upload ist noch nicht bestätigt. @@ -89,6 +90,7 @@ npm audit --omit=dev ## Zuletzt verifiziert +- Gültigkeitsdauer-Layout: neue Electron-Regression erfolgreich, Screenshot visuell geprüft, Lint und 18 Servertests erfolgreich. Hauptlauf 838/839 erfolgreich: Menü-Fokustest reagierte einmal zu früh auf asynchronen Fokus. Test wartet jetzt begrenzt auf den tatsächlichen Fokus statt pauschal 240 ms; kompletter Wiederholungslauf der betroffenen Datei 25/25 erfolgreich. Kein Release erstellt. - Backup-Untermenü nach `2.1.49`: 838 Haupttests, 18 Servertests und Lint erfolgreich. Gezielter Electron-Test nach abschließender Fokuskorrektur erneut erfolgreich; ein Mausklick auf den Trigger hält das Menü beim Verlassen nicht unbeabsichtigt offen. Änderungen noch nicht veröffentlicht. - Release `2.1.49`: Titel, Tags, englischer GitHub- und deutscher Forgejo-Changelog, jeweils vier Assets und Update-Metadaten geprüft. Alle acht veröffentlichten Dateien erneut heruntergeladen und Größe sowie SHA-512 mit lokalen Dateien verglichen. Echter Updater erkennt `2.1.49` ausgehend von `2.1.48` und akzeptiert englische Hinweise sowie Forgejo-Manifest. Öffentlicher Quellcheck einschließlich Screenshots erfolgreich (164 Dateien). Keine produktive Serveränderung erforderlich. - Releasevorbereitung `2.1.49`: 837 Haupttests und 18 Backup-API-Tests erfolgreich, Lint erfolgreich, Produktionsaudit ohne Schwachstellen. Installer 98.033.241 Bytes, Portable 97.808.535 Bytes, beide Produktversion `2.1.49`. Gepackte Vidmoly-, Upload-, UI- und Backupmodule entsprechen dem Quellstand; keine Nutzerdaten enthalten. Installer-SHA-512 und Größe stimmen mit dem Update-Manifest überein. diff --git a/renderer/styles.css b/renderer/styles.css index ea30851..cc241c5 100644 --- a/renderer/styles.css +++ b/renderer/styles.css @@ -2243,7 +2243,8 @@ select.hs-input { max-width: none; width: auto; min-width: 140px; } .online-backup-footer { display: flex; - align-items: flex-end; + align-items: center; + flex-wrap: wrap; gap: 12px; justify-content: flex-end; min-width: 0; @@ -2251,13 +2252,16 @@ select.hs-input { max-width: none; width: auto; min-width: 140px; } .online-backup-retention-field { display: grid; - gap: 6px; - min-width: 190px; + grid-template-columns: 150px minmax(210px, 300px); + align-items: center; + gap: 10px; + flex: 1 1 370px; + min-width: 0; } .online-backup-retention-field label { color: var(--text); - font-size: 12px; + font-size: 14px; font-weight: 600; } @@ -2280,15 +2284,15 @@ select.hs-input { max-width: none; width: auto; min-width: 140px; } .online-backup-retention-select select { width: 100%; - min-height: 34px; + min-height: 40px; padding: 7px 38px 7px 11px; border: 1px solid var(--border); border-radius: 6px; appearance: none; color: var(--text); - background: var(--bg-card); + background: var(--bg-input); font: inherit; - font-size: 13px; + font-size: 14px; } .online-backup-retention-select select:focus { @@ -2307,6 +2311,10 @@ select.hs-input { max-width: none; width: auto; min-width: 140px; } font-size: 12px; } +.online-backup-status:empty { + display: none; +} + .online-backup-status[data-state="success"] { color: var(--success); } @@ -2338,6 +2346,8 @@ select.hs-input { max-width: none; width: auto; min-width: 140px; } .online-backup-retention-field { width: 100%; + grid-template-columns: 1fr; + flex-basis: auto; } } diff --git a/tests/startup-renderer.test.js b/tests/startup-renderer.test.js index 92774bd..36ca8af 100644 --- a/tests/startup-renderer.test.js +++ b/tests/startup-renderer.test.js @@ -140,7 +140,8 @@ app.whenReady().then(async () => { await wait(500); assert.equal((await state()).display, 'none'); await js('document.querySelector(".menu-submenu-trigger").focus();document.querySelector(".menu-submenu-trigger").dispatchEvent(new KeyboardEvent("keydown",{key:"ArrowLeft",bubbles:true}))'); - await wait(240); + const focusDeadline = Date.now() + 3000; + while (await js('document.activeElement.dataset.menuAction') !== 'backup-export' && Date.now() < focusDeadline) await wait(50); assert.equal(await js('document.activeElement.dataset.menuAction'), 'backup-export'); await js('document.activeElement.dispatchEvent(new KeyboardEvent("keydown",{key:"Escape",bubbles:true}))'); await wait(240); @@ -164,6 +165,58 @@ app.whenReady().then(async () => { assert.equal(data.ok, true); }); +test('online backup validity controls match settings sizing and adapt without overflow', { skip: process.platform !== 'win32' }, t => { + const root = path.resolve(__dirname, '..'); + const directory = fs.mkdtempSync(path.join(os.tmpdir(), 'mhu-retention-layout-')); + t.after(() => fs.rmSync(directory, { recursive: true, force: true })); + const probe = path.join(directory, 'probe.cjs'); + const result = path.join(directory, 'result.json'); + fs.writeFileSync(probe, ` +const { app, BrowserWindow } = require('electron'); +const fs = require('node:fs'); +const path = require('node:path'); +const assert = require('node:assert/strict'); +app.whenReady().then(async () => { + const root=process.env.MHU_RETENTION_ROOT; + const css=fs.readFileSync(path.join(root,'renderer/styles.css'),'utf8'); + const source=fs.readFileSync(path.join(root,'renderer/app.js'),'utf8'); + const footer=source.match(/