v0.5.84: matches origin filter, mobile gate, refresh reliability.
Ship Web refresh cache/lock, mobile demand gate, matches 职业/国服 filter, and related site updates through 0.5.84. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
* Early mobile client gate (loaded from <head>).
|
||||
* Sets html.mobile-client before paint; wires the demand button after DOM ready.
|
||||
* Exposes window.__CLIMPEROR_MOBILE__ for app.js to skip the desktop boot path.
|
||||
*/
|
||||
(function () {
|
||||
function isMobileClient() {
|
||||
var ua = navigator.userAgent || "";
|
||||
if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(ua)) {
|
||||
return true;
|
||||
}
|
||||
// iPadOS 13+ reports as MacIntel with touch.
|
||||
if (navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
var mobile = isMobileClient();
|
||||
window.__CLIMPEROR_MOBILE__ = mobile;
|
||||
if (!mobile) return;
|
||||
|
||||
document.documentElement.classList.add("mobile-client");
|
||||
|
||||
var STORAGE_KEY = "climperor_mobile_demand_voted";
|
||||
|
||||
function $(id) {
|
||||
return document.getElementById(id);
|
||||
}
|
||||
|
||||
function markVoted(btn) {
|
||||
try {
|
||||
localStorage.setItem(STORAGE_KEY, "1");
|
||||
} catch (_) {
|
||||
/* ignore quota / private mode */
|
||||
}
|
||||
if (btn) {
|
||||
btn.disabled = true;
|
||||
btn.textContent = "已记录催更";
|
||||
}
|
||||
}
|
||||
|
||||
function alreadyVoted() {
|
||||
try {
|
||||
return localStorage.getItem(STORAGE_KEY) === "1";
|
||||
} catch (_) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function setCount(n) {
|
||||
var el = $("mobile-demand-count-n");
|
||||
if (el) el.textContent = String(n);
|
||||
var wrap = $("mobile-demand-count");
|
||||
if (wrap) wrap.hidden = false;
|
||||
}
|
||||
|
||||
async function refreshCount() {
|
||||
try {
|
||||
var res = await fetch("/api/mobile-demand");
|
||||
if (!res.ok) return;
|
||||
var data = await res.json();
|
||||
var n = Number(data && data.count);
|
||||
if (Number.isFinite(n) && n >= 0) setCount(Math.floor(n));
|
||||
} catch (_) {
|
||||
/* soft-fail: keep count hidden */
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
var logo = document.querySelector(".mobile-gate-logo");
|
||||
if (logo && typeof STATIC_ASSET_BASE === "string") {
|
||||
var base = STATIC_ASSET_BASE.trim().replace(/\/+$/, "");
|
||||
if (base) logo.src = base + "/ui-icon/dota2_logo_wordmark.png";
|
||||
}
|
||||
var btn = $("mobile-demand-btn");
|
||||
var voted = alreadyVoted();
|
||||
if (voted) markVoted(btn);
|
||||
refreshCount();
|
||||
if (!btn || voted) return;
|
||||
btn.addEventListener("click", async function () {
|
||||
btn.disabled = true;
|
||||
try {
|
||||
var res = await fetch("/api/mobile-demand", { method: "POST" });
|
||||
if (!res.ok) {
|
||||
btn.disabled = false;
|
||||
return;
|
||||
}
|
||||
var data = await res.json();
|
||||
var n = Number(data && data.count);
|
||||
if (Number.isFinite(n) && n >= 0) setCount(Math.floor(n));
|
||||
markVoted(btn);
|
||||
} catch (_) {
|
||||
btn.disabled = false;
|
||||
}
|
||||
});
|
||||
});
|
||||
})();
|
||||
Reference in New Issue
Block a user