(function () { "use strict"; var API_BASE_URL = "https://jvapi.haiyihy.com"; var ASSET_BASE = "/assets/yumi-ranking/Ranking/Overall/"; var BG_VERSION = "20260424c"; var DEFAULT_AVATAR = "/assets/da.png"; var COIN_ICON = ""; var LOADING_GIF = "/assets/loading-ranking.gif"; var BACK_ICON = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABICAYAAABV7bNHAAAACXBIWXMAACE4AAAhOAFFljFgAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAADxSURBVHgB7dvBDYJAFEXRHyuhBEuzA+3EWAmlUIJ2MDJCNATy5m1I1H9PwoZhww3Mgh8iAAAAAACllG48joGlOUxfPoZ6LvCOM5S1PrITcV4is1acuhY7O8SXmveX+gp14rJbZGQ8OdUlMiKOQByBOAJxBOIIxBGIIxBHII5AHIE4AnEE4gjEEYgjEKeBOMJ488d/irPHN+lHYz33JKIqywHflnNkZm7SRCJSA5EMRDIQyUAkA5EMRDIQyUAkA5EMRDIQyUAkA5EMRDIQyWBGOkVmRqR7ZNeKFJCRroHJRqS+8DvUWpkGk10AAAAAwO96AiOznp1YXpZWAAAAAElFTkSuQmCC"; var RANKING_TYPES = ["Wealth", "Charm", "Room"]; var PERIODS = [ { key: "Daily", api: "DAY", label: "ranking_daily" }, { key: "Weekly", api: "WEEK", label: "ranking_weekly" }, { key: "Monthly", api: "MONTH", label: "ranking_monthly" } ]; var TYPE_LABELS = { Wealth: "ranking_wealth", Charm: "ranking_charm", Room: "ranking_room" }; var TYPE_TO_MY_RANK = { Wealth: "GIFTS_SEND", Charm: "GIFTS_RECEIVED", Room: "ROOM_GIFTS" }; var TYPE_ENDPOINTS = { Wealth: "/activity/leaderboard/gifts-send", Charm: "/activity/leaderboard/gifts-received", Room: "/activity/leaderboard/room-gifts" }; var TYPE_ASSETS = { Wealth: { bg: "bgWealth", top1: "rankAvatarFrame1", top2: "rankAvatarFrame2", top3: "rankAvatarFrame3" }, Charm: { bg: "bgCharm", top1: "rankAvatarFrame1", top2: "rankAvatarFrame2", top3: "rankAvatarFrame3" }, Room: { bg: "bgRoom", top1: "rankAvatarFrame1", top2: "rankAvatarFrame2", top3: "rankAvatarFrame3" } }; var I18N = { en: { ranking_wealth: "Wealth", ranking_charm: "Charm", ranking_room: "Room", ranking_daily: "Daily", ranking_weekly: "Weekly", ranking_monthly: "Monthly", loading: "Loading" } }; var commonHeaders = { authorization: "Bearer undefined", "req-app-intel": "version=1.0.0;build=1;model=SM-G9550;sysVersion=9;channel=Google", "req-client": "Android", "req-imei": "8fa54d728ab449e04f9292329ed44bda", "req-lang": "id-ID", "req-sys-origin": "origin=ATYOU;originChild=ATYOU", "req-version": "V2", "req-zone": "Asia/Shanghai" }; var state = { rankingType: getInitialRankingType(), period: "Daily", dateType: "DAY", myRankType: "GIFTS_SEND", sourceRanking: {}, visibleRanking: [], myRanking: {}, visibleCount: 10, hasMore: true, loading: true, locale: getLocale(), isApp: isAppEnvironment(), requestId: 0 }; var stickyObserver = null; var loadObserver = null; var lastTypeClick = 0; var lastPeriodClick = 0; function asset(name) { return ASSET_BASE + name + ".png"; } function backgroundAsset(type) { return asset(TYPE_ASSETS[type].bg) + "?v=" + BG_VERSION; } function t(key) { var messages = I18N[state.locale] || I18N.en; return messages[key] || I18N.en[key] || key; } function getLocale() { var raw = getParam("lang") || navigator.language || "en"; raw = String(raw).toLowerCase(); if (raw.indexOf("ar") === 0) return "ar"; if (raw.indexOf("tr") === 0) return "tr"; if (raw.indexOf("bn") === 0) return "bn"; return "en"; } function getInitialRankingType() { var first = getParam("first") || "Wealth"; return RANKING_TYPES.indexOf(first) >= 0 ? first : "Wealth"; } function getParam(name) { var hashQuery = ""; if (window.location.hash && window.location.hash.indexOf("?") >= 0) { hashQuery = window.location.hash.slice(window.location.hash.indexOf("?") + 1); } var hashValue = hashQuery ? new URLSearchParams(hashQuery).get(name) : null; var searchValue = new URLSearchParams(window.location.search).get(name); return hashValue || searchValue; } function setHeadersFromApp(info) { var next = {}; if (info.authorization !== undefined) next.authorization = info.authorization; if (info.reqLang) next["req-lang"] = info.reqLang; if (info.appVersion || info.buildVersion || info.appChannel) { var appIntel = []; if (info.appVersion) appIntel.push("version=" + info.appVersion); if (info.buildVersion) appIntel.push("build=" + info.buildVersion); if (info.appChannel) appIntel.push("channel=" + info.appChannel); if (appIntel.length) next["req-app-intel"] = appIntel.join(";"); } if (info.reqImei) next["req-imei"] = info.reqImei; if (info.sysOrigin) { var origin = ["origin=" + info.sysOrigin]; if (info.sysOriginChild) origin.push("child=" + info.sysOriginChild); next["req-sys-origin"] = origin.join(";"); } commonHeaders = Object.assign({}, commonHeaders, next); } function isMobileDevice() { return /Android|iPad|iPhone|iPod/.test(navigator.userAgent); } function isAppEnvironment() { return !!(window.app || window.webkit || window.FlutterPageControl); } function defaultBrowserHeaders() { var lang = navigator.language || ""; return { authorization: "", reqLang: lang.toLowerCase().indexOf("ar") === 0 ? "ar" : lang.toLowerCase().indexOf("tr") === 0 ? "tr" : lang.toLowerCase().indexOf("bn") === 0 ? "bn" : "en", appVersion: "1.0.0", buildVersion: "1", appChannel: "Web", reqImei: "H5-STATIC", sysOrigin: "LIKEI", sysOriginChild: "LIKEI" }; } function mockAppAccessOrigin() { return JSON.stringify({ Authorization: "Bearer FLUTTER_MOCK_TOKEN", "Req-Lang": "en", "Req-App-Intel": "build=1.0;version=2.1;channel=flutter;Req-Imei=flutter-device", "Req-Sys-Origin": "origin=ATYOU;originChild=ATYOU" }); } function parseKeyValueList(value) { var result = {}; if (!value) return result; String(value).split(";").forEach(function (part) { if (!part || part.indexOf("=") < 0) return; var index = part.indexOf("="); result[part.slice(0, index)] = part.slice(index + 1); }); return result; } function normalizeAccessOrigin(data) { if (!data) return {}; var appIntel = parseKeyValueList(data["Req-App-Intel"] || ""); var sysOrigin = parseKeyValueList(data["Req-Sys-Origin"] || ""); return { reqLang: data["Req-Lang"], authorization: data.Authorization, buildVersion: appIntel.build, appVersion: appIntel.version, appChannel: appIntel.channel, reqImei: appIntel["Req-Imei"], sysOrigin: sysOrigin.origin, sysOriginChild: sysOrigin.child }; } function getAccessOriginFromApp() { return new Promise(function (resolve) { var resolved = false; var finish = function (value) { if (resolved) return; resolved = true; resolve(value); }; window.renderData = finish; window.getIosAccessOriginParam = finish; var attempts = 0; var check = function () { attempts += 1; if (window.app && typeof window.app.getAccessOrigin === "function") { try { finish(window.app.getAccessOrigin()); } catch (error) { console.error("getAccessOrigin failed:", error); finish(mockAppAccessOrigin()); } return; } if (attempts < 50) { window.setTimeout(check, 100); return; } if (window.FlutterApp && window.FlutterApp.postMessage) { window.FlutterApp.postMessage("requestAccessOrigin"); } finish(mockAppAccessOrigin()); }; if (isMobileDevice()) { check(); } else { finish(mockAppAccessOrigin()); } }); } async function initializeAppConnection() { if (!isAppEnvironment()) { setHeadersFromApp(defaultBrowserHeaders()); await fetchUserProfileAfterConnection(); return; } try { var raw = await getAccessOriginFromApp(); var parsed = JSON.parse(raw); setHeadersFromApp(normalizeAccessOrigin(parsed)); } catch (error) { console.error("Failed to parse access origin:", error); setHeadersFromApp(defaultBrowserHeaders()); } await fetchUserProfileAfterConnection(); } async function fetchUserProfileAfterConnection() { try { var response = await apiGet("/team/member/profile"); if (response && response.status && response.body) { localStorage.setItem("userProfile", JSON.stringify(response.body)); } } catch (error) { console.warn("Failed to fetch user info after connection:", error); } } async function apiRequest(path, options) { var url = path.indexOf("http") === 0 ? path : API_BASE_URL + path; var init = Object.assign({ method: "GET" }, options || {}); init.headers = Object.assign({}, commonHeaders, init.headers || {}); if (init.body && typeof init.body !== "string" && !(init.body instanceof FormData)) { init.headers["Content-Type"] = "application/json"; init.body = JSON.stringify(init.body); } var response = await fetch(url, init); var data = await response.json(); if (!response.ok) { throw makeApiError("HTTP Error: " + response.status + " " + response.statusText, response.status, data); } if (data && data.status === false) { throw makeApiError(data.errorMsg || data.message || "API Error: " + data.errorCode, response.status, data); } return data; } function apiGet(path) { return apiRequest(path, { method: "GET" }); } function makeApiError(message, status, response) { var error = new Error(message); error.name = "ApiError"; error.status = status || null; error.response = response || null; error.errorMsg = response && response.errorMsg; error.errorCode = response && response.errorCode; return error; } async function fetchLeaderboard(type) { var response = await apiGet(TYPE_ENDPOINTS[type]); if (response && response.status && response.body) { state.sourceRanking = response.body; updatePeriodRanking(); } } async function fetchMyRanking() { var path = "/activity/leaderboard/my-rank?type=" + encodeURIComponent(state.myRankType) + "&dateType=" + encodeURIComponent(state.dateType); var response = await apiGet(path); state.myRanking = response && response.status && response.body ? response.body : {}; } function updatePeriodRanking() { var body = state.sourceRanking || {}; var rows = []; if (state.period === "Hourly" && body.hourly) rows = body.hourly; if (state.period === "Daily" && body.daily) rows = body.daily; if (state.period === "Weekly" && body.weekly) rows = body.weekly; if (state.period === "Monthly" && body.monthly) rows = body.monthly; state.visibleRanking = Array.isArray(rows) ? rows : []; state.visibleCount = 10; state.hasMore = true; } async function preloadImages(urls) { await Promise.all(urls.map(function (url) { return new Promise(function (resolve) { var image = new Image(); image.onload = resolve; image.onerror = resolve; image.src = url; }); })); } function preloadRankingAssets() { return preloadImages([ backgroundAsset("Wealth"), backgroundAsset("Charm"), backgroundAsset("Room"), asset("rankAvatarFrame1"), asset("rankAvatarFrame2"), asset("rankAvatarFrame3") ]); } async function loadInitialData() { applyTypeState(state.rankingType); render(); try { await initializeAppConnection(); await Promise.all([ fetchCurrentRankingGroup(), preloadRankingAssets() ]); } catch (error) { console.error("Ranking preload failed:", error); } finally { state.loading = false; render(); } } async function fetchCurrentRankingGroup() { var requestId = ++state.requestId; var type = state.rankingType; await Promise.all([ fetchLeaderboard(type).catch(function (error) { console.error("Leaderboard request failed:", error); }), fetchMyRanking().catch(function (error) { console.error("My ranking request failed:", error); }) ]); if (requestId !== state.requestId) return; render(); } async function fetchOnlyMyRanking() { var requestId = ++state.requestId; try { await fetchMyRanking(); } catch (error) { console.error("My ranking request failed:", error); } if (requestId !== state.requestId) return; render(); } function applyTypeState(type) { state.rankingType = type; state.myRankType = TYPE_TO_MY_RANK[type]; } function switchRankingType(type) { if (state.rankingType === type) return; var now = Date.now(); if (now - lastTypeClick < 1000) return; lastTypeClick = now; applyTypeState(type); state.period = "Daily"; state.dateType = "DAY"; state.sourceRanking = {}; state.visibleRanking = []; state.myRanking = {}; state.visibleCount = 10; state.hasMore = true; render(); fetchCurrentRankingGroup(); } function switchPeriod(period) { if (state.period === period.key) return; var now = Date.now(); if (now - lastPeriodClick < 500) return; lastPeriodClick = now; state.period = period.key; state.dateType = period.api; state.visibleRanking = []; state.myRanking = {}; updatePeriodRanking(); render(); fetchOnlyMyRanking(); } function loadMoreRows() { if (!state.hasMore) return; var total = state.visibleRanking.filter(function (_, index) { return index >= 3; }).length; var current = state.visibleCount; if (current < total) { state.visibleCount = Math.min(current + 10, total); if (state.visibleCount >= total) state.hasMore = false; render(); } else { state.hasMore = false; } } function getTopUsers() { var list = state.visibleRanking.slice(); while (list.length < 3) { list.push({ avatar: "", id: "", nickname: "", quantityFormat: "" }); } return list.slice(0, 3); } function getListRows() { return state.visibleRanking.filter(function (_, index) { return index >= 3; }).slice(0, state.visibleCount); } function topLayout(isTopOne) { return { width: isTopOne ? "44%" : "34%", minHeight: isTopOne ? "66vw" : "55vw", avatarLayer: "height:55%", avatarWidth: isTopOne ? "45%" : "47%", nameBox: isTopOne ? "height:6vw;width:55%" : "height:4.5vw;width:65%", pillWidth: isTopOne ? "55%" : "70%", infoStyle: isTopOne ? "bottom:27%" : "bottom:29%" }; } function render() { var app = document.getElementById("app"); if (!app) return; if (state.loading) { app.innerHTML = renderLoading(); return; } app.innerHTML = renderRanking(); bindEvents(); setupObservers(); } function renderBgLayer(zIndex) { var style = zIndex === undefined ? "" : ' style="z-index:' + zIndex + '"'; return '
background-0
'; } function renderLoading() { return '
' + '
' + renderBgLayer() + '' + '

' + escapeHtml(t("loading")) + '...

' + '
' + '
'; } function renderRanking() { return '
' + '
' + renderBgLayer(-1) + '
' + renderHeader() + '
' + renderTopSection() + renderRankList() + '
' + '
' + '
' + renderMyRanking() + '
' + '
'; } function renderHeader() { return ''; } function renderTopSection() { var users = getTopUsers(); return '
' + '
' + renderTopUser(users[0], 0, true) + '
' + '
' + renderTopUser(users[1], 1, false) + renderTopUser(users[2], 2, false) + '
' + '
'; } function renderTopUser(user, index, isTopOne) { var assets = TYPE_ASSETS[state.rankingType]; var frame = isTopOne ? assets.top1 : index === 1 ? assets.top2 : assets.top3; var layout = topLayout(isTopOne); var name = user && user.nickname ? user.nickname : ""; var avatar = user && user.avatar ? user.avatar : ""; var quantity = user && user.quantityFormat ? user.quantityFormat : ""; var id = user && user.id ? user.id : ""; return '
' + '
' + '' + '
' + '
' + '' + '
' + '
' + '' + '
' + '
'; } function renderQuantityPill(quantity, width, isTopOne) { return '
' + '
' + '
' + escapeHtml(quantity) + '
' + '
' + '
'; } function renderRankList() { var rows = getListRows(); return '
' + rows.map(function (row, index) { return renderRankRow(row, index + 4); }).join("") + (state.hasMore ? '
' : "") + '
'; } function renderItemCenter(classes, minHeight, image, content, attrs) { return '
' + '
' + content + '
' + '
'; } function renderRankRow(row, rank) { var id = row && row.id ? row.id : ""; var avatar = row && row.avatar ? row.avatar : ""; var name = row && row.nickname ? row.nickname : ""; var quantity = row && row.quantityFormat ? row.quantityFormat : ""; var content = '
' + '
' + rank + '
' + '' + '
' + escapeHtml(name) + '
' + '
' + '
' + '
' + escapeHtml(quantity) + '
' + '
'; return renderItemCenter( "rank-row", "19vw", asset("RankingItem"), content, ' data-user-id="' + escapeAttribute(id) + '"' ); } function renderMyRanking() { var mine = state.myRanking || {}; var rank = mine.rank || 999; var avatar = mine.avatar || ""; var name = mine.nickname || ""; var quantity = mine.quantityFormat || 0; var content = '
' + '
' + escapeHtml(String(rank)) + '
' + '' + '
' + escapeHtml(name) + '
' + '
' + '
' + '
' + escapeHtml(String(quantity)) + '
' + '
'; return renderItemCenter("my-ranking", "", asset("myRankingBg"), content); } function bindEvents() { document.querySelectorAll("[data-ranking-type]").forEach(function (button) { button.addEventListener("click", function () { switchRankingType(button.getAttribute("data-ranking-type")); }); }); document.querySelectorAll("[data-period]").forEach(function (button) { button.addEventListener("click", function () { var key = button.getAttribute("data-period"); var period = PERIODS.filter(function (item) { return item.key === key; })[0]; if (period) switchPeriod(period); }); }); var back = document.querySelector(".back-btn"); if (back) back.addEventListener("click", closePage); document.querySelectorAll("[data-user-id]").forEach(function (node) { node.addEventListener("click", function () { openAppTarget(node.getAttribute("data-user-id")); }); }); document.querySelectorAll("[data-avatar]").forEach(function (img) { img.addEventListener("error", function () { if (img.getAttribute("src") !== DEFAULT_AVATAR) { img.setAttribute("src", DEFAULT_AVATAR); } }); }); } function setupObservers() { if (stickyObserver) stickyObserver.disconnect(); if (loadObserver) loadObserver.disconnect(); var sentinel = document.querySelector(".sentinel"); var stickyHeader = document.querySelector(".sticky-header"); if (sentinel && stickyHeader && "IntersectionObserver" in window) { stickyObserver = new IntersectionObserver(function (entries) { entries.forEach(function (entry) { if (entry.isIntersecting) { stickyHeader.classList.remove("stuck"); } else { stickyHeader.classList.add("stuck"); } }); }); stickyObserver.observe(sentinel); } var loadMore = document.querySelector(".load-more-sentinel"); if (loadMore && "IntersectionObserver" in window) { loadObserver = new IntersectionObserver(function (entries) { entries.forEach(function (entry) { if (entry.isIntersecting && state.hasMore) loadMoreRows(); }); }, { rootMargin: "100px" }); loadObserver.observe(loadMore); } } function closePage() { try { if (window.app && window.app.closePage) { window.app.closePage(); } else if (window.FlutterPageControl && window.FlutterPageControl.postMessage) { window.FlutterPageControl.postMessage("close_page"); } else { window.history.back(); } } catch (error) { console.error("close page failed:", error); window.history.back(); } } function openAppTarget(id) { if (!id || !state.isApp) return; try { if (state.rankingType === "Room") { if (window.app && window.app.gotoRoom) { window.app.gotoRoom(id); } else if (window.FlutterPageControl && window.FlutterPageControl.postMessage) { window.FlutterPageControl.postMessage("go_to_room:" + id); } } else if (window.app && window.app.viewUserInfo) { window.app.viewUserInfo(id); } else if (window.FlutterPageControl && window.FlutterPageControl.postMessage) { window.FlutterPageControl.postMessage("view_user_info:" + id); } } catch (error) { console.error("open app target failed:", error); } } function escapeHtml(value) { return String(value == null ? "" : value) .replace(/&/g, "&") .replace(//g, ">") .replace(/"/g, """) .replace(/'/g, "'"); } function escapeAttribute(value) { return escapeHtml(value); } loadInitialData(); })();