Allow queued confirmation during source pause

This commit is contained in:
Codex committed 2026-10-14 09:42:21 +02:00
1 parent a22913129a
commit b96ab42add
4 files changed
+51 -5

No files matched your search

+24 -3
View File
@@ -128,7 +128,17 @@
const summary = event.target.closest('summary');
const details = summary?.parentElement;
const key = details?.dataset.scraperDisclosure;
if (key && Object.hasOwn(disclosureOpen, key)) disclosureOpen[key] = !details.open;
if (key && Object.hasOwn(disclosureOpen, key)) {
const intended = !details.open;
disclosureOpen[key] = intended;
// A filter click can redraw the panel while this summary click is
// bubbling. Apply the click to the replacement node as well; the
// browser's native toggle will only affect the detached original.
if (!details.isConnected) {
const replacement = card.querySelector(`[data-scraper-disclosure="${key}"]`);
if (replacement) replacement.open = intended;
}
}
});
card.addEventListener('toggle', event => {
const details = event.target;
@@ -227,9 +237,12 @@
const expected = availability?.expectedLastChapter;
const sparse = /^\d+$/.test(String(expected || '')) && Number(availability?.numberedChapters) < Number(expected);
const partialCoverage = availability?.coverage === 'partial' || sparse;
const sourceIsPaused = !!state.sourcePaused?.[item.source];
const outcome = item.status === 'complete'
? `${item.publishedCount ?? 0} chapter${item.publishedCount === 1 ? '' : 's'} published · finished ${when(item.completed)}`
: item.status === 'ready' ? 'Awaiting edition confirmation' : item.status.replaceAll('_', ' ');
: item.status === 'ready' ? 'Awaiting edition confirmation'
: item.status === 'queued' && sourceIsPaused ? 'Confirmed · waiting for source access review'
: item.status.replaceAll('_', ' ');
return h('div', { class: 'scraper-item' + (running ? ' active' : ''), 'data-source': item.source },
h('div', { class: 'grow' }, h('b', {}, item.title),
item.status === 'complete' || availability ? h('div', { class: 'coverage-indicators' },
@@ -241,11 +254,17 @@
+ (item.existingPolicy === 'add-source' ? ' · alternate source' : '')),
item.error ? h('div', { class: 'small error' }, item.error) : null,
item.sourceTitle ? h('div', { class: 'small' }, `Source edition: ${item.sourceTitle}`) : null,
item.status === 'ready' && sourceIsPaused ? h('div', { class: 'small error' },
'This source is paused after an access response. Confirming saves your choice, but downloading will not start until access is reviewed and the source is resumed.') : null,
availability ? h('div', { class: 'muted small' }, `${availability.selectedChapters} hosted selections${availability.specialReleases ? ` · ${availability.specialReleases} unnumbered releases` : ''}${availability.expectedLastChapter ? ` · metadata last chapter: ${availability.expectedLastChapter}` : ''}`) : null),
movable ? h('button', { class: 'btn small', disabled: running || pending[0]?.id === item.id, title: 'Move up', onclick: () => move(item, -1) }, '↑') : null,
movable ? h('button', { class: 'btn small', disabled: running || pending.at(-1)?.id === item.id, title: 'Move down', onclick: () => move(item, 1) }, '↓') : null,
item.status === 'error' ? h('button', { class: 'btn small primary', onclick: () => command({ command: 'control', action: 'retry', id: item.id }) }, 'Retry') : null,
['unavailable', 'quarantined', 'complete', 'ready'].includes(item.status) ? h('button', { class: 'btn small', onclick: () => command({ command: 'control', action: 'inspect', id: item.id }) }, 'Inspect again') : null,
['unavailable', 'quarantined', 'complete', 'ready'].includes(item.status) ? h('button', {
class: 'btn small', disabled: sourceIsPaused,
title: sourceIsPaused ? 'Source access must be reviewed before another inspection' : '',
onclick: () => command({ command: 'control', action: 'inspect', id: item.id }),
}, 'Inspect again') : null,
item.status === 'ready' ? h('button', { class: 'btn small primary', onclick: () => command({ command: 'control', action: 'confirm', id: item.id }) }, 'Confirm download') : null,
h('button', { class: 'btn small', disabled: running, onclick: async () => {
if (confirm(`Remove ${item.title} from the queue? Its library chapters will stay.`)) await command({ command: 'remove', id: item.id });
@@ -273,6 +292,8 @@
h('div', { class: 'row', style: 'margin-top:8px' }, state.paused
? h('button', { class: 'btn primary', onclick: () => command({ command: 'control', action: 'resume' }) }, 'Resume queue')
: h('button', { class: 'btn', onclick: () => command({ command: 'control', action: 'pause' }) }, 'Pause queue'))),
Object.entries(state.sourcePaused || {}).filter(([, paused]) => paused).map(([source]) =>
h('p', { class: 'small error', role: 'status' }, `${source} is paused after a source-access problem. Confirmed jobs wait; confirmation does not resume this source.`)),
h('div', { class: 'field' }, h('span', {}, `Needs attention · ${attention.length}`),
attention.length ? h('div', { class: 'scraper-queue' }, attention.map(item => jobRow(item)))
: h('p', { class: 'muted small' }, 'Nothing needs action on this source.'),