UNPKG

twilio-video

Version:

Twilio Video JavaScript Library

161 lines (144 loc) 4.68 kB
/* globals chrome, navigator */ 'use strict'; /** * Check whether the current browser is an Android device. * @returns {boolean} */ function isAndroid() { return /Android/.test(navigator.userAgent); } /** * Detects whether or not a device is an Apple touch screen device. * @returns {boolean} */ function hasTouchScreen() { return !!(navigator && navigator.maxTouchPoints && navigator.maxTouchPoints > 2); } /** * Detects whether or not a device is an iPad. * @returns {boolean} */ function isIpad() { return hasTouchScreen() && window.screen.width >= 744 && (/Macintosh/i.test(navigator.userAgent) || /iPad/.test(navigator.userAgent) || /iPad/.test(navigator.platform)); } /** * Detects whether or not a device is an iPhone. * @returns {boolean} */ function isIphone() { return hasTouchScreen() && window.screen.width <= 476 && (/Macintosh/i.test(navigator.userAgent) || /iPhone/.test(navigator.userAgent) || /iPhone/.test(navigator.platform)); } /** * Check whether the current device is an iOS device. * @returns {boolean} */ function isIOS() { return isIpad() || isIphone(); } /** * Check whether the current browser is a mobile browser * @returns {boolean} */ function isMobile() { return /Mobi/.test(navigator.userAgent); } /** * Check whether the current browser is non-Chromium Edge. * @param {string} browser * @returns {boolean} */ function isNonChromiumEdge(browser) { return browser === 'chrome' && /Edge/.test(navigator.userAgent) && ( typeof chrome === 'undefined' || typeof chrome.runtime === 'undefined' ); } /** * Get the name of the rebranded Chromium browser, if any. Re-branded Chrome's user * agent has the following format: * <source>/<version> (<os>) <engine>/<version> (<engine_name>) Chrome/<version> [Mobile] Safari/<version> * @param browser * @returns {?string} Name of the rebranded Chrome browser, or null if the browser * is either not Chrome or vanilla Chrome. */ function rebrandedChromeBrowser(browser) { // If the browser is not Chrome based, then it is not a rebranded Chrome browser. if (browser !== 'chrome') { return null; } // Latest desktop Brave browser has a "brave" property in navigator. if ('brave' in navigator) { return 'brave'; } // Remove the "(.+)" entries from the user agent thereby retaining only the // <name>[/<version>] entries. const parenthesizedSubstrings = getParenthesizedSubstrings(navigator.userAgent); const nameAndVersions = parenthesizedSubstrings.reduce( (userAgent, substring) => userAgent.replace(substring, ''), navigator.userAgent ); // Extract the potential browser <name>s by ignoring the first two names, which // point to <source> and <engine>. const matches = nameAndVersions.match(/[^\s]+/g) || []; const [/* source */, /* engine */, ...browserNames] = matches.map(nameAndVersion => { return nameAndVersion.split('/')[0].toLowerCase(); }); // Extract the <name> that is not expected to be present in the vanilla Chrome // browser, which indicates the rebranded name (ex: "edg[e]", "electron"). If null, // then this is a vanilla Chrome browser. return browserNames.find(name => { return !['chrome', 'mobile', 'safari'].includes(name); }) || null; } /** * Get the name of the mobile webkit based browser, if any. * @param browser * @returns {?string} Name of the mobile webkit based browser, or null if the browser * is either not webkit based or mobile safari. */ function mobileWebKitBrowser(browser) { if (browser !== 'safari') { return null; } if ('brave' in navigator) { return 'brave'; } return ['edge', 'edg'].find(name => { return navigator.userAgent.toLowerCase().includes(name); }) || null; } /** * Get the top level parenthesized substrings within a given string. Unmatched * parentheses are ignored. * Ex: "abc) (def) gh(ij) (kl (mn)o) (pqr" => ["(def)", "(ij)", "(kl (mn)o)"] * @param {string} string * @returns {string[]} */ function getParenthesizedSubstrings(string) { const openParenthesisPositions = []; const substrings = []; for (let i = 0; i < string.length; i++) { if (string[i] === '(') { openParenthesisPositions.push(i); } else if (string[i] === ')' && openParenthesisPositions.length > 0) { const openParenthesisPosition = openParenthesisPositions.pop(); if (openParenthesisPositions.length === 0) { substrings.push(string.substring(openParenthesisPosition, i + 1)); } } } return substrings; } module.exports = { isAndroid, isIOS, isIpad, isIphone, isMobile, isNonChromiumEdge, mobileWebKitBrowser, rebrandedChromeBrowser };