mirror of
https://gitee.com/wanwujie/sub2api
synced 2026-05-05 13:40:44 +08:00
63 lines
1.7 KiB
TypeScript
63 lines
1.7 KiB
TypeScript
interface NavigatorUADataLike {
|
|
mobile?: boolean
|
|
}
|
|
|
|
interface NavigatorLike {
|
|
userAgent?: string
|
|
platform?: string
|
|
maxTouchPoints?: number
|
|
userAgentData?: NavigatorUADataLike
|
|
}
|
|
|
|
interface MediaQueryResultLike {
|
|
matches: boolean
|
|
}
|
|
|
|
interface DeviceDetectionEnvironment {
|
|
navigator?: NavigatorLike
|
|
matchMedia?: (query: string) => MediaQueryResultLike | null | undefined
|
|
}
|
|
|
|
const MOBILE_UA_RE = /\b(Mobi|Android|iPhone|iPod|Windows Phone|webOS|BlackBerry|IEMobile)\b/i
|
|
const TABLET_UA_RE = /\b(iPad|Tablet)\b/i
|
|
|
|
function matchesQuery(
|
|
matchMedia: DeviceDetectionEnvironment['matchMedia'],
|
|
query: string,
|
|
): boolean {
|
|
try {
|
|
return matchMedia?.(query)?.matches === true
|
|
} catch {
|
|
return false
|
|
}
|
|
}
|
|
|
|
export function detectMobileDevice(env: DeviceDetectionEnvironment = {}): boolean {
|
|
const nav = env.navigator
|
|
if (!nav) return false
|
|
|
|
if (nav.userAgentData?.mobile === true) {
|
|
return true
|
|
}
|
|
|
|
const userAgent = nav.userAgent || ''
|
|
const maxTouchPoints = nav.maxTouchPoints ?? 0
|
|
const isIPadOSDesktopMode = nav.platform === 'MacIntel' && maxTouchPoints > 1
|
|
const isMobileUA = MOBILE_UA_RE.test(userAgent)
|
|
const isTabletUA = TABLET_UA_RE.test(userAgent) || isIPadOSDesktopMode
|
|
const coarsePointer = matchesQuery(env.matchMedia, '(pointer: coarse)')
|
|
const noHover = matchesQuery(env.matchMedia, '(hover: none)')
|
|
const hasTouch = maxTouchPoints > 0
|
|
|
|
return isMobileUA || isTabletUA || (coarsePointer && noHover && hasTouch)
|
|
}
|
|
|
|
export function isMobileDevice(): boolean {
|
|
if (typeof navigator === 'undefined') return false
|
|
|
|
return detectMobileDevice({
|
|
navigator,
|
|
matchMedia: typeof window !== 'undefined' ? window.matchMedia.bind(window) : undefined,
|
|
})
|
|
}
|