mirror of
https://github.com/chillpadclub/bedolaga-cabinet.git
synced 2026-07-29 10:03:46 +00:00
Кастомное лого квадратное, и в фавиконе показывалось с острыми углами. Теперь лого прогоняется через canvas со скруглённым клипом (radiusRatio 0.3 — как rounded-linear-lg 12px на плитке 40px в хедере) и отдаётся скруглённым PNG. При сбое canvas (taint/нет 2d-контекста) — фолбэк на сырой лого. Применяется и в кабинете (useBranding), и на лендинге (QuickPurchase); буквенная монограмма уже скруглена через rx.
88 lines
2.6 KiB
TypeScript
88 lines
2.6 KiB
TypeScript
import { useEffect, useRef } from 'react';
|
|
import { useQuery } from '@tanstack/react-query';
|
|
import { useAuthStore } from '@/store/auth';
|
|
import { useTelegramSDK, setCachedFullscreenEnabled } from '@/hooks/useTelegramSDK';
|
|
import {
|
|
brandingApi,
|
|
getCachedBranding,
|
|
setCachedBranding,
|
|
preloadLogo,
|
|
isLogoPreloaded,
|
|
} from '@/api/branding';
|
|
import { setFavicon, letterFaviconDataUri, roundedFaviconDataUri } from '@/utils/favicon';
|
|
|
|
const FALLBACK_NAME = import.meta.env.VITE_APP_NAME || 'Cabinet';
|
|
const FALLBACK_LOGO = import.meta.env.VITE_APP_LOGO || 'V';
|
|
|
|
export function useBranding() {
|
|
const isAuthenticated = useAuthStore((state) => state.isAuthenticated);
|
|
const { isTelegramWebApp, requestFullscreen, isMobile } = useTelegramSDK();
|
|
|
|
// Branding data
|
|
const { data: branding } = useQuery({
|
|
queryKey: ['branding'],
|
|
queryFn: async () => {
|
|
const data = await brandingApi.getBranding();
|
|
setCachedBranding(data);
|
|
await preloadLogo(data);
|
|
return data;
|
|
},
|
|
initialData: getCachedBranding() ?? undefined,
|
|
initialDataUpdatedAt: 0,
|
|
staleTime: 60000,
|
|
enabled: isAuthenticated,
|
|
});
|
|
|
|
const appName = branding ? branding.name : FALLBACK_NAME;
|
|
const logoLetter = branding?.logo_letter || FALLBACK_LOGO;
|
|
const hasCustomLogo = branding?.has_custom_logo || false;
|
|
const logoUrl = branding ? brandingApi.getLogoUrl(branding) : null;
|
|
|
|
// Set document title
|
|
useEffect(() => {
|
|
document.title = appName || 'VPN';
|
|
}, [appName]);
|
|
|
|
// Update favicon — custom logo (rounded like the header tile) when available,
|
|
// else a brand-letter monogram so the tab always carries an icon.
|
|
useEffect(() => {
|
|
if (!logoUrl) {
|
|
setFavicon(letterFaviconDataUri(logoLetter));
|
|
return;
|
|
}
|
|
let cancelled = false;
|
|
roundedFaviconDataUri(logoUrl).then((rounded) => {
|
|
if (!cancelled) setFavicon(rounded || logoUrl);
|
|
});
|
|
return () => {
|
|
cancelled = true;
|
|
};
|
|
}, [logoUrl, logoLetter]);
|
|
|
|
// Fullscreen setting from server
|
|
const { data: fullscreenSetting } = useQuery({
|
|
queryKey: ['fullscreen-enabled'],
|
|
queryFn: brandingApi.getFullscreenEnabled,
|
|
staleTime: 60000,
|
|
});
|
|
|
|
const fullscreenRequestedRef = useRef(false);
|
|
|
|
useEffect(() => {
|
|
if (!fullscreenSetting || !isTelegramWebApp) return;
|
|
setCachedFullscreenEnabled(fullscreenSetting.enabled);
|
|
if (fullscreenSetting.enabled && isMobile && !fullscreenRequestedRef.current) {
|
|
fullscreenRequestedRef.current = true;
|
|
requestFullscreen();
|
|
}
|
|
}, [fullscreenSetting, isTelegramWebApp, requestFullscreen, isMobile]);
|
|
|
|
return {
|
|
appName,
|
|
logoLetter,
|
|
hasCustomLogo,
|
|
logoUrl,
|
|
isLogoPreloaded,
|
|
};
|
|
}
|