mirror of
https://github.com/wu736139669/hapi.git
synced 2026-08-08 07:17:39 +00:00
Add lazy loading of Telegram SDK only when running inside Telegram Mini App environment instead of unconditionally loading in all browsers. Includes: - New environment detection functions: isTelegramEnvironment(), isTelegramApp() - Dynamic SDK loading with 3s timeout via loadTelegramSdk() - Removed static script tag from index.html - Made haptic feedback lazy (SDK check on each call) - Made theme listeners lazy (attached in initializeTheme()) - Updated all components to use unified detection functions This prevents SDK load time overhead in regular browser environments while ensuring the app works correctly both in Telegram and browser contexts.
145 lines
3.9 KiB
TypeScript
145 lines
3.9 KiB
TypeScript
/**
|
|
* Detects if the current environment is Telegram Mini App
|
|
* by checking URL hash/query parameters that Telegram passes.
|
|
* This works BEFORE the SDK is loaded.
|
|
*/
|
|
export function isTelegramEnvironment(): boolean {
|
|
if (typeof window === 'undefined') return false
|
|
|
|
// Telegram passes launch params via window.location.hash
|
|
// Format: #tgWebAppVersion=...&tgWebAppData=...&tgWebAppPlatform=...
|
|
const hash = window.location.hash.slice(1)
|
|
const hashParams = new URLSearchParams(hash)
|
|
|
|
// Primary detection: check hash parameters
|
|
if (hashParams.has('tgWebAppVersion') || hashParams.has('tgWebAppData')) {
|
|
return true
|
|
}
|
|
|
|
// Fallback: check query parameters (alternative flow)
|
|
const search = window.location.search
|
|
if (search.includes('tgWebApp') || search.includes('initData')) {
|
|
return true
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
export type TelegramWebAppThemeParams = {
|
|
bg_color?: string
|
|
text_color?: string
|
|
hint_color?: string
|
|
link_color?: string
|
|
button_color?: string
|
|
button_text_color?: string
|
|
secondary_bg_color?: string
|
|
}
|
|
|
|
export type TelegramWebAppUser = {
|
|
id: number
|
|
username?: string
|
|
first_name: string
|
|
last_name?: string
|
|
}
|
|
|
|
export type TelegramWebAppInitDataUnsafe = {
|
|
start_param?: string
|
|
user?: TelegramWebAppUser
|
|
}
|
|
|
|
export type TelegramWebApp = {
|
|
initData: string
|
|
initDataUnsafe?: TelegramWebAppInitDataUnsafe
|
|
themeParams: TelegramWebAppThemeParams
|
|
colorScheme?: 'light' | 'dark'
|
|
ready: () => void
|
|
expand: () => void
|
|
close?: () => void
|
|
onEvent?: (eventType: string, callback: () => void) => void
|
|
offEvent?: (eventType: string, callback: () => void) => void
|
|
BackButton?: {
|
|
show: () => void
|
|
hide: () => void
|
|
onClick: (callback: () => void) => void
|
|
offClick: (callback: () => void) => void
|
|
}
|
|
MainButton?: {
|
|
text: string
|
|
color: string
|
|
textColor: string
|
|
isVisible: boolean
|
|
isActive: boolean
|
|
show: () => void
|
|
hide: () => void
|
|
enable: () => void
|
|
disable: () => void
|
|
setText: (text: string) => void
|
|
onClick: (callback: () => void) => void
|
|
offClick: (callback: () => void) => void
|
|
}
|
|
HapticFeedback?: {
|
|
impactOccurred: (style: 'light' | 'medium' | 'heavy' | 'rigid' | 'soft') => void
|
|
notificationOccurred: (type: 'error' | 'success' | 'warning') => void
|
|
selectionChanged: () => void
|
|
}
|
|
SettingsButton?: {
|
|
isVisible: boolean
|
|
show: () => void
|
|
hide: () => void
|
|
onClick: (callback: () => void) => void
|
|
offClick: (callback: () => void) => void
|
|
}
|
|
}
|
|
|
|
declare global {
|
|
interface Window {
|
|
Telegram?: {
|
|
WebApp?: TelegramWebApp
|
|
}
|
|
}
|
|
}
|
|
|
|
export function getTelegramWebApp(): TelegramWebApp | null {
|
|
return window.Telegram?.WebApp ?? null
|
|
}
|
|
|
|
/**
|
|
* Checks if running inside a real Telegram Mini App.
|
|
* Requires SDK to be loaded. Returns true only if initData is present.
|
|
*/
|
|
export function isTelegramApp(): boolean {
|
|
const tg = getTelegramWebApp()
|
|
return tg !== null && Boolean(tg.initData)
|
|
}
|
|
|
|
/**
|
|
* Dynamically loads the Telegram Web App SDK with timeout.
|
|
* Only call this if isTelegramEnvironment() returns true.
|
|
*/
|
|
export function loadTelegramSdk(timeoutMs = 3000): Promise<void> {
|
|
return new Promise((resolve) => {
|
|
if (window.Telegram?.WebApp) {
|
|
resolve()
|
|
return
|
|
}
|
|
|
|
let settled = false
|
|
const settle = () => {
|
|
if (!settled) {
|
|
settled = true
|
|
resolve()
|
|
}
|
|
}
|
|
|
|
// Timeout - don't block app indefinitely
|
|
setTimeout(settle, timeoutMs)
|
|
|
|
const script = document.createElement('script')
|
|
script.src = 'https://telegram.org/js/telegram-web-app.js'
|
|
script.async = true
|
|
script.onload = settle
|
|
script.onerror = settle
|
|
document.head.appendChild(script)
|
|
})
|
|
}
|