🐛 fix(queue): deleted jobs reappear after restart
Three root causes fixed: - handleProgress() re-created deleted jobs from stale progress callbacks - Queue save was debounced (10s during uploads), deletion lost on app close - Delete was blocked during active uploads (removed !uploading guard) Now: deletions save immediately, deleted IDs are tracked to prevent re-creation, and active uploads are cancelled when their jobs are deleted. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
5569c690a1
commit
176cadc2dd
@ -35,6 +35,7 @@ let _sessionUploadedBytes = 0; // Bytes fully uploaded this session (done jobs)
|
||||
let _sessionTrackedJobs = new Set(); // Job IDs already counted for totalBytes
|
||||
let _sessionDoneJobs = new Set(); // Job IDs already counted for uploadedBytes
|
||||
let _completedUploadKeys = new Set(); // 'filepath|hoster' keys for done uploads (survives removeFromQueueOnDone)
|
||||
let _deletedJobIds = new Set(); // IDs of jobs explicitly deleted by user (prevents re-creation from stale progress callbacks)
|
||||
let queueSortState = { key: 'filename', direction: 'asc' };
|
||||
|
||||
// History state
|
||||
@ -696,6 +697,9 @@ function indexJob(job) {
|
||||
function removeJobFromIndex(job) {
|
||||
_jobIndexById.delete(job.id);
|
||||
if (job.uploadId) _jobIndexByUploadId.delete(job.uploadId);
|
||||
// Track deletion so handleProgress() won't re-create this job from stale callbacks
|
||||
_deletedJobIds.add(job.id);
|
||||
if (job.uploadId) _deletedJobIds.add(job.uploadId);
|
||||
}
|
||||
|
||||
// --- Queue Table Rendering (debounced with virtual scrolling) ---
|
||||
@ -1150,7 +1154,14 @@ document.addEventListener('keydown', (e) => {
|
||||
e.preventDefault();
|
||||
if (selectedRecentIds.size > 0) {
|
||||
deleteSelectedRecentFiles();
|
||||
} else if (selectedJobIds.size > 0 && !uploading) {
|
||||
} else if (selectedJobIds.size > 0) {
|
||||
const deletedIds = [...selectedJobIds];
|
||||
// Cancel active uploads for deleted jobs
|
||||
const activeIds = deletedIds.filter(id => {
|
||||
const j = _jobIndexById.get(id);
|
||||
return j && (j.status === 'uploading' || j.status === 'queued' || j.status === 'retrying' || j.status === 'getting-server');
|
||||
});
|
||||
if (activeIds.length > 0) window.api.cancelSelectedJobs(activeIds);
|
||||
queueJobs = queueJobs.filter(j => {
|
||||
if (selectedJobIds.has(j.id)) { removeJobFromIndex(j); return false; }
|
||||
return true;
|
||||
@ -1160,7 +1171,7 @@ document.addEventListener('keydown', (e) => {
|
||||
renderQueueTable();
|
||||
if (queueJobs.length === 0) { selectedFiles = []; updateUploadView(); }
|
||||
updateStatusBar();
|
||||
persistQueueStateSoon();
|
||||
persistQueueStateSoon(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1184,6 +1195,12 @@ async function handleContextAction(action) {
|
||||
} else if (action === 'retry-selected') {
|
||||
retrySelectedJobs();
|
||||
} else if (action === 'delete-selected') {
|
||||
// Cancel active uploads for deleted jobs
|
||||
const activeIds = [...selectedJobIds].filter(id => {
|
||||
const j = _jobIndexById.get(id);
|
||||
return j && (j.status === 'uploading' || j.status === 'queued' || j.status === 'retrying' || j.status === 'getting-server');
|
||||
});
|
||||
if (activeIds.length > 0) window.api.cancelSelectedJobs(activeIds);
|
||||
queueJobs = queueJobs.filter(j => {
|
||||
if (selectedJobIds.has(j.id)) {
|
||||
removeJobFromIndex(j);
|
||||
@ -1196,10 +1213,15 @@ async function handleContextAction(action) {
|
||||
renderQueueTable();
|
||||
if (queueJobs.length === 0) { selectedFiles = []; updateUploadView(); }
|
||||
updateStatusBar();
|
||||
persistQueueStateSoon();
|
||||
persistQueueStateSoon(true);
|
||||
} else if (action === 'copy-all-links') {
|
||||
copyAllLinks();
|
||||
} else if (action === 'delete-all') {
|
||||
// Cancel all active uploads
|
||||
const activeIds = queueJobs
|
||||
.filter(j => j.status === 'uploading' || j.status === 'queued' || j.status === 'retrying' || j.status === 'getting-server')
|
||||
.map(j => j.id);
|
||||
if (activeIds.length > 0) window.api.cancelSelectedJobs(activeIds);
|
||||
queueJobs.forEach(j => removeJobFromIndex(j));
|
||||
queueJobs = [];
|
||||
selectedJobIds.clear();
|
||||
@ -1208,7 +1230,7 @@ async function handleContextAction(action) {
|
||||
renderQueueTable();
|
||||
updateUploadView();
|
||||
updateStatusBar();
|
||||
persistQueueStateSoon();
|
||||
persistQueueStateSoon(true);
|
||||
} else if (action === 'always-on-top') {
|
||||
alwaysOnTopState = !alwaysOnTopState;
|
||||
await window.api.setAlwaysOnTop(alwaysOnTopState);
|
||||
@ -1406,6 +1428,10 @@ function handleProgress(data) {
|
||||
}
|
||||
}
|
||||
if (!job) {
|
||||
// Don't re-create jobs that were explicitly deleted by the user
|
||||
if ((data.jobId && _deletedJobIds.has(data.jobId)) || (data.uploadId && _deletedJobIds.has(data.uploadId))) {
|
||||
return;
|
||||
}
|
||||
job = {
|
||||
id: data.jobId || data.uploadId || `job-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
|
||||
uploadId: data.uploadId,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user