Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 32 additions & 1 deletion apps/site/hooks/react-client/useDetectOS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,37 @@ type UserOSState = {
architecture: Architecture | '';
};

// taken from https://github.com/faisalman/ua-parser-js/issues/732#issue-2348848266
function isAppleSilicon() {
try {
// Best guess if the device uses Apple Silicon: https://stackoverflow.com/a/65412357
const webglContext = document.createElement('canvas').getContext('webgl');
if (webglContext == null) {
return false;
}
const debugInfo = webglContext.getExtension('WEBGL_debug_renderer_info');
const renderer =
(debugInfo &&
webglContext.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL)) ||
'';
if (renderer.match(/Apple/) && !renderer.match(/Apple GPU/)) {
return true;
}

if (
webglContext
.getSupportedExtensions()
?.includes('WEBGL_compressed_texture_s3tc_srgb')
) {
return true;
}
} catch {
/**/
}

return false;
}

Comment on lines +18 to +48
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, this approach isn't the one the authors of that library ended up going with

Suggested change
// taken from https://github.com/faisalman/ua-parser-js/issues/732#issue-2348848266
function isAppleSilicon() {
try {
// Best guess if the device uses Apple Silicon: https://stackoverflow.com/a/65412357
const webglContext = document.createElement('canvas').getContext('webgl');
if (webglContext == null) {
return false;
}
const debugInfo = webglContext.getExtension('WEBGL_debug_renderer_info');
const renderer =
(debugInfo &&
webglContext.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL)) ||
'';
if (renderer.match(/Apple/) && !renderer.match(/Apple GPU/)) {
return true;
}
if (
webglContext
.getSupportedExtensions()
?.includes('WEBGL_compressed_texture_s3tc_srgb')
) {
return true;
}
} catch {
/**/
}
return false;
}
// Ref: https://github.com/faisalman/ua-parser-js/commit/c391d8a73c1a030c24845bc191b021bfb6cba256
function isAppleSilicon() {
try {
const canvas = document.createElement('canvas');
const webgl = canvas.getContext('webgl2') || canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
const debug = webgl.getExtension('WEBGL_debug_renderer_info');
const renderer = webgl.getParameter(debug.UNMASKED_RENDERER_WEBGL);
if (renderer.match(/apple m\d/i)) {
return true;
}
} catch {
return false;
}
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure, i can pull in that approach if it's better.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

more importantly, ua-parser-js is AGPL, and as far as I know the strong copy-left would prohibit MIT usage

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When that is the only issue left, I'll reach out and see if I can get written permission to consider the snippet MIT.

const useDetectOS = () => {
const [userOSState, setUserOSState] = useState<UserOSState>({
os: 'LOADING',
Expand All @@ -41,7 +72,7 @@ const useDetectOS = () => {
// If there is no getHighEntropyValues API on the Browser or it failed to resolve
// we attempt to fallback to what the User Agent indicates
bitness = uaIndicates64 ? '64' : '32',
architecture = 'x86',
architecture = isAppleSilicon() ? 'arm' : 'x86',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a fan of "platform specific" workarounds. + We are literally creating an element on the page, that is breaking the "React" bubble. I'm not a fan of using API's outside of React (window/globals/etc) and we usually only use with Hooks. If you see the only window. API we have is on an explicit hook for watchMedia (https://github.com/search?q=repo%3Anodejs%2Fnodejs.org+window.&type=code)

}) => {
setUserOSState(current => ({
...current,
Expand Down
Loading