diff --git a/js/gridHealth.js b/js/gridHealth.js index 7f90e6e5..eac90b61 100644 --- a/js/gridHealth.js +++ b/js/gridHealth.js @@ -62,9 +62,11 @@ function formatTime(ts) { } } -function buildTooltip({ peers = 0, checkedAt, reason } = {}) { +function buildTooltip({ peers = 0, checkedAt, reason, webseedOnly } = {}) { const parts = []; - if (Number.isFinite(peers)) { + if (webseedOnly) { + parts.push("Webseed only"); + } else if (Number.isFinite(peers)) { parts.push(`Peers: ${Math.max(0, peers)}`); } if (Number.isFinite(checkedAt)) { @@ -97,6 +99,7 @@ function normalizeResult(result) { healthy: false, peers: 0, reason: "error", + webseedOnly: false, appendedTrackers: false, hasProbeTrackers: false, usedTrackers: Array.isArray(TorrentClient.PROBE_TRACKERS) @@ -112,10 +115,12 @@ function normalizeResult(result) { : 0; const healthy = Boolean(result.healthy) && peers > 0; const reason = typeof result.reason === "string" ? result.reason : "error"; + const webseedOnly = Boolean(result.webseedOnly) && peers === 0; return { healthy, peers: healthy ? Math.max(1, peers) : peers, reason, + webseedOnly, appendedTrackers: Boolean(result.appendedTrackers), hasProbeTrackers: typeof result.hasProbeTrackers === "boolean" @@ -416,6 +421,7 @@ function setBadge(card, state, details) { : 0; const hasPeerCount = details ? Number.isFinite(details.peers) : false; const peersTextValue = hasPeerCount ? String(peersValue) : ""; + const webseedOnly = Boolean(details?.webseedOnly); card.dataset.streamHealthState = normalizedState; if (hasPeerCount) { @@ -489,6 +495,7 @@ function setBadge(card, state, details) { peers: peersValue, checkedAt: details?.checkedAt, reason: details?.reason, + webseedOnly, }); badge.setAttribute("aria-label", tooltip); badge.setAttribute("title", tooltip); @@ -507,6 +514,7 @@ function setBadge(card, state, details) { state: normalizedState, peers: hasPeerCount ? peersValue : null, reason: details && typeof details.reason === "string" ? details.reason : null, + webseedOnly, checkedAt: details && Number.isFinite(details.checkedAt) ? Number(details.checkedAt) : null, text: badge.textContent, diff --git a/js/ui/components/VideoCard.js b/js/ui/components/VideoCard.js index 5ea8fa4e..4574823a 100644 --- a/js/ui/components/VideoCard.js +++ b/js/ui/components/VideoCard.js @@ -2168,9 +2168,16 @@ export class VideoCard { } } - buildTorrentTooltip({ peers = null, checkedAt = null, reason = null } = {}) { + buildTorrentTooltip({ + peers = null, + checkedAt = null, + reason = null, + webseedOnly = false, + } = {}) { const parts = []; - if (Number.isFinite(peers)) { + if (webseedOnly) { + parts.push("Webseed only"); + } else if (Number.isFinite(peers)) { parts.push(`Peers: ${Math.max(0, Number(peers))}`); } if (Number.isFinite(checkedAt)) { @@ -2255,6 +2262,7 @@ export class VideoCard { : null; const reason = typeof entry?.reason === "string" && entry.reason ? entry.reason : null; + const webseedOnly = Boolean(entry?.webseedOnly); const text = typeof entry?.text === "string" && entry.text ? entry.text : null; const tooltip = @@ -2318,7 +2326,8 @@ export class VideoCard { checkedAt: Number.isFinite(entry?.checkedAt) ? entry.checkedAt : null, - reason + reason, + webseedOnly, })); badge.setAttribute("aria-label", tooltipValue); diff --git a/js/ui/views/VideoListView.js b/js/ui/views/VideoListView.js index 8aed5849..9be143f6 100644 --- a/js/ui/views/VideoListView.js +++ b/js/ui/views/VideoListView.js @@ -1040,6 +1040,9 @@ export class VideoListView { if (Number.isFinite(entry.peers)) { normalized.peers = Math.max(0, Number(entry.peers)); } + if (typeof entry.webseedOnly === "boolean") { + normalized.webseedOnly = entry.webseedOnly; + } if (typeof entry.reason === "string" && entry.reason) { normalized.reason = entry.reason; } diff --git a/js/webtorrent.js b/js/webtorrent.js index 5a567114..e13a7ca8 100644 --- a/js/webtorrent.js +++ b/js/webtorrent.js @@ -257,6 +257,7 @@ export class TorrentClient { reason: "error", error: toError(err), peers: 0, + webseedOnly: hasWebSeed, }); return; } @@ -275,6 +276,7 @@ export class TorrentClient { reason: "error", error: toError(err), peers, + webseedOnly: peers === 0 && hasWebSeed, }); }); @@ -285,6 +287,7 @@ export class TorrentClient { healthy: false, peers, reason: "timeout", + webseedOnly: peers === 0 && hasWebSeed, }); }, safeTimeout); }