mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-30 17:32:26 +00:00
Merge pull request #106 from PR0M3TH3AN/codex/add-webtorrent-peer-indicator-5n39k5
Match WebTorrent badge styling to CDN indicator
This commit is contained in:
3 files changed
+72
-77
No files matched your search
@@ -74,44 +74,6 @@ header img {
|
||||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
|
||||
.video-card .stream-health {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 2rem;
|
||||
font-size: 1.1rem;
|
||||
line-height: 1;
|
||||
transition: transform 150ms ease, filter 150ms ease, opacity 150ms ease;
|
||||
}
|
||||
|
||||
.video-card .stream-health[data-stream-health-state="good"] {
|
||||
filter: drop-shadow(0 0 6px rgba(34, 197, 94, 0.45));
|
||||
}
|
||||
|
||||
.video-card .stream-health[data-stream-health-state="none"] {
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
.video-card .stream-health[data-stream-health-state="noresp"],
|
||||
.video-card .stream-health[data-stream-health-state="unknown"] {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.video-card .stream-health[data-stream-health-state="checking"] {
|
||||
animation: stream-health-pulse 1.2s ease-in-out infinite alternate;
|
||||
}
|
||||
|
||||
@keyframes stream-health-pulse {
|
||||
from {
|
||||
transform: scale(0.95);
|
||||
opacity: 0.65;
|
||||
}
|
||||
to {
|
||||
transform: scale(1.05);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.video-card--enter {
|
||||
opacity: 0;
|
||||
animation: video-card-fade-in 220ms ease-out forwards;
|
||||
|
||||
@@ -2167,34 +2167,31 @@ class bitvidApp {
|
||||
const includeMargin = options?.includeMargin !== false;
|
||||
const classes = [
|
||||
"torrent-health-badge",
|
||||
"inline-flex",
|
||||
"items-center",
|
||||
"gap-2",
|
||||
"text-xs",
|
||||
"font-semibold",
|
||||
"px-2",
|
||||
"py-1",
|
||||
"rounded",
|
||||
"inline-flex",
|
||||
"items-center",
|
||||
"gap-1",
|
||||
"bg-gray-800",
|
||||
"text-gray-300",
|
||||
"text-xs",
|
||||
"font-semibold",
|
||||
"transition-colors",
|
||||
"duration-200",
|
||||
];
|
||||
if (includeMargin) {
|
||||
classes.unshift("mt-3");
|
||||
}
|
||||
|
||||
return `
|
||||
<div class="${classes.join(" ")}">
|
||||
<span
|
||||
class="stream-health text-lg"
|
||||
aria-live="polite"
|
||||
aria-label="Checking WebTorrent availability"
|
||||
title="Checking WebTorrent availability"
|
||||
>
|
||||
🟦
|
||||
</span>
|
||||
<span class="uppercase tracking-wide text-[0.65rem] text-gray-400">
|
||||
WebTorrent
|
||||
</span>
|
||||
<div
|
||||
class="${classes.join(" ")}"
|
||||
data-stream-health-state="checking"
|
||||
aria-live="polite"
|
||||
role="status"
|
||||
>
|
||||
⏳ Torrent
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
+58
-22
@@ -54,46 +54,82 @@ function toVisual(health) {
|
||||
return "noresp";
|
||||
}
|
||||
|
||||
function formatCount(health) {
|
||||
if (!health || !Number.isFinite(health.seeders) || health.seeders <= 0) {
|
||||
return "";
|
||||
}
|
||||
return ` (${health.seeders})`;
|
||||
}
|
||||
|
||||
function setBadge(card, visual, health) {
|
||||
const el = card.querySelector(".stream-health");
|
||||
if (!el) {
|
||||
const badge = card.querySelector(".torrent-health-badge");
|
||||
if (!badge) {
|
||||
return;
|
||||
}
|
||||
const hadMargin = badge.classList.contains("mt-3");
|
||||
|
||||
const baseClasses = [
|
||||
"torrent-health-badge",
|
||||
"text-xs",
|
||||
"font-semibold",
|
||||
"px-2",
|
||||
"py-1",
|
||||
"rounded",
|
||||
"inline-flex",
|
||||
"items-center",
|
||||
"gap-1",
|
||||
"transition-colors",
|
||||
"duration-200",
|
||||
];
|
||||
if (hadMargin) {
|
||||
baseClasses.unshift("mt-3");
|
||||
}
|
||||
badge.className = baseClasses.join(" ");
|
||||
|
||||
const map = {
|
||||
good: {
|
||||
text: "🟢",
|
||||
aria: "Streamable: seeders available",
|
||||
icon: "✅",
|
||||
aria: "WebTorrent fallback ready",
|
||||
classes: ["bg-green-900", "text-green-200"],
|
||||
role: "status",
|
||||
},
|
||||
none: {
|
||||
text: "🟡",
|
||||
icon: "⚠️",
|
||||
aria: "No seeders reported by trackers",
|
||||
classes: ["bg-amber-900", "text-amber-200"],
|
||||
role: "status",
|
||||
},
|
||||
noresp: {
|
||||
text: "⚫",
|
||||
icon: "❌",
|
||||
aria: "No tracker response",
|
||||
classes: ["bg-red-900", "text-red-200"],
|
||||
role: "alert",
|
||||
},
|
||||
checking: {
|
||||
text: "🟦",
|
||||
aria: "Checking stream availability",
|
||||
icon: "⏳",
|
||||
aria: "Checking Torrent availability",
|
||||
classes: ["bg-gray-800", "text-gray-300"],
|
||||
role: "status",
|
||||
},
|
||||
unknown: {
|
||||
text: "⚪",
|
||||
aria: "Unknown stream availability",
|
||||
icon: "⚠️",
|
||||
aria: "Torrent availability unknown",
|
||||
classes: ["bg-amber-900", "text-amber-200"],
|
||||
role: "status",
|
||||
},
|
||||
};
|
||||
|
||||
const entry = map[visual] || map.unknown;
|
||||
const countText = formatCount(health);
|
||||
el.textContent = `${entry.text}${countText}`;
|
||||
el.setAttribute("aria-label", countText ? `${entry.aria}${countText}` : entry.aria);
|
||||
el.setAttribute("title", countText ? `${entry.aria}${countText}` : entry.aria);
|
||||
el.dataset.streamHealthState = visual;
|
||||
entry.classes.forEach((cls) => badge.classList.add(cls));
|
||||
|
||||
const seederCount =
|
||||
health && Number.isFinite(health.seeders) && health.seeders > 0
|
||||
? health.seeders
|
||||
: null;
|
||||
const countText = seederCount ? ` (${seederCount})` : "";
|
||||
const ariaCount = seederCount ? ` with ${seederCount} seeders` : "";
|
||||
|
||||
const iconPrefix = entry.icon ? `${entry.icon} ` : "";
|
||||
badge.textContent = `${iconPrefix}Torrent${countText}`;
|
||||
const ariaLabel = `${entry.aria}${ariaCount}`;
|
||||
badge.setAttribute("aria-label", ariaLabel);
|
||||
badge.setAttribute("title", ariaLabel);
|
||||
badge.setAttribute("aria-live", "polite");
|
||||
badge.setAttribute("role", entry.role);
|
||||
badge.dataset.streamHealthState = visual;
|
||||
}
|
||||
|
||||
function applyHealth(card, health) {
|
||||
|
||||
Reference in new issue
Block a user