UI Phase 2: Einstellungen-Tab neu strukturiert (Untergruppen + Erklaertexte) + konfigurierbarer Verlauf (Obergrenze + Zeitlimit)
Settings-Rework (User-Wunsch, mit Multi-Agent-Design-Runde fuer die Taxonomie: 3 Lenses -> Synthese, gegen das echte settingsDraft-Inventar auf Vollstaendigkeit geprueft, 51 Einstellungen je genau einmal platziert). UI (App.tsx + styles.css): - 5 der 6 Bereiche (Allgemein/Entpacken/Geschwindigkeit/Bereinigung/Updates) in klare Untergruppen mit Unter-Ueberschriften (.settings-subhead) gegliedert, je Bereich ein Intro, und unter JEDER Einstellung ein knapper Erklaertext (.setting-hint, <= ~90 Zeichen, echte Umlaute). Reihenfolge nach Aufgaben-Logik (z.B. Allgemein: Speicherort / Download-Verhalten / Verlauf / Oberflaeche / Discord; Entpacken: Ziel & Ablauf / Deutsche Tonspur / Ablageform / Leistung / Passwoerter). Einige Labels praezisiert (z.B. "Codeberg Repo" -> "Update-Quelle", "Light Mode" -> "Heller Modus"). Account-Bereich bleibt fuer Phase 3 unangetastet. Verlauf-Retention konfigurierbar (vorher: hart 500, kein Zeitlimit): - Neue Settings historyMaxEntries (Standard 500) + historyMaxAgeDays (Standard 0=aus) in types/constants/normalizeSettings (geclamped 50..100000 bzw. 0..3650) + App- Default-Snapshot. Zwei neue Zahlenfelder im Bereich Allgemein -> Verlauf, direkt unter "Verlauf speichern"; ausgegraut wenn nicht "Dauerhaft". - storage.ts: pruneHistoryEntries(entries, limits) wendet Alters- (completedAt < jetzt - Tage) und Anzahl-Grenze an; load/save/addHistoryEntry + die *ForRetention- Wrapper nehmen optionale Limits. app-controller reicht die Limits aus den Settings durch (historyLimits()) und schneidet den Verlauf bei Aenderung der Grenzen aktiv neu (damit "aelter als X Tage" wirklich von der Platte fliegt). 2 neue storage-Tests (Anzahl-Cap, Alters-Pruning). 810 Tests gruen, tsc=6 Baseline, self-check + build ok.
This commit is contained in:
@@ -332,6 +332,59 @@ describe("settings storage", () => {
|
||||
expect(loadHistory(paths)).toEqual([]);
|
||||
});
|
||||
|
||||
it("caps persisted history to the configured maxEntries", () => {
|
||||
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "rd-store-"));
|
||||
tempDirs.push(dir);
|
||||
const paths = createStoragePaths(dir);
|
||||
const now = Date.now();
|
||||
const entries = Array.from({ length: 10 }, (_unused, i) => ({
|
||||
id: `h-${i}`,
|
||||
name: `e${i}`,
|
||||
totalBytes: 1,
|
||||
downloadedBytes: 1,
|
||||
fileCount: 1,
|
||||
provider: "realdebrid" as const,
|
||||
completedAt: now - i * 1000,
|
||||
durationSeconds: 1,
|
||||
status: "completed" as const,
|
||||
outputDir: path.join(dir, "out"),
|
||||
urls: []
|
||||
}));
|
||||
|
||||
saveHistory(paths, entries, { maxEntries: 3, maxAgeDays: 0 });
|
||||
|
||||
const loaded = loadHistory(paths, { maxEntries: 3, maxAgeDays: 0 });
|
||||
expect(loaded).toHaveLength(3);
|
||||
expect(loaded.map((e) => e.id)).toEqual(["h-0", "h-1", "h-2"]);
|
||||
});
|
||||
|
||||
it("drops history entries older than maxAgeDays", () => {
|
||||
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "rd-store-"));
|
||||
tempDirs.push(dir);
|
||||
const paths = createStoragePaths(dir);
|
||||
const now = Date.now();
|
||||
const day = 24 * 60 * 60 * 1000;
|
||||
const fresh = {
|
||||
id: "fresh",
|
||||
name: "fresh",
|
||||
totalBytes: 1,
|
||||
downloadedBytes: 1,
|
||||
fileCount: 1,
|
||||
provider: "realdebrid" as const,
|
||||
completedAt: now - 2 * day,
|
||||
durationSeconds: 1,
|
||||
status: "completed" as const,
|
||||
outputDir: path.join(dir, "out"),
|
||||
urls: []
|
||||
};
|
||||
const old = { ...fresh, id: "old", name: "old", completedAt: now - 40 * day };
|
||||
|
||||
saveHistory(paths, [fresh, old], { maxEntries: 500, maxAgeDays: 30 });
|
||||
|
||||
const loaded = loadHistory(paths, { maxEntries: 500, maxAgeDays: 30 });
|
||||
expect(loaded.map((e) => e.id)).toEqual(["fresh"]);
|
||||
});
|
||||
|
||||
it("assigns and preserves bandwidth schedule ids", () => {
|
||||
const normalized = normalizeSettings({
|
||||
...defaultSettings(),
|
||||
|
||||
Reference in New Issue
Block a user