@dcl/hooks 1.6.1-20260826143734.commit-05ecd74 → 2.0.1-20261005192007.commit-377b5c0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { AdvancedNavigatorUAData } from "./useAdvancedUserAgentData.type";
|
|
2
2
|
/** @internal Reset module-level cache — only for testing. */
|
|
3
|
-
|
|
3
|
+
declare function resetUserAgentCache(): void;
|
|
4
4
|
/**
|
|
5
5
|
* extract or infer the [UserAgentData](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/userAgentData)
|
|
6
6
|
* that is an object which can be used to access the User-Agent Client Hints API.
|
|
7
7
|
*/
|
|
8
|
-
|
|
8
|
+
declare function useAdvancedUserAgentData(): [
|
|
9
9
|
boolean,
|
|
10
10
|
AdvancedNavigatorUAData | undefined
|
|
11
11
|
];
|
|
12
|
+
export { resetUserAgentCache, useAdvancedUserAgentData };
|
|
@@ -3,6 +3,10 @@ import { UAParser } from "ua-parser-js";
|
|
|
3
3
|
import { isAppleSilicon } from "ua-parser-js/device-detection";
|
|
4
4
|
import { useAsyncEffect } from "../useAsyncEffect";
|
|
5
5
|
const DEFAULT_VALUE = "Unknown";
|
|
6
|
+
// Upper bound for the Client Hints round trip. `getHighEntropyValues` can
|
|
7
|
+
// reject (permissions policy, blocked by the browser) or never settle, and the
|
|
8
|
+
// hook must still leave `isLoading` in a bounded time.
|
|
9
|
+
const CLIENT_HINTS_TIMEOUT_MS = 1500;
|
|
6
10
|
// Module-level cache: the user agent never changes during a session, so once
|
|
7
11
|
// resolved the result is reused across component remounts (React StrictMode,
|
|
8
12
|
// Suspense boundaries, lazy chunks, etc.). Without this cache every remount
|
|
@@ -10,8 +14,48 @@ const DEFAULT_VALUE = "Unknown";
|
|
|
10
14
|
// and causing a visible flash in any UI that depends on the detected OS.
|
|
11
15
|
let _cachedData;
|
|
12
16
|
let _cacheResolved = false;
|
|
17
|
+
/**
|
|
18
|
+
* Resolves with the value of `promise`, or `undefined` if it rejects or does
|
|
19
|
+
* not settle within `ms`. The timer is always cleared.
|
|
20
|
+
*/
|
|
21
|
+
async function settleWithin(promise, ms) {
|
|
22
|
+
let timer;
|
|
23
|
+
const timeout = new Promise((resolve) => {
|
|
24
|
+
timer = setTimeout(() => resolve(undefined), ms);
|
|
25
|
+
});
|
|
26
|
+
try {
|
|
27
|
+
return await Promise.race([promise, timeout]);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
finally {
|
|
33
|
+
clearTimeout(timer);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
async function readWithClientHints(ua, uaResult) {
|
|
37
|
+
const [uaResultWithClientHints, os, cpu] = await Promise.all([
|
|
38
|
+
uaResult.withClientHints(),
|
|
39
|
+
ua.getOS().withClientHints(),
|
|
40
|
+
ua.getCPU().withClientHints(),
|
|
41
|
+
]);
|
|
42
|
+
return {
|
|
43
|
+
os,
|
|
44
|
+
architecture: cpu.architecture,
|
|
45
|
+
uaResult: uaResultWithClientHints,
|
|
46
|
+
hintsBrowserName: uaResultWithClientHints.browser.name,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
// A fresh result: `uaResult` may still be updated by Client Hints that settle later.
|
|
50
|
+
function readFromUserAgent(ua) {
|
|
51
|
+
return {
|
|
52
|
+
os: ua.getOS(),
|
|
53
|
+
architecture: ua.getCPU().architecture,
|
|
54
|
+
uaResult: ua.getResult(),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
13
57
|
/** @internal Reset module-level cache — only for testing. */
|
|
14
|
-
|
|
58
|
+
function resetUserAgentCache() {
|
|
15
59
|
_cachedData = undefined;
|
|
16
60
|
_cacheResolved = false;
|
|
17
61
|
}
|
|
@@ -19,7 +63,7 @@ export function resetUserAgentCache() {
|
|
|
19
63
|
* extract or infer the [UserAgentData](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/userAgentData)
|
|
20
64
|
* that is an object which can be used to access the User-Agent Client Hints API.
|
|
21
65
|
*/
|
|
22
|
-
|
|
66
|
+
function useAdvancedUserAgentData() {
|
|
23
67
|
const [isLoading, setLoading] = useState(!_cacheResolved);
|
|
24
68
|
const [data, setData] = useState(_cachedData);
|
|
25
69
|
useAsyncEffect(async () => {
|
|
@@ -30,33 +74,41 @@ export function useAdvancedUserAgentData() {
|
|
|
30
74
|
}
|
|
31
75
|
setLoading(true);
|
|
32
76
|
const ua = new UAParser(navigator.userAgent);
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
};
|
|
77
|
+
const uaResult = ua.getResult();
|
|
78
|
+
// Browser and engine come from the user-agent string. They are copied before
|
|
79
|
+
// the Client Hints call because `uaResult.withClientHints()` updates `uaResult`
|
|
80
|
+
// in place (and keeps doing so if the hints settle after the timeout).
|
|
38
81
|
const engine = {
|
|
39
|
-
name:
|
|
40
|
-
version:
|
|
82
|
+
name: uaResult.engine.name ?? DEFAULT_VALUE,
|
|
83
|
+
version: uaResult.engine.version ?? DEFAULT_VALUE,
|
|
41
84
|
};
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
85
|
+
const browser = {
|
|
86
|
+
name: uaResult.browser.name ?? DEFAULT_VALUE,
|
|
87
|
+
version: uaResult.browser.version ?? DEFAULT_VALUE,
|
|
88
|
+
};
|
|
89
|
+
// OS and CPU also use Client Hints, which are optional: if they reject or take
|
|
90
|
+
// too long, the user-agent string alone is used.
|
|
91
|
+
const parts = (await settleWithin(readWithClientHints(ua, uaResult), CLIENT_HINTS_TIMEOUT_MS)) ?? readFromUserAgent(ua);
|
|
92
|
+
// Brave sends a Chrome-form user agent. It is told apart by its Client Hints
|
|
93
|
+
// brand or, when the hints are missing, late or rejected, by `navigator.brave`
|
|
94
|
+
// (synchronous in ua-parser-js 2.x although typed as possibly async).
|
|
95
|
+
const featureChecked = ua.getBrowser().withFeatureCheck();
|
|
96
|
+
if (parts.hintsBrowserName === "Brave" || featureChecked.name === "Brave") {
|
|
97
|
+
browser.name = "Brave";
|
|
98
|
+
}
|
|
47
99
|
const os = {
|
|
48
|
-
name:
|
|
49
|
-
version:
|
|
100
|
+
name: parts.os.name ?? DEFAULT_VALUE,
|
|
101
|
+
version: parts.os.version ?? DEFAULT_VALUE,
|
|
50
102
|
};
|
|
51
103
|
let architecture;
|
|
52
|
-
if (!
|
|
104
|
+
if (!parts.architecture) {
|
|
53
105
|
architecture =
|
|
54
|
-
os.name === "macOS" && isAppleSilicon(
|
|
106
|
+
os.name === "macOS" && isAppleSilicon(parts.uaResult)
|
|
55
107
|
? "arm64"
|
|
56
108
|
: "Unknown";
|
|
57
109
|
}
|
|
58
110
|
else {
|
|
59
|
-
architecture =
|
|
111
|
+
architecture = parts.architecture;
|
|
60
112
|
}
|
|
61
113
|
const result = {
|
|
62
114
|
browser,
|
|
@@ -75,4 +127,5 @@ export function useAdvancedUserAgentData() {
|
|
|
75
127
|
}, []);
|
|
76
128
|
return [isLoading, _cachedData ?? data];
|
|
77
129
|
}
|
|
130
|
+
export { resetUserAgentCache, useAdvancedUserAgentData };
|
|
78
131
|
//# sourceMappingURL=useAdvancedUserAgentData.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAdvancedUserAgentData.js","sourceRoot":"","sources":["../../../src/hooks/useAdvancedUserAgentData/useAdvancedUserAgentData.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAChC,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAA;AAE9D,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAClD,MAAM,aAAa,GAAG,SAAS,CAAA;AAE/B,6EAA6E;AAC7E,6EAA6E;AAC7E,6EAA6E;AAC7E,+EAA+E;AAC/E,yEAAyE;AACzE,IAAI,WAAgD,CAAA;AACpD,IAAI,cAAc,GAAG,KAAK,CAAA;
|
|
1
|
+
{"version":3,"file":"useAdvancedUserAgentData.js","sourceRoot":"","sources":["../../../src/hooks/useAdvancedUserAgentData/useAdvancedUserAgentData.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAChC,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAA;AAE9D,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAClD,MAAM,aAAa,GAAG,SAAS,CAAA;AAE/B,0EAA0E;AAC1E,+EAA+E;AAC/E,uDAAuD;AACvD,MAAM,uBAAuB,GAAG,IAAI,CAAA;AAEpC,6EAA6E;AAC7E,6EAA6E;AAC7E,6EAA6E;AAC7E,+EAA+E;AAC/E,yEAAyE;AACzE,IAAI,WAAgD,CAAA;AACpD,IAAI,cAAc,GAAG,KAAK,CAAA;AAY1B;;;GAGG;AACH,KAAK,UAAU,YAAY,CACzB,OAAmB,EACnB,EAAU;IAEV,IAAI,KAAgD,CAAA;IACpD,MAAM,OAAO,GAAG,IAAI,OAAO,CAAY,CAAC,OAAO,EAAE,EAAE;QACjD,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,EAAE,CAAC,CAAA;IAClD,CAAC,CAAC,CAAA;IACF,IAAI,CAAC;QACH,OAAO,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAA;IAC/C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAA;IAClB,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,KAAK,CAAC,CAAA;IACrB,CAAC;AACH,CAAC;AAED,KAAK,UAAU,mBAAmB,CAChC,EAAY,EACZ,QAA6B;IAE7B,MAAM,CAAC,uBAAuB,EAAE,EAAE,EAAE,GAAG,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC3D,QAAQ,CAAC,eAAe,EAAE;QAC1B,EAAE,CAAC,KAAK,EAAE,CAAC,eAAe,EAAE;QAC5B,EAAE,CAAC,MAAM,EAAE,CAAC,eAAe,EAAE;KAC9B,CAAC,CAAA;IACF,OAAO;QACL,EAAE;QACF,YAAY,EAAE,GAAG,CAAC,YAAY;QAC9B,QAAQ,EAAE,uBAAuB;QACjC,gBAAgB,EAAE,uBAAuB,CAAC,OAAO,CAAC,IAAI;KACvD,CAAA;AACH,CAAC;AAED,qFAAqF;AACrF,SAAS,iBAAiB,CAAC,EAAY;IACrC,OAAO;QACL,EAAE,EAAE,EAAE,CAAC,KAAK,EAAE;QACd,YAAY,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,YAAY;QACtC,QAAQ,EAAE,EAAE,CAAC,SAAS,EAAE;KACzB,CAAA;AACH,CAAC;AAED,6DAA6D;AAC7D,SAAS,mBAAmB;IAC1B,WAAW,GAAG,SAAS,CAAA;IACvB,cAAc,GAAG,KAAK,CAAA;AACxB,CAAC;AAED;;;GAGG;AACH,SAAS,wBAAwB;IAI/B,MAAM,CAAC,SAAS,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,CAAC,cAAc,CAAC,CAAA;IACzD,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAC9B,WAAW,CACZ,CAAA;IAED,cAAc,CAAC,KAAK,IAAI,EAAE;QACxB,6DAA6D;QAC7D,wDAAwD;QACxD,IAAI,cAAc,EAAE,CAAC;YACnB,OAAM;QACR,CAAC;QAED,UAAU,CAAC,IAAI,CAAC,CAAA;QAChB,MAAM,EAAE,GAAG,IAAI,QAAQ,CAAC,SAAS,CAAC,SAAS,CAAC,CAAA;QAC5C,MAAM,QAAQ,GAAG,EAAE,CAAC,SAAS,EAAE,CAAA;QAE/B,6EAA6E;QAC7E,gFAAgF;QAChF,uEAAuE;QACvE,MAAM,MAAM,GAAG;YACb,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,IAAI,aAAa;YAC3C,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,OAAO,IAAI,aAAa;SAClD,CAAA;QACD,MAAM,OAAO,GAAG;YACd,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,IAAI,IAAI,aAAa;YAC5C,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,OAAO,IAAI,aAAa;SACnD,CAAA;QAED,+EAA+E;QAC/E,iDAAiD;QACjD,MAAM,KAAK,GACT,CAAC,MAAM,YAAY,CACjB,mBAAmB,CAAC,EAAE,EAAE,QAAQ,CAAC,EACjC,uBAAuB,CACxB,CAAC,IAAI,iBAAiB,CAAC,EAAE,CAAC,CAAA;QAE7B,6EAA6E;QAC7E,+EAA+E;QAC/E,sEAAsE;QACtE,MAAM,cAAc,GAAG,EAAE,CAAC,UAAU,EAAE,CAAC,gBAAgB,EAEtD,CAAA;QACD,IAAI,KAAK,CAAC,gBAAgB,KAAK,OAAO,IAAI,cAAc,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YAC1E,OAAO,CAAC,IAAI,GAAG,OAAO,CAAA;QACxB,CAAC;QAED,MAAM,EAAE,GAAG;YACT,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,IAAI,IAAI,aAAa;YACpC,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,OAAO,IAAI,aAAa;SAC3C,CAAA;QAED,IAAI,YAAoB,CAAA;QACxB,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC;YACxB,YAAY;gBACV,EAAE,CAAC,IAAI,KAAK,OAAO,IAAI,cAAc,CAAC,KAAK,CAAC,QAAQ,CAAC;oBACnD,CAAC,CAAC,OAAO;oBACT,CAAC,CAAC,SAAS,CAAA;QACjB,CAAC;aAAM,CAAC;YACN,YAAY,GAAG,KAAK,CAAC,YAAY,CAAA;QACnC,CAAC;QAED,MAAM,MAAM,GAA4B;YACtC,OAAO;YACP,MAAM;YACN,EAAE;YACF,GAAG,EAAE;gBACH,YAAY;aACb;YACD,MAAM,EAAE,EAAE,CAAC,SAAS,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC;YACnC,MAAM,EAAE,EAAE,CAAC,SAAS,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC;SACpC,CAAA;QAED,WAAW,GAAG,MAAM,CAAA;QACpB,cAAc,GAAG,IAAI,CAAA;QAErB,OAAO,CAAC,MAAM,CAAC,CAAA;QACf,UAAU,CAAC,KAAK,CAAC,CAAA;IACnB,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,OAAO,CAAC,SAAS,EAAE,WAAW,IAAI,IAAI,CAAC,CAAA;AACzC,CAAC;AAED,OAAO,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dcl/hooks",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.1-20261005192007.commit-377b5c0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "esm/index.js",
|
|
6
6
|
"module": "esm/index.js",
|
|
@@ -80,5 +80,5 @@
|
|
|
80
80
|
"<rootDir>/test/setup.ts"
|
|
81
81
|
]
|
|
82
82
|
},
|
|
83
|
-
"commit": "
|
|
83
|
+
"commit": "377b5c0587443779fe91cd52e27e9abfdcd9835a"
|
|
84
84
|
}
|