style: swap date and status in queue card footer
Windows CI / verify (push) Canceled after 0s

This commit is contained in:
Sucukdeluxe
2026-09-06 13:17:20 +02:00
parent ea708c0461
commit cb85e08eec
7 changed files with 20 additions and 11 deletions
+4
View File
@@ -1,5 +1,9 @@
# Changelog # Changelog
## Unreleased
- Place the queue-card date on the left beside the details arrow and the download status on the right below the progress bar.
## 1.0.20 - 2026-09-06 ## 1.0.20 - 2026-09-06
- Fix automatic media-tool setup in long Windows paths by using the built-in archive extractor. Report extraction failures instead of accepting incomplete installations. - Fix automatic media-tool setup in long Windows paths by using the built-in archive extractor. Report extraction failures instead of accepting incomplete installations.
+1
View File
@@ -20,6 +20,7 @@ Aktueller veröffentlichter Stand: **1.0.20**, Tag `v1.0.20`, veröffentlicht am
## Letzte Änderungen ## Letzte Änderungen
- Nach Release 1.0.20: Datum und Status in der Queue-Card getauscht. Datum steht jetzt links neben dem Detailpfeil, Status rechts unter dem Fortschrittsbalken. Schriftgrößen, gelber Wartepunkt und Aufklappanimation bleiben erhalten. Build, 19 gezielte Tests, Queue-UI-Test in Deutsch/Englisch und Hell/Dunkel sowie vollständiger Workspace-UI-Test erfolgreich; Lint ohne Fehler bei 15 bestehenden Warnungen. Änderung zunächst nur auf `public-v1`/Hot-Dev, noch nicht veröffentlicht.
- Queue-Detailpfeil reagiert seit der Nachbesserung am 6. September 2026 auf jeden Klick, auch während der Animation. Die frühere Sperre für `MouseEvent.detail > 1` hatte schnelle Folge-Klicks verschluckt und wurde entfernt. Doppelklick auf freie Kartenflächen bleibt erhalten; auf dem Pfeil zählen beide Klicks einzeln. Build, gezielte Queue-Tests und isolierte UI-Prüfung inklusive schneller Klickfolgen erfolgreich. - Queue-Detailpfeil reagiert seit der Nachbesserung am 6. September 2026 auf jeden Klick, auch während der Animation. Die frühere Sperre für `MouseEvent.detail > 1` hatte schnelle Folge-Klicks verschluckt und wurde entfernt. Doppelklick auf freie Kartenflächen bleibt erhalten; auf dem Pfeil zählen beide Klicks einzeln. Build, gezielte Queue-Tests und isolierte UI-Prüfung inklusive schneller Klickfolgen erfolgreich.
- Queue-Details fahren seit dem 6. September 2026 beim Auf-/Zuklappen animiert ein und aus: Grid-Höhe und Deckkraft über 220/180 ms, Pfeilrotation über 220 ms. Bei reduzierten Windows-Animationen bleibt eine kurze 160-ms-Transition wie bei den bestehenden Workspace-Steuerelementen erhalten. Eingeklappte Details sind `inert`, damit unsichtbare Dateiaktionen nicht per Tastatur erreichbar sind. Build, 19 gezielte Tests und isolierter Queue-UI-Test einschließlich gemessener Zwischenhöhen in beiden Bewegungsmodi erfolgreich. - Queue-Details fahren seit dem 6. September 2026 beim Auf-/Zuklappen animiert ein und aus: Grid-Höhe und Deckkraft über 220/180 ms, Pfeilrotation über 220 ms. Bei reduzierten Windows-Animationen bleibt eine kurze 160-ms-Transition wie bei den bestehenden Workspace-Steuerelementen erhalten. Eingeklappte Details sind `inert`, damit unsichtbare Dateiaktionen nicht per Tastatur erreichbar sind. Build, 19 gezielte Tests und isolierter Queue-UI-Test einschließlich gemessener Zwischenhöhen in beiden Bewegungsmodi erfolgreich.
- Queue-Card-Nachbesserung am 6. September 2026: Wartestatus ohne sichtbare Umrandung und ohne gelblichen Hintergrund; gelber Statuspunkt und bisherige Abstände bleiben erhalten. In Hell/Dunkel geprüft, Queue-UI- und Stylesheet-Tests erfolgreich. - Queue-Card-Nachbesserung am 6. September 2026: Wartestatus ohne sichtbare Umrandung und ohne gelblichen Hintergrund; gelber Statuspunkt und bisherige Abstände bleiben erhalten. In Hell/Dunkel geprüft, Queue-UI- und Stylesheet-Tests erfolgreich.
+5 -2
View File
@@ -51,11 +51,14 @@ async function main() {
const rect = (selector) => item.querySelector(selector).getBoundingClientRect(); const rect = (selector) => item.querySelector(selector).getBoundingClientRect();
const date = rect('.queue-date'); const date = rect('.queue-date');
const bar = rect('.queue-progress-wrap'); const bar = rect('.queue-progress-wrap');
const status = rect('.queue-status-badge');
const toggle = rect('.queue-details-toggle');
const remove = rect('.remove'); const remove = rect('.remove');
return { return {
id: item.dataset.id, id: item.dataset.id,
dateBelow: date.top >= bar.bottom, dateBelow: date.top >= bar.bottom,
dateRight: Math.abs(date.right - bar.right) <= 1, dateLeft: date.left >= toggle.right && date.right < status.left,
statusRight: Math.abs(status.right - bar.right) <= 1,
dateSize: parseFloat(getComputedStyle(item.querySelector('.queue-date')).fontSize), dateSize: parseFloat(getComputedStyle(item.querySelector('.queue-date')).fontSize),
removeSize: Math.min(remove.width, remove.height), removeSize: Math.min(remove.width, remove.height),
overflow: item.scrollWidth - item.clientWidth, overflow: item.scrollWidth - item.clientWidth,
@@ -63,7 +66,7 @@ async function main() {
}; };
})); }));
for (const card of layout) { for (const card of layout) {
assert(card.dateBelow && card.dateRight, `Date placement: ${JSON.stringify(card)}`); assert(card.dateBelow && card.dateLeft && card.statusRight, `Footer placement: ${JSON.stringify(card)}`);
assert(card.dateSize >= 12 && card.removeSize >= 32 && card.tinyText === 0, `Readability: ${JSON.stringify(card)}`); assert(card.dateSize >= 12 && card.removeSize >= 32 && card.tinyText === 0, `Readability: ${JSON.stringify(card)}`);
assert(card.overflow <= 1, `Card overflow: ${JSON.stringify(card)}`); assert(card.overflow <= 1, `Card overflow: ${JSON.stringify(card)}`);
} }
+4 -4
View File
@@ -1222,7 +1222,7 @@ async function run() {
const remove = downloading?.querySelector('.remove'); const remove = downloading?.querySelector('.remove');
const statusRect = statusLabel?.getBoundingClientRect(); const statusRect = statusLabel?.getBoundingClientRect();
const removeRect = remove?.getBoundingClientRect(); const removeRect = remove?.getBoundingClientRect();
const statusLeftEdges = leftEdges('.status'); const statusRightEdges = alignedRows.map((row) => row?.querySelector('.queue-status-badge')?.getBoundingClientRect().right || 0);
const titleLeftEdges = leftEdges('.title'); const titleLeftEdges = leftEdges('.title');
const dateLeftEdges = leftEdges('.queue-date'); const dateLeftEdges = leftEdges('.queue-date');
const successProbe = document.createElement('span'); const successProbe = document.createElement('span');
@@ -1258,7 +1258,7 @@ async function run() {
startingAnimated: starting?.querySelector('.queue-progress-status')?.classList.contains('is-starting') === true, startingAnimated: starting?.querySelector('.queue-progress-status')?.classList.contains('is-starting') === true,
resumedProgress: paused?.querySelector('.queue-progress-wrap')?.getAttribute('aria-valuenow') || '', resumedProgress: paused?.querySelector('.queue-progress-wrap')?.getAttribute('aria-valuenow') || '',
resumedBarWidth: paused?.querySelector('.queue-progress-bar')?.style.width || '', resumedBarWidth: paused?.querySelector('.queue-progress-bar')?.style.width || '',
statusLeftEdges, statusRightEdges,
titleLeftEdges, titleLeftEdges,
dateLeftEdges, dateLeftEdges,
dateText: starting?.querySelector('.queue-date')?.textContent || '', dateText: starting?.querySelector('.queue-date')?.textContent || '',
@@ -1283,8 +1283,8 @@ async function run() {
check(dynamicQueue.startingStatusCount === 1, `Starting queue status is rendered ${dynamicQueue.startingStatusCount} times instead of once`); check(dynamicQueue.startingStatusCount === 1, `Starting queue status is rendered ${dynamicQueue.startingStatusCount} times instead of once`);
check(dynamicQueue.startingStatusText === dynamicQueue.expectedStartingStatusText && dynamicQueue.startingAnimated, `Queue start state is not visibly active: ${dynamicQueue.startingStatusText}`); check(dynamicQueue.startingStatusText === dynamicQueue.expectedStartingStatusText && dynamicQueue.startingAnimated, `Queue start state is not visibly active: ${dynamicQueue.startingStatusText}`);
check(dynamicQueue.resumedProgress === '42' && dynamicQueue.resumedBarWidth === '42%', `Resuming queue item loses its paused progress: value=${dynamicQueue.resumedProgress}, width=${dynamicQueue.resumedBarWidth}`); check(dynamicQueue.resumedProgress === '42' && dynamicQueue.resumedBarWidth === '42%', `Resuming queue item loses its paused progress: value=${dynamicQueue.resumedProgress}, width=${dynamicQueue.resumedBarWidth}`);
check(dynamicQueue.statusLeftEdges.every((value) => value > 0) && dynamicQueue.titleLeftEdges.every((value) => value > 0) && dynamicQueue.dateLeftEdges.every((value) => value > 0), 'Queue alignment fixture was measured while hidden'); check(dynamicQueue.statusRightEdges.every((value) => value > 0) && dynamicQueue.titleLeftEdges.every((value) => value > 0) && dynamicQueue.dateLeftEdges.every((value) => value > 0), 'Queue alignment fixture was measured while hidden');
check(Math.max(...dynamicQueue.statusLeftEdges) - Math.min(...dynamicQueue.statusLeftEdges) <= 1, `Queue status columns are offset: ${dynamicQueue.statusLeftEdges.join(', ')}`); check(Math.max(...dynamicQueue.statusRightEdges) - Math.min(...dynamicQueue.statusRightEdges) <= 1, `Queue status columns are offset: ${dynamicQueue.statusRightEdges.join(', ')}`);
check(Math.max(...dynamicQueue.titleLeftEdges) - Math.min(...dynamicQueue.titleLeftEdges) <= 1, `Queue title columns are offset: ${dynamicQueue.titleLeftEdges.join(', ')}`); check(Math.max(...dynamicQueue.titleLeftEdges) - Math.min(...dynamicQueue.titleLeftEdges) <= 1, `Queue title columns are offset: ${dynamicQueue.titleLeftEdges.join(', ')}`);
check(Math.max(...dynamicQueue.dateLeftEdges) - Math.min(...dynamicQueue.dateLeftEdges) <= 1, `Queue date columns are offset: ${dynamicQueue.dateLeftEdges.join(', ')}`); check(Math.max(...dynamicQueue.dateLeftEdges) - Math.min(...dynamicQueue.dateLeftEdges) <= 1, `Queue date columns are offset: ${dynamicQueue.dateLeftEdges.join(', ')}`);
check(dynamicQueue.dateText === '10.08.2026', `Queue VOD date is missing or incorrectly formatted: ${dynamicQueue.dateText}`); check(dynamicQueue.dateText === '10.08.2026', `Queue VOD date is missing or incorrectly formatted: ${dynamicQueue.dateText}`);
+2 -2
View File
@@ -718,10 +718,10 @@ function renderQueue(): void {
<div class="queue-footer"> <div class="queue-footer">
<div class="queue-summary"> <div class="queue-summary">
<button class="queue-details-toggle" type="button" aria-label="${escapeHtml(UI_TEXT.queue.toggleDetails)}" title="${escapeHtml(UI_TEXT.queue.toggleDetails)}" aria-expanded="${expandedQueueIds.has(item.id) ? 'true' : 'false'}" aria-controls="${detailsId}" data-queue-action="details"><svg aria-hidden="true" viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="m7 10 5 5 5-5"/></svg></button> <button class="queue-details-toggle" type="button" aria-label="${escapeHtml(UI_TEXT.queue.toggleDetails)}" title="${escapeHtml(UI_TEXT.queue.toggleDetails)}" aria-expanded="${expandedQueueIds.has(item.id) ? 'true' : 'false'}" aria-controls="${detailsId}" data-queue-action="details"><svg aria-hidden="true" viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="m7 10 5 5 5-5"/></svg></button>
<span class="queue-status-badge" title="${safeProgressStatus}"><span class="status ${item.status}" aria-hidden="true"></span><span class="queue-status-label">${safeStatusLabel}</span></span>
</div>
<span class="queue-date">${safeDate}</span> <span class="queue-date">${safeDate}</span>
</div> </div>
<span class="queue-status-badge" title="${safeProgressStatus}"><span class="status ${item.status}" aria-hidden="true"></span><span class="queue-status-label">${safeStatusLabel}</span></span>
</div>
<div class="queue-progress-info${item.status === 'pending' || item.status === 'completed' ? ' is-hidden' : ''}"> <div class="queue-progress-info${item.status === 'pending' || item.status === 'completed' ? ' is-hidden' : ''}">
<span class="queue-progress-status${progressStatusClass}${item.status === 'paused' ? ' is-hidden' : ''}">${safeProgressStatus}</span> <span class="queue-progress-status${progressStatusClass}${item.status === 'paused' ? ' is-hidden' : ''}">${safeProgressStatus}</span>
<span class="queue-progress-metrics">${safeProgressMetrics}</span> <span class="queue-progress-metrics">${safeProgressMetrics}</span>
+1 -1
View File
@@ -20,7 +20,7 @@ describe('production style modules', () => {
.replace(/\r\n/g, '\n')); .replace(/\r\n/g, '\n'));
const digest = createHash('sha256').update(content).digest('hex'); const digest = createHash('sha256').update(content).digest('hex');
expect(digest).toBe('b937d229d00f4a35098f288399331025580a1448f7c7aab7908f12ec826628e9'); expect(digest).toBe('eccaa49c879b53f95816408514a741f9aef7701ec9153ef9c8d70173a5b67056');
}); });
test('derives the Windows hot-development executable version from package metadata', () => { test('derives the Windows hot-development executable version from package metadata', () => {
+3 -2
View File
@@ -209,16 +209,17 @@
.queue-date { .queue-date {
flex-shrink: 0; flex-shrink: 0;
margin-left: auto;
color: var(--text-secondary); color: var(--text-secondary);
font-size: 12px; font-size: 12px;
line-height: 18px; line-height: 18px;
font-variant-numeric: tabular-nums; font-variant-numeric: tabular-nums;
text-align: right; text-align: left;
} }
.queue-status-badge { .queue-status-badge {
display: inline-flex; display: inline-flex;
flex-shrink: 0;
margin-left: auto;
align-items: center; align-items: center;
gap: 6px; gap: 6px;
padding: 2px 7px; padding: 2px 7px;