import Debug from '../../conf/Debug'; import VideoData from './VideoData'; import RescanReason from './enums/RescanReason.enum'; import AspectRatioType from '../../../common/enums/AspectRatioType.enum'; import CropModePersistence from '../../../common/enums/CropModePersistence.enum'; import Logger from '../Logger'; import Settings from '../Settings'; import ExtensionMode from '../../../common/enums/ExtensionMode.enum'; import CommsClient from '../comms/CommsClient'; if (process.env.CHANNEL !== 'stable'){ console.info("Loading PageInfo"); } class PageInfo { //#region flags readOnly: boolean = false; hasVideos: boolean = false; siteDisabled: boolean = false; //#endregion //#region timers and timeouts rescanTimer: any; urlCheckTimer: any; announceZoomTimeout: any; //#endregion //#region helper objects logger: Logger; settings: Settings; comms: CommsClient; videos: {videoData: VideoData, element: HTMLVideoElement}[] = []; //#endregion //#region misc stuff lastUrl: string; extensionMode: ExtensionMode; defaultCrop: any; currentCrop: any; actionHandlerInitQueue: any[] = []; currentZoomScale: number = 1; actionHandler: any; //#endregion constructor(comms, settings, logger, extensionMode, readOnly = false){ this.logger = logger; this.settings = settings; this.lastUrl = window.location.href; this.extensionMode = extensionMode; this.readOnly = readOnly; if (comms){ this.comms = comms; } try { // request inject css immediately const playerStyleString = this.settings.active.sites[window.location.hostname].css.replace('\\n', ''); this.comms.sendMessage({ cmd: 'inject-css', cssString: playerStyleString }); } catch (e) { // do nothing. It's ok if there's no special settings for the player element or crop persistence } // try getting default crop immediately. // const cropModePersistence = this.settings.getDefaultCropPersistenceMode(window.location.hostname); // try { // if (cropModePersistence === CropModePersistence.Forever) { // this.defaultCrop = this.settings.active.sites[window.location.hostname].defaultCrop; // } else if (cropModePersistence === CropModePersistence.CurrentSession) { // this.defaultCrop = JSON.parse(sessionStorage.getItem('uw-crop-mode-session-persistence')); // } // } catch (e) { // // do nothing. It's ok if there's no special settings for the player element or crop persistence // } this.currentCrop = this.defaultCrop; this.rescan(RescanReason.PERIODIC); this.scheduleUrlCheck(); } async injectCss(cssString) { await this.comms.sendMessage({ cmd: 'inject-css', cssString: cssString }); } async ejectCss(cssString) { await this.comms.sendMessage({ cmd: 'eject-css', cssString: cssString }); } async replaceCss(oldCssString, newCssString) { await this.comms.sendMessage({ cmd: 'replace-css', newCssString, oldCssString }); } destroy() { this.logger.log('info', ['debug', 'init'], "[PageInfo::destroy] destroying all videos!") if(this.rescanTimer){ clearTimeout(this.rescanTimer); } for (let video of this.videos) { try { (this.comms.unregisterVideo as any)(video.videoData.vdid) video.videoData.destroy(); } catch (e) { this.logger.log('error', ['debug', 'init'], '[PageInfo::destroy] unable to destroy video! Error:', e); } } try { const playerStyleString = this.settings.active.sites[window.location.hostname].css; if (playerStyleString) { this.comms.sendMessage({ cmd: 'eject-css', cssString: playerStyleString }); } } catch (e) { // do nothing. It's ok if there's no special settings for the player element } } reset() { for(let video of this.videos) { video.videoData.destroy(); video.videoData = null; } this.videos = []; this.rescan(RescanReason.MANUAL); } initMouseActionHandler(videoData) { if (this.actionHandler) { this.actionHandler.registerHandleMouse(videoData); } else { this.actionHandlerInitQueue.push(videoData); } } setActionHandler(actionHandler) { this.actionHandler = actionHandler; for (let item of this.actionHandlerInitQueue) { this.actionHandler.registerHandleMouse(item); } this.actionHandlerInitQueue = []; } getVideos(host) { if (this.settings.active.sites[host]?.DOM?.video?.manual && this.settings.active.sites[host]?.DOM?.video?.querySelectors){ const videos = document.querySelectorAll(this.settings.active.sites[host].DOM.video.querySelectors) as NodeListOf; if (videos.length) { return videos; } } return document.getElementsByTagName('video'); } hasVideo() { return this.readOnly ? this.hasVideos : this.videos.length; } /** * Re-scans the page for videos. Removes any videos that no longer exist from our list * of videos. Destroys all videoData objects for all the videos that don't have their * own