From c86605d67b0631b9eaafd12ae58e89e1cf260195 Mon Sep 17 00:00:00 2001 From: Sucukdeluxe <259325684+Sucukdeluxe@users.noreply.github.com> Date: Tue, 22 Sep 2026 05:58:33 +0200 Subject: [PATCH] Separate online backup creation, import and management sections --- PROJECT_MEMORY.md | 2 ++ renderer/app.js | 36 ++++++++++++++++++++-------------- renderer/i18n.js | 2 ++ renderer/styles.css | 16 +++++++++++++++ tests/startup-renderer.test.js | 13 ++++++++---- 5 files changed, 50 insertions(+), 19 deletions(-) diff --git a/PROJECT_MEMORY.md b/PROJECT_MEMORY.md index a30e014..dd1cac2 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-Seite nach `2.1.49`: drei klar abgegrenzte Bereiche in Reihenfolge „Schlüssel erstellen“, „Schlüssel importieren“, „Auf diesem Gerät erstellt“. Vorhandene IDs, Import-/Exportlogik, Statusmeldungen und Suchziele bleiben erhalten. Neue Überschriften auf Deutsch/Englisch; konsistente Karten ohne Akzentstreifen. Electron-Test nutzt jetzt das echte Seitenmarkup und prüft Modulzuordnung, Ausrichtung sowie Überlauf bei 1000/600/360 px. Lokale Entwicklerversion automatisch neu gestartet; breiter Screenshot visuell geprüft. Noch nicht veröffentlicht. - Lokale Entwicklung auf Nutzerwunsch dauerhaft mit automatischem Neustart: `.artifacts/dev-watch.cjs` überwacht Main-/Preload-Dateien, `lib`, `renderer` und den lokalen Bootstrap `.artifacts/menu-test.cjs`. Start über `node .artifacts/dev-watch.cjs`; separater Fenstertitel „Multi-Hoster – Entwicklung (automatischer Neustart)“. Persistentes Testprofil unter `%LOCALAPPDATA%/Multi-Hoster-Upload-Development`, ohne automatische Accountchecks/Ordnerüberwachung/Remote-Steuerung initialisiert. Installierte Anwendung bleibt getrennt. Neustart durch CSS-Dateiänderung anhand gewechselter Electron-PID und erneut sichtbarem Fenster verifiziert. Bei weiteren Code-/UI-Änderungen diesen Watcher verwenden und den Neustart prüfen. - 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. @@ -91,6 +92,7 @@ npm audit --omit=dev ## Zuletzt verifiziert +- Getrennte Online-Backup-Module: 839 Haupttests, 18 Servertests und Lint erfolgreich. Echtes Modulmarkup in Electron bei drei Fensterbreiten geprüft; Entwicklerversion nach Renderer-Änderung mit neuem Prozess sichtbar bestätigt. Noch kein Release. - 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. diff --git a/renderer/app.js b/renderer/app.js index ca83956..bbfc41a 100644 --- a/renderer/app.js +++ b/renderer/app.js @@ -6609,21 +6609,8 @@ function renderSettings() {

Verschlüsseltes Online-Backup

Die Verschlüsselung findet ausschließlich auf diesem Gerät statt. Der Server speichert nur verschlüsselte Daten.

-
- - - -
-

Behandle den Schlüssel wie ein Passwort. Wer ihn besitzt, kann die verschlüsselten Einstellungen entschlüsseln.

-
-

Auf diesem Gerät erstellt

-
- -
-
+
+

Schlüssel erstellen

+
+
+

Schlüssel importieren

+
+ + + +
+
+

Behandle den Schlüssel wie ein Passwort. Wer ihn besitzt, kann die verschlüsselten Einstellungen entschlüsseln.

+
+
+

Auf diesem Gerät erstellt

+
+ +
Lokales Datei-Backup
diff --git a/renderer/i18n.js b/renderer/i18n.js index 72a3c25..136541c 100644 --- a/renderer/i18n.js +++ b/renderer/i18n.js @@ -380,6 +380,8 @@ ['Verschlüsseltes Online-Backup', 'Encrypted online backup'], ['Die Verschlüsselung findet ausschließlich auf diesem Gerät statt. Der Server speichert nur verschlüsselte Daten.', 'Encryption takes place only on this device. The server stores encrypted data only.'], ['Neuen Schlüssel erzeugen', 'Generate new key'], + ['Schlüssel erstellen', 'Create key'], + ['Online-Schlüssel', 'Online key'], ['Gültigkeitsdauer', 'Validity period'], ['24 Stunden', '24 hours'], ['3 Tage', '3 days'], diff --git a/renderer/styles.css b/renderer/styles.css index cc241c5..b475fa0 100644 --- a/renderer/styles.css +++ b/renderer/styles.css @@ -2250,6 +2250,22 @@ select.hs-input { max-width: none; width: auto; min-width: 140px; } min-width: 0; } +.online-backup-module { + display: grid; + gap: 16px; + min-width: 0; + padding: 16px; + border: 1px solid var(--border); + border-radius: 8px; + background: var(--bg-card); +} + +.online-backup-module h4 { + margin: 0; + font-size: 14px; + font-weight: 600; +} + .online-backup-retention-field { display: grid; grid-template-columns: 150px minmax(210px, 300px); diff --git a/tests/startup-renderer.test.js b/tests/startup-renderer.test.js index 36ca8af..262e929 100644 --- a/tests/startup-renderer.test.js +++ b/tests/startup-renderer.test.js @@ -180,12 +180,17 @@ 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(/
')); + const win=new BrowserWindow({show:false,width:1000,height:800,webPreferences:{backgroundThrottling:false}}); const wc=win.webContents; for(const width of [1000,600,360]) { - win.setContentSize(width,500); - await wc.loadURL('data:text/html;charset=utf-8,'+encodeURIComponent('

Verschlüsseltes Online-Backup

'+footer+'
')); + win.setContentSize(width,800); + await wc.loadURL('data:text/html;charset=utf-8,'+encodeURIComponent('
'+panel+'
')); + assert.deepEqual(await wc.executeJavaScript('Array.from(document.querySelectorAll(".online-backup-module")).map(module=>({heading:module.getAttribute("aria-labelledby"),create:!!module.querySelector("#createOnlineBackupBtn"),import:!!module.querySelector("#restoreOnlineBackupBtn"),manage:!!module.querySelector("#managedOnlineBackupList")}))'),[ + {heading:'onlineBackupCreateHeading',create:true,import:false,manage:false}, + {heading:'onlineBackupImportHeading',create:false,import:true,manage:false}, + {heading:'managedOnlineBackupHeading',create:false,import:false,manage:true} + ]); const layout=await wc.executeJavaScript('(() => { const s=document.querySelector("select"), b=document.querySelector("footer button"), l=document.querySelector(".online-backup-retention-field label"), i=document.querySelector(".key-input"); const rect=e=>{const r=e.getBoundingClientRect();return {left:r.left,right:r.right,top:r.top,bottom:r.bottom,height:r.height}}; return {select:rect(s),button:rect(b),input:rect(i),labelFont:getComputedStyle(l).fontSize,selectFont:getComputedStyle(s).fontSize,buttonFont:getComputedStyle(b).fontSize,arrowRight:getComputedStyle(s.parentElement,"::after").right,empty:getComputedStyle(document.querySelector(".online-backup-status")).display,scroll:document.documentElement.scrollWidth,viewport:innerWidth}; })()'); assert.equal(layout.select.height,40); assert.equal(layout.button.height,40);