Files
hapi/web/src/hooks/useTheme.ts
T

70 lines
1.7 KiB
TypeScript

import { useSyncExternalStore } from 'react'
import { getTelegramWebApp } from './useTelegram'
type ColorScheme = 'light' | 'dark'
function getColorScheme(): ColorScheme {
const tg = getTelegramWebApp()
return tg?.colorScheme === 'dark' ? 'dark' : 'light'
}
function isIOS(): boolean {
return /iPad|iPhone|iPod/.test(navigator.userAgent)
}
function applyTheme(scheme: ColorScheme): void {
document.documentElement.setAttribute('data-theme', scheme)
}
function applyPlatform(): void {
if (isIOS()) {
document.documentElement.classList.add('ios')
}
}
// External store for theme state
let currentScheme: ColorScheme = getColorScheme()
const listeners = new Set<() => void>()
function subscribe(callback: () => void): () => void {
listeners.add(callback)
return () => listeners.delete(callback)
}
function getSnapshot(): ColorScheme {
return currentScheme
}
function updateScheme(): void {
const newScheme = getColorScheme()
if (newScheme !== currentScheme) {
currentScheme = newScheme
applyTheme(newScheme)
listeners.forEach((cb) => cb())
}
}
// Initialize theme on module load
applyTheme(currentScheme)
// Listen for Telegram theme changes
const tg = getTelegramWebApp()
if (tg?.onEvent) {
tg.onEvent('themeChanged', updateScheme)
}
export function useTheme(): { colorScheme: ColorScheme; isDark: boolean } {
const colorScheme = useSyncExternalStore(subscribe, getSnapshot, getSnapshot)
return {
colorScheme,
isDark: colorScheme === 'dark',
}
}
// Call this once at app startup to ensure theme is applied
export function initializeTheme(): void {
currentScheme = getColorScheme()
applyTheme(currentScheme)
}