diff --git a/src/assets/img/devices/firetv.svg b/src/assets/img/devices/firetv.svg
new file mode 100644
index 0000000000..b7348a3bd7
--- /dev/null
+++ b/src/assets/img/devices/firetv.svg
@@ -0,0 +1 @@
+
diff --git a/src/components/apphost.js b/src/components/apphost.js
index ce88435a50..0693663f3c 100644
--- a/src/components/apphost.js
+++ b/src/components/apphost.js
@@ -13,6 +13,7 @@ const BrowserName = {
tizen: 'Samsung Smart TV',
web0s: 'LG Smart TV',
titanos: 'Titan OS',
+ vega: 'Vega OS',
operaTv: 'Opera TV',
xboxOne: 'Xbox One',
ps4: 'Sony PS4',
diff --git a/src/scripts/browser.d.ts b/src/scripts/browser.d.ts
index 3d211441ce..fc24fae03a 100644
--- a/src/scripts/browser.d.ts
+++ b/src/scripts/browser.d.ts
@@ -21,6 +21,7 @@ declare namespace browser {
export let animate: boolean;
export let hisense: boolean;
export let tizen: boolean;
+ export let vega: boolean;
export let vidaa: boolean;
export let web0s: boolean;
export let titanos: boolean;
diff --git a/src/scripts/browser.js b/src/scripts/browser.js
index 0539cd4371..b930f29706 100644
--- a/src/scripts/browser.js
+++ b/src/scripts/browser.js
@@ -235,10 +235,10 @@ const uaMatch = function (ua) {
}
return {
- browser: browser,
- version: version,
+ browser,
+ version,
platform: platformMatch[0] || '',
- versionMajor: versionMajor
+ versionMajor
};
};
@@ -283,10 +283,11 @@ export const detectBrowser = (userAgent = navigator.userAgent) => {
browser.animate = typeof document !== 'undefined' && document.documentElement.animate != null;
browser.hisense = normalizedUA.includes('hisense');
browser.tizen = normalizedUA.includes('tizen') || window.tizen != null;
+ browser.vega = normalizedUA.includes('kepler');
browser.vidaa = normalizedUA.includes('vidaa');
browser.web0s = isWeb0s(normalizedUA);
- browser.tv = browser.ps4 || browser.xboxOne || isTv(normalizedUA);
+ browser.tv = browser.ps4 || browser.vega || browser.xboxOne || isTv(normalizedUA);
browser.operaTv = browser.tv && normalizedUA.includes('opr/');
browser.edgeUwp = (browser.edge || browser.edgeChromium) && (normalizedUA.includes('msapphost') || normalizedUA.includes('webview'));
@@ -305,9 +306,15 @@ export const detectBrowser = (userAgent = navigator.userAgent) => {
delete browser.chrome;
delete browser.safari;
} else if (browser.titanos) {
- // UserAgent string contains 'Opr' and 'Safari', but we only want 'titanos' to be true
+ // UserAgent string contains 'Opr' and 'Safari', but we only want 'titanos' to be true
delete browser.operaTv;
delete browser.safari;
+ } else if (browser.vega) {
+ // UserAgent string contains 'Chrome' and 'Safari', but we only want 'vega' to be true
+ delete browser.chrome;
+ delete browser.safari;
+ // UserAgent string contains 'Mobile Chrome', but it is a TV
+ delete browser.mobile;
} else {
browser.orsay = normalizedUA.includes('smarthub');
}
diff --git a/src/scripts/browser.test.ts b/src/scripts/browser.test.ts
index 96b9fe8d54..a86f473618 100644
--- a/src/scripts/browser.test.ts
+++ b/src/scripts/browser.test.ts
@@ -3,7 +3,7 @@ import { describe, expect, it } from 'vitest';
import { detectBrowser } from './browser';
describe('Browser', () => {
- it('should identify TitanOS devices', async () => {
+ it('should identify TitanOS devices', () => {
// Ref: https://docs.titanos.tv/user-agents-specifications
// Philips example
let browser = detectBrowser('Mozilla/5.0 (Linux armv7l) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.4147.62 Safari/537.36 OPR/46.0.2207.0 OMI/4.24, TV_NT72690_2025_4K / (Philips, , wired) CE-HTML/1.0 NETTV/4.6.0.8 SignOn/2.0 SmartTvA/5.0.0 TitanOS/3.0 en Ginga');
@@ -20,7 +20,17 @@ describe('Browser', () => {
expect(browser.tv).toBe(true);
});
- it('should identify Xbox devices', async () => {
+ it('should identify Vega devices', () => {
+ // Ref: https://developer.amazon.com/docs/vega/0.21/webview-development-best-practices-tv.html#avoid-relying-on-the-useragent
+ const browser = detectBrowser('Mozilla/5.0 (Linux; Kepler 1.1; AFTCA002 user/1234; wv) AppleWebKit/537.36 (KHTML, like Gecko) Mobile Chrome/130.0.6723.192 Safari/537.36');
+ expect(browser.vega).toBe(true);
+ expect(browser.chrome).toBeFalsy();
+ expect(browser.safari).toBeFalsy();
+ expect(browser.mobile).toBeFalsy();
+ expect(browser.tv).toBe(true);
+ });
+
+ it('should identify Xbox devices', () => {
const browser = detectBrowser('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0 WebView2 Xbox');
expect(browser.xboxOne).toBe(true);
expect(browser.tv).toBe(true);
diff --git a/src/utils/image.ts b/src/utils/image.ts
index 60d10798e2..cf5edc60f6 100644
--- a/src/utils/image.ts
+++ b/src/utils/image.ts
@@ -33,6 +33,8 @@ function getWebDeviceIcon(browser: string | null | undefined) {
return BASE_DEVICE_IMAGE_URL + 'msie.svg';
case 'Titan OS':
return BASE_DEVICE_IMAGE_URL + 'titanos.svg';
+ case 'Vega OS':
+ return BASE_DEVICE_IMAGE_URL + 'firetv.svg';
default:
return BASE_DEVICE_IMAGE_URL + 'html5.svg';
}