Compare commits

..

No commits in common. "c73108afff914b78cbc5f42429a33ac16520a13e" and "1bcd7a20780c2dbccec7127b9271de65fd8bb980" have entirely different histories.

2 changed files with 16 additions and 59 deletions

View File

@ -1,6 +1,6 @@
{
"name": "multi-hoster-uploader",
"version": "2.8.8",
"version": "2.8.7",
"description": "Upload files to doodstream, voe, vidmoly, byse simultaneously",
"main": "main.js",
"scripts": {

View File

@ -200,21 +200,13 @@ async function init() {
}
// --- Tab switching ---
let _historyDirty = false;
function _isHistoryTabActive() {
const tab = document.querySelector('.tab.active');
return !!(tab && tab.dataset.view === 'history');
}
document.querySelectorAll('.tab').forEach(tab => {
tab.addEventListener('click', () => {
document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
document.querySelectorAll('.view').forEach(v => v.classList.remove('active'));
tab.classList.add('active');
document.getElementById(`${tab.dataset.view}-view`).classList.add('active');
if (tab.dataset.view === 'history') {
_historyDirty = false;
loadHistory();
}
if (tab.dataset.view === 'history') loadHistory();
});
});
@ -1828,25 +1820,16 @@ function handleBatchDone(summary) {
updateQueueActionButtons();
renderQueueTable();
renderRecentUploadsPanel();
// History is only visible on the Verlauf tab. Mark it dirty and refresh when
// the user actually switches to it — skips an IPC + full table rebuild per
// batch-done when the user is watching the upload view.
_historyDirty = true;
if (_isHistoryTabActive()) loadHistory();
loadHistory();
const removeOnDone = config.globalSettings && config.globalSettings.removeFromQueueOnDone;
if (removeOnDone) {
// Single pass: build the keep-list and clean up the index for removed jobs.
const nextJobs = [];
for (const job of queueJobs) {
if (job.status === 'done') {
removeJobFromIndex(job);
selectedJobIds.delete(job.id);
} else {
nextJobs.push(job);
}
const doneJobs = queueJobs.filter(j => j.status === 'done');
for (const job of doneJobs) {
removeJobFromIndex(job);
selectedJobIds.delete(job.id);
}
queueJobs = nextJobs;
queueJobs = queueJobs.filter(j => j.status !== 'done');
renderQueueTable();
}
@ -3232,50 +3215,24 @@ function updateRecentSortHeaders() {
let _recentListenersBound = false;
function _buildRecentRowHtml(row) {
const cls = `recent-file-row${row.isError ? ' error' : ''}${selectedRecentIds.has(row.order) ? ' selected' : ''}`;
return `<tr class="${cls}" data-order="${row.order}" data-link="${escapeAttr(row.link)}">`
+ `<td>${escapeHtml(row.date)}</td>`
+ `<td title="${escapeAttr(row.filename)}">${escapeHtml(row.filename)}</td>`
+ `<td>${escapeHtml(row.host)}</td>`
+ `<td title="${escapeAttr(row.link)}">${escapeHtml(row.link)}</td>`
+ `</tr>`;
}
// Tracks the last rendered dataset so we can append-only when the user is just
// accumulating new uploads (the default case: sort=date desc, rows only grow).
let _recentLastRenderedSig = '';
let _recentLastRenderedLen = 0;
function renderRecentUploadsPanel() {
const tbody = document.getElementById('recentFilesBody');
if (!tbody) return;
if (!sessionFilesData.length) {
tbody.innerHTML = '<tr><td colspan="4" class="empty-state">Noch keine Uploads in dieser Session.</td></tr>';
_recentLastRenderedSig = '';
_recentLastRenderedLen = 0;
return;
}
const rows = sortRecentFiles(sessionFilesData);
const sig = `${recentSortState.key}|${recentSortState.direction}`;
const dateDescAppendOnly = sig === 'date|desc'
&& _recentLastRenderedSig === sig
&& rows.length > _recentLastRenderedLen
&& tbody.querySelectorAll('.recent-file-row').length === _recentLastRenderedLen;
if (dateDescAppendOnly) {
// Fast path: only new rows (date desc puts newest on top) — insert them
// at the top without rebuilding the 5000-row tbody below.
const added = rows.length - _recentLastRenderedLen;
let html = '';
for (let i = 0; i < added; i++) html += _buildRecentRowHtml(rows[i]);
tbody.insertAdjacentHTML('afterbegin', html);
} else {
tbody.innerHTML = rows.map(_buildRecentRowHtml).join('');
}
_recentLastRenderedSig = sig;
_recentLastRenderedLen = rows.length;
tbody.innerHTML = rows.map(row => `
<tr class="recent-file-row${row.isError ? ' error' : ''}${selectedRecentIds.has(row.order) ? ' selected' : ''}" data-order="${row.order}" data-link="${escapeAttr(row.link)}">
<td>${escapeHtml(row.date)}</td>
<td title="${escapeAttr(row.filename)}">${escapeHtml(row.filename)}</td>
<td>${escapeHtml(row.host)}</td>
<td title="${escapeAttr(row.link)}">${escapeHtml(row.link)}</td>
</tr>
`).join('');
// Event delegation bind once, not per-row
if (!_recentListenersBound) {