diff --git a/lib/upload-manager.js b/lib/upload-manager.js index a4ec3e7..7ac1481 100644 --- a/lib/upload-manager.js +++ b/lib/upload-manager.js @@ -38,6 +38,25 @@ class UploadManager extends EventEmitter { this.globalThrottle = null; } + updateSettings(hosterSettings, globalSettings) { + this.hosterSettings = hosterSettings || this.hosterSettings; + this.globalSettings = globalSettings || this.globalSettings; + // Live-update semaphores for running uploads + for (const [hoster, sem] of Object.entries(this.semaphores)) { + const settings = this._getSettings(hoster); + sem.updateLimit(settings.parallelCount); + } + // Update global throttle if speed limit changed + if (this.globalThrottle) { + const newKbs = (this.globalSettings.globalMaxSpeedKbs || 0); + if (newKbs > 0) { + this.globalThrottle.updateRate(newKbs * 1024); + } else { + this.globalThrottle = null; + } + } + } + _getSettings(hoster) { const settings = { ...DEFAULT_SETTINGS, ...(this.hosterSettings[hoster] || {}) }; const globalLimit = this._getGlobalParallelLimit(); diff --git a/main.js b/main.js index 2462d33..64eff0b 100644 --- a/main.js +++ b/main.js @@ -543,9 +543,11 @@ ipcMain.handle('start-upload', (_event, payload) => { } // Write to fileuploader.log immediately when a single upload finishes if (data.status === 'done' && data.result) { - const link = data.result.download_url || data.result.embed_url || ''; + const link = data.result.download_url || data.result.embed_url || data.result.file_code || ''; if (link) { appendUploadLog(data.hoster || '', link, data.fileName || ''); + } else { + debugLog(`WARNING: done but no link for ${data.fileName} @ ${data.hoster}: ${JSON.stringify(data.result)}`); } } if (mainWindow && !mainWindow.isDestroyed()) { @@ -666,6 +668,7 @@ ipcMain.handle('get-hoster-settings', () => { ipcMain.handle('save-hoster-settings', async (_event, hosterSettings) => { await configStore.save({ hosterSettings }); + if (uploadManager) uploadManager.updateSettings(hosterSettings, null); return true; }); @@ -677,6 +680,7 @@ ipcMain.handle('get-global-settings', () => { ipcMain.handle('save-global-settings', async (_event, globalSettings) => { await configStore.save({ globalSettings }); + if (uploadManager) uploadManager.updateSettings(null, globalSettings); return true; }); diff --git a/renderer/app.js b/renderer/app.js index 3e88b76..2232c20 100644 --- a/renderer/app.js +++ b/renderer/app.js @@ -28,6 +28,7 @@ let historySortState = { key: 'date', direction: 'desc' }; // Session-specific files for the "Files" panel (resets each session) let sessionFilesData = []; +let recentSortState = { key: 'date', direction: 'desc' }; // null key = default (date desc) // --- Init --- async function init() { @@ -827,7 +828,9 @@ document.getElementById('contextMenu').addEventListener('click', (e) => { }); async function handleContextAction(action) { - if (action === 'copy-links') { + if (action === 'start-selected') { + startSelectedUpload(); + } else if (action === 'copy-links') { const links = getSelectedJobLinks(); if (links.length) { window.api.copyToClipboard(links.join('\n')); showCopyToast(`${links.length} Links kopiert`); } } else if (action === 'retry-selected') { @@ -1935,6 +1938,33 @@ async function loadHistory() { renderHistoryTable(container); } +function sortRecentFiles(data) { + const sorted = data.slice(); + const { key, direction } = recentSortState; + const dir = direction === 'asc' ? 1 : -1; + sorted.sort((a, b) => { + if (key === 'date') return dir * ((a.dateTs - b.dateTs) || (a.order - b.order)); + if (key === 'filename') return dir * a.filename.localeCompare(b.filename, 'de', { sensitivity: 'base' }); + if (key === 'host') return dir * a.host.localeCompare(b.host, 'de', { sensitivity: 'base' }); + if (key === 'link') return dir * a.link.localeCompare(b.link, 'de', { sensitivity: 'base' }); + return 0; + }); + return sorted; +} + +function updateRecentSortHeaders() { + const head = document.getElementById('recentFilesHead'); + if (!head) return; + head.querySelectorAll('th[data-recent-sort]').forEach(th => { + const key = th.dataset.recentSort; + const active = recentSortState.key === key; + const arrow = active ? (recentSortState.direction === 'asc' ? '▲' : '▼') : '↕'; + th.classList.toggle('active', active); + const indicator = th.querySelector('.sort-indicator'); + if (indicator) indicator.textContent = arrow; + }); +} + function renderRecentUploadsPanel() { const tbody = document.getElementById('recentFilesBody'); if (!tbody) return; @@ -1943,10 +1973,7 @@ function renderRecentUploadsPanel() { return; } - const rows = sessionFilesData - .slice() - .sort((a, b) => b.dateTs - a.dateTs || b.order - a.order) - .slice(0, 20); + const rows = sortRecentFiles(sessionFilesData); tbody.innerHTML = rows.map(row => `
| Datum | -Dateiname | -Host | -Link | +Datum▼ | +Dateiname↕ | +Host↕ | +Link↕ |
|---|