feat(merge-split): add queue checkboxes and merge-group selection UI
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
c1a72ebd66
commit
ad4e540952
@ -31,7 +31,8 @@ function getQueueRenderFingerprint(items: QueueItem[]): string {
|
|||||||
item.speed || '',
|
item.speed || '',
|
||||||
item.eta || '',
|
item.eta || '',
|
||||||
item.progressStatus || '',
|
item.progressStatus || '',
|
||||||
item.last_error || ''
|
item.last_error || '',
|
||||||
|
item.mergeGroup?.mergePhase || ''
|
||||||
].join(':'));
|
].join(':'));
|
||||||
|
|
||||||
return `${lang}|${pieces.join('|')}`;
|
return `${lang}|${pieces.join('|')}`;
|
||||||
@ -138,6 +139,45 @@ function getQueueMetaText(item: QueueItem): string {
|
|||||||
return parts.join(' | ');
|
return parts.join(' | ');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function toggleQueueSelection(id: string): void {
|
||||||
|
if (selectedQueueIds.has(id)) {
|
||||||
|
selectedQueueIds.delete(id);
|
||||||
|
} else {
|
||||||
|
selectedQueueIds.add(id);
|
||||||
|
}
|
||||||
|
renderQueue();
|
||||||
|
updateMergeGroupButton();
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateMergeGroupButton(): void {
|
||||||
|
const btn = byId<HTMLButtonElement>('btnMergeGroup');
|
||||||
|
if (!btn) return;
|
||||||
|
|
||||||
|
// Clean up selections: only keep IDs that are still pending in queue
|
||||||
|
const validIds = new Set(
|
||||||
|
queue.filter(item => item.status === 'pending' && !item.mergeGroup).map(item => item.id)
|
||||||
|
);
|
||||||
|
selectedQueueIds = new Set([...selectedQueueIds].filter(id => validIds.has(id)));
|
||||||
|
|
||||||
|
if (selectedQueueIds.size >= 2) {
|
||||||
|
btn.style.display = '';
|
||||||
|
btn.textContent = `${UI_TEXT.mergeGroup.btn} (${selectedQueueIds.size})`;
|
||||||
|
btn.disabled = false;
|
||||||
|
} else {
|
||||||
|
btn.style.display = 'none';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function createMergeGroupFromSelection(): Promise<void> {
|
||||||
|
if (selectedQueueIds.size < 2) return;
|
||||||
|
|
||||||
|
const ids = [...selectedQueueIds];
|
||||||
|
selectedQueueIds.clear();
|
||||||
|
queue = await window.api.createMergeGroup(ids);
|
||||||
|
renderQueue();
|
||||||
|
updateMergeGroupButton();
|
||||||
|
}
|
||||||
|
|
||||||
function renderQueue(): void {
|
function renderQueue(): void {
|
||||||
if (!Array.isArray(queue)) {
|
if (!Array.isArray(queue)) {
|
||||||
queue = [];
|
queue = [];
|
||||||
@ -172,15 +212,29 @@ function renderQueue(): void {
|
|||||||
: (hasDeterminateProgress ? Math.max(0, Math.min(100, item.progress)) : 0);
|
: (hasDeterminateProgress ? Math.max(0, Math.min(100, item.progress)) : 0);
|
||||||
const progressClass = item.status === 'downloading' && !hasDeterminateProgress ? ' indeterminate' : '';
|
const progressClass = item.status === 'downloading' && !hasDeterminateProgress ? ' indeterminate' : '';
|
||||||
|
|
||||||
|
const isMergeGroup = !!item.mergeGroup;
|
||||||
|
const showCheckbox = item.status === 'pending' && !isMergeGroup;
|
||||||
|
const isChecked = selectedQueueIds.has(item.id);
|
||||||
|
const mergeIcon = isMergeGroup
|
||||||
|
? '<svg class="merge-group-icon" viewBox="0 0 24 24" fill="currentColor" width="14" height="14"><path d="M17 20.41L18.41 19 15 15.59 13.59 17 17 20.41zM7.5 8H11v5.59L5.59 19 7 20.41l6-6V8h3.5L12 3.5 7.5 8z"/></svg> '
|
||||||
|
: '';
|
||||||
|
const mergeMetaExtra = isMergeGroup
|
||||||
|
? ` (${item.mergeGroup!.items.length} VODs)`
|
||||||
|
: '';
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<div class="queue-item">
|
<div class="queue-item${isMergeGroup ? ' merge-group' : ''}">
|
||||||
|
${showCheckbox
|
||||||
|
? `<input type="checkbox" class="queue-checkbox" ${isChecked ? 'checked' : ''} onchange="toggleQueueSelection('${item.id}')" />`
|
||||||
|
: ''
|
||||||
|
}
|
||||||
<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}">${isClip}${safeTitle}</div>
|
<div class="title" title="${safeTitle}">${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}</div>
|
<div class="queue-meta">${safeMeta}${mergeMetaExtra}</div>
|
||||||
<div class="queue-progress-wrap">
|
<div class="queue-progress-wrap">
|
||||||
<div class="queue-progress-bar${progressClass}" style="width: ${progressValue}%;"></div>
|
<div class="queue-progress-bar${progressClass}" style="width: ${progressValue}%;"></div>
|
||||||
</div>
|
</div>
|
||||||
@ -191,6 +245,7 @@ function renderQueue(): void {
|
|||||||
`;
|
`;
|
||||||
}).join('');
|
}).join('');
|
||||||
|
|
||||||
|
updateMergeGroupButton();
|
||||||
lastQueueRenderFingerprint = renderFingerprint;
|
lastQueueRenderFingerprint = renderFingerprint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -24,6 +24,7 @@ let currentStreamer: string | null = null;
|
|||||||
let isConnected = false;
|
let isConnected = false;
|
||||||
let downloading = false;
|
let downloading = false;
|
||||||
let queue: QueueItem[] = [];
|
let queue: QueueItem[] = [];
|
||||||
|
let selectedQueueIds: Set<string> = new Set();
|
||||||
|
|
||||||
let cutterFile: string | null = null;
|
let cutterFile: string | null = null;
|
||||||
let cutterVideoInfo: VideoInfo | null = null;
|
let cutterVideoInfo: VideoInfo | null = null;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user