fix: split layout, top-to-bottom queue processing, persist queue on close
- Queue table limited to 50% height with scrollbar, links panel below - Upload processes files sequentially (file1 all hosters, then file2, etc.) - Queue state persists immediately after adding files (not debounced) - Add beforeunload handler to flush pending queue state Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
6fbfa4b61e
commit
f7e8f9a56c
@ -67,9 +67,24 @@ class UploadManager extends EventEmitter {
|
|||||||
// Start global stats emitter
|
// Start global stats emitter
|
||||||
this._startStatsTimer();
|
this._startStatsTimer();
|
||||||
|
|
||||||
// Create job promises — semaphore controls concurrency per hoster
|
// Group tasks by file to process files top-to-bottom
|
||||||
const promises = tasks.map((task) => this._runJob(task, results, signal));
|
// Within each file, all hosters run in parallel
|
||||||
await Promise.allSettled(promises);
|
const fileOrder = [];
|
||||||
|
const tasksByFile = new Map();
|
||||||
|
for (const task of tasks) {
|
||||||
|
if (!tasksByFile.has(task.file)) {
|
||||||
|
tasksByFile.set(task.file, []);
|
||||||
|
fileOrder.push(task.file);
|
||||||
|
}
|
||||||
|
tasksByFile.get(task.file).push(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const file of fileOrder) {
|
||||||
|
if (signal.aborted) break;
|
||||||
|
const fileTasks = tasksByFile.get(file);
|
||||||
|
const promises = fileTasks.map((task) => this._runJob(task, results, signal));
|
||||||
|
await Promise.allSettled(promises);
|
||||||
|
}
|
||||||
|
|
||||||
this._stopStatsTimer();
|
this._stopStatsTimer();
|
||||||
this.running = false;
|
this.running = false;
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "multi-hoster-uploader",
|
"name": "multi-hoster-uploader",
|
||||||
"version": "1.5.1",
|
"version": "1.5.2",
|
||||||
"description": "Upload files to doodstream, voe, vidmoly, byse simultaneously",
|
"description": "Upload files to doodstream, voe, vidmoly, byse simultaneously",
|
||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@ -200,7 +200,7 @@ function applyHosterSelection() {
|
|||||||
}
|
}
|
||||||
renderHosterSummary();
|
renderHosterSummary();
|
||||||
updateUploadView();
|
updateUploadView();
|
||||||
persistQueueStateSoon();
|
persistQueueStateSoon(true); // immediate persist after adding files
|
||||||
document.getElementById('hosterModal').style.display = 'none';
|
document.getElementById('hosterModal').style.display = 'none';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -297,8 +297,12 @@ async function persistQueueStateNow() {
|
|||||||
await window.api.saveGlobalSettings(globalSettings);
|
await window.api.saveGlobalSettings(globalSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
function persistQueueStateSoon() {
|
function persistQueueStateSoon(immediate) {
|
||||||
clearTimeout(queuePersistTimer);
|
clearTimeout(queuePersistTimer);
|
||||||
|
if (immediate) {
|
||||||
|
persistQueueStateNow().catch(() => {});
|
||||||
|
return;
|
||||||
|
}
|
||||||
// Use longer debounce during uploads to reduce disk I/O
|
// Use longer debounce during uploads to reduce disk I/O
|
||||||
const delay = uploading ? 3000 : 500;
|
const delay = uploading ? 3000 : 500;
|
||||||
queuePersistTimer = setTimeout(() => {
|
queuePersistTimer = setTimeout(() => {
|
||||||
@ -1515,6 +1519,16 @@ function sortHistoryRows(rows) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Flush pending queue state on window close
|
||||||
|
window.addEventListener('beforeunload', () => {
|
||||||
|
if (queuePersistTimer) {
|
||||||
|
clearTimeout(queuePersistTimer);
|
||||||
|
queuePersistTimer = null;
|
||||||
|
// Synchronous-ish: fire and forget since window is closing
|
||||||
|
persistQueueStateNow().catch(() => {});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// --- Setup Listeners ---
|
// --- Setup Listeners ---
|
||||||
function setupListeners() {
|
function setupListeners() {
|
||||||
document.getElementById('addFilesBtn').addEventListener('click', pickFiles);
|
document.getElementById('addFilesBtn').addEventListener('click', pickFiles);
|
||||||
|
|||||||
@ -175,8 +175,9 @@ body {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
.queue-container {
|
.queue-container {
|
||||||
flex: 1;
|
flex: 1 1 50%;
|
||||||
min-height: 220px;
|
min-height: 150px;
|
||||||
|
max-height: 50%;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
background: rgba(255, 255, 255, 0.02);
|
background: rgba(255, 255, 255, 0.02);
|
||||||
@ -290,12 +291,13 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.recent-files-panel {
|
.recent-files-panel {
|
||||||
min-height: 220px;
|
flex: 1 1 auto;
|
||||||
max-height: 280px;
|
min-height: 150px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
border-top: 1px solid var(--border);
|
border-top: 1px solid var(--border);
|
||||||
background: linear-gradient(180deg, rgba(255,255,255,0.015), rgba(0,0,0,0.12));
|
background: linear-gradient(180deg, rgba(255,255,255,0.015), rgba(0,0,0,0.12));
|
||||||
|
overflow: auto;
|
||||||
}
|
}
|
||||||
.recent-files-header {
|
.recent-files-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user