/** * Early mobile client gate (loaded from ). * 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. * Search / AI crawlers skip the gate so prerendered HTML stays indexable. */ (function () { function isCrawler() { var ua = navigator.userAgent || ""; return /bot|crawl|spider|slurp|bingpreview|facebookexternalhit|embedly|quora link preview|pinterest|redditbot|linkedinbot|twitterbot|whatsapp|google-inspectiontool|bytespider|baiduspider|yandex|duckduckbot|applebot|semrush|ahrefs|gptbot|claudebot|anthropic|perplexity|oai-searchbot|chatgpt/i.test( ua ); } 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; } if (isCrawler()) { window.__CLIMPEROR_MOBILE__ = false; return; } 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; } }); }); })();