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:
Sucukdeluxe
2026-08-11 04:42:14 +02:00
parent 14090011e3
commit eda3a3f744
10 changed files with 274 additions and 25 deletions
@@ -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) {
actions.onToggleSelection(entry.id, 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)}
+40 -1
View File
@@ -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,