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]);
|
||||
}
|
||||
|
||||
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 {
|
||||
if (!Array.isArray(queue)) {
|
||||
queue = [];
|
||||
@ -244,7 +287,7 @@ function renderQueue(): void {
|
||||
: '';
|
||||
|
||||
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
|
||||
? `<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="queue-main">
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
<span class="remove" onclick="removeFromQueue('${item.id}')">x</span>
|
||||
</div>
|
||||
|
||||
@ -42,6 +42,7 @@ async function init(): Promise<void> {
|
||||
changeTheme(config.theme ?? 'twitch');
|
||||
renderStreamers();
|
||||
renderQueue();
|
||||
initQueueDragDrop();
|
||||
updateDownloadButtonState();
|
||||
|
||||
window.api.onQueueUpdated((q: QueueItem[]) => {
|
||||
|
||||
@ -334,6 +334,29 @@ body {
|
||||
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 {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user