fix: move cabinet_branding to sessionStorage and add WebGL availability check

- Branding cache moved from localStorage to sessionStorage so it clears
  when the mini-app is closed, preventing stale names after admin updates
- Added initialDataUpdatedAt: 0 to all branding queries so fresh data is
  always fetched on page refresh while showing cached data instantly
- One-time migration moves existing localStorage value to sessionStorage
- Aurora component now checks WebGL availability upfront, skipping all
  hooks and subscriptions when WebGL is not supported
This commit is contained in:
Fringg
2026-02-16 07:25:06 +03:00
parent 54f1483312
commit fc7ee6abfe
6 changed files with 40 additions and 6 deletions

View File

@@ -46,25 +46,32 @@ export const isLogoPreloaded = (): boolean => {
}
};
// Get cached branding from localStorage
// Get cached branding from sessionStorage
export const getCachedBranding = (): BrandingInfo | null => {
try {
const cached = localStorage.getItem(BRANDING_CACHE_KEY);
const cached = sessionStorage.getItem(BRANDING_CACHE_KEY);
if (cached) {
return JSON.parse(cached);
}
// One-time migration: move stale localStorage value to sessionStorage
const legacy = localStorage.getItem(BRANDING_CACHE_KEY);
if (legacy) {
localStorage.removeItem(BRANDING_CACHE_KEY);
sessionStorage.setItem(BRANDING_CACHE_KEY, legacy);
return JSON.parse(legacy);
}
} catch {
// localStorage not available or invalid JSON
// storage not available or invalid JSON
}
return null;
};
// Update branding cache in localStorage
// Update branding cache in sessionStorage
export const setCachedBranding = (branding: BrandingInfo) => {
try {
localStorage.setItem(BRANDING_CACHE_KEY, JSON.stringify(branding));
sessionStorage.setItem(BRANDING_CACHE_KEY, JSON.stringify(branding));
} catch {
// localStorage not available
// sessionStorage not available
}
};

View File

@@ -93,6 +93,7 @@ export function AppHeader({
return data;
},
initialData: getCachedBranding() ?? undefined,
initialDataUpdatedAt: 0,
staleTime: 60000,
refetchOnWindowFocus: true,
retry: 1,

View File

@@ -127,7 +127,30 @@ function generateColorStops(background: string, surface: string, accent: string)
return [background, surface, dimAccent(accent)];
}
let _webglAvailable: boolean | null = null;
function isWebglAvailable(): boolean {
if (_webglAvailable === null) {
try {
const renderer = new Renderer({
alpha: true,
antialias: false,
powerPreference: 'low-power',
});
_webglAvailable = !!renderer.gl;
} catch {
_webglAvailable = false;
}
}
return _webglAvailable;
}
export function Aurora() {
if (!isWebglAvailable()) return null;
return <AuroraImpl />;
}
function AuroraImpl() {
const containerRef = useRef<HTMLDivElement>(null);
const animationFrameRef = useRef<number>(0);
const rendererRef = useRef<Renderer | null>(null);

View File

@@ -62,6 +62,7 @@ export function DesktopSidebar({
return data;
},
initialData: getCachedBranding() ?? undefined,
initialDataUpdatedAt: 0,
staleTime: 60000,
refetchOnWindowFocus: true,
retry: 1,

View File

@@ -27,6 +27,7 @@ export function useBranding() {
return data;
},
initialData: getCachedBranding() ?? undefined,
initialDataUpdatedAt: 0,
staleTime: 60000,
enabled: isAuthenticated,
});

View File

@@ -90,6 +90,7 @@ export default function Login() {
},
staleTime: 60000,
initialData: cachedBranding ?? undefined,
initialDataUpdatedAt: 0,
});
// Check if email auth is enabled