Skip to content

Commit

Permalink
Merge pull request #929 from decentraland/feat/add-advanced-ua-probing
Browse files Browse the repository at this point in the history
feat: Add advanced UA probing
  • Loading branch information
LautaroPetaccio authored Oct 11, 2024
2 parents 4715f20 + 82be9e6 commit 94cd9ce
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 12 deletions.
86 changes: 86 additions & 0 deletions src/hooks/useAdvancedUserAgentData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// TODO(2fd): add Docs, set as good practice
import { useState } from 'react'

import { UAParser } from 'ua-parser-js'
// @ts-expect-error: missing types
// eslint-disable-next-line import/no-unresolved
import { isAppleSilicon } from 'ua-parser-js/helpers'

import useAsyncEffect from './useAsyncEffect'
const DEFAULT_VALUE = 'Unknown'

export type AdvancedNavigatorUAData = {
browser: {
name: string
version: string
}
engine: {
name: string
version: string
}
os: {
name: string
version: string
}
cpu: {
architecture: string
}
mobile: boolean
}

/**
* extract or infer the [UserAgentData](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/userAgentData)
* that is an object which can be used to access the User-Agent Client Hints API.
*/
export default function useAdvancedUserAgentData(): [
boolean,
AdvancedNavigatorUAData | undefined
] {
const [isLoading, setLoading] = useState(true)
const [data, setData] = useState<AdvancedNavigatorUAData>()

useAsyncEffect(async () => {
setLoading(true)
const ua = new UAParser(navigator.userAgent)
const uaData = ua.getResult()
const browser = {
name: uaData.browser.name ?? DEFAULT_VALUE,
version: uaData.browser.version ?? DEFAULT_VALUE,
}
const engine = {
name: uaData.engine.name ?? DEFAULT_VALUE,
version: uaData.engine.version ?? DEFAULT_VALUE,
}
const [osData, cpuData] = await Promise.all([
ua.getOS().withClientHints(),
ua.getCPU().withClientHints(),
])

const os = {
name: osData.name ?? DEFAULT_VALUE,
version: osData.version ?? DEFAULT_VALUE,
}

let architecture: string
if (!cpuData.architecture) {
architecture =
os.name === 'macOS' && isAppleSilicon(ua) ? 'arm64' : 'Unknown'
} else {
architecture = cpuData.architecture
}

setData({
browser,
engine,
os,
cpu: {
architecture,
},
mobile: ua.getDevice().is('mobile'),
})

setLoading(false)
}, [])

return [isLoading, data]
}
12 changes: 0 additions & 12 deletions src/hooks/useUserAgentData.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// TODO(2fd): add Docs, set as good practice
import { useEffect, useMemo, useState } from 'react'

import { UAParser } from 'ua-parser-js'
Expand All @@ -13,7 +12,6 @@ export type NavigatorUAData = {
brands: Brand[]
mobile: boolean
platform: string
cpu: string
}

export type Brand = {
Expand All @@ -25,7 +23,6 @@ const defaultGlobalValue: NavigatorUAData = {
brands: [],
mobile: false,
platform: 'Unknown',
cpu: 'Unknown',
}

const getUserAgentData = once((): NavigatorUAData => {
Expand All @@ -50,17 +47,8 @@ const getUserAgentData = once((): NavigatorUAData => {
})
}

let architecture
if (!ua.cpu.architecture) {
architecture =
ua.os.name === 'Mac OS' && isAppleSilicon(ua) ? 'arm64' : 'Unknown'
} else {
architecture = ua.cpu.architecture
}

return {
platform: ua.os.name ?? defaultGlobalValue.platform,
cpu: architecture,
mobile: isMobile(),
brands,
}
Expand Down

0 comments on commit 94cd9ce

Please sign in to comment.