diff --git a/public/app.js b/public/app.js index 6ee3f14..7981c56 100644 --- a/public/app.js +++ b/public/app.js @@ -9,6 +9,8 @@ const SPLASH_MIN_MS = 1200; // minimum splash display time let historyDays = parseInt(localStorage.getItem('sofarr-history-days'), 10) || 7; let historyRefreshHandle = null; const HISTORY_REFRESH_MS = 5 * 60 * 1000; // auto-refresh history every 5 min +let ignoreAvailable = localStorage.getItem('sofarr-ignore-available') === 'true'; +let lastHistoryItems = []; // raw items from last fetch, for re-filtering without a network round-trip // SSE stream state let sseSource = null; @@ -869,6 +871,7 @@ function hideLoading() { function initHistoryControls() { const daysInput = document.getElementById('history-days'); const refreshBtn = document.getElementById('history-refresh-btn'); + const ignoreToggle = document.getElementById('ignore-available-toggle'); if (daysInput) { daysInput.addEventListener('change', () => { const v = parseInt(daysInput.value, 10); @@ -882,6 +885,14 @@ function initHistoryControls() { if (refreshBtn) { refreshBtn.addEventListener('click', () => loadHistory(true)); } + if (ignoreToggle) { + ignoreToggle.checked = ignoreAvailable; + ignoreToggle.addEventListener('change', () => { + ignoreAvailable = ignoreToggle.checked; + localStorage.setItem('sofarr-ignore-available', ignoreAvailable); + renderHistory(lastHistoryItems); + }); + } } function startHistoryRefresh() { @@ -897,6 +908,7 @@ function stopHistoryRefresh() { } function clearHistory() { + lastHistoryItems = []; document.getElementById('history-list').innerHTML = ''; document.getElementById('no-history').style.display = 'none'; document.getElementById('history-error').style.display = 'none'; @@ -920,7 +932,8 @@ async function loadHistory(forceRefresh = false) { if (!res.ok) throw new Error(`HTTP ${res.status}`); const data = await res.json(); loadingEl.style.display = 'none'; - renderHistory(data.history || []); + lastHistoryItems = data.history || []; + renderHistory(lastHistoryItems); } catch (err) { loadingEl.style.display = 'none'; errorEl.textContent = 'Failed to load history.'; @@ -933,12 +946,15 @@ function renderHistory(items) { const listEl = document.getElementById('history-list'); const noHistoryEl = document.getElementById('no-history'); listEl.innerHTML = ''; - if (!items.length) { + const visible = ignoreAvailable + ? items.filter(item => !(item.outcome === 'failed' && item.availableForUpgrade)) + : items; + if (!visible.length) { noHistoryEl.style.display = 'block'; return; } noHistoryEl.style.display = 'none'; - items.forEach(item => listEl.appendChild(createHistoryCard(item))); + visible.forEach(item => listEl.appendChild(createHistoryCard(item))); } function createHistoryCard(item) { diff --git a/public/index.html b/public/index.html index dec9207..7eeb1fb 100644 --- a/public/index.html +++ b/public/index.html @@ -98,6 +98,10 @@ days + diff --git a/public/style.css b/public/style.css index 290c89b..8aeae00 100644 --- a/public/style.css +++ b/public/style.css @@ -714,6 +714,22 @@ body { color: var(--text-primary); } +.history-toggle-label { + display: inline-flex; + align-items: center; + gap: 5px; + font-size: 0.82rem; + color: var(--text-secondary); + cursor: pointer; + user-select: none; + margin-left: 4px; +} + +.history-toggle-label input[type="checkbox"] { + cursor: pointer; + accent-color: var(--accent, #2980b9); +} + .history-loading, .history-error, .no-history {