new ui changes
This commit is contained in:
61
web/app.js
61
web/app.js
@@ -2,10 +2,11 @@
|
||||
|
||||
/* ============================================================
|
||||
Transmission Manager - frontend
|
||||
Vanilla SPA. Auto-refreshes every 3s with in-place updates.
|
||||
Vanilla SPA. Auto-refreshes on a selectable interval with in-place updates.
|
||||
============================================================ */
|
||||
|
||||
const REFRESH_MS = 3000;
|
||||
const DEFAULT_REFRESH_MS = 3000;
|
||||
const REFRESH_INTERVALS = new Set([1000, 3000, 5000, 10000]);
|
||||
const TRANSMISSION_STATUSES = {
|
||||
0: "stopped",
|
||||
1: "check-wait",
|
||||
@@ -21,6 +22,7 @@ const state = {
|
||||
stats: {},
|
||||
filter: "",
|
||||
sortKey: "status",
|
||||
refreshMs: DEFAULT_REFRESH_MS,
|
||||
lastError: null,
|
||||
};
|
||||
|
||||
@@ -28,6 +30,7 @@ const torrentCards = new Map();
|
||||
const actionStates = new Map();
|
||||
let syncInFlight = false;
|
||||
let syncQueued = false;
|
||||
let refreshTimer = null;
|
||||
|
||||
const $ = (sel) => document.querySelector(sel);
|
||||
|
||||
@@ -91,8 +94,34 @@ function setSyncing(on) {
|
||||
const el = $("#refresh-indicator");
|
||||
if (!el) return;
|
||||
el.classList.toggle("syncing", on);
|
||||
const t = el.querySelector(".refresh-text");
|
||||
if (t) t.textContent = on ? "syncing" : "live";
|
||||
updateRefreshMetadata(on);
|
||||
}
|
||||
|
||||
function refreshLabel() {
|
||||
return `${state.refreshMs / 1000}s`;
|
||||
}
|
||||
|
||||
function updateRefreshMetadata(syncing = false) {
|
||||
const label = refreshLabel();
|
||||
const indicator = $("#refresh-indicator");
|
||||
if (indicator) {
|
||||
indicator.title = `Auto-refreshes every ${label}`;
|
||||
indicator.setAttribute(
|
||||
"aria-label",
|
||||
syncing ? `Syncing; auto-refresh every ${label}` : `Auto-refresh active every ${label}`,
|
||||
);
|
||||
}
|
||||
|
||||
const hint = $("#error-hint");
|
||||
if (hint) hint.textContent = `Retrying in ${label}...`;
|
||||
}
|
||||
|
||||
function setRefreshInterval(ms) {
|
||||
state.refreshMs = REFRESH_INTERVALS.has(ms) ? ms : DEFAULT_REFRESH_MS;
|
||||
updateRefreshMetadata(syncInFlight);
|
||||
|
||||
if (refreshTimer) clearInterval(refreshTimer);
|
||||
refreshTimer = setInterval(sync, state.refreshMs);
|
||||
}
|
||||
|
||||
async function runTorrentAction(id, action) {
|
||||
@@ -217,6 +246,10 @@ function compareName(a, b) {
|
||||
return (a.name || "").localeCompare(b.name || "");
|
||||
}
|
||||
|
||||
function activitySpeed(t) {
|
||||
return (t.rateDownload || 0) + (t.rateUpload || 0);
|
||||
}
|
||||
|
||||
function sortTorrents(list) {
|
||||
const key = state.sortKey;
|
||||
const sorted = list.slice();
|
||||
@@ -230,6 +263,11 @@ function sortTorrents(list) {
|
||||
return (b.uploadRatio || 0) - (a.uploadRatio || 0) || compareName(a, b);
|
||||
case "size":
|
||||
return (b.totalSize || 0) - (a.totalSize || 0) || compareName(a, b);
|
||||
case "speed":
|
||||
return (activitySpeed(b) - activitySpeed(a))
|
||||
|| ((b.rateDownload || 0) - (a.rateDownload || 0))
|
||||
|| ((b.rateUpload || 0) - (a.rateUpload || 0))
|
||||
|| compareName(a, b);
|
||||
case "peer100": {
|
||||
const pa = peerStatus(a);
|
||||
const pb = peerStatus(b);
|
||||
@@ -513,6 +551,19 @@ function wireEvents() {
|
||||
});
|
||||
});
|
||||
|
||||
const refreshSelect = $("#refresh-interval");
|
||||
if (refreshSelect) {
|
||||
refreshSelect.value = String(state.refreshMs);
|
||||
refreshSelect.addEventListener("change", (e) => {
|
||||
const next = Number(e.target.value);
|
||||
if (!REFRESH_INTERVALS.has(next)) {
|
||||
e.target.value = String(state.refreshMs);
|
||||
return;
|
||||
}
|
||||
setRefreshInterval(next);
|
||||
});
|
||||
}
|
||||
|
||||
$("#torrents").addEventListener("click", (e) => {
|
||||
const button = e.target.closest("[data-action-button]");
|
||||
if (!button || button.disabled) return;
|
||||
@@ -535,8 +586,8 @@ function wireEvents() {
|
||||
/* ---------- Init ---------- */
|
||||
function boot() {
|
||||
wireEvents();
|
||||
setRefreshInterval(state.refreshMs);
|
||||
sync();
|
||||
setInterval(sync, REFRESH_MS);
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", boot);
|
||||
|
||||
Reference in New Issue
Block a user