release: publish v2.0.19 sidebar interaction fixes
Restore the shared sliding-selection transition after React StrictMode effect restarts, disable redundant service filters, add regression coverage, and update the public English changelog and package metadata for v2.0.19.
This commit is contained in:
@@ -486,6 +486,16 @@ describe("downloads view", () => {
|
||||
expect(html.match(/data-sliding-selection-active="true"/g)).toHaveLength(1);
|
||||
});
|
||||
|
||||
it("disables the service filter until more than one concrete service is available", () => {
|
||||
const none = renderToStaticMarkup(<DownloadsSidebar actions={createActions()} model={withRuntime(createInput(), { providerOptions: [] })} />);
|
||||
const one = renderToStaticMarkup(<DownloadsSidebar actions={createActions()} model={withRuntime(createInput(), { providerOptions: [{ id: "rapidgator", label: "RapidGator" }] })} />);
|
||||
const multiple = renderToStaticMarkup(<DownloadsSidebar actions={createActions()} model={withRuntime(createInput(), { providerOptions: [{ id: "rapidgator", label: "RapidGator" }, { id: "ddownload", label: "DDownload" }] })} />);
|
||||
|
||||
expect(none).toMatch(/<select[^>]*aria-label="Service filtern"[^>]*disabled=""/);
|
||||
expect(one).toMatch(/<select[^>]*aria-label="Service filtern"[^>]*disabled=""/);
|
||||
expect(multiple).not.toMatch(/<select[^>]*aria-label="Service filtern"[^>]*disabled=""/);
|
||||
});
|
||||
|
||||
it("shows only the package mode while the file mode remains hidden", () => {
|
||||
const html = renderToStaticMarkup(<DownloadsSidebar actions={createActions()} model={withRuntime(createInput())} />);
|
||||
const css = fs.readFileSync(path.join(process.cwd(), "src/renderer/views/downloads/downloads.css"), "utf8");
|
||||
|
||||
@@ -1,6 +1,34 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
describe("sliding selection scheduling", () => {
|
||||
it("re-arms transitions when a StrictMode effect cleanup cancels the first frame", async () => {
|
||||
const selectionModule = await import("../src/renderer/ui/SlidingSelection");
|
||||
const schedule = Reflect.get(selectionModule, "scheduleSelectionTransitions");
|
||||
|
||||
expect(schedule).toBeTypeOf("function");
|
||||
|
||||
let transitionsEnabled = false;
|
||||
let nextFrame = 0;
|
||||
const pending = new Map<number, FrameRequestCallback>();
|
||||
const requestFrame = (callback: FrameRequestCallback): number => {
|
||||
nextFrame += 1;
|
||||
pending.set(nextFrame, callback);
|
||||
return nextFrame;
|
||||
};
|
||||
const cancelFrame = (frame: number): void => {
|
||||
pending.delete(frame);
|
||||
};
|
||||
|
||||
const firstFrame = schedule(false, 0, () => { transitionsEnabled = true; }, requestFrame, cancelFrame);
|
||||
cancelFrame(firstFrame);
|
||||
const secondFrame = schedule(false, 0, () => { transitionsEnabled = true; }, requestFrame, cancelFrame);
|
||||
|
||||
expect(transitionsEnabled).toBe(false);
|
||||
expect(pending.has(firstFrame)).toBe(false);
|
||||
pending.get(secondFrame)?.(0);
|
||||
expect(transitionsEnabled).toBe(true);
|
||||
});
|
||||
|
||||
it("applies the first mounted selection before scheduling later movements", async () => {
|
||||
const selectionModule = await import("../src/renderer/ui/SlidingSelection");
|
||||
const schedule = Reflect.get(selectionModule, "scheduleSelectionLayout");
|
||||
|
||||
Reference in New Issue
Block a user