release: publish Multi-Debrid Downloader v2.0.14

Add live English and German localization, queue availability and metadata resolution, responsive package controls, polished navigation and drag interactions, clearer history and account states, and a rebuilt public README. Harden Windows packaging with verified icons and version metadata, archive inspection, and expanded release tests.
This commit is contained in:
Sucukdeluxe
2026-08-10 19:42:49 +02:00
parent 069babfd54
commit a5758aa905
61 changed files with 9117 additions and 6754 deletions
+47 -11
View File
@@ -14,8 +14,9 @@ import {
type HistoryViewEntry
} from "../src/renderer/views/history/history-model";
import {
HistoryContent,
HistoryToolbar,
HistoryContent,
HistorySidebar,
HistoryToolbar,
HistoryView,
type HistoryViewActions
} from "../src/renderer/views/history/HistoryView";
@@ -203,8 +204,17 @@ describe("history model", () => {
});
});
describe("HistoryView", () => {
it("keeps the header and rows inside the same internal horizontal scroll context", () => {
describe("HistoryView", () => {
it("marks history filters for one measured vertical selection indicator", () => {
const model = buildHistoryViewModel(entries, "week", "", [], [], false, "", now);
const html = renderToStaticMarkup(<HistorySidebar actions={createActions()} model={model} />);
expect(html).toContain("ui-sliding-selection ui-sliding-selection-vertical");
expect(html.match(/data-sliding-selection-item="true"/g)).toHaveLength(7);
expect(html.match(/data-sliding-selection-active="true"/g)).toHaveLength(1);
});
it("keeps the header and rows inside the same internal horizontal scroll context", () => {
const html = renderToStaticMarkup(
<HistoryView
actions={createActions()}
@@ -273,11 +283,25 @@ describe("HistoryView", () => {
expect(html).toContain("history-status-failed");
expect(html).toContain("Abgeschlossen");
expect(html).toContain("Gelöscht");
expect(html).toContain("Fehlgeschlagen");
expect(html).not.toMatch(/>Start<|>Pause<|>Stop<|Priorität/);
});
it("renders each visual marker once, occupied main rows separately from closed detail rows and an honest footer", () => {
expect(html).toContain("Fehlgeschlagen");
expect(html).not.toMatch(/>Start<|>Pause<|>Stop<|Priorität/);
});
it("matches the download action control and centers every header except package and file", () => {
const content = HistoryContent({
actions: createActions(),
model: buildHistoryViewModel(entries.slice(0, 1), "all", "", [], [], false, "", now)
});
const actionCell = findElement(content, (element) => element.props.className === "history-row-action");
const styles = readFileSync(new URL("../src/renderer/views/history/history.css", import.meta.url), "utf8").replaceAll("\r\n", "\n");
expect(actionCell.props.children.props.children).toBe("⋮");
expect(styles).toMatch(/\.history-row-action button\s*\{[^}]*background:\s*var\(--ui-input\);[^}]*border:\s*1px solid var\(--ui-border\);[^}]*height:\s*30px;[^}]*width:\s*30px;/s);
expect(styles).toMatch(/\.history-table-header-row > span\s*\{[^}]*text-align:\s*center;/s);
expect(styles).toMatch(/\.history-table-header-row > span:nth-child\(2\)\s*\{[^}]*text-align:\s*left;/s);
});
it("renders each visual marker once, occupied main rows separately from closed detail rows and an honest footer", () => {
const html = renderToStaticMarkup(
<HistoryView
actions={createActions()}
@@ -392,8 +416,20 @@ describe("HistoryView", () => {
});
});
describe("visual history states", () => {
it("re-arms the real App mounted gate before every StrictMode lifecycle setup can start async work", () => {
describe("visual history states", () => {
it("keeps the selected category visible immediately while only its geometry glides", () => {
const styles = readFileSync(new URL("../src/renderer/styles.css", import.meta.url), "utf8").replaceAll("\r\n", "\n");
const selection = readFileSync(new URL("../src/renderer/ui/SlidingSelection.tsx", import.meta.url), "utf8").replaceAll("\r\n", "\n");
const selectionStyles = styles.slice(styles.indexOf(".ui-sliding-selection"), styles.indexOf("html,"));
expect(selectionStyles).toMatch(/\.ui-sliding-selection::before\s*\{[^}]*opacity:\s*1;/s);
expect(selectionStyles).not.toContain(".ui-sliding-selection.has-sliding-selection::before");
expect(selectionStyles).not.toMatch(/transition(?:-property)?:[^;]*opacity/);
expect(selection).not.toContain("classList.add(\"has-sliding-selection\")");
expect(selection).not.toContain("classList.remove(\"has-sliding-selection\")");
});
it("re-arms the real App mounted gate before every StrictMode lifecycle setup can start async work", () => {
const source = readFileSync(new URL("../src/renderer/App.tsx", import.meta.url), "utf8").replaceAll("\r\n", "\n");
const firstRequest = source.indexOf("window.rd.getVersion()");
const effectStart = source.lastIndexOf("useEffect(() => {", firstRequest);