From 6e1fe930acac1b770c06f65ec9255cb10d1e74c9 Mon Sep 17 00:00:00 2001 From: Tamius Han Date: Thu, 17 Dec 2020 01:51:10 +0100 Subject: [PATCH 01/38] Remove Edge/Microsoft store links from description --- README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 2d3efae..a8d70fa 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,9 @@ ## Super TL;DR: I'm just looking for the install links, thanks -[Firefox](https://addons.mozilla.org/en/firefox/addon/ultrawidify/), [Chrome](https://chrome.google.com/webstore/detail/ultrawidify/dndehlekllfkaijdlokmmicgnlanfjbi), [Edge](https://microsoftedge.microsoft.com/addons/detail/lmpgpgechmkkkehkihpiddbcbgibokbi) (Chromium-based only) +[Firefox](https://addons.mozilla.org/en/firefox/addon/ultrawidify/), [Chrome](https://chrome.google.com/webstore/detail/ultrawidify/dndehlekllfkaijdlokmmicgnlanfjbi). + +**Microsoft Edge is not supported at this time, as Edge features some bugs that make it impossible for extension to work.** [Read more](https://github.com/tamius-han/ultrawidify/issues/117#issuecomment-747109695). There's also [nightly "builds"](https://stuff.lionsarch.tamius.net/ultrawidify/nightly/). @@ -235,7 +237,6 @@ However, I do plan on implementing this feature. Hopefully by the end of the yea - ## Plans for the future 1. Handle porting of extension settings between versions. @@ -254,7 +255,8 @@ However, I do plan on implementing this feature. Hopefully by the end of the yea [Latest stable for Chrome — download from Chrome store](https://chrome.google.com/webstore/detail/ultrawidify/dndehlekllfkaijdlokmmicgnlanfjbi) -[Latest stable for Edge — Download from Microsoft store](https://microsoftedge.microsoft.com/addons/detail/lmpgpgechmkkkehkihpiddbcbgibokbi) +Edge version is currently not available, as Edge has some bugs that prevent this extension from working correctly. [Read more](https://github.com/tamius-han/ultrawidify/issues/117#issuecomment-747109695) + ### Installing the current, github version @@ -268,7 +270,7 @@ Requirements: npm, node. 1. Clone this repo 2. run `npm install` -3. If using **Firefox,** run: `npm run watch:dev`. If using **Chrome,** run: `npm run watch-chrome:dev`. If using Edge, run: `npm run watch-edge:dev`. +3. If using **Firefox,** run: `npm run watch:dev`. If using **Chrome,** run: `npm run watch-chrome:dev`. TODO: see if #3 already loads the extension in FF From 769ff6aace916d2f5e3b3c3c689ac98c371871ca Mon Sep 17 00:00:00 2001 From: Tamius Han Date: Fri, 18 Dec 2020 01:44:45 +0100 Subject: [PATCH 02/38] Fix the issue where videos on players that were narrower than the video got cropped a lil bit too much --- src/ext/lib/video-data/VideoData.js | 48 ++++++++++++++ src/ext/lib/video-transform/Resizer.js | 79 ++++++++++++------------ src/ext/lib/video-transform/Scaler.js | 44 ++++++++++--- src/ext/lib/video-transform/Stretcher.js | 16 +++++ 4 files changed, 136 insertions(+), 51 deletions(-) diff --git a/src/ext/lib/video-data/VideoData.js b/src/ext/lib/video-data/VideoData.js index 25eb991..47e78a6 100644 --- a/src/ext/lib/video-data/VideoData.js +++ b/src/ext/lib/video-data/VideoData.js @@ -277,6 +277,54 @@ class VideoData { return a < b + diff && a > b - diff } + /** + * Gets the contents of the style attribute of the video element + * in a form of an object. + */ + getVideoStyle() { + // This will _always_ give us an array. Empty string gives an array + // that contains one element. That element is an empty string. + const styleArray = (this.video.getAttribute('style') || '').split(';'); + + const styleObject = {}; + + for (const style of styleArray) { + // not a valid CSS, so we skip those + if (style.indexOf(':') === -1) { + continue; + } + + // let's play _very_ safe + let {property, value} = style.split('!important')[0].split(':'); + value = value.trim(); + styleObject[property] = value; + } + + return styleObject; + } + + /** + * Some sites try to accomodate ultrawide users by "cropping" videos + * by setting 'style' attribute of the video element to 'height: X%', + * where 'X' is something greater than 100. + * + * This function gets that percentage and converts it into a factor. + */ + getHeightCompensationFactor() { + const heightStyle = this.getVideoStyle()?.height; + + if (!heightStyle || !heightStyle.endsWith('%')) { + return 1; + } + + const heightCompensationFactor = heightStyle.split('%')[0] / 100; + if (isNaN(heightCompensationFactor)) { + return 1; + } + return heightCompensationFactor; + } + + firstTimeArdInit(){ if(this.destroyed || this.invalid) { // throw {error: 'VIDEO_DATA_DESTROYED', data: {videoData: this}}; diff --git a/src/ext/lib/video-transform/Resizer.js b/src/ext/lib/video-transform/Resizer.js index af4f8cb..eec7daa 100644 --- a/src/ext/lib/video-transform/Resizer.js +++ b/src/ext/lib/video-transform/Resizer.js @@ -177,43 +177,41 @@ class Resizer { this.conf.pageInfo.updateCurrentCrop(ar); } - if (ar.type === AspectRatio.Automatic || - ar.type === AspectRatio.Reset && this.lastAr.type === AspectRatio.Initial) { - // some sites do things that interfere with our site (and aspect ratio setting in general) - // first, we check whether video contains anything we don't like - if (siteSettings?.autoarPreventConditions?.videoStyleString) { - const styleString = (this.video.getAttribute('style') || '').split(';'); + // if (ar.type === AspectRatio.Automatic || + // ar.type === AspectRatio.Reset && this.lastAr.type === AspectRatio.Initial) { + // // some sites do things that interfere with our site (and aspect ratio setting in general) + // // first, we check whether video contains anything we don't like + // if (siteSettings?.autoarPreventConditions?.videoStyleString) { + // const styleString = (this.video.getAttribute('style') || '').split(';'); - if (siteSettings.autoarPreventConditions.videoStyleString.containsProperty) { - const bannedProperties = siteSettings.autoarPreventConditions.videoStyleString.containsProperty; - for (const prop in bannedProperties) { - for (const s of styleString) { - if (s.trim().startsWith(prop)) { + // if (siteSettings.autoarPreventConditions.videoStyleString.containsProperty) { + // const bannedProperties = siteSettings.autoarPreventConditions.videoStyleString.containsProperty; + // for (const prop in bannedProperties) { + // for (const s of styleString) { + // if (s.trim().startsWith(prop)) { - // check if css property has a list of allowed values: - if (bannedProperties[prop].allowedValues) { - const styleValue = s.split(':')[1].trim(); + // // check if css property has a list of allowed values: + // if (bannedProperties[prop].allowedValues) { + // const styleValue = s.split(':')[1].trim(); - // check if property value is on the list of allowed values - // if it's not, we aren't allowed to start aard - if (bannedProperties[prop].allowedValues.indexOf(styleValue) === -1) { - this.logger.log('error', 'debug', "%c[Resizer::setAr] video style contains forbidden css property/value combo: ", "color: #900, background: #100", prop, " — we aren't allowed to start autoar.") - return; - } - } else { - // no allowed values, no problem. We have forbidden property - // and this means aard can't start. - this.logger.log('info', 'debug', "%c[Resizer::setAr] video style contains forbidden css property: ", "color: #900, background: #100", prop, " — we aren't allowed to start autoar.") - return; - } - } - } - } - } - } - } - - + // // check if property value is on the list of allowed values + // // if it's not, we aren't allowed to start aard + // if (bannedProperties[prop].allowedValues.indexOf(styleValue) === -1) { + // this.logger.log('error', 'debug', "%c[Resizer::setAr] video style contains forbidden css property/value combo: ", "color: #900, background: #100", prop, " — we aren't allowed to start autoar.") + // return; + // } + // } else { + // // no allowed values, no problem. We have forbidden property + // // and this means aard can't start. + // this.logger.log('info', 'debug', "%c[Resizer::setAr] video style contains forbidden css property: ", "color: #900, background: #100", prop, " — we aren't allowed to start autoar.") + // return; + // } + // } + // } + // } + // } + // } + // } if (lastAr) { this.lastAr = this.calculateRatioForLegacyOptions(lastAr); @@ -229,11 +227,11 @@ class Resizer { this.lastAr = {type: ar.type, ratio: ar.ratio} } - if (this.extensionMode === ExtensionMode.Basic && !PlayerData.isFullScreen() && ar.type !== AspectRatio.Reset) { - // don't actually apply or calculate css when using basic mode if not in fullscreen - // ... unless we're resetting the aspect ratio to original - return; - } + // if (this.extensionMode === ExtensionMode.Basic && !PlayerData.isFullScreen() && ar.type !== AspectRatio.Reset) { + // // don't actually apply or calculate css when using basic mode if not in fullscreen + // // ... unless we're resetting the aspect ratio to original + // return; + // } if (! this.video) { this.conf.destroy(); @@ -259,7 +257,6 @@ class Resizer { var stretchFactors = this.scaler.calculateCrop(ar); - if(! stretchFactors || stretchFactors.error){ this.logger.log('error', 'debug', `[Resizer::setAr] failed to set AR due to problem with calculating crop. Error:`, stretchFactors?.error); if (stretchFactors?.error === 'no_video'){ @@ -297,7 +294,7 @@ class Resizer { var stretchFactors = this.stretcher.calculateBasicStretch(); this.logger.log('info', 'debug', '[Resizer::setAr] Processed stretch factors for basic stretch. Stretch factors are:', stretchFactors); } else { - var stretchFactors = {xFactor: 1, yFactor: 1} + var stretchFactors = {xFactor: 1, yFactor: 1}; this.logger.log('error', 'debug', '[Resizer::setAr] Okay wtf happened? If you see this, something has gone wrong', stretchFactors,"\n------[ i n f o d u m p ]------\nstretcher:", this.stretcher); } diff --git a/src/ext/lib/video-transform/Scaler.js b/src/ext/lib/video-transform/Scaler.js index d846274..552a0e0 100644 --- a/src/ext/lib/video-transform/Scaler.js +++ b/src/ext/lib/video-transform/Scaler.js @@ -66,6 +66,28 @@ class Scaler { } calculateCrop(ar) { + /** + * STEP 1: NORMALIZE ASPECT RATIO + * + * Video width is normalized based on 100% of the parent. That means if the player AR + * is narrower than video ar, we need to pre-downscale the video. This scaling already + * undoes any zoom that style="height:123%" on the video element adds. + * + * Quick notes: + * * when I say 'video AR', I actually mean aspect ratio after we've compensated for + * any possible 'height:' stuffs in the style attribute of the video tag + * * because video width is normalized on 100% of the parent, we don't need to correct + * anything when the player is wider than the video. + */ + const streamAr = this.conf.video.videoWidth / this.conf.video.videoHeight; + const playerAr = this.conf.player.dimensions.width / this.conf.player.dimensions.height; + const compensatedStreamAr = streamAr * this.conf.videoData.getHeightCompensationFactor(); + + let arCorrectionFactor = 1; + if (playerAr < compensatedStreamAr) { + arCorrectionFactor = this.conf.player.dimensions.width / this.conf.video.offsetWidth; + } + if(!this.conf.video){ this.logger.log('info', 'debug', "[Scaler::calculateCrop] ERROR — no video detected. Conf:", this.conf, "video:", this.conf.video, "video dimensions:", this.conf.video && this.conf.video.videoWidth, '×', this.conf.video && this.conf.video.videoHeight); @@ -81,7 +103,7 @@ class Scaler { } if (ar.type === AspectRatio.Reset){ - return {xFactor: 1, yFactor: 1} + return {xFactor: arCorrectionFactor, yFactor: arCorrectionFactor} } // handle fuckie-wuckies @@ -102,15 +124,13 @@ class Scaler { // Dejansko razmerje stranic datoteke/