release: bump version to 0.31.1

This commit is contained in:
rayd1o
2026-04-21 22:49:39 +08:00
parent b7647379de
commit 4b0be4cb76
46 changed files with 1129 additions and 64 deletions

View File

@@ -30,6 +30,11 @@ import {
ensureNewsPanelReady,
updateNewsToggleUI,
} from "./news.js";
import {
setButtonTooltip,
setLayerButtonState,
updateLayerButtonState,
} from "./layer-button-state.js";
export let autoRotate = true;
export let zoomLevel = 1.0;
@@ -67,6 +72,8 @@ const SETTINGS_SHEET_MAX_SCALE_Y = 0.18;
let settingsModalTimer = null;
let settingsSheetAnimation = null;
let terrainToggleToken = 0;
let terrainPrefetchStarted = false;
let terrainPrefetchScheduled = false;
let focusViewAnimationToken = 0;
function getViewRotation(targetLat, targetRotLon) {
@@ -91,10 +98,40 @@ function dispatchRotationModeChange() {
function applyTerrainUiState(button, enabled) {
showTerrain = enabled;
toggleTerrain(enabled);
updateLayerButtonState(button, enabled);
setButtonTooltip(button, enabled ? "隐藏地形" : "显示地形");
const terrainStatus = document.getElementById("terrain-status");
if (terrainStatus) terrainStatus.textContent = enabled ? "开启" : "关闭";
setLayerButtonState(button, {
active: enabled,
loading: false,
tooltip: enabled ? "隐藏地形" : "显示地形",
statusText: enabled ? "开启" : "关闭",
});
}
function prewarmTerrainIfNeeded() {
if (terrainPrefetchStarted || isTerrainReady()) return;
terrainPrefetchStarted = true;
ensureTerrainReady().catch((error) => {
terrainPrefetchStarted = false;
console.warn("地形预热加载失败:", error);
});
}
function scheduleTerrainPrefetch() {
if (terrainPrefetchScheduled || terrainPrefetchStarted || isTerrainReady()) {
return;
}
terrainPrefetchScheduled = true;
const runPrefetch = () => {
terrainPrefetchScheduled = false;
prewarmTerrainIfNeeded();
};
if (typeof window !== "undefined" && "requestIdleCallback" in window) {
window.requestIdleCallback(runPrefetch, { timeout: 2200 });
return;
}
window.setTimeout(runPrefetch, 1400);
}
export function applyImmediateView(targetEarthObj, camera, options = {}) {
@@ -670,24 +707,6 @@ function setFloatingMenuOpen(group, shouldOpen) {
group?.classList.toggle("open", shouldOpen);
}
function setButtonTooltip(button, text) {
const tooltip = button?.querySelector(".earth-toolbar-tooltip");
if (tooltip) {
tooltip.textContent = text;
}
}
export function updateLayerButtonState(button, isActive) {
if (!button) return;
button.classList.toggle("active", isActive);
button.setAttribute("aria-checked", isActive ? "true" : "false");
// Legacy badge text (kept for compatibility)
const state = button.querySelector(".earth-layer-btn__state");
if (state) {
state.textContent = isActive ? "ON" : "OFF";
}
}
function clearSelectionIfHiding(shouldHide) {
if (shouldHide) {
clearLockedObject();
@@ -1070,15 +1089,30 @@ function setupTerrainControls() {
setupLayerPanel();
if (trailsBtn) {
updateLayerButtonState(trailsBtn, true);
setButtonTooltip(trailsBtn, "隐藏轨迹");
setLayerButtonState(trailsBtn, {
active: true,
tooltip: "隐藏轨迹",
});
}
bindListener(searchBtn, "click", () => {
showStatusMessage("搜索功能待开发", "info");
});
bindListener(terrainBtn, "pointerenter", () => {
prewarmTerrainIfNeeded();
});
bindListener(terrainBtn, "focus", () => {
prewarmTerrainIfNeeded();
});
scheduleTerrainPrefetch();
bindListener(terrainBtn, "click", async function () {
if (this.classList.contains("is-loading")) {
return;
}
const nextShowTerrain = !showTerrain;
const toggleToken = ++terrainToggleToken;
@@ -1090,6 +1124,11 @@ function setupTerrainControls() {
try {
if (!isTerrainReady()) {
setLayerButtonState(this, {
loading: true,
tooltip: "地形加载中...",
statusText: "加载中",
});
showStatusMessage("正在加载真实地形数据...", "info");
await ensureTerrainReady();
}
@@ -1108,6 +1147,13 @@ function setupTerrainControls() {
const showSats = !getShowSatellites();
clearSelectionIfHiding(!showSats);
try {
if (showSats) {
setLayerButtonState(this, {
active: false,
loading: true,
tooltip: "卫星加载中...",
});
}
await setSatellitesEnabled(showSats);
if (!showSats) {
showStatusMessage("卫星已隐藏", "info");
@@ -1119,6 +1165,11 @@ function setupTerrainControls() {
}
} catch (error) {
console.error("切换卫星显示失败:", error);
setLayerButtonState(this, {
active: false,
loading: false,
tooltip: "显示卫星",
});
}
});
@@ -1129,8 +1180,10 @@ function setupTerrainControls() {
if (!showNextBGP && rotationMode === ROTATION_MODE.CRUISE && autoRotate) {
setAutoRotate(false);
}
updateLayerButtonState(this, showNextBGP);
setButtonTooltip(this, showNextBGP ? "隐藏BGP观测" : "显示BGP观测");
setLayerButtonState(this, {
active: showNextBGP,
tooltip: showNextBGP ? "隐藏BGP观测" : "显示BGP观测",
});
const bgpCountEl = document.getElementById("bgp-anomaly-count");
if (bgpCountEl) {
bgpCountEl.textContent = `${getBGPCount()}`;
@@ -1142,8 +1195,10 @@ function setupTerrainControls() {
const isActive = this.classList.contains("active");
const nextShowTrails = !isActive;
toggleTrails(nextShowTrails);
updateLayerButtonState(this, nextShowTrails);
setButtonTooltip(this, nextShowTrails ? "隐藏轨迹" : "显示轨迹");
setLayerButtonState(this, {
active: nextShowTrails,
tooltip: nextShowTrails ? "隐藏轨迹" : "显示轨迹",
});
showStatusMessage(nextShowTrails ? "轨迹已显示" : "轨迹已隐藏", "info");
});

View File

@@ -0,0 +1,46 @@
export function setButtonTooltip(button, text) {
if (button instanceof HTMLElement) {
button.title = text;
}
const tooltip = button?.querySelector(".earth-toolbar-tooltip");
if (tooltip) {
tooltip.textContent = text;
}
}
export function updateLayerButtonState(button, isActive) {
if (!button) return;
button.classList.toggle("active", isActive);
button.setAttribute("aria-checked", isActive ? "true" : "false");
const state = button.querySelector(".earth-layer-btn__state");
if (state) {
state.textContent = isActive ? "ON" : "OFF";
}
}
export function setLayerButtonState(button, options = {}) {
if (!(button instanceof HTMLButtonElement)) return;
const {
active = null,
loading = false,
tooltip = null,
statusText = null,
} = options;
button.classList.toggle("is-loading", loading);
button.toggleAttribute("aria-busy", loading);
button.disabled = loading;
if (typeof active === "boolean") {
updateLayerButtonState(button, active);
}
if (tooltip) {
setButtonTooltip(button, tooltip);
}
if (statusText) {
const statusTarget = button.dataset.statusTarget
? document.getElementById(button.dataset.statusTarget)
: null;
if (statusTarget) {
statusTarget.textContent = statusText;
}
}
}

View File

@@ -134,8 +134,10 @@ import {
focusEarthView,
getZoomLevel,
teardownControls,
updateLayerButtonState,
} from "./controls.js";
import {
setLayerButtonState,
} from "./layer-button-state.js";
import {
initInfoCard,
showInfoCard,
@@ -1502,9 +1504,11 @@ function buildLoadErrorMessage(errors) {
function updateSatelliteToggleUi(enabled, satelliteCount = getSatelliteCount()) {
const satBtn = document.getElementById("toggle-satellites");
if (satBtn) {
updateLayerButtonState(satBtn, enabled);
const tooltip = satBtn.querySelector(".earth-toolbar-tooltip");
if (tooltip) tooltip.textContent = enabled ? "隐藏卫星" : "显示卫星";
setLayerButtonState(satBtn, {
active: enabled,
loading: false,
tooltip: enabled ? "隐藏卫星" : "显示卫星",
});
}
const satelliteCountEl = document.getElementById("satellite-count");
@@ -1516,9 +1520,11 @@ function updateSatelliteToggleUi(enabled, satelliteCount = getSatelliteCount())
function updateCableToggleUi(enabled) {
const cableBtn = document.getElementById("toggle-cables");
if (cableBtn) {
updateLayerButtonState(cableBtn, enabled);
const tooltip = cableBtn.querySelector(".earth-toolbar-tooltip");
if (tooltip) tooltip.textContent = enabled ? "隐藏线缆" : "显示线缆";
setLayerButtonState(cableBtn, {
active: enabled,
loading: false,
tooltip: enabled ? "隐藏线缆" : "显示线缆",
});
}
const cableCountEl = document.getElementById("cable-count");