release: bump version to 0.38.0
This commit is contained in:
@@ -36,6 +36,7 @@ const tabPanelState = {
|
||||
live: null,
|
||||
news: null,
|
||||
};
|
||||
let mobileMetaCollapsed = false;
|
||||
|
||||
const META_AUTO_COLLAPSE_DELAY = 2500;
|
||||
const PROBE_INTERVAL_MS = 2 * 60 * 1000;
|
||||
@@ -72,8 +73,8 @@ function getElements() {
|
||||
empty: document.getElementById(isMobile ? "mobile-tv-empty-state" : "tv-empty-state"),
|
||||
refreshBtn: document.getElementById(isMobile ? "mobile-tv-refresh" : "tv-refresh"),
|
||||
openBtn: document.getElementById(isMobile ? "mobile-tv-open-external" : "tv-open-external"),
|
||||
metaWrap: document.getElementById("tv-meta-wrap"),
|
||||
metaToggle: document.getElementById("tv-meta-toggle"),
|
||||
metaWrap: document.getElementById(isMobile ? "mobile-tv-meta-wrap" : "tv-meta-wrap"),
|
||||
metaToggle: document.getElementById(isMobile ? "mobile-tv-meta-toggle" : "tv-meta-toggle"),
|
||||
liveHeaderControls: document.getElementById("tv-header-controls-live"),
|
||||
newsHeaderControls: document.getElementById("tv-header-controls-news"),
|
||||
liveTabBtn: document.getElementById("tv-tab-live"),
|
||||
@@ -84,8 +85,43 @@ function getElements() {
|
||||
};
|
||||
}
|
||||
|
||||
function isMobileLayout() {
|
||||
return document.body.classList.contains("layout-mode-mobile");
|
||||
}
|
||||
|
||||
function syncMetaToggleState(collapsed) {
|
||||
const mobileOverviewBar = document.getElementById("mobile-tv-overview-bar");
|
||||
if (mobileOverviewBar instanceof HTMLElement) {
|
||||
mobileOverviewBar.setAttribute("aria-expanded", collapsed ? "false" : "true");
|
||||
}
|
||||
const desktopToggle = document.getElementById("tv-meta-toggle");
|
||||
if (desktopToggle instanceof HTMLButtonElement) {
|
||||
desktopToggle.setAttribute("aria-expanded", collapsed ? "false" : "true");
|
||||
desktopToggle.setAttribute(
|
||||
"aria-label",
|
||||
collapsed ? "展开新闻直播内容" : "折叠新闻直播内容",
|
||||
);
|
||||
desktopToggle.title = collapsed ? "展开新闻直播内容" : "折叠新闻直播内容";
|
||||
}
|
||||
}
|
||||
|
||||
function isMetaCollapsed() {
|
||||
if (isMobileLayout()) {
|
||||
return mobileMetaCollapsed;
|
||||
}
|
||||
return mediaPanel?.isCollapsed() ?? false;
|
||||
}
|
||||
|
||||
function setMetaCollapsed(collapsed) {
|
||||
if (isMobileLayout()) {
|
||||
const { metaWrap } = getElements();
|
||||
mobileMetaCollapsed = Boolean(collapsed);
|
||||
metaWrap?.classList.toggle("is-collapsed", mobileMetaCollapsed);
|
||||
syncMetaToggleState(mobileMetaCollapsed);
|
||||
return;
|
||||
}
|
||||
mediaPanel?.setCollapsed(collapsed);
|
||||
syncMetaToggleState(Boolean(collapsed));
|
||||
}
|
||||
|
||||
function syncPanelActiveTab(tab = activeTab) {
|
||||
@@ -120,6 +156,10 @@ function syncNewsDefaultMaxHeight() {
|
||||
}
|
||||
|
||||
function autoExpandMeta() {
|
||||
if (isMobileLayout()) {
|
||||
clearTimeout(metaAutoCollapseTimer);
|
||||
return;
|
||||
}
|
||||
clearTimeout(metaAutoCollapseTimer);
|
||||
setMetaCollapsed(false);
|
||||
metaAutoCollapseTimer = setTimeout(() => setMetaCollapsed(true), META_AUTO_COLLAPSE_DELAY);
|
||||
@@ -154,7 +194,7 @@ function captureTabState(tab = activeTab) {
|
||||
tabPanelState[tab] = {
|
||||
layout: readPanelLayoutState(panel),
|
||||
metaCollapsed:
|
||||
tab === "live" ? (mediaPanel?.isCollapsed() ?? false) : null,
|
||||
tab === "live" ? isMetaCollapsed() : null,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -749,15 +789,59 @@ function getExternalUrl(source) {
|
||||
}
|
||||
|
||||
function updateOpenButton(source) {
|
||||
const { openBtn } = getElements();
|
||||
if (!openBtn) return;
|
||||
const targetUrl = getExternalUrl(source);
|
||||
openBtn.disabled = !targetUrl;
|
||||
openBtn.onclick = targetUrl
|
||||
? () => {
|
||||
window.open(targetUrl, "_blank", "noopener,noreferrer");
|
||||
}
|
||||
: null;
|
||||
[
|
||||
document.getElementById("mobile-tv-open-external"),
|
||||
document.getElementById("tv-open-external"),
|
||||
].forEach((button) => {
|
||||
if (!(button instanceof HTMLButtonElement)) return;
|
||||
button.disabled = !targetUrl;
|
||||
button.onclick = targetUrl
|
||||
? () => {
|
||||
window.open(targetUrl, "_blank", "noopener,noreferrer");
|
||||
}
|
||||
: null;
|
||||
});
|
||||
}
|
||||
|
||||
function syncMobileOverviewSummary(source) {
|
||||
const headline = document.getElementById("mobile-tv-overview-headline");
|
||||
const summary = document.getElementById("mobile-tv-overview-summary");
|
||||
const tags = document.getElementById("mobile-tv-overview-tags");
|
||||
if (headline instanceof HTMLElement) {
|
||||
headline.textContent = source?.name || "暂无可用频道";
|
||||
}
|
||||
if (summary instanceof HTMLElement) {
|
||||
if (!source) {
|
||||
summary.textContent = "点击查看当前频道来源、目录和补充说明";
|
||||
} else {
|
||||
const parts = [
|
||||
source.provider,
|
||||
source.region,
|
||||
source.language,
|
||||
].filter(Boolean);
|
||||
summary.textContent = parts.length
|
||||
? parts.join(" · ")
|
||||
: "点击查看完整频道信息";
|
||||
}
|
||||
}
|
||||
if (tags instanceof HTMLElement) {
|
||||
const tagValues = source
|
||||
? [
|
||||
{ label: source.source_type || "频道", kind: "status" },
|
||||
source.collector_source ? { label: `采集:${source.collector_source}`, kind: "" } : { label: "内置源", kind: "" },
|
||||
source.region ? { label: source.region, kind: "" } : null,
|
||||
].filter(Boolean).slice(0, 3)
|
||||
: [{ label: "待加载", kind: "status" }];
|
||||
tags.replaceChildren(
|
||||
...tagValues.map(({ label, kind }) => {
|
||||
const chip = document.createElement("span");
|
||||
chip.className = `earth-mobile-tv-overview-tag${kind ? ` earth-mobile-tv-overview-tag--${kind}` : ""}`;
|
||||
chip.textContent = label;
|
||||
return chip;
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function findSourceById(sourceId) {
|
||||
@@ -926,6 +1010,7 @@ function renderSource(source) {
|
||||
if (notes) {
|
||||
notes.textContent = source?.notes || "支持后台配置默认源与采集器补充源。";
|
||||
}
|
||||
syncMobileOverviewSummary(source);
|
||||
|
||||
if (!source || (!embeddedUrl && !videoUrl)) {
|
||||
destroyHlsPlayer();
|
||||
@@ -1031,6 +1116,7 @@ export function initTVPanel() {
|
||||
liveTabBtn,
|
||||
newsTabBtn,
|
||||
} = getElements();
|
||||
const mobileOverviewBar = document.getElementById("mobile-tv-overview-bar");
|
||||
|
||||
if (panel && metaToggle) {
|
||||
mediaPanel = createHUDPanel({
|
||||
@@ -1045,6 +1131,10 @@ export function initTVPanel() {
|
||||
});
|
||||
}
|
||||
|
||||
mobileMetaCollapsed = true;
|
||||
syncMetaToggleState(isMetaCollapsed());
|
||||
setMetaCollapsed(isMetaCollapsed());
|
||||
|
||||
updateToggleButton(mediaPanel?.isVisible() ?? !panel?.classList.contains("hud-panel-hidden"));
|
||||
syncSettingsToggle(mediaPanel?.isVisible() ?? !panel?.classList.contains("hud-panel-hidden"));
|
||||
|
||||
@@ -1084,10 +1174,31 @@ export function initTVPanel() {
|
||||
});
|
||||
});
|
||||
|
||||
metaToggle?.addEventListener("click", () => {
|
||||
[metaToggle, document.getElementById("tv-meta-toggle")]
|
||||
.filter((element, index, array) => element && array.indexOf(element) === index)
|
||||
.forEach((toggleEl) => {
|
||||
toggleEl?.addEventListener("click", () => {
|
||||
clearTimeout(metaAutoCollapseTimer);
|
||||
const isNowCollapsed = !isMetaCollapsed();
|
||||
setMetaCollapsed(isNowCollapsed);
|
||||
});
|
||||
});
|
||||
|
||||
const toggleMobileMeta = (event) => {
|
||||
const interactiveTarget = event.target instanceof Element
|
||||
? event.target.closest("button, a, select, input, textarea, video, iframe")
|
||||
: null;
|
||||
if (interactiveTarget) return;
|
||||
clearTimeout(metaAutoCollapseTimer);
|
||||
const isNowCollapsed = !(mediaPanel?.isCollapsed() ?? false);
|
||||
const isNowCollapsed = !isMetaCollapsed();
|
||||
setMetaCollapsed(isNowCollapsed);
|
||||
};
|
||||
|
||||
mobileOverviewBar?.addEventListener("click", toggleMobileMeta);
|
||||
mobileOverviewBar?.addEventListener("keydown", (event) => {
|
||||
if (event.key !== "Enter" && event.key !== " ") return;
|
||||
event.preventDefault();
|
||||
toggleMobileMeta(event);
|
||||
});
|
||||
|
||||
[refreshBtn, document.getElementById("mobile-tv-refresh"), document.getElementById("tv-refresh")]
|
||||
|
||||
Reference in New Issue
Block a user