Refactor playerData/player size changing a bit. Settings can now only be patched from ExtConfPatches
This commit is contained in:
parent
baa7c79f6c
commit
095a3daadd
2
package-lock.json
generated
2
package-lock.json
generated
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ultrawidify",
|
||||
"version": "6.3.98",
|
||||
"version": "6.3.993",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ultrawidify",
|
||||
"version": "6.3.98",
|
||||
"version": "6.3.993",
|
||||
"description": "Aspect ratio fixer for youtube and other sites, with automatic aspect ratio detection. Supports ultrawide and other ratios.",
|
||||
"author": "Tamius Han <tamius.han@gmail.com>",
|
||||
"scripts": {
|
||||
|
||||
@ -165,7 +165,7 @@
|
||||
<div class="label">Subtitle detection:</div>
|
||||
<div class="select">
|
||||
<select v-model="aardSettings.subtitles.subtitleCropMode" @change="settings.saveWithoutReload">
|
||||
<option :value="AardSubtitleCropMode.DisableScan">Do not detect subtitles</option>
|
||||
<!-- <option :value="AardSubtitleCropMode.DisableScan">Do not detect subtitles</option> -->
|
||||
<option :value="AardSubtitleCropMode.ResetAR">Do not crop while subtitles are on screen</option>
|
||||
<option :value="AardSubtitleCropMode.ResetAndDisable">Stop autodetection if subtitles are detected</option>
|
||||
<option :value="AardSubtitleCropMode.CropSubtitles">Always crop subtitles</option>
|
||||
|
||||
@ -97,6 +97,8 @@ class Logger {
|
||||
}
|
||||
|
||||
static saveConfig(conf: LoggerConfig) {
|
||||
console.warn('LEGACY LOGGER IS STILL BEING CALLED FROM SOMEWHERE!', new Error().stack);
|
||||
|
||||
if (process.env.CHANNEL === 'dev') {
|
||||
console.info('Saving logger conf:', conf)
|
||||
}
|
||||
|
||||
@ -954,7 +954,7 @@ export class Aard {
|
||||
searchRow += scanSpacing
|
||||
) {
|
||||
if (++outerIteration > height) {
|
||||
console.warn('[ultrawidify|aard::subtitleScanRegionLinear] — scan got stuck in an infinite loop. This shouldn\'t happen.');
|
||||
// console.warn('[ultrawidify|aard::subtitleScanRegionLinear] — scan got stuck in an infinite loop. This shouldn\'t happen.');
|
||||
results.uncertain;
|
||||
break outerLoop;
|
||||
}
|
||||
|
||||
@ -113,7 +113,7 @@ export class LogAggregator {
|
||||
|
||||
private storageChangeListener(changes, area) {
|
||||
if (!changes[STORAGE_LOG_SETTINGS_KEY]) {
|
||||
console.info('We dont have any logging settings, not processing frther', changes);
|
||||
// console.info('We dont have any logging settings, not processing frther', changes);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -213,6 +213,8 @@ class Settings {
|
||||
}
|
||||
);
|
||||
|
||||
// this.active.newFeatureTracker = {};
|
||||
|
||||
|
||||
// apply all remaining patches
|
||||
this.logger?.info('applySettingsPatches', `There are ${ExtensionConfPatch.length - index} settings patches to apply`);
|
||||
@ -288,19 +290,6 @@ class Settings {
|
||||
return this.active;
|
||||
}
|
||||
|
||||
// This means extension update happened.
|
||||
// btw fun fact — we can do version rollbacks, which might come in handy while testing
|
||||
this.active.version = this.version;
|
||||
|
||||
// if extension has been updated, update existing settings with any options added in the
|
||||
// new version. In addition to that, we remove old keys that are no longer used.
|
||||
const patched = ObjectCopy.addNew(settings, this.default);
|
||||
this.logger?.info('init',"Results from ObjectCopy.addNew()?", patched, "\n\nSettings from storage", settings, "\ndefault?", this.default);
|
||||
|
||||
if (patched) {
|
||||
this.active = patched;
|
||||
}
|
||||
|
||||
// in case settings in previous version contained a fucky wucky, we overwrite existing settings with a patch
|
||||
this.applySettingsPatches(oldVersion);
|
||||
|
||||
|
||||
@ -11,6 +11,7 @@ import PageInfo from './PageInfo';
|
||||
import { RunLevel } from '../../enum/run-level.enum';
|
||||
import { ExtensionEnvironment } from '../../../common/interfaces/SettingsInterface';
|
||||
import { ComponentLogger } from '../logging/ComponentLogger';
|
||||
import { collectionHas, equalish } from '../../util/comparators';
|
||||
|
||||
if (process.env.CHANNEL !== 'stable'){
|
||||
console.info("Loading: PlayerData.js");
|
||||
@ -96,6 +97,7 @@ class PlayerData {
|
||||
isTooSmall: boolean = true;
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region misc stuff
|
||||
extensionMode: any;
|
||||
dimensions: PlayerDimensions;
|
||||
@ -144,11 +146,12 @@ class PlayerData {
|
||||
private dimensionChangeListener = {
|
||||
that: this,
|
||||
handleEvent: function(event: Event) {
|
||||
this.that.trackEnvironmentChanges(event);
|
||||
this.that.trackDimensionChanges()
|
||||
this.that.requestTick();
|
||||
}
|
||||
}
|
||||
|
||||
private fallbackDimensionChangeInterval: any;
|
||||
|
||||
/**
|
||||
* Gets player aspect ratio. If in full screen, it returns screen aspect ratio unless settings say otherwise.
|
||||
*/
|
||||
@ -158,8 +161,7 @@ class PlayerData {
|
||||
return window.innerWidth / window.innerHeight;
|
||||
}
|
||||
if (!this.dimensions) {
|
||||
this.trackDimensionChanges();
|
||||
this.trackEnvironmentChanges();
|
||||
return (this.element?.scrollWidth ?? this.videoElement.videoWidth) / (this.element?.scrollHeight ?? this.videoElement.videoHeight);
|
||||
}
|
||||
|
||||
return this.dimensions.width / this.dimensions.height;
|
||||
@ -225,7 +227,6 @@ class PlayerData {
|
||||
}
|
||||
|
||||
this.startChangeDetection();
|
||||
|
||||
document.addEventListener('fullscreenchange', this.dimensionChangeListener);
|
||||
|
||||
// we want to reload on storage changes
|
||||
@ -236,35 +237,6 @@ class PlayerData {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if player dimensions are too small for autodetection to run.
|
||||
* Full screen is never too small, even if it's
|
||||
* @param playerDimensions
|
||||
* @returns
|
||||
*/
|
||||
private checkIfTooSmall(playerDimensions?: PlayerDimensions) {
|
||||
if (playerDimensions) {
|
||||
return !playerDimensions.fullscreen && (playerDimensions.width < 1208 || playerDimensions.height < 720);
|
||||
} else {
|
||||
return !document.fullscreenElement && (this.element.clientWidth < 1208 || this.element.clientHeight < 720);
|
||||
}
|
||||
}
|
||||
|
||||
private reloadPlayerDataConfig(siteConfUpdate) {
|
||||
// this.siteSettings = siteConfUpdate;
|
||||
this.updatePlayer();
|
||||
|
||||
this.periodicallyRefreshPlayerElement = false;
|
||||
try {
|
||||
this.periodicallyRefreshPlayerElement = this.siteSettings.data.currentDOMConfig.periodicallyRefreshPlayerElement;
|
||||
} catch (e) {
|
||||
// no biggie — that means we don't have any special settings for this site.
|
||||
}
|
||||
|
||||
// because this is often caused by the UI
|
||||
this.handlePlayerTreeRequest();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes event bus
|
||||
*/
|
||||
@ -276,18 +248,27 @@ class PlayerData {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Completely stops everything the extension is doing
|
||||
*/
|
||||
destroy() {
|
||||
document.removeEventListener('fullscreenchange', this.dimensionChangeListener);
|
||||
this.stopChangeDetection();
|
||||
this.ui?.destroy();
|
||||
this.notificationService?.destroy();
|
||||
private initFallbackDimensionMonitor() {
|
||||
this.stopFallbackDimensionMonitor();
|
||||
this.fallbackDimensionChangeInterval = setInterval( () => {
|
||||
this.processTick();
|
||||
}, 2000);
|
||||
}
|
||||
//#endregion
|
||||
|
||||
deferredUiInitialization(playerDimensions) {
|
||||
/**
|
||||
* Stops manually scanning for dimension changes
|
||||
*/
|
||||
stopFallbackDimensionMonitor() {
|
||||
clearImmediate(this.fallbackDimensionChangeInterval);
|
||||
this.fallbackDimensionChangeInterval = undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialized player UI at a later time.
|
||||
* @param playerDimensions
|
||||
* @returns
|
||||
*/
|
||||
deferredUiInitialization(playerDimensions = this.dimensions) {
|
||||
if (this.ui || this.siteSettings.data.enableUI.fullscreen === ExtensionMode.Disabled) {
|
||||
return;
|
||||
}
|
||||
@ -325,6 +306,44 @@ class PlayerData {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Completely stops everything the extension is doing
|
||||
*/
|
||||
destroy() {
|
||||
document.removeEventListener('fullscreenchange', this.dimensionChangeListener);
|
||||
this.stopChangeDetection();
|
||||
this.ui?.destroy();
|
||||
this.notificationService?.destroy();
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region utils
|
||||
/**
|
||||
* Checks if player dimensions are too small for autodetection to run.
|
||||
* Full screen is never too small, even if it's
|
||||
* @param playerDimensions
|
||||
* @returns
|
||||
*/
|
||||
private checkIfTooSmall() {
|
||||
return !document.fullscreenElement && (this.element.clientWidth < 1208 || this.element.clientHeight < 720);
|
||||
}
|
||||
|
||||
private reloadPlayerDataConfig(siteConfUpdate) {
|
||||
// this.siteSettings = siteConfUpdate;
|
||||
this.updatePlayer();
|
||||
|
||||
this.periodicallyRefreshPlayerElement = false;
|
||||
try {
|
||||
this.periodicallyRefreshPlayerElement = this.siteSettings.data.currentDOMConfig.periodicallyRefreshPlayerElement;
|
||||
} catch (e) {
|
||||
// no biggie — that means we don't have any special settings for this site.
|
||||
}
|
||||
|
||||
// because this is often caused by the UI
|
||||
this.handlePlayerTreeRequest();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets extension runLevel and sets or unsets appropriate css classes as necessary
|
||||
* @param runLevel
|
||||
@ -356,161 +375,12 @@ class PlayerData {
|
||||
this.runLevel = runLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detects whether player element is in theater mode or not.
|
||||
* If theater mode changed, emits event.
|
||||
* @returns whether player is in theater mode
|
||||
*/
|
||||
private detectTheaterMode() {
|
||||
const oldTheaterMode = this.isTheaterMode;
|
||||
const newTheaterMode = this.equalish(window.innerWidth, this.element.offsetWidth, 32);
|
||||
//#endregion
|
||||
|
||||
this.isTheaterMode = newTheaterMode;
|
||||
|
||||
// theater mode changed
|
||||
if (oldTheaterMode !== newTheaterMode) {
|
||||
if (newTheaterMode) {
|
||||
this.eventBus.send('player-theater-enter', {});
|
||||
} else {
|
||||
this.eventBus.send('player-theater-exit', {});
|
||||
}
|
||||
}
|
||||
|
||||
return newTheaterMode;
|
||||
}
|
||||
|
||||
trackEnvironmentChanges() {
|
||||
if (this.environment !== this.lastEnvironment) {
|
||||
this.lastEnvironment = this.environment;
|
||||
this.eventBus.send('uw-environment-change', {newEnvironment: this.environment});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
trackDimensionChanges() {
|
||||
if (this._isTrackDimensionChangesActive) {
|
||||
// this shouldn't really get called, _ever_ ... but sometimes it happens
|
||||
console.warn('[PlayerData::trackDimensionChanges] trackDimensionChanges is already active!');
|
||||
return;
|
||||
}
|
||||
|
||||
this._isTrackDimensionChangesActive = true;
|
||||
|
||||
try {
|
||||
// get player dimensions _once_
|
||||
let currentPlayerDimensions;
|
||||
let fsChanged = this.isFullscreen !== !!document.fullscreenElement;
|
||||
|
||||
this.isFullscreen = !!document.fullscreenElement;
|
||||
|
||||
if (this.isFullscreen) {
|
||||
currentPlayerDimensions = {
|
||||
width: window.innerWidth,
|
||||
height: window.innerHeight,
|
||||
};
|
||||
} else {
|
||||
currentPlayerDimensions = {
|
||||
width: this.element.offsetWidth,
|
||||
height: this.element.offsetHeight
|
||||
};
|
||||
|
||||
this.detectTheaterMode();
|
||||
}
|
||||
|
||||
// defer creating UI
|
||||
this.deferredUiInitialization(currentPlayerDimensions);
|
||||
|
||||
// if dimensions of the player box are the same as the last known
|
||||
// dimensions, we don't have to do anything ... in theory. In practice,
|
||||
// sometimes restore-ar doesn't appear to register the first time, and
|
||||
// this function doesn't really run often enough to warrant finding a
|
||||
// real, optimized fix.
|
||||
if (
|
||||
this.dimensions?.width == currentPlayerDimensions.width
|
||||
&& this.dimensions?.height == currentPlayerDimensions.height
|
||||
) {
|
||||
this.eventBus.send('restore-ar', null);
|
||||
this.eventBus.send('delayed-restore-ar', {delay: 500});
|
||||
this.dimensions = currentPlayerDimensions;
|
||||
this._isTrackDimensionChangesActive = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
if (fsChanged) {
|
||||
this.updatePlayer();
|
||||
}
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
|
||||
this._isTrackDimensionChangesActive = false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks if extension is allowed to run in current environment.
|
||||
* @param currentPlayerDimensions
|
||||
*/
|
||||
private handleSizeConstraints(currentPlayerDimensions: PlayerDimensions) {
|
||||
// Check if extension is allowed to run in current combination of theater + full screen
|
||||
const canEnable = this.siteSettings.isEnabledForEnvironment(this.isFullscreen, this.isTheaterMode) === ExtensionMode.Enabled;
|
||||
|
||||
if (this.runLevel === RunLevel.Off && canEnable) {
|
||||
this.eventBus.send('restore-ar', null);
|
||||
// must be called after
|
||||
this.handleDimensionChanges(currentPlayerDimensions, this.dimensions);
|
||||
} else if (!canEnable && this.runLevel !== RunLevel.Off) {
|
||||
// must be called before
|
||||
this.handleDimensionChanges(currentPlayerDimensions, this.dimensions);
|
||||
this.setRunLevel(RunLevel.Off);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private handleDimensionChanges(newDimensions: PlayerDimensions, oldDimensions: PlayerDimensions) {
|
||||
if (this.runLevel === RunLevel.Off ) {
|
||||
this.logger.info('handleDimensionChanges', "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.info('handleDimensionChanges', "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.eventBus.send('restore-ar', null);
|
||||
this.eventBus.send('delayed-restore-ar', {delay: 500});
|
||||
// this.videoData.resizer?.restore();
|
||||
this.eventBus.send('uw-config-broadcast', {
|
||||
type: 'player-dimensions',
|
||||
data: newDimensions
|
||||
});
|
||||
|
||||
|
||||
this.isTooSmall = this.checkIfTooSmall(newDimensions);
|
||||
}
|
||||
}
|
||||
|
||||
onPlayerDimensionsChanged: ResizeObserverCallback = _.debounce(
|
||||
(mutationList?, observer?) => {
|
||||
this.trackDimensionChanges();
|
||||
this.trackEnvironmentChanges();
|
||||
this._requestTick(true);
|
||||
},
|
||||
250, // do it once per this many ms
|
||||
{
|
||||
@ -519,6 +389,112 @@ class PlayerData {
|
||||
}
|
||||
);
|
||||
|
||||
private _requestTick(immediately?: boolean) {
|
||||
if (immediately) {
|
||||
this.processTick();
|
||||
}
|
||||
}
|
||||
|
||||
// Currently just a dummy, but at some point we could try to avoid running
|
||||
// processTick on every tick — instead, running it only when needed.
|
||||
// But today is not that day.
|
||||
requestTick() {
|
||||
this._requestTick();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if anything changed
|
||||
* @returns
|
||||
*/
|
||||
private processTick() {
|
||||
let changeDetected = false;
|
||||
let changes = {
|
||||
player: false,
|
||||
fullScreen: false,
|
||||
theater: false,
|
||||
dimensions: false,
|
||||
}
|
||||
let fs, newPlayerCandidate, isTheaterMode, currentDimensions;
|
||||
|
||||
fullScreenCheck:
|
||||
{
|
||||
fs = !!document.fullscreenElement;
|
||||
if (fs !== this.isFullscreen) {
|
||||
changes.fullScreen = true;
|
||||
changeDetected = true;
|
||||
}
|
||||
}
|
||||
|
||||
playerCheck:
|
||||
{
|
||||
newPlayerCandidate = this.getPlayer();
|
||||
if (!newPlayerCandidate) {
|
||||
console.warn('[uw->PlayerData::processTick()] — player not detected — dimensions will not be checked')
|
||||
return;
|
||||
}
|
||||
if (newPlayerCandidate !== this.element) {
|
||||
changes.player = true;
|
||||
changeDetected = true;
|
||||
}
|
||||
}
|
||||
|
||||
theaterModeCheck:
|
||||
{
|
||||
isTheaterMode = equalish(window.innerWidth, this.element.offsetWidth, 32);
|
||||
if (isTheaterMode !== this.isTheaterMode) {
|
||||
changes.theater = true;
|
||||
changeDetected = true;
|
||||
}
|
||||
}
|
||||
|
||||
dimensionCheck:
|
||||
{
|
||||
if (this.isFullscreen) {
|
||||
currentDimensions = {
|
||||
width: window.innerWidth,
|
||||
height: window.innerHeight,
|
||||
};
|
||||
} else {
|
||||
currentDimensions = {
|
||||
width: this.element.offsetWidth,
|
||||
height: this.element.offsetHeight
|
||||
};
|
||||
}
|
||||
|
||||
if (currentDimensions.width !== this.dimensions?.width || currentDimensions.height !== this.dimensions?.height) {
|
||||
changes.dimensions = true;
|
||||
changeDetected = true;
|
||||
}
|
||||
}
|
||||
|
||||
// we only commit changes if no errors were encountered
|
||||
commitChanges:
|
||||
{
|
||||
if (changes.fullScreen) this.isFullscreen = fs;
|
||||
if (changes.player) this.element = newPlayerCandidate;
|
||||
if (changes.theater) this.isTheaterMode = isTheaterMode;
|
||||
if (changes.dimensions) this.dimensions = currentDimensions;
|
||||
|
||||
this.isTooSmall = this.checkIfTooSmall();
|
||||
}
|
||||
|
||||
const canEnable = this.siteSettings.isEnabledForEnvironment(this.isFullscreen, this.isTheaterMode) === ExtensionMode.Enabled;
|
||||
|
||||
if (this.runLevel === RunLevel.Off && canEnable) {
|
||||
this.eventBus.send('restore-ar', null);
|
||||
} else if (!canEnable && this.runLevel !== RunLevel.Off) {
|
||||
// must be called before
|
||||
this.eventBus.send('restore-ar', null);
|
||||
this.setRunLevel(RunLevel.Off);
|
||||
}
|
||||
|
||||
if (changeDetected) {
|
||||
this.deferredUiInitialization();
|
||||
this.eventBus.send('restore-ar', null);
|
||||
this.eventBus.send('delayed-restore-ar', {delay: 500});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//#region player element change detection
|
||||
/**
|
||||
@ -546,46 +522,13 @@ class PlayerData {
|
||||
|
||||
// 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) {
|
||||
await sleep(1000);
|
||||
try {
|
||||
this.forceRefreshPlayerElement();
|
||||
} catch (e) {
|
||||
console.error('[PlayerData::legacycd] this message is pretty high on the list of messages you shouldn\'t see', e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
doPeriodicPlayerElementChangeCheck() {
|
||||
if (this.periodicallyRefreshPlayerElement) {
|
||||
this.forceRefreshPlayerElement();
|
||||
}
|
||||
this.initFallbackDimensionMonitor();
|
||||
}
|
||||
|
||||
stopChangeDetection(){
|
||||
this.observer.disconnect();
|
||||
}
|
||||
|
||||
|
||||
//#region helper functions
|
||||
collectionHas(collection, element) {
|
||||
for (let i = 0, len = collection.length; i < len; i++) {
|
||||
if (collection[i] == element) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
equalish(a,b, tolerance) {
|
||||
return a > b - tolerance && a < b + tolerance;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
private getElementStack(): ElementStack {
|
||||
const elementStack: ElementStack = [{
|
||||
element: this.videoElement,
|
||||
@ -617,19 +560,22 @@ class PlayerData {
|
||||
return this.elementStack;
|
||||
}
|
||||
|
||||
|
||||
updatePlayer(options?: {verbose?: boolean, newElement?: HTMLElement}) {
|
||||
const newPlayer = options?.newElement ?? this.getPlayer(options);
|
||||
|
||||
if (newPlayer === this.element) {
|
||||
if (newPlayer === this.element || !newPlayer) {
|
||||
return;
|
||||
}
|
||||
this.observer?.unobserve(this.element);
|
||||
|
||||
// clean up and re-initialize UI
|
||||
this.ui?.destroy();
|
||||
delete this.ui;
|
||||
|
||||
// Don't forget to also move observer to the new player
|
||||
// (if observer exists)
|
||||
this.element = newPlayer;
|
||||
this.observer?.observe(this.element);
|
||||
|
||||
this.ui = new UI(
|
||||
'ultrawidifyUi',
|
||||
@ -642,8 +588,7 @@ class PlayerData {
|
||||
}
|
||||
);
|
||||
|
||||
this.trackDimensionChanges();
|
||||
this.trackEnvironmentChanges();
|
||||
this.requestTick();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -695,10 +640,14 @@ class PlayerData {
|
||||
return playerCandidate.element;
|
||||
} else {
|
||||
const playerCandidate = this.getPlayerAuto(elementStack, videoWidth, videoHeight);
|
||||
if (playerCandidate === null) {
|
||||
console.warn('[uw::getPlayer] getPlayerAuto returned null — no player detected?');
|
||||
} else {
|
||||
playerCandidate.heuristics['activePlayer'] = true;
|
||||
return playerCandidate.element;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private nextPlayerElement() {
|
||||
@ -713,8 +662,8 @@ class PlayerData {
|
||||
const elementStack = this.getElementStack();
|
||||
|
||||
if (
|
||||
this.equalish(elementStack[currentIndex].element.offsetWidth, elementStack[nextIndex].element.offsetWidth, 2)
|
||||
&& this.equalish(elementStack[currentIndex].element.offsetHeight, elementStack[nextIndex].element.offsetHeight, 2)
|
||||
equalish(elementStack[currentIndex].element.offsetWidth, elementStack[nextIndex].element.offsetWidth, 2)
|
||||
&& equalish(elementStack[currentIndex].element.offsetHeight, elementStack[nextIndex].element.offsetHeight, 2)
|
||||
) {
|
||||
// this.siteSettings.set('playerAutoConfig.initialIndex', this.siteSettings.data.playerAutoConfig.initialIndex + 1, {noSave: true});
|
||||
// this.siteSettings.set('playerAutoConfig.modified', true);
|
||||
@ -765,8 +714,9 @@ class PlayerData {
|
||||
// Don't bother thinking about this too much, as any "thinking" was quickly
|
||||
// corrected by bugs caused by various edge cases.
|
||||
if (
|
||||
this.equalish(elementData.height, videoHeight, 5)
|
||||
|| this.equalish(elementData.width, videoWidth, 5)
|
||||
|
||||
equalish(elementData.height, videoHeight, 5)
|
||||
|| equalish(elementData.width, videoWidth, 5)
|
||||
) {
|
||||
let score = 1000;
|
||||
|
||||
@ -877,14 +827,14 @@ class PlayerData {
|
||||
const allSelectors = document.querySelectorAll(queryString);
|
||||
|
||||
for (const element of elementStack) {
|
||||
if (this.collectionHas(allSelectors, element.element)) {
|
||||
if (collectionHas(allSelectors, element.element)) {
|
||||
let score = 100;
|
||||
|
||||
// we award points to elements which match video size in one
|
||||
// dimension and exceed it in the other
|
||||
if (
|
||||
(element.width >= videoWidth && this.equalish(element.height, videoHeight, 2))
|
||||
|| (element.height >= videoHeight && this.equalish(element.width, videoWidth, 2))
|
||||
(element.width >= videoWidth && equalish(element.height, videoHeight, 2))
|
||||
|| (element.height >= videoHeight && equalish(element.width, videoWidth, 2))
|
||||
) {
|
||||
score += 75;
|
||||
}
|
||||
@ -917,8 +867,6 @@ class PlayerData {
|
||||
private handlePlayerTreeRequest() {
|
||||
// this populates this.elementStack fully
|
||||
this.updatePlayer({verbose: true});
|
||||
console.log('tree:', JSON.parse(JSON.stringify(this.elementStack)));
|
||||
console.log('————————————————————— handling player tree request!')
|
||||
this.eventBus.send('uw-config-broadcast', {type: 'player-tree', config: JSON.parse(JSON.stringify(this.elementStack))});
|
||||
}
|
||||
|
||||
@ -933,7 +881,7 @@ class PlayerData {
|
||||
this.markedElement.remove();
|
||||
}
|
||||
|
||||
const elementBB = this.elementStack[data.parentIndex].element.getBoundingClientRect();
|
||||
const elementBB = this.elementStack[data.parentIndex].element.getBoundingClientRect();;
|
||||
|
||||
// console.log('element bounding box:', elementBB);
|
||||
|
||||
|
||||
@ -65,6 +65,8 @@ class Resizer {
|
||||
|
||||
private effectiveZoom: {x: number, y: number} = {x: 1, y: 1};
|
||||
|
||||
private pendingAr?: {ar: Ar, lastAr?: Ar};
|
||||
|
||||
_lastAr: Ar = {type: AspectRatioType.Initial};
|
||||
set lastAr(x: Ar) {
|
||||
// emit updates for UI when setting lastAr, but only if AR really changed
|
||||
@ -332,6 +334,19 @@ class Resizer {
|
||||
return;
|
||||
}
|
||||
|
||||
// If we are missing some data that's necessary for crop calculations,
|
||||
// set pendingAr and quit
|
||||
if (!this.videoData.player.dimensions?.width || !this.videoData.player.dimensions?.height) {
|
||||
this.pendingAr = {ar, lastAr};
|
||||
this.videoData.player.requestTick();
|
||||
return;
|
||||
}
|
||||
this.pendingAr = null;
|
||||
|
||||
if (! this.videoData.player.dimensions) {
|
||||
this.videoData.player.updatePlayer();
|
||||
}
|
||||
|
||||
// If no aspect ratio is applied AND if no stretch mode is active,
|
||||
// we disable our CSS in order to prevent breaking websites by default,
|
||||
// without any human interaction
|
||||
@ -465,8 +480,12 @@ class Resizer {
|
||||
// this.videoData.eventBus.send('announce-zoom', this.manualZoom ? {x: this.zoom.scale, y: this.zoom.scaleY} : this.zoom.effectiveZoom);
|
||||
// }
|
||||
|
||||
let translate = this.computeOffsets(stretchFactors, options?.ar);
|
||||
try {
|
||||
const translate = this.computeOffsets(stretchFactors, options?.ar);
|
||||
this.applyCss(stretchFactors, translate);
|
||||
} catch (e) {
|
||||
// don't apply CSS if there's an error
|
||||
}
|
||||
}
|
||||
|
||||
toFixedAr() {
|
||||
@ -567,6 +586,10 @@ class Resizer {
|
||||
* @returns
|
||||
*/
|
||||
restore() {
|
||||
if (this.pendingAr) {
|
||||
this.setAr(this.pendingAr.ar, this.pendingAr.lastAr);
|
||||
return;
|
||||
}
|
||||
if (!this.manualZoom) {
|
||||
this.logger.info('restore', `<rid:${this.resizerId}> attempting to restore aspect ratio`, {'lastAr': this.lastAr} );
|
||||
|
||||
@ -858,16 +881,15 @@ class Resizer {
|
||||
) {
|
||||
this.logger.warn('computeOffsets', `<rid:${this.resizerId}> We are getting some incredibly funny results here.\n\n`,
|
||||
`Video seems to be both wider and taller (or shorter and narrower) than player element at the same time. This is super duper not supposed to happen.\n\n`,
|
||||
`Something is probably undefined:\n`,
|
||||
`\n videoData.video offset w x h:`, this.videoData.video.offsetWidth, 'x', this.videoData.video.offsetHeight,
|
||||
`\n videoData.player.dimensions w x h:`, this.videoData.player.dimensions.width, 'x', this.videoData.player.dimensions.height,
|
||||
`Player element needs to be checked.`
|
||||
);
|
||||
|
||||
// sometimes this appears to randomly recurse.
|
||||
// There seems to be no way to reproduce it.
|
||||
if (! this._computeOffsetsRecursionGuard) {
|
||||
this._computeOffsetsRecursionGuard = true;
|
||||
this.videoData.player.trackDimensionChanges();
|
||||
this._computeOffsetsRecursionGuard = false;
|
||||
}
|
||||
// request dimension change tick.
|
||||
// this will cause
|
||||
this.videoData.player.requestTick();
|
||||
throw 'DIMENSIONS_ERROR';
|
||||
}
|
||||
|
||||
return translate;
|
||||
|
||||
12
src/ext/util/comparators.ts
Normal file
12
src/ext/util/comparators.ts
Normal file
@ -0,0 +1,12 @@
|
||||
export function collectionHas(collection, element): boolean {
|
||||
for (let i = 0, len = collection.length; i < len; i++) {
|
||||
if (collection[i] == element) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function equalish(a: number,b: number, tolerance: number): boolean {
|
||||
return a > b - tolerance && a < b + tolerance;
|
||||
}
|
||||
@ -2,7 +2,7 @@
|
||||
"manifest_version": 3,
|
||||
"name": "Ultrawidify",
|
||||
"description": "Removes black bars on ultrawide videos and offers advanced options to fix aspect ratio.",
|
||||
"version": "6.3.990",
|
||||
"version": "6.3.993",
|
||||
"icons": {
|
||||
"32":"res/icons/uw-32.png",
|
||||
"64":"res/icons/uw-64.png"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user