feat: add drag & drop queue reordering and expandable queue item details
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
2481230983
commit
fbcf3935d0
@ -198,6 +198,49 @@ function updateQueueItemProgress(progress: DownloadProgress): void {
|
|||||||
if (meta) meta.textContent = getQueueMetaText(queue[idx]);
|
if (meta) meta.textContent = getQueueMetaText(queue[idx]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function toggleQueueDetails(id: string): void {
|
||||||
|
const el = document.getElementById(`details-${id}`);
|
||||||
|
if (el) el.style.display = el.style.display === 'none' ? 'block' : 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
function initQueueDragDrop(): void {
|
||||||
|
const list = byId('queueList');
|
||||||
|
|
||||||
|
list.addEventListener('dragstart', (e: DragEvent) => {
|
||||||
|
const el = (e.target as HTMLElement).closest('.queue-item') as HTMLElement;
|
||||||
|
if (!el) return;
|
||||||
|
draggedQueueItemId = el.dataset.id || null;
|
||||||
|
el.classList.add('dragging');
|
||||||
|
if (e.dataTransfer) e.dataTransfer.effectAllowed = 'move';
|
||||||
|
});
|
||||||
|
|
||||||
|
list.addEventListener('dragover', (e: DragEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
if (e.dataTransfer) e.dataTransfer.dropEffect = 'move';
|
||||||
|
});
|
||||||
|
|
||||||
|
list.addEventListener('drop', (e: DragEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
const target = (e.target as HTMLElement).closest('.queue-item') as HTMLElement;
|
||||||
|
if (!target || !draggedQueueItemId) return;
|
||||||
|
const targetId = target.dataset.id;
|
||||||
|
if (!targetId || targetId === draggedQueueItemId) return;
|
||||||
|
|
||||||
|
const fromIdx = queue.findIndex(i => i.id === draggedQueueItemId);
|
||||||
|
const toIdx = queue.findIndex(i => i.id === targetId);
|
||||||
|
if (fromIdx < 0 || toIdx < 0) return;
|
||||||
|
const [moved] = queue.splice(fromIdx, 1);
|
||||||
|
queue.splice(toIdx, 0, moved);
|
||||||
|
window.api.reorderQueue(queue.map(i => i.id));
|
||||||
|
renderQueue();
|
||||||
|
});
|
||||||
|
|
||||||
|
list.addEventListener('dragend', () => {
|
||||||
|
draggedQueueItemId = null;
|
||||||
|
document.querySelectorAll('.queue-item.dragging').forEach(el => el.classList.remove('dragging'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function renderQueue(): void {
|
function renderQueue(): void {
|
||||||
if (!Array.isArray(queue)) {
|
if (!Array.isArray(queue)) {
|
||||||
queue = [];
|
queue = [];
|
||||||
@ -244,7 +287,7 @@ function renderQueue(): void {
|
|||||||
: '';
|
: '';
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<div class="queue-item${isMergeGroup ? ' merge-group' : ''}">
|
<div class="queue-item${isMergeGroup ? ' merge-group' : ''}" draggable="${item.status === 'pending' ? 'true' : 'false'}" data-id="${item.id}">
|
||||||
${showSelector
|
${showSelector
|
||||||
? `<div class="queue-selector${isSelected ? ' selected' : ''}" onclick="toggleQueueSelection('${item.id}')">${isSelected ? selectionIndex + 1 : ''}</div>`
|
? `<div class="queue-selector${isSelected ? ' selected' : ''}" onclick="toggleQueueSelection('${item.id}')">${isSelected ? selectionIndex + 1 : ''}</div>`
|
||||||
: ''
|
: ''
|
||||||
@ -252,7 +295,7 @@ function renderQueue(): void {
|
|||||||
<div class="status ${item.status}"></div>
|
<div class="status ${item.status}"></div>
|
||||||
<div class="queue-main">
|
<div class="queue-main">
|
||||||
<div class="queue-title-row">
|
<div class="queue-title-row">
|
||||||
<div class="title" title="${safeTitle}">${mergeIcon}${isClip}${safeTitle}</div>
|
<div class="title" title="${safeTitle}" onclick="toggleQueueDetails('${item.id}')" style="cursor:pointer">${mergeIcon}${isClip}${safeTitle}</div>
|
||||||
<div class="queue-status-label">${safeStatusLabel}</div>
|
<div class="queue-status-label">${safeStatusLabel}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="queue-meta">${safeMeta}${mergeMetaExtra}</div>
|
<div class="queue-meta">${safeMeta}${mergeMetaExtra}</div>
|
||||||
@ -260,6 +303,12 @@ function renderQueue(): void {
|
|||||||
<div class="queue-progress-bar${progressClass}" style="width: ${progressValue}%;"></div>
|
<div class="queue-progress-bar${progressClass}" style="width: ${progressValue}%;"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="queue-progress-text">${safeProgressText}</div>
|
<div class="queue-progress-text">${safeProgressText}</div>
|
||||||
|
<div class="queue-details" id="details-${item.id}" style="display:none">
|
||||||
|
<div>URL: ${escapeHtml(item.url)}</div>
|
||||||
|
<div>Streamer: ${escapeHtml(item.streamer)}</div>
|
||||||
|
<div>Dauer: ${escapeHtml(item.duration_str)}</div>
|
||||||
|
<div>Datum: ${escapeHtml(new Date(item.date).toLocaleString())}</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<span class="remove" onclick="removeFromQueue('${item.id}')">x</span>
|
<span class="remove" onclick="removeFromQueue('${item.id}')">x</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -42,6 +42,7 @@ async function init(): Promise<void> {
|
|||||||
changeTheme(config.theme ?? 'twitch');
|
changeTheme(config.theme ?? 'twitch');
|
||||||
renderStreamers();
|
renderStreamers();
|
||||||
renderQueue();
|
renderQueue();
|
||||||
|
initQueueDragDrop();
|
||||||
updateDownloadButtonState();
|
updateDownloadButtonState();
|
||||||
|
|
||||||
window.api.onQueueUpdated((q: QueueItem[]) => {
|
window.api.onQueueUpdated((q: QueueItem[]) => {
|
||||||
|
|||||||
@ -334,6 +334,29 @@ body {
|
|||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.queue-item[draggable="true"] {
|
||||||
|
cursor: grab;
|
||||||
|
}
|
||||||
|
|
||||||
|
.queue-item[draggable="true"]:active {
|
||||||
|
cursor: grabbing;
|
||||||
|
}
|
||||||
|
|
||||||
|
.queue-item.dragging {
|
||||||
|
opacity: 0.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.queue-details {
|
||||||
|
font-size: 10px;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
padding: 4px 0;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
|
.queue-details div {
|
||||||
|
margin-bottom: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
.queue-selector {
|
.queue-selector {
|
||||||
width: 22px;
|
width: 22px;
|
||||||
height: 22px;
|
height: 22px;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user