Add fullscreen functionality: introduce API methods for getting and updating fullscreen settings, implement caching for fullscreen state, and integrate fullscreen toggle in AdminSettings. Remove unused fullscreen icons from Layout component.

This commit is contained in:
PEDZEO
2026-01-20 02:17:22 +03:00
parent e0df8a1a16
commit 64acfbee72
4 changed files with 91 additions and 27 deletions

View File

@@ -11,6 +11,10 @@ export interface AnimationEnabled {
enabled: boolean
}
export interface FullscreenEnabled {
enabled: boolean
}
const BRANDING_CACHE_KEY = 'cabinet_branding'
const LOGO_PRELOADED_KEY = 'cabinet_logo_preloaded'
@@ -121,4 +125,21 @@ export const brandingApi = {
const response = await apiClient.patch<AnimationEnabled>('/cabinet/branding/animation', { enabled })
return response.data
},
// Get fullscreen enabled (public, no auth required)
getFullscreenEnabled: async (): Promise<FullscreenEnabled> => {
try {
const response = await apiClient.get<FullscreenEnabled>('/cabinet/branding/fullscreen')
return response.data
} catch {
// If endpoint doesn't exist, default to disabled
return { enabled: false }
}
},
// Update fullscreen enabled (admin only)
updateFullscreenEnabled: async (enabled: boolean): Promise<FullscreenEnabled> => {
const response = await apiClient.patch<FullscreenEnabled>('/cabinet/branding/fullscreen', { enabled })
return response.data
},
}

View File

