mirror of
https://github.com/wu736139669/hapi.git
synced 2026-08-08 07:17:39 +00:00
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.
93 lines
2.5 KiB
TypeScript
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
|
|
}
|
|
}
|