381 lines
24 KiB
HTML
381 lines
24 KiB
HTML
<!doctype html>
|
||
<html lang="en" translate="no">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="google" content="notranslate">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover">
|
||
<title>Level</title>
|
||
<link rel="stylesheet" href="../common/theme.css">
|
||
<style>
|
||
* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
|
||
:root { --app-scale: 1; }
|
||
html, body { margin: 0; width: 100%; min-height: 100%; overflow-x: hidden; background: #130a2b; color: #fff; font-family: Arial, Helvetica, sans-serif; }
|
||
button { border: 0; padding: 0; background: transparent; color: inherit; font: inherit; cursor: pointer; outline: none; }
|
||
.app-viewport { position: relative; width: 375px; height: 826px; margin: 0 auto; transform: scale(var(--app-scale)); transform-origin: top center; }
|
||
.page { position: relative; width: 375px; height: 826px; overflow: hidden; background: #130a2b; }
|
||
.page-bg { position: absolute; left: -28px; top: -297px; width: 599px; height: 1123px; object-fit: cover; opacity: .54; pointer-events: none; }
|
||
.home-indicator { position: absolute; left: 121px; bottom: 8px; z-index: 8; width: 134px; height: 5px; border-radius: 100px; background: #fff; }
|
||
.nav { position: absolute; left: 0; top: 0; z-index: 5; width: 375px; height: 44px; }
|
||
.back { position: absolute; left: 16px; top: 10px; width: 24px; height: 24px; }
|
||
.back::before { content: ""; position: absolute; left: 7px; top: 5px; width: 13px; height: 13px; border-left: 2px solid #fff; border-bottom: 2px solid #fff; transform: rotate(45deg); }
|
||
.title { position: absolute; left: 0; top: 13px; width: 375px; font-size: 18px; line-height: 18px; font-weight: 500; text-align: center; text-transform: capitalize; }
|
||
.tabs { position: absolute; left: 0; top: 58px; z-index: 5; width: 375px; height: 30px; }
|
||
.tab { position: absolute; top: 0; width: 92px; height: 30px; color: rgba(255,255,255,.5); font-size: 18px; line-height: 18px; font-weight: 700; text-align: center; text-transform: capitalize; }
|
||
.tab[data-track="wealth"] { left: 16px; }
|
||
.tab[data-track="charm"] { left: 142px; }
|
||
.tab[data-track="game"] { left: 266px; }
|
||
.tab.active { color: #fff; opacity: 1; }
|
||
.tab.active::after { content: ""; position: absolute; left: 50%; top: 24px; width: 16px; height: 3px; margin-left: -8px; border-radius: 31px; background: #fff; }
|
||
.level-card { position: absolute; left: 16px; top: 111px; z-index: 2; width: 343px; height: 111px; overflow: hidden; background: transparent; }
|
||
.level-card-bg { display: block; width: 343px; height: 111px; object-fit: cover; }
|
||
.card-decor { position: absolute; left: 24px; top: 99px; z-index: 3; width: 164px; height: 27px; object-fit: cover; }
|
||
.card-decor.right { left: 188px; transform: rotate(180deg) scaleY(-1); }
|
||
.level-name { position: absolute; left: 40px; top: 133px; z-index: 4; font-size: 16px; line-height: 16px; font-weight: 900; text-transform: capitalize; color: var(--title-fill, #fff); text-shadow: 0 2px 0 var(--title-shadow); }
|
||
.avatar-wrap { position: absolute; left: 259px; top: 126px; z-index: 4; width: 80px; height: 80px; }
|
||
.avatar { position: absolute; left: 11px; top: 11px; width: 58px; height: 58px; border-radius: 50%; object-fit: cover; }
|
||
.avatar-frame { position: absolute; inset: 0; width: 80px; height: 80px; object-fit: cover; }
|
||
.progress { position: absolute; left: 40px; top: 171px; z-index: 4; width: 182px; height: 38px; color: var(--progress-text); }
|
||
.lv-current, .lv-next { position: absolute; top: 7px; font-size: 12px; line-height: 12px; text-transform: capitalize; }
|
||
.lv-current { left: 0; }
|
||
.lv-next { left: 159px; }
|
||
.progress-percent { position: absolute; left: 67px; top: 0; width: 45px; font-size: 8px; line-height: 8px; text-align: center; }
|
||
.progress-track { position: absolute; left: 24px; top: 12px; width: 133px; height: 4px; border-radius: 3px; background: var(--progress-track); }
|
||
.progress-fill { width: 0; height: 4px; border-radius: 3px; background: var(--progress-fill); }
|
||
.need { position: absolute; left: 0; top: 27px; width: 220px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font-size: 8px; line-height: 8px; color: var(--need-text); }
|
||
.level-table { position: absolute; left: 16px; top: 238px; z-index: 2; width: 343px; height: 318px; border-radius: 12px; background: rgba(67,0,255,.11); }
|
||
.table-head { position: absolute; top: 16px; height: 16px; font-size: 16px; line-height: 16px; font-weight: 500; text-align: center; text-transform: capitalize; white-space: nowrap; }
|
||
.head-range { left: 19px; width: 49px; }
|
||
.head-icons { left: 124px; width: 42px; }
|
||
.head-frame { left: 226px; width: 96px; }
|
||
.tier-row { position: absolute; left: 0; z-index: 2; width: 343px; height: 46px; }
|
||
.tier-row.r1 { top: 44px; }
|
||
.tier-row.r2 { top: 98px; }
|
||
.tier-row.r3 { top: 152px; }
|
||
.tier-row.r4 { top: 206px; }
|
||
.tier-row.r5 { top: 260px; }
|
||
.range { position: absolute; left: 29px; top: 16px; width: 30px; font-size: 14px; line-height: 14px; text-align: center; }
|
||
.badge-icon { position: absolute; left: 113px; top: 11px; width: 62px; height: 24px; object-fit: contain; }
|
||
.frame-icon { position: absolute; left: 250px; top: 0; width: 46px; height: 46px; object-fit: contain; }
|
||
.upgrade-title { position: absolute; left: 0; top: 574px; z-index: 3; width: 375px; color: var(--upgrade-title); font-size: 20px; line-height: 20px; font-weight: 700; text-align: center; }
|
||
.upgrade-list { position: absolute; left: 0; top: 616px; z-index: 3; width: 375px; height: 98px; }
|
||
.upgrade-item { position: absolute; top: 0; width: 119px; text-align: center; }
|
||
.upgrade-one { left: 128px; width: 120px; }
|
||
.upgrade-three:nth-child(1) { left: 1px; }
|
||
.upgrade-three:nth-child(2) { left: 128px; }
|
||
.upgrade-three:nth-child(3) { left: 255px; }
|
||
.upgrade-icon { display: block; width: 54px; height: 54px; margin: 0 auto; object-fit: contain; }
|
||
.upgrade-name { margin-top: 10px; font-size: 14px; line-height: 14px; font-weight: 500; white-space: nowrap; }
|
||
.upgrade-exp { margin-top: 8px; font-size: 14px; line-height: 14px; white-space: nowrap; }
|
||
.consume { position: absolute; left: 43px; top: 736px; z-index: 4; width: 289px; height: 50px; overflow: hidden; border: 1.5px solid #fff09b; background: #2a1351; color: #fff; font-size: 18px; line-height: 49px; font-weight: 700; text-align: center; }
|
||
.consume-bg { position: absolute; inset: -26px -38px; width: 363px; height: 104px; object-fit: cover; opacity: .8; mix-blend-mode: plus-lighter; pointer-events: none; }
|
||
.consume.gold .consume-bg { inset: -38px -79px; width: 447px; height: 127px; opacity: 1; mix-blend-mode: normal; }
|
||
.consume span { position: relative; z-index: 2; }
|
||
.corner { position: absolute; z-index: 3; width: 16px; height: 16px; object-fit: contain; }
|
||
.corner.c1 { left: 0; top: 0; }
|
||
.corner.c2 { right: 0; top: 0; transform: rotate(90deg); }
|
||
.corner.c3 { right: 0; bottom: 0; transform: rotate(180deg); }
|
||
.corner.c4 { left: 0; bottom: 0; transform: rotate(270deg); }
|
||
.hit { position: absolute; z-index: 7; border-radius: 8px; }
|
||
.hit-consume { left: 43px; top: 736px; width: 289px; height: 50px; }
|
||
.loading-overlay { position: absolute; inset: 0; z-index: 20; display: none; align-items: center; justify-content: center; background: rgba(19,10,43,.32); backdrop-filter: blur(1px); pointer-events: auto; }
|
||
.loading-overlay.active { display: flex; }
|
||
.cat-loader { width: 72px; height: 72px; display: flex; align-items: center; justify-content: center; border-radius: 50%; background: rgba(0,0,0,.18); box-shadow: 0 8px 28px rgba(0,0,0,.28); }
|
||
.cat-loader svg { width: 54px; height: 54px; overflow: visible; animation: cat-float 1.1s ease-in-out infinite; }
|
||
.cat-line { fill: none; stroke: #fff; stroke-width: 3.4; stroke-linecap: round; stroke-linejoin: round; }
|
||
.cat-eye { transform-origin: center; animation: cat-blink 1.6s ease-in-out infinite; }
|
||
.cat-whisker { opacity: .9; animation: cat-whisker 1.1s ease-in-out infinite; }
|
||
.toast { position: fixed; left: 50%; bottom: calc(34px * var(--app-scale)); z-index: 60; max-width: 300px; transform: translateX(-50%); padding: 8px 12px; border-radius: 16px; background: rgba(0,0,0,.62); color: #fff; font-size: 12px; line-height: 16px; text-align: center; opacity: 0; pointer-events: none; transition: opacity .18s ease; }
|
||
.toast.show { opacity: 1; }
|
||
@keyframes cat-float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-5px); } }
|
||
@keyframes cat-blink { 0%, 72%, 100% { transform: scaleY(1); } 80%, 88% { transform: scaleY(.18); } }
|
||
@keyframes cat-whisker { 0%, 100% { opacity: .62; } 50% { opacity: 1; } }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div id="appViewport" class="app-viewport">
|
||
<main id="page" class="page">
|
||
<img id="pageBg" class="page-bg" alt="">
|
||
<nav class="nav" aria-label="Level navigation">
|
||
<button id="backButton" class="back" aria-label="Back"></button>
|
||
<div class="title">Level</div>
|
||
</nav>
|
||
<div id="tabs" class="tabs">
|
||
<button class="tab" data-track="wealth">Wealth</button>
|
||
<button class="tab" data-track="charm">Charm</button>
|
||
<button class="tab" data-track="game">Game</button>
|
||
</div>
|
||
|
||
<section class="level-card" aria-label="Current level"><img id="cardBg" class="level-card-bg" alt=""></section>
|
||
<img id="decorLeft" class="card-decor" alt="">
|
||
<img id="decorRight" class="card-decor right" alt="">
|
||
<div id="levelName" class="level-name">Level 0</div>
|
||
<div class="avatar-wrap">
|
||
<img id="avatar" class="avatar" alt="">
|
||
<img id="avatarFrame" class="avatar-frame" alt="">
|
||
</div>
|
||
<div class="progress">
|
||
<div id="lvCurrent" class="lv-current">Lv.0</div>
|
||
<div id="progressPercent" class="progress-percent">0%</div>
|
||
<div class="progress-track"><div id="progressFill" class="progress-fill"></div></div>
|
||
<div id="lvNext" class="lv-next">Lv.1</div>
|
||
<div id="needText" class="need">You need 12,345,600 more experience points</div>
|
||
</div>
|
||
|
||
<section class="level-table" aria-label="Level tiers">
|
||
<div class="table-head head-range">Range</div>
|
||
<div class="table-head head-icons">Icons</div>
|
||
<div class="table-head head-frame">Profile Frame</div>
|
||
<div id="tierRows"></div>
|
||
</section>
|
||
|
||
<div id="upgradeTitle" class="upgrade-title">How to upgrade?</div>
|
||
<div id="upgradeList" class="upgrade-list"></div>
|
||
<button id="consumeButton" class="consume" aria-label="To consume"></button>
|
||
<button id="consumeHit" class="hit hit-consume" aria-label="To consume"></button>
|
||
<div class="home-indicator"></div>
|
||
|
||
<div id="loadingOverlay" class="loading-overlay" aria-hidden="true">
|
||
<div class="cat-loader" aria-label="Loading">
|
||
<svg viewBox="0 0 64 64" role="img" aria-hidden="true">
|
||
<path class="cat-line" d="M15 31 C15 19 24 14 32 14 C40 14 49 19 49 31 C49 43 42 50 32 50 C22 50 15 43 15 31 Z"/>
|
||
<path class="cat-line" d="M20 18 L16 7 L27 14"/>
|
||
<path class="cat-line" d="M44 18 L48 7 L37 14"/>
|
||
<path class="cat-line cat-eye" d="M25 31 L25 32"/>
|
||
<path class="cat-line cat-eye" d="M39 31 L39 32"/>
|
||
<path class="cat-line" d="M32 35 L29 38 L35 38 Z"/>
|
||
<path class="cat-line cat-whisker" d="M11 32 H23"/>
|
||
<path class="cat-line cat-whisker" d="M10 40 L23 37"/>
|
||
<path class="cat-line cat-whisker" d="M41 32 H53"/>
|
||
<path class="cat-line cat-whisker" d="M41 37 L54 40"/>
|
||
</svg>
|
||
</div>
|
||
</div>
|
||
</main>
|
||
</div>
|
||
<div id="toast" class="toast"></div>
|
||
|
||
<script src="../common/api.js"></script>
|
||
<script src="../common/toast.js"></script>
|
||
<script src="../common/params.js"></script>
|
||
<script src="../common/jsbridge.js"></script>
|
||
<script>
|
||
(function () {
|
||
var A = "assets/component/";
|
||
var tracks = {
|
||
charm: {
|
||
bg: A + "bg-charm.png", cardBg: A + "card-charm.png", decor: A + "decor-charm.png", avatar: A + "avatar-charm.png", frame: A + "avatar-frame-charm.png",
|
||
card: "#130828", texture: "url('" + A + "button-purple.png')", textureOpacity: .26, glow: "linear-gradient(176deg, #462a78 36%, rgba(59,36,100,0) 63%)",
|
||
titleFill: "#ffffff", titleShadow: "#be1e21", titleGradient: "linear-gradient(135deg, #fff 27%, #f4cbff 49%, #fff 72%)",
|
||
progress: "#fff", progressTrack: "rgba(255,255,255,.2)", progressFill: "#fff", need: "rgba(255,255,255,.6)", upgrade: "#f718e9",
|
||
button: "purple", upgrades: [{ icon: A + "upgrade-gift-charm.svg", name: "Receive a gift", exp: "1 Coins = 1 EXP" }]
|
||
},
|
||
wealth: {
|
||
bg: A + "bg-wealth.png", cardBg: A + "card-wealth.png", decor: A + "decor-wealth.png", avatar: A + "avatar-wealth.png", frame: A + "avatar-frame-wealth.png",
|
||
card: "#ffa85c", texture: "url('" + A + "button-gold.png')", textureOpacity: .41, glow: "linear-gradient(165deg, rgba(255,242,130,.62) 35%, rgba(255,242,130,0) 48%), linear-gradient(-12deg, rgba(255,242,130,.55) 26%, rgba(255,242,130,0) 28%)",
|
||
titleFill: "#fff7e8", titleShadow: "#be561e", titleGradient: "linear-gradient(135deg, #fff 27%, #ffdfcb 49%, #fff 72%)",
|
||
progress: "#b7420c", progressTrack: "rgba(183,66,12,.2)", progressFill: "#b7420c", need: "rgba(183,66,12,.6)", upgrade: "#ffbe5f",
|
||
button: "gold", upgrades: [
|
||
{ icon: A + "upgrade-gift-wealth.svg", name: "Receive a Gift", exp: "1 Coins = 1 EXP" },
|
||
{ icon: A + "upgrade-car-wealth.svg", name: "Buy a car", exp: "1 Coins = 1 EXP" },
|
||
{ icon: A + "upgrade-avatar-wealth.svg", name: "Buy Avatar Frame", exp: "1 Coins = 1 EXP" }
|
||
]
|
||
},
|
||
game: {
|
||
bg: A + "bg-game.png", cardBg: A + "card-game.png", decor: A + "decor-game.png", avatar: A + "avatar-game.png", frame: A + "avatar-frame-game.png",
|
||
card: "#118624", texture: "url('" + A + "button-purple.png')", textureOpacity: .38, glow: "linear-gradient(165deg, rgba(255,242,130,.34) 35%, rgba(255,242,130,0) 48%), linear-gradient(-12deg, rgba(255,242,130,.3) 26%, rgba(255,242,130,0) 28%)",
|
||
titleFill: "#f2fff2", titleShadow: "#5ba626", titleGradient: "linear-gradient(135deg, #fff 27%, #cbffd7 49%, #fff 72%)",
|
||
progress: "#fff", progressTrack: "rgba(255,255,255,.2)", progressFill: "#fff", need: "rgba(255,255,255,.6)", upgrade: "#ffbe5f",
|
||
button: "purple", upgrades: [{ icon: A + "upgrade-game.svg", name: "Earned through gameplay", exp: "1 Coins = 1 EXP" }]
|
||
}
|
||
};
|
||
var state = { track: new URLSearchParams(window.location.search).get("track") || "charm", loading: false, details: {}, userAvatar: "", toastTimer: 0 };
|
||
|
||
function byId(id) { return document.getElementById(id); }
|
||
function track() { return tracks[state.track] ? state.track : "charm"; }
|
||
function fmt(n) { return Number(n || 0).toLocaleString("en-US"); }
|
||
function ratio(d) {
|
||
var o = d && d.overview ? d.overview : {};
|
||
var cur = Number(o.current_level_required_value || 0);
|
||
var next = Number(o.next_level_required_value || 0);
|
||
var total = Number(o.total_value || 0);
|
||
if (!d || !d.overview) return 0;
|
||
if (next <= cur) return total >= cur && cur > 0 ? 1 : 0;
|
||
return Math.max(0, Math.min(1, (total - cur) / (next - cur)));
|
||
}
|
||
function profileFromOverview(current) {
|
||
var user = current && current.user;
|
||
return (user && (user.profile || user.user || user)) || {};
|
||
}
|
||
function profileAvatar(profile) {
|
||
return String((profile && (profile.avatar || profile.user_avatar || profile.userAvatar || profile.avatar_url || profile.avatarUrl || profile.profile_avatar || profile.profileAvatar)) || "");
|
||
}
|
||
function applyUserProfile(current) {
|
||
state.userAvatar = profileAvatar(profileFromOverview(current));
|
||
render();
|
||
}
|
||
function setAvatarSource(src, fallback) {
|
||
var avatar = byId("avatar");
|
||
if (!avatar) return;
|
||
var fallbackSrc = fallback || "";
|
||
var nextSrc = src || fallbackSrc;
|
||
avatar.onerror = function () {
|
||
if (fallbackSrc && avatar.getAttribute("src") !== fallbackSrc) {
|
||
avatar.src = fallbackSrc;
|
||
}
|
||
};
|
||
if (avatar.getAttribute("src") !== nextSrc) avatar.src = nextSrc;
|
||
}
|
||
function resizeApp() {
|
||
var scale = Math.min(window.innerWidth / 375, 1.25);
|
||
document.documentElement.style.setProperty("--app-scale", String(scale));
|
||
byId("appViewport").style.height = "826px";
|
||
document.body.style.minHeight = Math.ceil(826 * scale) + "px";
|
||
}
|
||
function syncLoading() {
|
||
var overlay = byId("loadingOverlay");
|
||
overlay.classList.toggle("active", state.loading);
|
||
overlay.setAttribute("aria-hidden", state.loading ? "false" : "true");
|
||
}
|
||
function showToast(message) {
|
||
var toast = byId("toast");
|
||
toast.textContent = message;
|
||
toast.classList.add("show");
|
||
window.clearTimeout(state.toastTimer);
|
||
state.toastTimer = window.setTimeout(function () { toast.classList.remove("show"); }, 1800);
|
||
}
|
||
function rowsHTML(name, detail) {
|
||
var tiers = ((detail && detail.tiers) || []).slice().sort(function (a, b) {
|
||
return Number(a.min_level || 0) - Number(b.min_level || 0);
|
||
});
|
||
function rangeText(index) {
|
||
var tier = tiers[index - 1];
|
||
if (!tier) return "1-10";
|
||
var min = Number(tier.min_level || 0);
|
||
var max = Number(tier.max_level || 0);
|
||
if (!min && !max) return "1-10";
|
||
return min + "-" + max;
|
||
}
|
||
return [1, 2, 3, 4, 5].map(function (i) {
|
||
return '<div class="tier-row r' + i + '"><div class="range">' + rangeText(i) + '</div><img class="badge-icon" src="' + A + name + '-icon-' + i + '.png" alt=""><img class="frame-icon" src="' + A + name + '-frame-' + i + '.png" alt=""></div>';
|
||
}).join("");
|
||
}
|
||
function upgradesHTML(cfg) {
|
||
var cls = cfg.upgrades.length === 3 ? "upgrade-three" : "upgrade-one";
|
||
return cfg.upgrades.map(function (item) {
|
||
return '<div class="upgrade-item ' + cls + '"><img class="upgrade-icon" src="' + item.icon + '" alt=""><div class="upgrade-name">' + item.name + '</div><div class="upgrade-exp">' + item.exp + '</div></div>';
|
||
}).join("");
|
||
}
|
||
function buttonHTML(cfg) {
|
||
var corner = cfg.button === "gold" ? A + "corner-gold.png" : A + "corner-purple.png";
|
||
var texture = cfg.button === "gold" ? A + "button-gold.png" : A + "button-purple.png";
|
||
return '<img class="consume-bg" src="' + texture + '" alt=""><img class="corner c1" src="' + corner + '" alt=""><img class="corner c2" src="' + corner + '" alt=""><img class="corner c3" src="' + corner + '" alt=""><img class="corner c4" src="' + corner + '" alt=""><span>To consume</span>';
|
||
}
|
||
function applyData() {
|
||
var d = state.details[state.track];
|
||
var o = d && d.overview ? d.overview : {};
|
||
var level = Number(o.level || 0);
|
||
var next = Number(o.next_level || level + 1);
|
||
var percent = Math.round(ratio(d) * 100);
|
||
byId("levelName").textContent = "Level " + level;
|
||
byId("lvCurrent").textContent = "Lv." + level;
|
||
byId("lvNext").textContent = "Lv." + next;
|
||
byId("progressPercent").textContent = percent + "%";
|
||
byId("progressFill").style.width = percent + "%";
|
||
var curRequired = Number(o.current_level_required_value || 0);
|
||
var nextRequired = Number(o.next_level_required_value || 0);
|
||
var total = Number(o.total_value || 0);
|
||
if (d && d.overview && nextRequired <= curRequired) {
|
||
byId("needText").textContent = "Max level reached";
|
||
return;
|
||
}
|
||
var need = Math.max(0, nextRequired - total);
|
||
byId("needText").textContent = "You need " + fmt(need) + " more experience points";
|
||
}
|
||
function render() {
|
||
state.track = track();
|
||
var cfg = tracks[state.track];
|
||
byId("pageBg").src = cfg.bg;
|
||
byId("cardBg").src = cfg.cardBg;
|
||
byId("decorLeft").src = cfg.decor;
|
||
byId("decorRight").src = cfg.decor;
|
||
setAvatarSource(state.userAvatar, cfg.avatar);
|
||
byId("avatarFrame").src = cfg.frame;
|
||
byId("tierRows").innerHTML = rowsHTML(state.track, state.details[state.track]);
|
||
byId("upgradeList").innerHTML = upgradesHTML(cfg);
|
||
byId("consumeButton").className = "consume " + (cfg.button === "gold" ? "gold" : "");
|
||
byId("consumeButton").innerHTML = buttonHTML(cfg);
|
||
document.documentElement.style.setProperty("--card-texture", cfg.texture);
|
||
document.documentElement.style.setProperty("--card-texture-opacity", cfg.textureOpacity);
|
||
document.documentElement.style.setProperty("--card-glow", cfg.glow);
|
||
document.documentElement.style.setProperty("--title-shadow", cfg.titleShadow);
|
||
document.documentElement.style.setProperty("--title-fill", cfg.titleFill);
|
||
document.documentElement.style.setProperty("--title-gradient", cfg.titleGradient);
|
||
document.documentElement.style.setProperty("--progress-text", cfg.progress);
|
||
document.documentElement.style.setProperty("--progress-track", cfg.progressTrack);
|
||
document.documentElement.style.setProperty("--progress-fill", cfg.progressFill);
|
||
document.documentElement.style.setProperty("--need-text", cfg.need);
|
||
document.documentElement.style.setProperty("--upgrade-title", cfg.upgrade);
|
||
document.querySelectorAll(".tab").forEach(function (node) { node.classList.toggle("active", node.dataset.track === state.track); });
|
||
applyData();
|
||
syncLoading();
|
||
resizeApp();
|
||
}
|
||
function loadOverview() {
|
||
if (!window.HyAppAPI || !window.HyAppAPI.level || !window.HyAppAPI.getAccessToken()) return Promise.resolve(null);
|
||
return window.HyAppAPI.level.overview().then(function (data) {
|
||
((data && data.tracks) || []).forEach(function (item) {
|
||
if (!item || !item.track || !tracks[item.track]) return;
|
||
if (!state.details[item.track]) state.details[item.track] = {};
|
||
state.details[item.track].overview = item;
|
||
});
|
||
render();
|
||
return data;
|
||
}).catch(function () { return null; });
|
||
}
|
||
function loadTrack(name) {
|
||
state.track = tracks[name] ? name : "charm";
|
||
if (window.history && window.history.replaceState) {
|
||
var url = new URL(window.location.href);
|
||
url.searchParams.set("track", state.track);
|
||
window.history.replaceState(null, "", url.toString());
|
||
}
|
||
render();
|
||
if (!window.HyAppAPI || !window.HyAppAPI.level || !window.HyAppAPI.getAccessToken()) return Promise.resolve(null);
|
||
state.loading = true;
|
||
render();
|
||
return window.HyAppAPI.level.track(state.track).then(function (data) {
|
||
state.details[state.track] = data;
|
||
}).catch(function (error) {
|
||
showToast((error && error.message) || "Network error");
|
||
}).finally(function () {
|
||
state.loading = false;
|
||
render();
|
||
});
|
||
}
|
||
function loadUserProfile() {
|
||
if (!window.HyAppParams || !window.HyAppParams.loadUser) return Promise.resolve(null);
|
||
return window.HyAppParams.loadUser().then(function (current) {
|
||
applyUserProfile(current);
|
||
return current;
|
||
}).catch(function () { return null; });
|
||
}
|
||
byId("tabs").addEventListener("click", function (event) {
|
||
var target = event.target.closest("[data-track]");
|
||
if (!target) return;
|
||
loadTrack(target.dataset.track);
|
||
});
|
||
byId("backButton").addEventListener("click", function () { window.HyAppBridge.back(); });
|
||
byId("consumeHit").addEventListener("click", function () { window.HyAppBridge.post("openLevelConsume", { track: state.track }); });
|
||
window.addEventListener("resize", resizeApp);
|
||
window.addEventListener("orientationchange", function () { window.requestAnimationFrame(resizeApp); });
|
||
render();
|
||
window.HyAppBridge.ready({ page: "level" });
|
||
loadTrack(state.track).finally(function () {
|
||
loadOverview();
|
||
loadUserProfile();
|
||
});
|
||
})();
|
||
</script>
|
||
</body>
|
||
</html>
|