@@ -123,18 +123,6 @@ const WheelIcon = () => (
</svg>
)
const FullscreenIcon = () => (
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}>
<path strokeLinecap="round" strokeLinejoin="round" d="M3.75 3.75v4.5m0-4.5h4.5m-4.5 0L9 9M3.75 20.25v-4.5m0 4.5h4.5m-4.5 0L9 15M20.25 3.75h-4.5m4.5 0v4.5m0-4.5L15 9m5.25 11.25h-4.5m4.5 0v-4.5m0 4.5L15 15" />
</svg>
)
const ExitFullscreenIcon = () => (
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}>
<path strokeLinecap="round" strokeLinejoin="round" d="M9 9V4.5M9 9H4.5M9 9L3.75 3.75M9 15v4.5M9 15H4.5M9 15l-5.25 5.25M15 9h4.5M15 9V4.5M15 9l5.25-5.25M15 15h4.5M15 15v4.5m0-4.5l5.25 5.25" />
</svg>
)
export default function Layout({ children }: LayoutProps) {
const { t } = useTranslation()
const location = useLocation()
@@ -142,7 +130,7 @@ export default function Layout({ children }: LayoutProps) {
const [mobileMenuOpen, setMobileMenuOpen] = useState(false)
const { toggleTheme, isDark } = useTheme()
const [userPhotoUrl, setUserPhotoUrl] = useState<string | null>(null)
const { isTelegramWebApp, isFullscreen, isFullscreenSupported, toggleFullscreen, safeAreaInset, contentSafeAreaInset } = useTelegramWebApp()
const { isFullscreen, safeAreaInset, contentSafeAreaInset } = useTelegramWebApp()
// Fetch enabled themes from API - same source of truth as AdminSettings
const { data: enabledThemes } = useQuery({
@@ -372,20 +360,6 @@ export default function Layout({ children }: LayoutProps) {
{/* Right side */}
<div className="flex items-center gap-2 sm:gap-3">
{/* Fullscreen toggle - only show in Telegram WebApp */}
{isTelegramWebApp && isFullscreenSupported && (
<button
onClick={toggleFullscreen}
className="relative p-2.5 rounded-xl transition-all duration-300 hover:scale-110 active:scale-95
dark:text-dark-400 dark:hover:text-dark-100 dark:hover:bg-dark-800
text-champagne-500 hover:text-champagne-800 hover:bg-champagne-200/50"
title={isFullscreen ? 'Exit fullscreen' : 'Fullscreen'}
aria-label={isFullscreen ? 'Exit fullscreen' : 'Enter fullscreen'}
>
{isFullscreen ? <ExitFullscreenIcon /> : <FullscreenIcon />}
</button>
)}
{/* Theme toggle button - only show if both themes are enabled */}
{canToggle && (
<button

View File

@@ -1,5 +1,25 @@
import { useEffect, useState, useCallback } from 'react'
const FULLSCREEN_CACHE_KEY = 'cabinet_fullscreen_enabled'
// Get cached fullscreen setting
export const getCachedFullscreenEnabled = (): boolean => {
try {
return localStorage.getItem(FULLSCREEN_CACHE_KEY) === 'true'
} catch {
return false
}
}
// Set cached fullscreen setting
export const setCachedFullscreenEnabled = (enabled: boolean) => {
try {
localStorage.setItem(FULLSCREEN_CACHE_KEY, String(enabled))
} catch {
// localStorage not available
}
}
/**
* Hook for Telegram WebApp API integration
* Provides fullscreen mode, safe area insets, and other WebApp features
@@ -123,5 +143,15 @@ export function initTelegramWebApp() {
if (webApp.disableVerticalSwipes) {
webApp.disableVerticalSwipes()
}
// Auto-enter fullscreen if enabled in settings (use cached value for instant response)
const fullscreenEnabled = getCachedFullscreenEnabled()
if (fullscreenEnabled && webApp.requestFullscreen && !webApp.isFullscreen) {
try {
webApp.requestFullscreen()
} catch (e) {
console.warn('Auto-fullscreen failed:', e)
}
}
}
}

View File

@@ -5,6 +5,7 @@ import { Link } from 'react-router-dom'
import { adminSettingsApi, SettingDefinition, SettingCategorySummary } from '../api/adminSettings'
import { brandingApi, setCachedBranding } from '../api/branding'
import { setCachedAnimationEnabled } from '../components/AnimatedBackground'
import { setCachedFullscreenEnabled } from '../hooks/useTelegramWebApp'
import { themeColorsApi } from '../api/themeColors'
import { DEFAULT_THEME_COLORS, DEFAULT_ENABLED_THEMES } from '../types/theme'
import { ColorPicker } from '../components/ColorPicker'
@@ -880,6 +881,21 @@ export default function AdminSettings() {
},
})
// Fullscreen toggle query and mutation
const { data: fullscreenSettings } = useQuery({
queryKey: ['fullscreen-enabled'],
queryFn: brandingApi.getFullscreenEnabled,
})
const updateFullscreenMutation = useMutation({
mutationFn: (enabled: boolean) => brandingApi.updateFullscreenEnabled(enabled),
onSuccess: (data) => {
// Update local cache immediately for instant effect
setCachedFullscreenEnabled(data.enabled)
queryClient.invalidateQueries({ queryKey: ['fullscreen-enabled'] })
},
})
const updateNameMutation = useMutation({
mutationFn: (name: string) => brandingApi.updateName(name),
onSuccess: (data) => {
@@ -1229,6 +1245,29 @@ export default function AdminSettings() {
</button>
</div>
</div>
{/* Fullscreen Toggle */}
<div className="mt-4 pt-4 border-t border-dark-700/50">
<div className="flex items-center justify-between">
<div>
<h3 className="text-sm font-medium text-dark-200">Авто-Fullscreen</h3>
<p className="text-xs text-dark-500 mt-0.5">
Автоматически открывать на полный экран в Telegram
</p>
</div>
<button
onClick={() => updateFullscreenMutation.mutate(!(fullscreenSettings?.enabled ?? false))}
disabled={updateFullscreenMutation.isPending}
className={`relative w-12 h-6 rounded-full transition-colors ${
(fullscreenSettings?.enabled ?? false) ? 'bg-accent-500' : 'bg-dark-600'
} ${updateFullscreenMutation.isPending ? 'opacity-50' : ''}`}
>
<div className={`absolute top-1 w-4 h-4 bg-white rounded-full transition-transform ${
(fullscreenSettings?.enabled ?? false) ? 'left-7' : 'left-1'
}`} />
</button>
</div>
</div>
</div>
{/* Theme Colors Card */}