feat: refine earth hud panel behaviors and news board

This commit is contained in:
linkong
2026-04-17 17:41:15 +08:00
parent 8f3ab88743
commit 1cf1f32ddd
20 changed files with 1803 additions and 250 deletions

View File

@@ -1,5 +1,6 @@
import Hls from "hls.js";
import { showStatusMessage } from "./ui.js";
import { createHUDPanel } from "./hud-panels.js";
const TV_STREAMS_API = "/api/v1/tv/streams";
const TV_PROXY_API = "/api/v1/tv/proxy";
@@ -21,6 +22,7 @@ let refreshPromise = null;
let hlsPlayer = null;
let hlsRecoveryAttempts = 0;
let metaAutoCollapseTimer = null;
let tvPanel = null;
const failedSourceIds = new Set();
let probeTimer = null;
@@ -58,36 +60,7 @@ function getElements() {
}
function setMetaCollapsed(collapsed) {
const { metaWrap, metaToggle, panel } = getElements();
if (!metaWrap) return;
const isDragged = panel?.dataset.dragged === "true" && panel.style.top;
if (isDragged) {
// Top-anchored panel: toggle instantly and compensate top so the player
// (panel bottom) stays visually fixed.
const bottomBefore = panel.getBoundingClientRect().bottom;
metaWrap.style.transition = "none";
metaWrap.classList.toggle("is-collapsed", collapsed);
metaToggle?.classList.toggle("is-collapsed", collapsed);
// Force synchronous reflow to get updated panel height
void panel.offsetHeight;
const delta = panel.getBoundingClientRect().bottom - bottomBefore;
if (delta !== 0) {
panel.style.top = `${parseFloat(panel.style.top) - delta}px`;
}
// Restore CSS transition after this paint
requestAnimationFrame(() => {
metaWrap.style.transition = "";
});
} else {
metaWrap.classList.toggle("is-collapsed", collapsed);
metaToggle?.classList.toggle("is-collapsed", collapsed);
}
tvPanel?.setCollapsed(collapsed);
}
function autoExpandMeta() {
@@ -209,7 +182,7 @@ function syncSettingsToggle(visible) {
function setPanelVisible(visible) {
const { panel } = getElements();
if (!panel) return;
panel.classList.toggle("hud-panel-hidden", !visible);
tvPanel?.setVisible(visible);
updateToggleButton(visible);
syncSettingsToggle(visible);
}
@@ -679,15 +652,28 @@ export function initTVPanel() {
if (initialized) return;
initialized = true;
const { select, refreshBtn, iframe, video, toggleBtn, panel } = getElements();
const { select, refreshBtn, iframe, video, toggleBtn, panel, metaToggle } = getElements();
updateToggleButton(!panel?.classList.contains("hud-panel-hidden"));
syncSettingsToggle(!panel?.classList.contains("hud-panel-hidden"));
if (panel && metaToggle) {
tvPanel = createHUDPanel({
panel,
header: ".hud-panel__header",
body: "#tv-meta-wrap",
collapseBtn: metaToggle,
bodyCollapsedClass: "is-collapsed",
preferredDirection: "up",
expandLabel: "展开新闻直播信息",
collapseLabel: "折叠新闻直播信息",
});
}
updateToggleButton(tvPanel?.isVisible() ?? !panel?.classList.contains("hud-panel-hidden"));
syncSettingsToggle(tvPanel?.isVisible() ?? !panel?.classList.contains("hud-panel-hidden"));
toggleBtn?.addEventListener("click", async (event) => {
event.preventDefault();
event.stopPropagation();
const nextVisible = panel?.classList.contains("hud-panel-hidden") ?? true;
const nextVisible = !(tvPanel?.isVisible() ?? false);
setPanelVisible(nextVisible);
if (nextVisible) {
await ensureTVPanelReady();
@@ -704,10 +690,9 @@ export function initTVPanel() {
renderSource(findSourceById(currentSourceId));
});
const { metaToggle } = getElements();
metaToggle?.addEventListener("click", () => {
clearTimeout(metaAutoCollapseTimer);
const isNowCollapsed = !metaToggle.classList.contains("is-collapsed");
const isNowCollapsed = !(tvPanel?.isCollapsed() ?? false);
setMetaCollapsed(isNowCollapsed);
});