Files
Varaverk/Plugin/unraid/js/varaverk.js
T
Gmer4Lfe a11e3d73a7 Escape what the arrs report about themselves, and give the tab an assistant
Health messages go straight from each arr's API into innerHTML and quote things
nobody here controls — indexer names from Prowlarr, import-list names, release
titles. The page used no escaping at all. _sz() was also binary while labelling
its output TB, so /tv read 86.9 TB here and 95.6 TB on every other tab; it has
one caller and that caller is disk capacity, so it now matches the rest.
2026-08-14 17:51:04 -04:00

99 lines
4.3 KiB
JavaScript

// Varaverk — shared JS utilities
// Page-specific JS lives inline in each page partial.
// ── Shared formatters ────────────────────────────────────────────────────────
const _GB = 1073741824, _MB = 1048576, _TB = 1099511627776;
// Relative timestamp → "just now" / "5m ago" / "yesterday" / "3d ago"
function _relTime(ts) {
if (!ts) return '—';
const d = Math.floor(Date.now() / 1000) - ts;
if (d < 60) return 'just now';
if (d < 3600) return Math.floor(d / 60) + 'm ago';
if (d < 86400) return Math.floor(d / 3600) + 'h ago';
if (d < 172800) return 'yesterday';
return Math.floor(d / 86400) + 'd ago';
}
// Bytes → human-readable size (GB / MB / KB)
function _fmtBytes(b) {
if (!b) return '—';
if (b >= _GB) return (b / _GB).toFixed(1) + ' GB';
if (b >= _MB) return (b / _MB).toFixed(0) + ' MB';
return (b / 1024).toFixed(0) + ' KB';
}
// Bytes → auto-scale TB / GB / MB, decimal.
//
// Its only caller is the arr disk bar, which is showing the same storage the Monitor and Watchdog
// tabs show. Those were moved to decimal so a disk reads the same number here as on Unraid's own
// Main page and as printed on the drive; leaving this one binary made /tv 86.9 TB on this tab and
// 95.6 TB on the next, which is worse than either convention chosen consistently.
//
// Capacity is decimal, memory stays binary — 128 GB of RAM genuinely is 125.8 GiB and every tool
// on the box agrees. See _vv_api_bytes_to_gib() in include/unraid_api.php for the same split on
// the PHP side.
function _sz(b) {
if (!b) return '—';
if (b >= 1e12) return (b / 1e12).toFixed(1) + ' TB';
if (b >= 1e9) return (b / 1e9).toFixed(1) + ' GB';
return (b / 1e6).toFixed(0) + ' MB';
}
function _gb(b) { return !b ? '—' : (b / _GB).toFixed(1) + ' GB'; }
function _tb(b) { return !b ? '—' : (b / _TB).toFixed(2) + ' TB'; }
function _n(v) { return v == null ? '—' : Number(v).toLocaleString(); }
// Seconds → uptime string: "2d 3h 5m" / "3h 5m" / "5m"
function _uptime(sec) {
if (!sec) return '—';
const d = Math.floor(sec / 86400), h = Math.floor((sec % 86400) / 3600), m = Math.floor((sec % 3600) / 60);
return d > 0 ? `${d}d ${h}h ${m}m` : h > 0 ? `${h}h ${m}m` : `${m}m`;
}
// Flash a status element briefly then fade
function vvFlashStatus(el, msg, ok) {
el.textContent = msg;
el.style.color = ok ? '#4caf50' : '#f44336';
setTimeout(() => { el.textContent = ''; }, 3000);
}
// ── Fullscreen toggle — hides Unraid header + menu ────────────────────────────
function vvToggleExpand() {
const on = document.body.classList.toggle('vv-fullscreen');
const btn = document.getElementById('vv-expand-btn');
if (btn) { btn.classList.toggle('active', on); btn.title = on ? 'Collapse' : 'Expand'; }
localStorage.setItem('vv-fullscreen', on ? '1' : '');
}
// Restore state on every page load
(function() {
if (localStorage.getItem('vv-fullscreen') !== '1') return;
document.body.classList.add('vv-fullscreen');
// Button may not exist yet if script runs before DOM — wait for it
const apply = () => {
const btn = document.getElementById('vv-expand-btn');
if (btn) { btn.classList.add('active'); btn.title = 'Collapse'; }
};
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', apply);
else apply();
})();
// Bring the current tab into view when the bar is too narrow to show them all. The bar scrolls
// itself now rather than dragging the page sideways, which means the active tab can start off
// screen — and a tab bar whose selected tab is invisible reads as no tab being selected.
//
// inline:'nearest' so a tab already visible is left exactly where it is; only an off-screen one
// moves, and only far enough. Guarded because Unraid swaps tab content by AJAX and this file is
// shared by every page.
(function () {
const show = () => {
const bar = document.getElementById('vv-tabs');
const cur = bar && bar.querySelector('.vv-tab.active');
if (!cur || bar.scrollWidth <= bar.clientWidth) return;
if (cur.scrollIntoView) cur.scrollIntoView({ block: 'nearest', inline: 'nearest' });
};
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', show);
else show();
})();