From d97946463d883495ccc15160b967be4c8ec49079 Mon Sep 17 00:00:00 2001 From: rgrgogu Date: Fri, 31 Jul 2026 00:35:45 +0800 Subject: [PATCH] added tier badge loading fallback --- src/modules/client/layout/ClientLayout.jsx | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/modules/client/layout/ClientLayout.jsx b/src/modules/client/layout/ClientLayout.jsx index ed3fe40..c971c8f 100644 --- a/src/modules/client/layout/ClientLayout.jsx +++ b/src/modules/client/layout/ClientLayout.jsx @@ -152,12 +152,20 @@ function ClientNav() { // Caches the resolved stream URL per asset_id — avoids re-hitting /media/token // for the same asset on re-renders. Token TTL is 4h so safe within a session. const badgeTokenCache = useRef({}) + // Starts false on every mount (incl. full page reloads) so the tier badge + // shows a gray skeleton instead of flashing "Free" before /tiers/me resolves — + // myTier stays null for genuinely-free users too, so it can't be used as the signal. + const [tierReady, setTierReady] = useState(false) useEffect(() => { if (!user) return; if (achievements.length === 0) getAchievements(); - if (!myTier) getMyTier(); if (tierCategories.length === 0) getTierCategories(); + if (!myTier) { + getMyTier().finally(() => setTierReady(true)); + } else { + setTierReady(true); + } }, [user]); // ── Derive directly from auth user — same pattern as admin UserMenu ────── @@ -247,7 +255,12 @@ function ClientNav() {
- {tierBadge && ( + {!tierReady ? ( +
+
+ Free +
+ ) : tierBadge && (
{badgeImgUrl ?