release: publish v2.0.20 selection and sidebar refinements
Complete zero-width sidebar collapse with synchronized bidirectional motion, add package-row selection and guarded double-click disclosure, render continuous selection edges across nested package boundaries, expand regression coverage, and update the public English changelog and package metadata for v2.0.20.
This commit is contained in:
@@ -2,6 +2,28 @@
|
||||
|
||||
All notable changes to Multi-Debrid Downloader are documented in this file.
|
||||
|
||||
## [2.0.20] - 2026-08-11
|
||||
|
||||
### Downloads and selection
|
||||
|
||||
- Added package selection through a normal row click while preserving Control, Command, and Shift selection behavior.
|
||||
- Added package expansion and collapse through a double-click on unused row space while keeping the disclosure button available.
|
||||
- Kept renaming, checkboxes, progress meters, links, form controls, and action buttons isolated from the row disclosure gesture.
|
||||
- Replaced segmented selection markers with a continuous three-pixel success-colored edge across adjacent selected packages and files.
|
||||
- Extended package selection markers across card separators so consecutive selected packages no longer show one-pixel gaps.
|
||||
|
||||
### Sidebar motion
|
||||
|
||||
- Removed the empty sidebar rail when the sidebar is collapsed.
|
||||
- Added synchronized 520-millisecond width and panel transitions for smooth sidebar opening and closing.
|
||||
- Kept the sidebar edge control visible and reachable while the sidebar content is fully hidden.
|
||||
- Preserved the requested sidebar motion when Windows application animations are disabled.
|
||||
|
||||
### Reliability and testing
|
||||
|
||||
- Added regression coverage for zero-width sidebar collapse, synchronized sidebar motion, package row selection, double-click disclosure boundaries, and continuous selection markers.
|
||||
- Added rendered-pixel verification for the updated interactions and continuous selection edge.
|
||||
|
||||
## [2.0.19] - 2026-08-11
|
||||
|
||||
### Interface fixes
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "real-debrid-downloader",
|
||||
"version": "2.0.19",
|
||||
"version": "2.0.20",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "real-debrid-downloader",
|
||||
"version": "2.0.19",
|
||||
"version": "2.0.20",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"adm-zip": "0.6.0",
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "real-debrid-downloader",
|
||||
"version": "2.0.19",
|
||||
"version": "2.0.20",
|
||||
"description": "Desktop downloader",
|
||||
"main": "build/main/main/main.js",
|
||||
"author": "Sucukdeluxe",
|
||||
|
||||
@@ -21,8 +21,10 @@ export function AppSidebar({
|
||||
className={`md-shell-sidebar${collapsed ? " is-collapsed" : ""}${responsiveRail ? " is-responsive-rail" : ""}`}
|
||||
data-ui-region="sidebar"
|
||||
>
|
||||
<div className="md-shell-sidebar-panel">
|
||||
{children ? <div className="md-shell-sidebar-scroll">{children}</div> : null}
|
||||
{status ? <div className="md-shell-sidebar-status" data-ui-region="sidebar-status">{status}</div> : null}
|
||||
</div>
|
||||
<button
|
||||
aria-label={collapsed ? "Seitenleiste ausklappen" : "Seitenleiste einklappen"}
|
||||
className="md-shell-sidebar-toggle"
|
||||
|
||||
@@ -404,6 +404,7 @@
|
||||
min-height: 0;
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
gap: 8px;
|
||||
transition: grid-template-columns 520ms cubic-bezier(0.22, 0.76, 0.22, 1);
|
||||
}
|
||||
|
||||
.md-shell.has-sidebar .md-shell-workspace {
|
||||
@@ -411,10 +412,10 @@
|
||||
}
|
||||
|
||||
.md-shell.has-collapsed-sidebar .md-shell-workspace {
|
||||
grid-template-columns: 56px minmax(0, 1fr);
|
||||
grid-template-columns: 0 minmax(0, 1fr);
|
||||
}
|
||||
|
||||
.md-shell-sidebar,
|
||||
.md-shell-sidebar-panel,
|
||||
.md-shell-main {
|
||||
position: relative;
|
||||
min-width: 0;
|
||||
@@ -425,8 +426,24 @@
|
||||
}
|
||||
|
||||
.md-shell-sidebar {
|
||||
position: relative;
|
||||
z-index: 4;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.md-shell-sidebar-panel {
|
||||
display: flex;
|
||||
width: 270px;
|
||||
height: 100%;
|
||||
flex-direction: column;
|
||||
opacity: 1;
|
||||
transform: translate3d(0, 0, 0);
|
||||
visibility: visible;
|
||||
transition:
|
||||
opacity 260ms ease,
|
||||
transform 520ms cubic-bezier(0.22, 0.76, 0.22, 1),
|
||||
visibility 0s linear 0s;
|
||||
}
|
||||
|
||||
.md-shell-sidebar-scroll {
|
||||
@@ -465,16 +482,12 @@
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
.md-shell-sidebar.is-collapsed :where(.md-shell-sidebar-scroll, .md-shell-sidebar-status) {
|
||||
overflow: hidden;
|
||||
.md-shell-sidebar.is-collapsed .md-shell-sidebar-panel {
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
transform: translateX(-8px);
|
||||
}
|
||||
|
||||
.md-shell-sidebar-scroll,
|
||||
.md-shell-sidebar-status {
|
||||
transition: opacity 160ms ease, transform 160ms ease;
|
||||
transform: translate3d(calc(-100% - 8px), 0, 0);
|
||||
pointer-events: none;
|
||||
transition-delay: 0s, 0s, 520ms;
|
||||
}
|
||||
|
||||
.md-shell-sidebar-toggle {
|
||||
@@ -507,6 +520,7 @@
|
||||
}
|
||||
|
||||
.md-shell-sidebar:hover .md-shell-sidebar-toggle,
|
||||
.md-shell-sidebar.is-collapsed .md-shell-sidebar-toggle,
|
||||
.md-shell-sidebar-toggle:focus-visible {
|
||||
opacity: 1;
|
||||
}
|
||||
@@ -907,6 +921,14 @@
|
||||
transition-duration: 0.01ms !important;
|
||||
}
|
||||
|
||||
.md-shell-workspace {
|
||||
transition-duration: 520ms !important;
|
||||
}
|
||||
|
||||
.md-shell-sidebar-panel {
|
||||
transition-duration: 260ms, 520ms, 0s !important;
|
||||
}
|
||||
|
||||
.md-shell-navigation::before {
|
||||
transition-duration: 420ms, 420ms, 420ms, 120ms !important;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ export type DownloadSortColumn = "name" | "size" | "hoster" | "progress";
|
||||
|
||||
const DOWNLOAD_SELECTION_COLUMN_WIDTH = "36px";
|
||||
const DOWNLOAD_ACTION_COLUMN_WIDTH = "60px";
|
||||
const PACKAGE_ROW_DISCLOSURE_EXCLUSION_SELECTOR = "button, input, select, textarea, a, [contenteditable='true'], .downloads-copyable, .downloads-meter";
|
||||
const useRendererLayoutEffect = typeof window === "undefined" ? useEffect : useLayoutEffect;
|
||||
|
||||
type HosterLabel = ReturnType<typeof formatHosterLabel>;
|
||||
@@ -40,6 +41,11 @@ function downloadGridTemplate(gridTemplate: string): string {
|
||||
return `${DOWNLOAD_SELECTION_COLUMN_WIDTH} ${gridTemplate} ${DOWNLOAD_ACTION_COLUMN_WIDTH}`;
|
||||
}
|
||||
|
||||
function isPackageRowDisclosureExcluded(target: EventTarget | null): boolean {
|
||||
const closest = (target as { closest?: (selector: string) => Element | null } | null)?.closest;
|
||||
return typeof closest === "function" && closest.call(target, PACKAGE_ROW_DISCLOSURE_EXCLUSION_SELECTOR) !== null;
|
||||
}
|
||||
|
||||
export const downloadColumnDefinitions: Record<string, { label: string; width: string; sortable?: DownloadSortColumn }> = {
|
||||
name: { label: "Name", width: "minmax(290px, 2.3fr)", sortable: "name" },
|
||||
size: { label: "Geladen / Größe", width: "minmax(140px, 1.1fr)", sortable: "size" },
|
||||
@@ -489,9 +495,14 @@ export function PackageCardContent({ row, selectedIds, editing, editingName, pac
|
||||
role="row"
|
||||
style={{ gridTemplateColumns: downloadGridTemplate(gridTemplate) }}
|
||||
onClick={(event) => {
|
||||
if (event.ctrlKey || event.metaKey || event.shiftKey) {
|
||||
if (event.detail > 1) return;
|
||||
if (!event.ctrlKey && !event.metaKey && !event.shiftKey && selectedIds.size === 1 && selectedIds.has(entry.id)) return;
|
||||
actions.onToggleSelection(entry.id, event.ctrlKey || event.metaKey, event.shiftKey);
|
||||
}
|
||||
}}
|
||||
onDoubleClick={(event) => {
|
||||
if (event.ctrlKey || event.metaKey || event.shiftKey || isPackageRowDisclosureExcluded(event.target)) return;
|
||||
event.preventDefault();
|
||||
actions.onTogglePackageCollapse(entry.id);
|
||||
}}
|
||||
onMouseDown={(event) => actions.onSelectionMouseDown(entry.id, event)}
|
||||
onMouseEnter={() => actions.onSelectionMouseEnter(entry.id)}
|
||||
|
||||
@@ -300,6 +300,11 @@
|
||||
opacity: 0.58;
|
||||
}
|
||||
|
||||
.downloads-package-card.is-selected,
|
||||
.downloads-package-card:has(.downloads-package-items-inner > .downloads-item-row:last-child.is-selected) {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.downloads-package-items {
|
||||
height: auto;
|
||||
overflow: hidden;
|
||||
@@ -332,6 +337,7 @@
|
||||
color: var(--ui-text);
|
||||
background: transparent;
|
||||
border-color: var(--ui-border);
|
||||
border-left: 3px solid transparent;
|
||||
contain: layout paint style;
|
||||
content-visibility: auto;
|
||||
contain-intrinsic-size: 40px;
|
||||
@@ -346,8 +352,41 @@
|
||||
|
||||
.downloads-item-row.is-selected,
|
||||
.downloads-package-card.is-selected > .downloads-package-row {
|
||||
position: relative;
|
||||
background: color-mix(in srgb, var(--ui-success) 14%, var(--ui-canvas));
|
||||
box-shadow: inset 3px 0 0 var(--ui-success);
|
||||
border-left-color: var(--ui-success);
|
||||
}
|
||||
|
||||
.downloads-item-row.is-selected::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
inset: -1px auto -1px -3px;
|
||||
width: 3px;
|
||||
background: var(--ui-success);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.downloads-package-card.is-selected::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
z-index: 3;
|
||||
inset: 0 auto auto 0;
|
||||
width: 3px;
|
||||
height: 41px;
|
||||
background: var(--ui-success);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.downloads-package-card:has(.downloads-package-items-inner > .downloads-item-row:last-child.is-selected)::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
z-index: 3;
|
||||
inset: auto auto -1px 0;
|
||||
width: 3px;
|
||||
height: 1px;
|
||||
background: var(--ui-success);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.downloads-package-row:hover,
|
||||
|
||||
@@ -115,6 +115,47 @@ describe("desktop shell", () => {
|
||||
expect(html).not.toContain("data-ui-region=\"footer\"");
|
||||
});
|
||||
|
||||
it("collapses a populated sidebar to zero width while preserving the edge toggle", () => {
|
||||
const html = renderToStaticMarkup(
|
||||
<AppShell
|
||||
activeView="downloads"
|
||||
onViewChange={() => {}}
|
||||
sidebar={<div>Filter</div>}
|
||||
sidebarStatus={<div>2 Downloads</div>}
|
||||
headerActions={null}
|
||||
toolbar={null}
|
||||
footer={null}
|
||||
contextInfo={null}
|
||||
sidebarCollapsed
|
||||
onSidebarCollapsedChange={() => {}}
|
||||
>
|
||||
<div>Downloads</div>
|
||||
</AppShell>
|
||||
);
|
||||
const shellCss = readFileSync(new URL("../src/renderer/shell/shell.css", import.meta.url), "utf8");
|
||||
|
||||
expect(html).toContain("has-collapsed-sidebar");
|
||||
expect(html).toContain("md-shell-sidebar-panel");
|
||||
expect(html).toContain("Seitenleiste ausklappen");
|
||||
expect(shellCss).toMatch(/\.md-shell\.has-collapsed-sidebar \.md-shell-workspace\s*\{[^}]*grid-template-columns:\s*0 minmax\(0,\s*1fr\);/s);
|
||||
});
|
||||
|
||||
it("slides the complete sidebar panel in both directions with the workspace width", () => {
|
||||
const shellCss = readFileSync(new URL("../src/renderer/shell/shell.css", import.meta.url), "utf8");
|
||||
|
||||
expect(shellCss).toMatch(/\.md-shell-workspace\s*\{[^}]*transition:\s*grid-template-columns 520ms cubic-bezier\(0\.22, 0\.76, 0\.22, 1\);/s);
|
||||
expect(shellCss).toMatch(/\.md-shell-sidebar-panel\s*\{[^}]*transform:\s*translate3d\(0, 0, 0\);[^}]*transition:[^}]*transform 520ms cubic-bezier\(0\.22, 0\.76, 0\.22, 1\)/s);
|
||||
expect(shellCss).toMatch(/\.md-shell-sidebar\.is-collapsed \.md-shell-sidebar-panel\s*\{[^}]*transform:\s*translate3d\(calc\(-100% - 8px\), 0, 0\);[^}]*pointer-events:\s*none;/s);
|
||||
expect(shellCss).toMatch(/\.md-shell-sidebar:hover \.md-shell-sidebar-toggle,\s*\.md-shell-sidebar\.is-collapsed \.md-shell-sidebar-toggle,\s*\.md-shell-sidebar-toggle:focus-visible\s*\{[^}]*opacity:\s*1;/s);
|
||||
});
|
||||
|
||||
it("keeps the explicitly requested sidebar motion active when Windows animations are disabled", () => {
|
||||
const shellCss = readFileSync(new URL("../src/renderer/shell/shell.css", import.meta.url), "utf8");
|
||||
|
||||
expect(shellCss).toMatch(/@media \(prefers-reduced-motion: reduce\)[\s\S]*\.md-shell-workspace\s*\{[^}]*transition-duration:\s*520ms !important;/s);
|
||||
expect(shellCss).toMatch(/@media \(prefers-reduced-motion: reduce\)[\s\S]*\.md-shell-sidebar-panel\s*\{[^}]*transition-duration:\s*260ms, 520ms, 0s !important;/s);
|
||||
});
|
||||
|
||||
it("keeps every view sidebar on the same content axis", () => {
|
||||
const shellCss = readFileSync(new URL("../src/renderer/shell/shell.css", import.meta.url), "utf8").replaceAll("\r\n", "\n");
|
||||
|
||||
|
||||
@@ -709,7 +709,11 @@ describe("downloads view", () => {
|
||||
const css = readFileSync(new URL("../src/renderer/views/downloads/downloads.css", import.meta.url), "utf8");
|
||||
const source = readFileSync(new URL("../src/renderer/views/downloads/DownloadsTable.tsx", import.meta.url), "utf8");
|
||||
|
||||
expect(css).toMatch(/\.downloads-item-row\.is-selected,\s*\.downloads-package-card\.is-selected\s*>\s*\.downloads-package-row\s*\{[^}]*background:\s*color-mix\(in srgb, var\(--ui-success\) 14%, var\(--ui-canvas\)\);[^}]*box-shadow:\s*inset 3px 0 0 var\(--ui-success\);/s);
|
||||
expect(css).toMatch(/\.downloads-item-row,\s*\.downloads-package-row\s*\{[^}]*border-left:\s*3px solid transparent;/s);
|
||||
expect(css).toMatch(/\.downloads-item-row\.is-selected,\s*\.downloads-package-card\.is-selected\s*>\s*\.downloads-package-row\s*\{[^}]*background:\s*color-mix\(in srgb, var\(--ui-success\) 14%, var\(--ui-canvas\)\);[^}]*border-left-color:\s*var\(--ui-success\);/s);
|
||||
expect(css).toMatch(/\.downloads-item-row\.is-selected::before\s*\{[^}]*content:\s*"";[^}]*position:\s*absolute;[^}]*inset:\s*-1px auto -1px -3px;[^}]*width:\s*3px;[^}]*background:\s*var\(--ui-success\);/s);
|
||||
expect(css).toMatch(/\.downloads-package-card\.is-selected::before\s*\{[^}]*content:\s*"";[^}]*position:\s*absolute;[^}]*inset:\s*0 auto auto 0;[^}]*width:\s*3px;[^}]*height:\s*41px;[^}]*background:\s*var\(--ui-success\);/s);
|
||||
expect(css).toMatch(/\.downloads-package-card:has\(\.downloads-package-items-inner\s*>\s*\.downloads-item-row:last-child\.is-selected\)::after\s*\{[^}]*content:\s*"";[^}]*position:\s*absolute;[^}]*inset:\s*auto auto -1px 0;[^}]*width:\s*3px;[^}]*height:\s*1px;[^}]*background:\s*var\(--ui-success\);/s);
|
||||
expect(css).toMatch(/\.downloads-selection-cell\s+input\[type="checkbox"\]\s*\{[^}]*width:\s*18px;[^}]*height:\s*18px;/s);
|
||||
expect(css).toMatch(/\.downloads-hoster-icon\s*\{[^}]*width:\s*18px;[^}]*height:\s*18px;[^}]*object-fit:\s*contain;/s);
|
||||
expect(css).toMatch(/\.downloads-hoster-icon\[data-hoster="rapidgator"\]\s*\{[^}]*transform:\s*translateY\(-4px\) scale\(2\);/s);
|
||||
@@ -996,12 +1000,39 @@ describe("download table row contracts", () => {
|
||||
expect(calls).toEqual(["select"]);
|
||||
});
|
||||
|
||||
it("only collapses a package through its visible disclosure button", () => {
|
||||
it("selects a package on a plain row click", () => {
|
||||
const calls: Array<[string, boolean, boolean]> = [];
|
||||
const model = withRuntime(createInput());
|
||||
const row = model.packageRows[0];
|
||||
const component = PackageCardContent({
|
||||
actions: createActions({
|
||||
onToggleSelection: (id, ctrl, shift) => calls.push([id, ctrl, shift])
|
||||
}),
|
||||
columnOrder: model.columnOrder,
|
||||
editing: false,
|
||||
editingName: "",
|
||||
gridTemplate: model.gridTemplate,
|
||||
packageSpeedBps: 0,
|
||||
row,
|
||||
selectedIds: new Set<string>(),
|
||||
selectedVersion: 1
|
||||
});
|
||||
const packageRow = findElement(component, (element) => element.props["data-download-row-id"] === row.package.id);
|
||||
|
||||
packageRow.props.onClick({ ctrlKey: false, metaKey: false, shiftKey: false });
|
||||
|
||||
expect(calls).toEqual([[row.package.id, false, false]]);
|
||||
});
|
||||
|
||||
it("collapses a package through its disclosure button or a free-row double click", () => {
|
||||
const calls: string[] = [];
|
||||
const model = withRuntime(createInput());
|
||||
const row = model.packageRows[0];
|
||||
const component = PackageCardContent({
|
||||
actions: createActions({ onTogglePackageCollapse: () => calls.push("collapse") }),
|
||||
actions: createActions({
|
||||
onTogglePackageCollapse: () => calls.push("collapse"),
|
||||
onToggleSelection: () => calls.push("select")
|
||||
}),
|
||||
columnOrder: model.columnOrder,
|
||||
editing: false,
|
||||
editingName: "",
|
||||
@@ -1014,14 +1045,95 @@ describe("download table row contracts", () => {
|
||||
const packageRow = findElement(component, (element) => element.props["data-download-row-id"] === row.package.id);
|
||||
const collapseButton = findElement(component, (element) => element.type === "button" && String(element.props.className || "").includes("downloads-collapse-button"));
|
||||
|
||||
packageRow.props.onClick({ ctrlKey: false, metaKey: false, shiftKey: false, target: {}, currentTarget: {} });
|
||||
packageRow.props.onClick({ ctrlKey: false, detail: 1, metaKey: false, shiftKey: false, target: {}, currentTarget: {} });
|
||||
packageRow.props.onClick({ ctrlKey: false, detail: 2, metaKey: false, shiftKey: false, target: {}, currentTarget: {} });
|
||||
expect(packageRow.props.onDoubleClick).toBeTypeOf("function");
|
||||
packageRow.props.onDoubleClick({
|
||||
ctrlKey: false,
|
||||
currentTarget: {},
|
||||
metaKey: false,
|
||||
preventDefault: () => calls.push("prevent"),
|
||||
shiftKey: false,
|
||||
target: { closest: () => null }
|
||||
});
|
||||
collapseButton.props.onClick({ stopPropagation: () => {} });
|
||||
|
||||
expect(calls).toEqual(["collapse"]);
|
||||
expect(calls).toEqual(["select", "prevent", "collapse", "collapse"]);
|
||||
expect(collapseButton.props["aria-expanded"]).toBe(true);
|
||||
expect(collapseButton.props["aria-controls"]).toBe(`downloads-package-items-${row.package.id}`);
|
||||
});
|
||||
|
||||
it("does not collapse a package when a row double click starts on interactive content", () => {
|
||||
const calls: string[] = [];
|
||||
const model = withRuntime(createInput());
|
||||
const row = model.packageRows[0];
|
||||
const component = PackageCardContent({
|
||||
actions: createActions({
|
||||
onStartPackageRename: () => calls.push("rename"),
|
||||
onTogglePackageCollapse: () => calls.push("collapse"),
|
||||
onToggleSelection: () => calls.push("select")
|
||||
}),
|
||||
columnOrder: model.columnOrder,
|
||||
editing: false,
|
||||
editingName: "",
|
||||
gridTemplate: model.gridTemplate,
|
||||
packageSpeedBps: 0,
|
||||
row,
|
||||
selectedIds: new Set<string>(),
|
||||
selectedVersion: 1
|
||||
});
|
||||
const packageRow = findElement(component, (element) => element.props["data-download-row-id"] === row.package.id);
|
||||
const title = findElement(component, (element) => element.type === "strong" && String(element.props.className || "").includes("downloads-copyable"));
|
||||
|
||||
packageRow.props.onClick({ ctrlKey: false, detail: 1, metaKey: false, shiftKey: false });
|
||||
packageRow.props.onClick({ ctrlKey: false, detail: 2, metaKey: false, shiftKey: false });
|
||||
expect(packageRow.props.onDoubleClick).toBeTypeOf("function");
|
||||
packageRow.props.onDoubleClick({
|
||||
ctrlKey: false,
|
||||
currentTarget: {},
|
||||
metaKey: false,
|
||||
preventDefault: () => calls.push("prevent"),
|
||||
shiftKey: false,
|
||||
target: { closest: () => ({}) }
|
||||
});
|
||||
title.props.onDoubleClick({ stopPropagation: () => calls.push("stop") });
|
||||
|
||||
expect(calls).toEqual(["select", "stop", "rename"]);
|
||||
});
|
||||
|
||||
it("keeps an already selected package selected during a row double click", () => {
|
||||
const calls: string[] = [];
|
||||
const model = withRuntime(createInput());
|
||||
const row = model.packageRows[0];
|
||||
const component = PackageCardContent({
|
||||
actions: createActions({
|
||||
onTogglePackageCollapse: () => calls.push("collapse"),
|
||||
onToggleSelection: () => calls.push("select")
|
||||
}),
|
||||
columnOrder: model.columnOrder,
|
||||
editing: false,
|
||||
editingName: "",
|
||||
gridTemplate: model.gridTemplate,
|
||||
packageSpeedBps: 0,
|
||||
row,
|
||||
selectedIds: new Set([row.package.id]),
|
||||
selectedVersion: 1
|
||||
});
|
||||
const packageRow = findElement(component, (element) => element.props["data-download-row-id"] === row.package.id);
|
||||
|
||||
packageRow.props.onClick({ ctrlKey: false, detail: 1, metaKey: false, shiftKey: false });
|
||||
packageRow.props.onClick({ ctrlKey: false, detail: 2, metaKey: false, shiftKey: false });
|
||||
packageRow.props.onDoubleClick({
|
||||
ctrlKey: false,
|
||||
metaKey: false,
|
||||
preventDefault: () => calls.push("prevent"),
|
||||
shiftKey: false,
|
||||
target: { closest: () => null }
|
||||
});
|
||||
|
||||
expect(calls).toEqual(["prevent", "collapse"]);
|
||||
});
|
||||
|
||||
it("keeps the complete package status and audio details in the tooltip", () => {
|
||||
const audioPackage = {
|
||||
...pkg("audio-package", "Audio package", ["audio-item"]),
|
||||
|
||||
@@ -46,7 +46,7 @@ describe("responsive shell mode", () => {
|
||||
expect(html).toContain("md-shell is-full");
|
||||
expect(css).toContain(".md-shell.is-compact");
|
||||
expect(css).toContain(".md-shell.is-minimum");
|
||||
expect(css).toMatch(/grid-template-columns:\s*56px minmax\(0,\s*1fr\)/);
|
||||
expect(css).toMatch(/\.md-shell\.has-collapsed-sidebar \.md-shell-workspace\s*\{[^}]*grid-template-columns:\s*0 minmax\(0,\s*1fr\);/s);
|
||||
});
|
||||
|
||||
it("keeps responsive rail content hidden behind a visible expand control", () => {
|
||||
|
||||
Reference in New Issue
Block a user