Files
hapi/web/src/hooks/usePlatform.ts
T
weishu aacab0be51 feat(web): add auto-focus to composer input on desktop devices only
Adds touch device detection via media query (pointer: coarse) to prevent
triggering virtual keyboard on mobile. Input auto-focus is now conditional
on desktop environments where it improves keyboard-based interactions.
2025-12-22 09:46:03 +08:00

93 lines
2.5 KiB
TypeScript

import { useMemo } from 'react'
import { getTelegramWebApp, isTelegramApp } from './useTelegram'
export type HapticStyle = 'light' | 'medium' | 'heavy' | 'rigid' | 'soft'
export type HapticNotification = 'error' | 'success' | 'warning'
export type PlatformHaptic = {
/** Trigger impact feedback */
impact: (style: HapticStyle) => void
/** Trigger notification feedback */
notification: (type: HapticNotification) => void
/** Trigger selection changed feedback */
selection: () => void
}
export type Platform = {
/** Whether running in Telegram Mini App */
isTelegram: boolean
/** Whether using a touch device (coarse pointer) */
isTouch: boolean
/** Haptic feedback (falls back to Vibration API on browser) */
haptic: PlatformHaptic
}
// Vibration patterns for web fallback (in ms)
const vibrationPatterns = {
light: 10,
medium: 20,
heavy: 30,
rigid: 15,
soft: 10,
success: 20,
warning: [20, 50, 20] as number | number[],
error: [30, 50, 30] as number | number[],
selection: 5,
}
function vibrate(pattern: number | number[]) {
navigator.vibrate?.(pattern)
}
// Lazy haptic - checks for Telegram SDK on each call
const haptic: PlatformHaptic = {
impact: (style: HapticStyle) => {
const tg = getTelegramWebApp()
if (tg?.HapticFeedback) {
tg.HapticFeedback.impactOccurred(style)
} else {
vibrate(vibrationPatterns[style])
}
},
notification: (type: HapticNotification) => {
const tg = getTelegramWebApp()
if (tg?.HapticFeedback) {
tg.HapticFeedback.notificationOccurred(type)
} else {
vibrate(vibrationPatterns[type])
}
},
selection: () => {
const tg = getTelegramWebApp()
if (tg?.HapticFeedback) {
tg.HapticFeedback.selectionChanged()
} else {
vibrate(vibrationPatterns.selection)
}
}
}
export function usePlatform(): Platform {
const isTelegram = useMemo(() => isTelegramApp(), [])
const isTouch = useMemo(
() => typeof window !== 'undefined' && window.matchMedia('(pointer: coarse)').matches,
[]
)
return {
isTelegram,
isTouch,
haptic
}
}
// Non-hook version for use outside React components
export function getPlatform(): Platform {
const isTouch = typeof window !== 'undefined' && window.matchMedia('(pointer: coarse)').matches
return {
isTelegram: isTelegramApp(),
isTouch,
haptic
}
}