2018-12-31 01:03:07 +01:00
import Debug from '../../conf/Debug' ;
2021-02-08 23:04:54 +01:00
import ExtensionMode from '../../../common/enums/ExtensionMode.enum'
import AspectRatioType from '../../../common/enums/AspectRatioType.enum' ;
2020-12-03 01:35:48 +01:00
import PlayerNotificationUi from '../uwui/PlayerNotificationUI' ;
2020-12-15 00:26:19 +01:00
import PlayerUi from '../uwui/PlayerUI' ;
2020-12-22 03:21:14 +01:00
import BrowserDetect from '../../conf/BrowserDetect' ;
2021-02-08 22:45:51 +01:00
import * as _ from 'lodash' ;
2021-02-08 20:43:56 +01:00
import { sleep } from '../../../common/js/utils' ;
2021-02-08 22:45:51 +01:00
import VideoData from './VideoData' ;
import Settings from '../Settings' ;
import Logger from '../Logger' ;
2021-10-26 22:19:41 +02:00
import EventBus from '../EventBus' ;
2018-12-31 01:03:07 +01:00
2020-12-03 01:05:39 +01:00
if ( process . env . CHANNEL !== 'stable' ) {
console . info ( "Loading: PlayerData.js" ) ;
}
2018-05-13 13:49:25 +02:00
2021-10-26 00:30:38 +02:00
interface PlayerDimensions {
width? : number ;
height? : number ;
fullscreen? : boolean ;
}
/ * *
* accepts < video > tag ( element ) and list of names that can appear in id or class
* returns player dimensions ( width , height )
* Theater mode is mildly broken on youtube . < video > tag remains bigger than the player after leaving the fullscreen mode , and
* there 's nothing we can do about that. This function aims to solve the problem by finding the player element that' s wrapped around
* the < video > tag .
* In general , an outer tag should be bigger than the inner tag . Therefore the smallest element between < video > tag and the document
* root should be the player .
* If list of names is provided , the function returns dimensions of the first element that contains any name from the list in either
* id or class .
* /
2018-05-13 13:49:25 +02:00
class PlayerData {
2021-10-26 00:30:38 +02:00
private playerCssClass = 'uw-ultrawidify-player-css' ;
2021-02-08 22:45:51 +01:00
//#region helper objects
logger : Logger ;
videoData : VideoData ;
settings : Settings ;
notificationService : PlayerNotificationUi ;
2021-10-26 22:19:41 +02:00
eventBus : EventBus ;
2021-02-08 22:45:51 +01:00
//#endregion
//#region HTML objects
video : any ;
element : any ;
overlayNode : any ;
//#endregion
//#region flags
2021-10-26 00:30:38 +02:00
enabled : boolean ;
2021-02-08 22:45:51 +01:00
invalid : boolean = false ;
private periodicallyRefreshPlayerElement : boolean = false ;
halted : boolean = true ;
//#region misc stuff
extensionMode : any ;
2021-10-26 00:30:38 +02:00
dimensions : PlayerDimensions ;
2021-02-08 22:45:51 +01:00
private playerIdElement : any ;
2021-03-29 23:30:54 +02:00
private observer : ResizeObserver ;
2021-08-26 01:07:39 +02:00
private ui : any ;
2021-02-08 22:45:51 +01:00
//#endregion
2021-04-10 04:08:09 +02:00
/ * *
* Gets player aspect ratio . If in full screen , it returns screen aspect ratio unless settings say otherwise .
* /
get aspectRatio() {
2021-04-12 19:01:28 +02:00
try {
if ( this . dimensions ? . fullscreen && ! this . settings . getSettingsForSite ( ) ? . usePlayerArInFullscreen ) {
return window . innerWidth / window . innerHeight ;
}
2021-04-10 04:08:09 +02:00
2021-04-12 19:01:28 +02:00
return this . dimensions . width / this . dimensions . height ;
} catch ( e ) {
console . error ( 'cannot determine aspect ratio!' , e ) ;
return 1 ;
}
2021-04-10 04:08:09 +02:00
}
2019-09-03 22:42:38 +02:00
constructor ( videoData ) {
2019-09-22 02:07:04 +02:00
try {
this . logger = videoData . logger ;
this . videoData = videoData ;
this . video = videoData . video ;
this . settings = videoData . settings ;
2021-10-26 22:19:41 +02:00
this . eventBus = videoData . eventBus ;
2019-09-22 02:07:04 +02:00
this . extensionMode = videoData . extensionMode ;
this . invalid = false ;
this . element = this . getPlayer ( ) ;
2020-12-22 03:21:14 +01:00
2021-10-26 23:13:11 +02:00
this . notificationService = new PlayerNotificationUi ( this . element , this . settings , this . eventBus ) ;
2021-11-13 00:51:59 +01:00
this . ui = new PlayerUi ( this . element , this . settings , this . eventBus , this . videoData ) ;
2021-08-26 01:07:39 +02:00
this . ui . init ( ) ;
2020-12-22 03:21:14 +01:00
2019-09-22 02:07:04 +02:00
this . dimensions = undefined ;
this . overlayNode = undefined ;
2019-11-29 01:33:58 +01:00
this . periodicallyRefreshPlayerElement = false ;
try {
2020-06-04 22:47:04 +02:00
this . periodicallyRefreshPlayerElement = this . settings . active . sites [ window . location . hostname ] . DOM . player . periodicallyRefreshPlayerElement ;
2019-11-29 01:33:58 +01:00
} catch ( e ) {
// no biggie — that means we don't have any special settings for this site.
}
2019-09-22 02:07:04 +02:00
// this happens when we don't find a matching player element
if ( ! this . element ) {
this . invalid = true ;
return ;
}
if ( this . extensionMode === ExtensionMode . Enabled ) {
2021-10-26 00:30:38 +02:00
this . trackDimensionChanges ( ) ;
2019-09-22 02:07:04 +02:00
}
this . startChangeDetection ( ) ;
2020-12-05 03:30:43 +01:00
2019-09-22 02:07:04 +02:00
} catch ( e ) {
console . error ( '[Ultrawidify::PlayerData::ctor] There was an error setting up player data. You should be never seeing this message. Error:' , e ) ;
2019-09-18 01:03:04 +02:00
this . invalid = true ;
}
2021-08-26 01:07:39 +02:00
2019-09-22 02:07:04 +02:00
}
2019-09-18 01:03:04 +02:00
2021-04-10 04:10:12 +02:00
/ * *
* Returns whether we ' re in fullscreen mode or not .
* /
2018-05-13 13:49:25 +02:00
static isFullScreen ( ) {
2021-04-10 04:10:12 +02:00
const ihdiff = Math . abs ( window . screen . height - window . innerHeight ) ;
const iwdiff = Math . abs ( window . screen . width - window . innerWidth ) ;
// Chrome on linux on X on mixed PPI displays may return ever so slightly different values
// for innerHeight vs screen.height abd innerWidth vs. screen.width, probably courtesy of
// fractional scaling or something. This means we'll give ourself a few px of margin — the
// window elements visible in not-fullscreen are usually double digit px tall
return ( ihdiff < 5 && iwdiff < 5 ) ;
2018-05-13 13:49:25 +02:00
}
2021-10-26 00:30:38 +02:00
/ * *
*
* /
trackDimensionChanges() {
// get player dimensions _once_
let currentPlayerDimensions ;
const isFullScreen = PlayerData . isFullScreen ( ) ;
if ( isFullScreen ) {
currentPlayerDimensions = {
width : window.innerWidth ,
height : window.innerHeight ,
fullscreen : true
} ;
} else {
currentPlayerDimensions = {
width : this.element.offsetWidth ,
height : this.element.offsetHeight ,
fullscreen : false ,
}
}
// if dimensions of the player box are the same as the last known
// dimensions, we don't have to do anything
if (
this . dimensions
&& this . dimensions . width == currentPlayerDimensions . width
&& this . dimensions . height == currentPlayerDimensions . height
) {
this . dimensions = currentPlayerDimensions ;
return ;
2019-08-25 21:19:56 +02:00
}
2021-10-26 00:30:38 +02:00
// in every other case, we need to check if the player is still
// big enough to warrant our extension running.
this . handleSizeConstraints ( currentPlayerDimensions ) ;
this . handleDimensionChanges ( currentPlayerDimensions , this . dimensions ) ;
// Save current dimensions to avoid triggering this function pointlessly
this . dimensions = currentPlayerDimensions ;
2019-08-25 21:19:56 +02:00
}
2018-05-23 23:57:51 +02:00
2021-10-26 00:30:38 +02:00
/ * *
* Handles size restrictions ( if any )
* @param currentPlayerDimensions
* /
private handleSizeConstraints ( currentPlayerDimensions : PlayerDimensions ) {
// never disable ultrawidify in full screen
if ( currentPlayerDimensions . fullscreen ) {
this . enable ( ) ;
return ;
}
const restrictions = this . settings . getSettingsForSite ( ) ? . restrictions ? ? this . settings . active ? . restrictions ;
// if 'disable on small players' option is not enabled, the extension will run in any case
if ( ! restrictions ? . disableOnSmallPlayers ) {
this . enable ( ) ;
return ;
}
// If we only allow ultrawidify in full screen, we disable it when not in full screen
if ( restrictions . onlyAllowInFullscreen && ! currentPlayerDimensions . fullscreen ) {
this . disable ( ) ;
return ;
}
// if current width or height are smaller than the minimum, the extension will not run
if ( restrictions . minAllowedHeight > currentPlayerDimensions ? . height || restrictions . minAllowedWidth > currentPlayerDimensions ? . width ) {
this . disable ( ) ;
return ;
}
// in this case, the player is big enough to warrant enabling Ultrawidify
this . enable ( ) ;
}
private handleDimensionChanges ( newDimensions : PlayerDimensions , oldDimensions : PlayerDimensions ) {
if ( ! this . enabled ) {
this . logger . log ( 'info' , 'debug' , "[PlayerDetect] player size changed, but PlayerDetect is in disabled state. The player element is probably too small." ) ;
return ;
}
// this 'if' is just here for debugging — real code starts later. It's safe to collapse and
// ignore the contents of this if (unless we need to change how logging works)
this . logger . log ( 'info' , 'debug' , "[PlayerDetect] player size potentially changed.\n\nold dimensions:" , oldDimensions , '\nnew dimensions:' , newDimensions ) ;
// if size doesn't match, trigger onPlayerDimensionChange
if (
newDimensions ? . width != oldDimensions ? . width
|| newDimensions ? . height != oldDimensions ? . height
|| newDimensions ? . fullscreen != oldDimensions ? . fullscreen
) {
// If player size changes, we restore aspect ratio
this . videoData . resizer ? . restore ( ) ;
}
}
/ * *
* Enables ultrawidify for this video by adding the relevant classes
* to the video and player element .
* /
enable() {
this . enabled = true ;
this . element . classList . add ( this . playerCssClass ) ;
2018-05-23 23:57:51 +02:00
this . startChangeDetection ( ) ;
2021-10-26 00:30:38 +02:00
this . videoData . enable ( { fromPlayer : true } ) ;
2018-05-23 23:57:51 +02:00
}
2021-10-26 00:30:38 +02:00
/ * *
* Disables ultrawidify for this video by removing the relevant classes
* from the video and player elements .
*
* NOTE : it is very important to keep change detection active while disabled ,
* because otherwise ultrawidify will otherwise remain inactive after
* switching ( back to ) full screen .
* /
disable() {
this . enabled = false ;
this . element . classList . remove ( this . playerCssClass ) ;
this . videoData . disable ( { fromPlayer : true } ) ;
}
onPlayerDimensionsChanged ( mutationList ? , observer ? ) {
this . trackDimensionChanges ( ) ;
2018-05-13 13:49:25 +02:00
}
2018-05-22 00:19:50 +02:00
destroy() {
this . stopChangeDetection ( ) ;
2018-12-09 01:37:19 +01:00
this . destroyOverlay ( ) ;
2020-12-03 01:35:48 +01:00
this . notificationService ? . destroy ( ) ;
2018-05-22 00:19:50 +02:00
}
2021-10-26 00:30:38 +02:00
//#region player element change detection
2018-05-23 23:57:51 +02:00
startChangeDetection ( ) {
2019-09-18 01:03:04 +02:00
if ( this . invalid ) {
2019-08-25 21:19:56 +02:00
return ;
}
2019-09-21 23:50:06 +02:00
2019-09-22 02:07:04 +02:00
try {
2021-02-08 20:43:56 +01:00
if ( BrowserDetect . firefox ) {
2021-03-29 23:30:54 +02:00
this . observer = new ResizeObserver (
2021-02-08 20:43:56 +01:00
_ . debounce ( // don't do this too much:
this . onPlayerDimensionsChanged ,
250 , // do it once per this many ms
{
leading : true , // do it when we call this fallback first
trailing : true // do it after the timeout if we call this callback few more times
}
)
) ;
} else {
// Chrome for some reason insists that this.onPlayerDimensionsChanged is not a function
// when it's not wrapped into an anonymous function
2021-03-29 23:30:54 +02:00
this . observer = new ResizeObserver (
2021-02-08 20:43:56 +01:00
_ . debounce ( // don't do this too much:
( m , o ) = > this . onPlayerDimensionsChanged ( m , o ) ,
250 , // do it once per this many ms
{
leading : true , // do it when we call this fallback first
trailing : true // do it after the timeout if we call this callback few more times
}
)
) ;
}
2019-11-29 01:33:58 +01:00
const observerConf = {
attributes : true ,
// attributeFilter: ['style', 'class'],
attributeOldValue : true ,
} ;
2021-10-25 23:11:34 +02:00
2021-03-29 23:30:54 +02:00
this . observer . observe ( this . element ) ;
2019-11-29 01:33:58 +01:00
} catch ( e ) {
console . error ( "failed to set observer" , e )
}
2019-09-21 23:50:06 +02:00
// legacy mode still exists, but acts as a fallback for observers and is triggered less
// frequently in order to avoid too many pointless checks
this . legacyChangeDetection ( ) ;
}
async legacyChangeDetection() {
while ( ! this . halted ) {
2021-02-08 20:43:56 +01:00
await sleep ( 1000 ) ;
2019-09-22 02:07:04 +02:00
try {
2021-10-26 00:30:38 +02:00
this . forceRefreshPlayerElement ( ) ;
2019-09-22 02:07:04 +02:00
} catch ( e ) {
2021-04-04 15:48:01 +02:00
console . error ( '[PlayerData::legacycd] this message is pretty high on the list of messages you shouldn\'t see' , e ) ;
2019-09-21 23:50:06 +02:00
}
}
2018-05-23 23:57:51 +02:00
}
2019-09-21 23:50:06 +02:00
2020-01-28 01:27:30 +01:00
doPeriodicPlayerElementChangeCheck() {
if ( this . periodicallyRefreshPlayerElement ) {
2021-10-26 00:30:38 +02:00
this . forceRefreshPlayerElement ( ) ;
2020-01-28 01:27:30 +01:00
}
}
2018-05-23 23:57:51 +02:00
stopChangeDetection ( ) {
2019-08-25 21:19:56 +02:00
this . observer . disconnect ( ) ;
2018-05-23 23:57:51 +02:00
}
2021-10-26 00:30:38 +02:00
//#region interface
2018-12-09 01:37:19 +01:00
makeOverlay() {
if ( ! this . overlayNode ) {
this . destroyOverlay ( ) ;
}
2021-02-18 22:38:32 +01:00
let overlay = document . createElement ( 'div' ) ;
2018-12-06 23:55:54 +01:00
overlay . style . width = '100%' ;
overlay . style . height = '100%' ;
2018-12-07 00:17:49 +01:00
overlay . style . position = 'absolute' ;
overlay . style . top = '0' ;
overlay . style . left = '0' ;
overlay . style . zIndex = '1000000000' ;
2018-12-07 00:22:27 +01:00
overlay . style . pointerEvents = 'none' ;
2018-12-06 23:55:54 +01:00
this . overlayNode = overlay ;
this . element . appendChild ( overlay ) ;
}
2018-12-09 01:37:19 +01:00
destroyOverlay() {
if ( this . playerIdElement ) {
this . playerIdElement . remove ( ) ;
this . playerIdElement = undefined ;
}
2018-12-06 23:55:54 +01:00
if ( this . overlayNode ) {
this . overlayNode . remove ( ) ;
2018-12-09 01:37:19 +01:00
this . overlayNode = undefined ;
2018-12-06 23:55:54 +01:00
}
}
2018-12-09 01:37:19 +01:00
markPlayer ( name , color ) {
if ( ! this . overlayNode ) {
this . makeOverlay ( ) ;
}
if ( this . playerIdElement ) {
this . playerIdElement . remove ( ) ;
}
this . playerIdElement = document . createElement ( 'div' ) ;
this . playerIdElement . innerHTML = ` <div style="background-color: ${ color } ; color: #fff; position: absolute; top: 0; left: 0"> ${ name } </div> ` ;
this . overlayNode . appendChild ( this . playerIdElement ) ;
}
unmarkPlayer() {
2020-05-17 02:30:16 +02:00
this . logger . log ( 'info' , 'debug' , "[PlayerData::unmarkPlayer] unmarking player!" , { playerIdElement : this.playerIdElement } ) ;
2018-12-09 01:37:19 +01:00
if ( this . playerIdElement ) {
2020-05-17 02:30:16 +02:00
this . playerIdElement . innerHTML = '' ;
2018-12-09 01:37:19 +01:00
this . playerIdElement . remove ( ) ;
}
this . playerIdElement = undefined ;
}
2021-10-26 00:30:38 +02:00
//#endregion
2018-12-09 01:37:19 +01:00
2021-10-26 00:30:38 +02:00
//#region helper functions
2019-06-10 23:45:15 +02:00
collectionHas ( collection , element ) {
2019-06-14 21:53:48 +02:00
for ( let i = 0 , len = collection . length ; i < len ; i ++ ) {
if ( collection [ i ] == element ) {
2019-06-10 23:45:15 +02:00
return true ;
}
}
return false ;
}
2021-10-26 00:30:38 +02:00
//#endregion
2019-11-04 23:53:28 +01:00
2019-09-18 01:03:04 +02:00
getPlayer() {
2020-06-04 22:47:04 +02:00
const host = window . location . hostname ;
2019-06-10 23:45:15 +02:00
let element = this . video . parentNode ;
2020-01-27 23:42:55 +01:00
const videoWidth = this . video . offsetWidth ;
const videoHeight = this . video . offsetHeight ;
2019-09-01 01:40:39 +02:00
const elementQ = [ ] ;
2021-04-12 19:03:18 +02:00
const scorePenalty = 10 ;
const sizePenaltyMultiplier = 0.1 ;
let penaltyMultiplier = 0 ;
2019-09-01 01:40:39 +02:00
let score ;
2018-05-13 13:49:25 +02:00
2019-09-18 01:03:04 +02:00
try {
if ( ! element ) {
this . logger . log ( 'info' , 'debug' , "[PlayerDetect::_pd_getPlayer] element is not valid, doing nothing." , element )
if ( this . element ) {
const ths = this ;
}
this . element = undefined ;
this . dimensions = undefined ;
return ;
2018-09-13 23:47:20 +02:00
}
2018-05-13 13:49:25 +02:00
2020-01-28 01:27:30 +01:00
// log the entire hierarchy from <video> to root
if ( this . logger . canLog ( 'playerDetect' ) ) {
const logObj = [ ] ;
logObj . push ( ` window size: ${ window . innerWidth } x ${ window . innerHeight } ` ) ;
let e = element ;
while ( e ) {
logObj . push ( { offsetSize : { width : e.offsetWidth , height : e.offsetHeight } , clientSize : { width : e.clientWidth , height : e.clientHeight } , element : e } ) ;
e = e . parentNode ;
}
this . logger . log ( 'info' , 'playerDetect' , "\n\n[PlayerDetect::getPlayer()] element hierarchy (video->root)" , logObj ) ;
}
2020-01-28 23:34:36 +01:00
if ( this . settings . active . sites [ host ] ? . DOM ? . player ? . manual ) {
if ( this . settings . active . sites [ host ] ? . DOM ? . player ? . useRelativeAncestor
&& this . settings . active . sites [ host ] ? . DOM ? . player ? . videoAncestor ) {
2019-06-10 23:45:15 +02:00
2019-09-18 01:03:04 +02:00
let parentsLeft = this . settings . active . sites [ host ] . DOM . player . videoAncestor - 1 ;
while ( parentsLeft -- > 0 ) {
element = element . parentNode ;
}
if ( element ) {
return element ;
}
2020-01-28 23:34:36 +01:00
} else if ( this . settings . active . sites [ host ] ? . DOM ? . player ? . querySelectors ) {
2019-09-18 01:03:04 +02:00
const allSelectors = document . querySelectorAll ( this . settings . active . sites [ host ] . DOM . player . querySelectors ) ;
// actually we'll also score this branch in a similar way we score the regular, auto branch
while ( element ) {
// Let's see how this works
if ( this . collectionHas ( allSelectors , element ) ) {
score = 100 ; // every matching element gets a baseline 100 points
2021-10-25 23:11:34 +02:00
2019-09-18 01:03:04 +02:00
// elements that match the size get a hefty bonus
if ( ( element . offsetWidth >= videoWidth && this . equalish ( element . offsetHeight , videoHeight , 2 ) )
|| ( element . offsetHeight >= videoHeight && this . equalish ( element . offsetWidth , videoHeight , 2 ) ) ) {
score += 75 ;
}
// elements farther away from the video get a penalty
2021-04-12 19:03:18 +02:00
score -= ( scorePenalty ) * 20 ;
2019-09-18 01:03:04 +02:00
// push the element on the queue/stack:
elementQ . push ( {
score : score ,
element : element ,
} ) ;
2019-09-01 01:40:39 +02:00
}
2019-09-18 01:03:04 +02:00
element = element . parentNode ;
2019-09-01 01:40:39 +02:00
}
2020-01-28 01:27:30 +01:00
// log player candidates
this . logger . log ( 'info' , 'playerDetect' , 'player detect via query selector: element queue and final element:' , { queue : elementQ , bestCandidate : elementQ.length ? elementQ . sort ( ( a , b ) = > b . score - a . score ) [ 0 ] . element : 'n/a' } ) ;
2019-09-18 01:03:04 +02:00
if ( elementQ . length ) {
// return element with biggest score
// if video player has not been found, proceed to automatic detection
2019-11-04 23:53:28 +01:00
const playerElement = elementQ . sort ( ( a , b ) = > b . score - a . score ) [ 0 ] . element ;
return playerElement ;
2019-09-18 01:03:04 +02:00
}
2019-06-10 23:45:15 +02:00
}
}
2019-09-18 01:03:04 +02:00
// try to find element the old fashioned way
2019-08-31 18:21:49 +02:00
2021-04-12 19:03:18 +02:00
while ( element ) {
2019-09-18 01:03:04 +02:00
// remove weird elements, those would break our stuff
if ( element . offsetWidth == 0 || element . offsetHeight == 0 ) {
element = element . parentNode ;
continue ;
2018-05-13 13:49:25 +02:00
}
2021-10-25 23:11:34 +02:00
2021-04-12 19:08:12 +02:00
// element is player, if at least one of the sides is as long as the video
// note that we can't make any additional assumptions with regards to player
// size, since there are both cases where the other side is bigger _and_ cases
// where other side is smaller than the video.
2021-10-25 23:11:34 +02:00
//
2021-04-12 19:08:12 +02:00
// Don't bother thinking about this too much, as any "thinking" was quickly
// corrected by bugs caused by various edge cases.
2021-04-12 19:03:18 +02:00
if (
this . equalish ( element . offsetHeight , videoHeight , 5 )
|| this . equalish ( element . offsetWidth , videoWidth , 5 )
) {
score = 1000 ;
2019-09-18 01:03:04 +02:00
2021-04-12 19:03:18 +02:00
// -------------------
// PENALTIES
// -------------------
2021-04-12 19:08:12 +02:00
//
// Our ideal player will be as close to the video element, and it will als
// be as close to the size of the video.
2021-04-12 19:03:18 +02:00
// prefer elements closer to <video>
score -= scorePenalty * penaltyMultiplier ++ ;
// the bigger the size difference between the video and the player,
2021-10-25 23:11:34 +02:00
// the more penalty we'll incur. Since we did some grace ith
2021-04-12 19:03:18 +02:00
let playerSizePenalty = 1 ;
if ( element . offsetHeight > ( videoHeight + 5 ) ) {
playerSizePenalty = ( element . offsetWidth - videoHeight ) * sizePenaltyMultiplier ;
}
if ( element . offsetWidth > ( videoWidth + 5 ) ) {
playerSizePenalty *= ( element . offsetWidth - videoWidth ) * sizePenaltyMultiplier
}
score -= playerSizePenalty ;
2019-09-18 01:03:04 +02:00
elementQ . push ( {
element : element ,
score : score ,
} ) ;
2019-06-10 23:45:15 +02:00
}
2021-10-25 23:11:34 +02:00
2019-09-18 01:03:04 +02:00
element = element . parentNode ;
2018-05-13 13:49:25 +02:00
}
2019-06-10 23:45:15 +02:00
2020-01-28 01:27:30 +01:00
// log player candidates
this . logger . log ( 'info' , 'playerDetect' , 'player detect, auto/fallback: element queue and final element:' , { queue : elementQ , bestCandidate : elementQ.length ? elementQ . sort ( ( a , b ) = > b . score - a . score ) [ 0 ] . element : 'n/a' } ) ;
2019-09-18 01:03:04 +02:00
if ( elementQ . length ) {
// return element with biggest score
2019-11-04 23:53:28 +01:00
const playerElement = elementQ . sort ( ( a , b ) = > b . score - a . score ) [ 0 ] . element ;
2021-10-25 23:11:34 +02:00
2019-11-04 23:53:28 +01:00
return playerElement ;
2019-09-18 01:03:04 +02:00
}
2019-06-12 23:55:15 +02:00
2019-09-18 01:03:04 +02:00
// if no candidates were found, something is obviously very, _very_ wrong.
// we return nothing. Player will be marked as invalid and setup will stop.
// VideoData should check for that before starting anything.
this . logger . log ( 'warn' , 'debug' , '[PlayerData::getPlayer] no matching player was found for video' , this . video , 'Extension cannot work on this site.' ) ;
return ;
} catch ( e ) {
this . logger . log ( 'crit' , 'debug' , '[PlayerData::getPlayer] something went wrong while detecting player:' , e , 'Shutting down extension for this page' ) ;
}
2019-06-10 23:45:15 +02:00
}
2019-08-31 18:21:49 +02:00
equalish ( a , b , tolerance ) {
return a > b - tolerance && a < b + tolerance ;
}
2019-06-10 23:45:15 +02:00
2019-08-31 22:10:51 +02:00
forceRefreshPlayerElement() {
2021-10-26 00:30:38 +02:00
this . element = this . getPlayer ( ) ;
this . notificationService ? . replace ( this . element ) ;
this . trackDimensionChanges ( ) ;
2018-11-02 21:19:34 +01:00
}
2020-12-05 03:30:43 +01:00
showNotification ( notificationId ) {
this . notificationService ? . showNotification ( notificationId ) ;
}
2020-12-23 01:15:11 +01:00
/ * *
* NOTE : this method needs to be deleted once Edge gets its shit together .
* /
showEdgeNotification() {
2021-01-10 16:12:20 +01:00
// if (BrowserDetect.isEdgeUA && !this.settings.active.mutedNotifications?.browserSpecific?.edge?.brokenDrm?.[window.hostname]) {
// this.ui = new PlayerUi(this.element, this.settings);
// }
2020-12-23 01:15:11 +01:00
}
2018-05-13 13:49:25 +02:00
}
2020-12-03 01:05:39 +01:00
if ( process . env . CHANNEL !== 'stable' ) {
console . info ( "PlayerData loaded" ) ;
}
2018-12-31 01:03:07 +01:00
export default PlayerData ;