2020-07-29 10:04:55 +01:00
|
|
|
function isTv() {
|
|
|
|
// This is going to be really difficult to get right
|
|
|
|
const userAgent = navigator.userAgent.toLowerCase();
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2021-12-19 09:54:39 +01:00
|
|
|
// The OculusBrowsers userAgent also has the samsungbrowser defined but is not a tv.
|
|
|
|
if (userAgent.indexOf('oculusbrowser') !== -1) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-07-29 10:04:55 +01:00
|
|
|
if (userAgent.indexOf('tv') !== -1) {
|
|
|
|
return true;
|
2019-01-10 15:39:37 +03:00
|
|
|
}
|
|
|
|
|
2020-07-29 10:04:55 +01:00
|
|
|
if (userAgent.indexOf('samsungbrowser') !== -1) {
|
|
|
|
return true;
|
2019-01-10 15:39:37 +03:00
|
|
|
}
|
|
|
|
|
2020-07-29 10:04:55 +01:00
|
|
|
if (userAgent.indexOf('viera') !== -1) {
|
|
|
|
return true;
|
|
|
|
}
|
2019-01-10 15:39:37 +03:00
|
|
|
|
2022-10-06 01:13:06 -04:00
|
|
|
return isWeb0s();
|
2021-07-03 17:13:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
function isWeb0s() {
|
|
|
|
const userAgent = navigator.userAgent.toLowerCase();
|
2021-09-16 16:13:29 +02:00
|
|
|
|
2022-10-06 01:13:06 -04:00
|
|
|
return userAgent.indexOf('netcast') !== -1
|
|
|
|
|| userAgent.indexOf('web0s') !== -1;
|
2020-07-29 10:04:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
function isMobile(userAgent) {
|
|
|
|
const terms = [
|
|
|
|
'mobi',
|
|
|
|
'ipad',
|
|
|
|
'iphone',
|
|
|
|
'ipod',
|
|
|
|
'silk',
|
|
|
|
'gt-p1000',
|
|
|
|
'nexus 7',
|
|
|
|
'kindle fire',
|
|
|
|
'opera mini'
|
|
|
|
];
|
|
|
|
|
|
|
|
const lower = userAgent.toLowerCase();
|
|
|
|
|
|
|
|
for (let i = 0, length = terms.length; i < length; i++) {
|
|
|
|
if (lower.indexOf(terms[i]) !== -1) {
|
2019-01-10 15:39:37 +03:00
|
|
|
return true;
|
|
|
|
}
|
2020-07-29 10:04:55 +01:00
|
|
|
}
|
2019-01-10 15:39:37 +03:00
|
|
|
|
2020-07-29 10:04:55 +01:00
|
|
|
return false;
|
|
|
|
}
|
2019-01-10 15:39:37 +03:00
|
|
|
|
2020-07-29 10:04:55 +01:00
|
|
|
function hasKeyboard(browser) {
|
|
|
|
if (browser.touch) {
|
|
|
|
return true;
|
2019-01-10 15:39:37 +03:00
|
|
|
}
|
|
|
|
|
2020-07-29 10:04:55 +01:00
|
|
|
if (browser.xboxOne) {
|
|
|
|
return true;
|
2019-01-10 15:39:37 +03:00
|
|
|
}
|
|
|
|
|
2020-07-29 10:04:55 +01:00
|
|
|
if (browser.ps4) {
|
|
|
|
return true;
|
|
|
|
}
|
2019-01-10 15:39:37 +03:00
|
|
|
|
2020-07-29 10:04:55 +01:00
|
|
|
if (browser.edgeUwp) {
|
|
|
|
// This is OK for now, but this won't always be true
|
|
|
|
// Should we use this?
|
|
|
|
// https://gist.github.com/wagonli/40d8a31bd0d6f0dd7a5d
|
|
|
|
return true;
|
|
|
|
}
|
2019-01-10 15:39:37 +03:00
|
|
|
|
2022-10-06 01:13:06 -04:00
|
|
|
return !!browser.tv;
|
2020-07-29 10:04:55 +01:00
|
|
|
}
|
2019-01-10 15:39:37 +03:00
|
|
|
|
2020-07-29 10:04:55 +01:00
|
|
|
function iOSversion() {
|
|
|
|
// MacIntel: Apple iPad Pro 11 iOS 13.1
|
|
|
|
if (/iP(hone|od|ad)|MacIntel/.test(navigator.platform)) {
|
2020-08-31 15:19:06 -04:00
|
|
|
const tests = [
|
|
|
|
// Original test for getting full iOS version number in iOS 2.0+
|
|
|
|
/OS (\d+)_(\d+)_?(\d+)?/,
|
|
|
|
// Test for iPads running iOS 13+ that can only get the major OS version
|
|
|
|
/Version\/(\d+)/
|
|
|
|
];
|
|
|
|
for (const test of tests) {
|
|
|
|
const matches = (navigator.appVersion).match(test);
|
|
|
|
if (matches) {
|
|
|
|
return [
|
|
|
|
parseInt(matches[1], 10),
|
|
|
|
parseInt(matches[2] || 0, 10),
|
|
|
|
parseInt(matches[3] || 0, 10)
|
|
|
|
];
|
|
|
|
}
|
|
|
|
}
|
2020-07-29 10:04:55 +01:00
|
|
|
}
|
2020-08-31 15:19:06 -04:00
|
|
|
return [];
|
2020-07-29 10:04:55 +01:00
|
|
|
}
|
|
|
|
|
2021-09-14 13:52:32 +03:00
|
|
|
function web0sVersion(browser) {
|
|
|
|
// Detect webOS version by web engine version
|
|
|
|
|
|
|
|
if (browser.chrome) {
|
2021-09-18 01:27:24 +03:00
|
|
|
const userAgent = navigator.userAgent.toLowerCase();
|
|
|
|
|
|
|
|
if (userAgent.indexOf('netcast') !== -1) {
|
|
|
|
// The built-in browser (NetCast) may have a version that doesn't correspond to the actual web engine
|
2021-09-25 13:36:55 +03:00
|
|
|
// Since there is no reliable way to detect webOS version, we return an undefined version
|
2021-09-18 01:27:24 +03:00
|
|
|
|
2021-09-25 13:36:55 +03:00
|
|
|
console.warn('Unable to detect webOS version - NetCast');
|
2021-09-18 01:27:24 +03:00
|
|
|
|
2021-09-25 13:36:55 +03:00
|
|
|
return undefined;
|
2021-09-18 01:27:24 +03:00
|
|
|
}
|
|
|
|
|
2021-09-25 13:36:55 +03:00
|
|
|
// The next is only valid for the app
|
2021-09-18 01:27:24 +03:00
|
|
|
|
2021-09-14 13:52:32 +03:00
|
|
|
if (browser.versionMajor >= 79) {
|
|
|
|
return 6;
|
|
|
|
} else if (browser.versionMajor >= 68) {
|
|
|
|
return 5;
|
|
|
|
} else if (browser.versionMajor >= 53) {
|
|
|
|
return 4;
|
|
|
|
} else if (browser.versionMajor >= 38) {
|
|
|
|
return 3;
|
|
|
|
} else if (browser.versionMajor >= 34) {
|
|
|
|
// webOS 2 browser
|
|
|
|
return 2;
|
|
|
|
} else if (browser.versionMajor >= 26) {
|
|
|
|
// webOS 1 browser
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
} else if (browser.versionMajor >= 538) {
|
|
|
|
// webOS 2 app
|
|
|
|
return 2;
|
|
|
|
} else if (browser.versionMajor >= 537) {
|
|
|
|
// webOS 1 app
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2021-09-25 13:36:55 +03:00
|
|
|
console.error('Unable to detect webOS version');
|
2021-09-14 13:52:32 +03:00
|
|
|
|
2021-09-25 13:36:55 +03:00
|
|
|
return undefined;
|
2021-09-14 13:52:32 +03:00
|
|
|
}
|
|
|
|
|
2020-07-29 10:04:55 +01:00
|
|
|
let _supportsCssAnimation;
|
|
|
|
let _supportsCssAnimationWithPrefix;
|
|
|
|
function supportsCssAnimation(allowPrefix) {
|
|
|
|
// TODO: Assess if this is still needed, as all of our targets should natively support CSS animations.
|
2023-08-18 22:46:34 -03:00
|
|
|
if (allowPrefix && (_supportsCssAnimationWithPrefix === true || _supportsCssAnimationWithPrefix === false)) {
|
|
|
|
return _supportsCssAnimationWithPrefix;
|
|
|
|
}
|
|
|
|
if (_supportsCssAnimation === true || _supportsCssAnimation === false) {
|
|
|
|
return _supportsCssAnimation;
|
2019-01-10 15:39:37 +03:00
|
|
|
}
|
|
|
|
|
2020-07-29 10:04:55 +01:00
|
|
|
let animation = false;
|
|
|
|
const domPrefixes = ['Webkit', 'O', 'Moz'];
|
|
|
|
const elm = document.createElement('div');
|
2019-01-10 15:39:37 +03:00
|
|
|
|
2020-07-29 10:04:55 +01:00
|
|
|
if (elm.style.animationName !== undefined) {
|
|
|
|
animation = true;
|
2019-01-10 15:39:37 +03:00
|
|
|
}
|
|
|
|
|
2020-07-29 10:04:55 +01:00
|
|
|
if (animation === false && allowPrefix) {
|
2023-05-04 11:27:15 -04:00
|
|
|
for (const domPrefix of domPrefixes) {
|
|
|
|
if (elm.style[domPrefix + 'AnimationName'] !== undefined) {
|
2020-07-29 10:04:55 +01:00
|
|
|
animation = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2019-01-10 15:39:37 +03:00
|
|
|
}
|
|
|
|
|
2020-07-29 10:04:55 +01:00
|
|
|
if (allowPrefix) {
|
|
|
|
_supportsCssAnimationWithPrefix = animation;
|
|
|
|
return _supportsCssAnimationWithPrefix;
|
|
|
|
} else {
|
|
|
|
_supportsCssAnimation = animation;
|
|
|
|
return _supportsCssAnimation;
|
2019-01-10 15:39:37 +03:00
|
|
|
}
|
2020-07-29 10:04:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
const uaMatch = function (ua) {
|
|
|
|
ua = ua.toLowerCase();
|
|
|
|
|
2023-08-11 00:49:22 -03:00
|
|
|
const match = /(chrome)[ /]([\w.]+)/.exec(ua)
|
|
|
|
|| /(edg)[ /]([\w.]+)/.exec(ua)
|
2023-03-29 00:38:22 -04:00
|
|
|
|| /(edga)[ /]([\w.]+)/.exec(ua)
|
|
|
|
|| /(edgios)[ /]([\w.]+)/.exec(ua)
|
|
|
|
|| /(edge)[ /]([\w.]+)/.exec(ua)
|
|
|
|
|| /(opera)[ /]([\w.]+)/.exec(ua)
|
|
|
|
|| /(opr)[ /]([\w.]+)/.exec(ua)
|
|
|
|
|| /(safari)[ /]([\w.]+)/.exec(ua)
|
|
|
|
|| /(firefox)[ /]([\w.]+)/.exec(ua)
|
|
|
|
|| ua.indexOf('compatible') < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua)
|
|
|
|
|| [];
|
2020-07-29 10:04:55 +01:00
|
|
|
|
2021-01-26 22:49:01 -05:00
|
|
|
const versionMatch = /(version)[ /]([\w.]+)/.exec(ua);
|
2020-07-29 10:04:55 +01:00
|
|
|
|
2023-03-29 00:38:22 -04:00
|
|
|
let platform_match = /(ipad)/.exec(ua)
|
|
|
|
|| /(iphone)/.exec(ua)
|
|
|
|
|| /(windows)/.exec(ua)
|
|
|
|
|| /(android)/.exec(ua)
|
|
|
|
|| [];
|
2020-07-29 10:04:55 +01:00
|
|
|
|
|
|
|
let browser = match[1] || '';
|
|
|
|
|
|
|
|
if (browser === 'edge') {
|
|
|
|
platform_match = [''];
|
2019-01-10 15:39:37 +03:00
|
|
|
}
|
|
|
|
|
2020-07-29 10:04:55 +01:00
|
|
|
if (browser === 'opr') {
|
|
|
|
browser = 'opera';
|
2020-05-14 23:25:22 +02:00
|
|
|
}
|
2019-01-10 15:39:37 +03:00
|
|
|
|
2020-07-29 10:04:55 +01:00
|
|
|
let version;
|
|
|
|
if (versionMatch && versionMatch.length > 2) {
|
|
|
|
version = versionMatch[2];
|
2019-01-10 15:39:37 +03:00
|
|
|
}
|
|
|
|
|
2020-07-29 10:04:55 +01:00
|
|
|
version = version || match[2] || '0';
|
2019-01-10 15:39:37 +03:00
|
|
|
|
2023-03-09 00:01:05 -05:00
|
|
|
let versionMajor = parseInt(version.split('.')[0], 10);
|
2019-01-10 15:39:37 +03:00
|
|
|
|
2020-07-29 10:04:55 +01:00
|
|
|
if (isNaN(versionMajor)) {
|
|
|
|
versionMajor = 0;
|
2019-01-10 15:39:37 +03:00
|
|
|
}
|
|
|
|
|
2020-07-29 10:04:55 +01:00
|
|
|
return {
|
|
|
|
browser: browser,
|
|
|
|
version: version,
|
|
|
|
platform: platform_match[0] || '',
|
|
|
|
versionMajor: versionMajor
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
const userAgent = navigator.userAgent;
|
|
|
|
|
|
|
|
const matched = uaMatch(userAgent);
|
|
|
|
const browser = {};
|
|
|
|
|
|
|
|
if (matched.browser) {
|
|
|
|
browser[matched.browser] = true;
|
|
|
|
browser.version = matched.version;
|
|
|
|
browser.versionMajor = matched.versionMajor;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (matched.platform) {
|
|
|
|
browser[matched.platform] = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
browser.edgeChromium = browser.edg || browser.edga || browser.edgios;
|
|
|
|
|
|
|
|
if (!browser.chrome && !browser.edgeChromium && !browser.edge && !browser.opera && userAgent.toLowerCase().indexOf('webkit') !== -1) {
|
|
|
|
browser.safari = true;
|
|
|
|
}
|
|
|
|
|
2021-03-01 14:19:04 +00:00
|
|
|
browser.osx = userAgent.toLowerCase().indexOf('mac os x') !== -1;
|
2020-08-31 15:19:06 -04:00
|
|
|
|
|
|
|
// This is a workaround to detect iPads on iOS 13+ that report as desktop Safari
|
|
|
|
// This may break in the future if Apple releases a touchscreen Mac
|
|
|
|
// https://forums.developer.apple.com/thread/119186
|
|
|
|
if (browser.osx && !browser.iphone && !browser.ipod && !browser.ipad && navigator.maxTouchPoints > 1) {
|
|
|
|
browser.ipad = true;
|
|
|
|
}
|
|
|
|
|
2020-07-29 10:04:55 +01:00
|
|
|
if (userAgent.toLowerCase().indexOf('playstation 4') !== -1) {
|
|
|
|
browser.ps4 = true;
|
|
|
|
browser.tv = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isMobile(userAgent)) {
|
|
|
|
browser.mobile = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (userAgent.toLowerCase().indexOf('xbox') !== -1) {
|
|
|
|
browser.xboxOne = true;
|
|
|
|
browser.tv = true;
|
|
|
|
}
|
|
|
|
browser.animate = typeof document !== 'undefined' && document.documentElement.animate != null;
|
2023-01-22 14:08:05 -05:00
|
|
|
browser.hisense = userAgent.toLowerCase().includes('hisense');
|
2020-08-25 10:12:35 +09:00
|
|
|
browser.tizen = userAgent.toLowerCase().indexOf('tizen') !== -1 || window.tizen != null;
|
2023-01-22 14:08:05 -05:00
|
|
|
browser.vidaa = userAgent.toLowerCase().includes('vidaa');
|
2021-07-03 17:13:37 +02:00
|
|
|
browser.web0s = isWeb0s();
|
2020-07-29 10:04:55 +01:00
|
|
|
browser.edgeUwp = browser.edge && (userAgent.toLowerCase().indexOf('msapphost') !== -1 || userAgent.toLowerCase().indexOf('webview') !== -1);
|
|
|
|
|
2021-09-14 13:52:32 +03:00
|
|
|
if (browser.web0s) {
|
|
|
|
browser.web0sVersion = web0sVersion(browser);
|
|
|
|
} else if (browser.tizen) {
|
2021-01-05 20:20:45 +03:00
|
|
|
// UserAgent string contains 'Safari' and 'safari' is set by matched browser, but we only want 'tizen' to be true
|
|
|
|
delete browser.safari;
|
|
|
|
|
2020-07-29 10:04:55 +01:00
|
|
|
const v = (navigator.appVersion).match(/Tizen (\d+).(\d+)/);
|
2023-03-09 00:01:05 -05:00
|
|
|
browser.tizenVersion = parseInt(v[1], 10);
|
2021-09-14 13:52:32 +03:00
|
|
|
} else {
|
|
|
|
browser.orsay = userAgent.toLowerCase().indexOf('smarthub') !== -1;
|
2020-07-29 10:04:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (browser.edgeUwp) {
|
|
|
|
browser.edge = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
browser.tv = isTv();
|
|
|
|
browser.operaTv = browser.tv && userAgent.toLowerCase().indexOf('opr/') !== -1;
|
|
|
|
|
|
|
|
if (browser.mobile || browser.tv) {
|
|
|
|
browser.slow = true;
|
|
|
|
}
|
|
|
|
|
2022-10-03 14:22:02 -04:00
|
|
|
/* eslint-disable-next-line compat/compat */
|
|
|
|
if (typeof document !== 'undefined' && ('ontouchstart' in window) || (navigator.maxTouchPoints > 0)) {
|
|
|
|
browser.touch = true;
|
2020-07-29 10:04:55 +01:00
|
|
|
}
|
2019-01-10 15:39:37 +03:00
|
|
|
|
2020-07-29 10:04:55 +01:00
|
|
|
browser.keyboard = hasKeyboard(browser);
|
|
|
|
browser.supportsCssAnimation = supportsCssAnimation;
|
2019-01-10 15:39:37 +03:00
|
|
|
|
2020-07-29 10:04:55 +01:00
|
|
|
browser.iOS = browser.ipad || browser.iphone || browser.ipod;
|
2019-01-10 15:39:37 +03:00
|
|
|
|
2020-07-29 10:04:55 +01:00
|
|
|
if (browser.iOS) {
|
|
|
|
browser.iOSVersion = iOSversion();
|
2019-11-14 16:29:33 +03:00
|
|
|
|
2020-07-29 10:04:55 +01:00
|
|
|
if (browser.iOSVersion && browser.iOSVersion.length >= 2) {
|
|
|
|
browser.iOSVersion = browser.iOSVersion[0] + (browser.iOSVersion[1] / 10);
|
2019-01-10 15:39:37 +03:00
|
|
|
}
|
2020-07-29 10:04:55 +01:00
|
|
|
}
|
2019-01-10 15:39:37 +03:00
|
|
|
|
2020-07-29 10:04:55 +01:00
|
|
|
export default browser;
|