holy shit we did it 🅱️ois, we made some progress on improving manual player detection

This commit is contained in:
Tamius Han 2022-06-10 00:22:06 +02:00
parent a1bfaaaf92
commit 320d35d9e5
4 changed files with 171 additions and 25 deletions

View File

@ -86,6 +86,9 @@
></VideoSettings>
<PlayerDetectionPanel
v-if="selectedTab === 'playerDetection'"
:settings="settings"
:eventBus="eventBus"
:site="site"
>
</PlayerDetectionPanel>
<!-- <ResizerDebugPanel :debugData="debugData">
@ -188,6 +191,8 @@ export default {
},
async created() {
console.log('player-tree: player UI base created')
this.logger = new Logger();
await this.logger.init({
allowLogging: true,
@ -291,7 +296,7 @@ export default {
selectTab(tab) {
console.log('selected tab:', tab);
console.warn('NOTE: tab selection is not syet inplemented!')
console.warn('NOTE: tab selection is not syet inplemented!');
this.selectedTab = tab;
}
}

View File

@ -16,6 +16,19 @@
You're probably on this page because Ultrawidify doesn't crop the player correctly. If you want to know more about
why this happens, explanation can be found on <a href="https://github.com/tamius-han/ultrawidify/wiki/2.-Player-detection-(and-related-problems)#why-does-ultrawidify-have-this-problem-when-this-other-extension-doesnt" target="_blank">the wiki page</a>.
</p>
<p>
If you hover over the boxes below, the corresponding element will change (sepia filter + higher brightness + reduced contrast + it gets an outline). Player element
should be the closest element to the video element, for which the sepia/brightness effect covers the area you expect the video will cover.
</p>
<div>
<b>Symbols:</b><br />
<mdicon name="alert-remove" class="invalid" /> Element of invalid dimensions<br />
<mdicon name="refresh-auto" class="auto-match" /> Ultrawidify's player detection thinks this should be the player<br />
<mdicon name="bookmark" class="parent-offset-match" /> Site settings say this should be the player (based on counting parents)<br />
<mdicon name="crosshairs" class="qs-match" /> Site settings say this should be the player (based on query selectors)<br />
<mdicon name="check-circle" class="activePlayer" /> Element that is actually the player
</div>
<div class="element-tree">
<div class="html-element-boxes">
@ -25,19 +38,52 @@
class="element-row"
>
<div class="status">
<div
v-if="element.heuristics?.invalidSize"
class="invalid"
>
<mdicon name="alert-remove" />
</div>
<div class="element-data">
<div
v-if="element.heuristics?.autoMatch"
class="auto-match"
>
<mdicon name="refresh-auto" />
</div>
<div
v-if="element.heuristics?.qsMatch"
class="qs-match"
>
<mdicon name="crosshairs" />
</div>
<div
v-if="element.heuristics?.manualElementByParentIndex"
class="parent-offset-match"
>
<mdicon name="bookmark" />
</div>
<div
v-if="element.heuristics?.activePlayer"
class="activePlayer"
>
<mdicon name="check-circle" />
</div>
</div>
<div
class="element-data"
@mouseover="markElement(index, true)"
@mouseleave="markElement(index, false)"
>
<div class="tag">
{{element.tagName}}
<b>{{element.tagName}}</b> <i class="id">{{element.id ? `#`:''}}{{element.id}}</i> @ <span class="dimensions">{{element.width}}</span>x<span class="dimensions">{{element.height}}</span>
</div>
<div v-if="element.id" class="id">
{{element.id}}
<div v-if="element.classList" class="class-list">
<div v-for="cls of element.classList" :key="cls">
{{cls}}
</div>
<div v-if="element.classList" id="class-list">
{{element.classList}}
</div>
<div class="dimensions">
{{element.width}} x {{element.height}}
</div>
</div>
<div class="css-fixes">
@ -75,17 +121,78 @@ export default({
'site'
],
created() {
this.eventBus.subscribe('uw-player-tree', {function: (elementStack) => this.handleElementStack(elementStack)});
this.eventBus.subscribe('uw-config-broadcast', {function: (config) => this.handleElementStack(config)});
},
mounted() {
this.eventBus.sendToTunnel('get-player-tree'); // TODO: implement this in PlayerData
},
computed: {},
methods: {
handleElementStack(elementStack) {
this.elementStack = elementStack;
handleElementStack(configBroadcast) {
if (configBroadcast.type === 'player-tree') {
this.elementStack = configBroadcast.config;
this.$nextTick( () => this.$forceUpdate() );
}
},
markElement(parentIndex, enable) {
console.log('will mark element:', parentIndex, enable);
this.eventBus.sendToTunnel('set-mark-element', {parentIndex, enable});
}
}
})
</script>
<style lang="scss" scoped>
.element-tree {
.html-element-boxes {
display: flex;
flex-direction: column;
.element-row {
display: flex;
flex-direction: row;
margin: 0.5rem;
.status {
width: 6.9rem;
margin-right: 1rem;
display: flex;
flex-direction: row;
justify-content: flex-end;
align-items: center;
.invalid {
color: #f00;
}
}
.element-data {
border: 1px solid rgba(255,255,255,0.5);
padding: 0.5rem 1rem;
display: flex;
flex-direction: column;
.tag {
text-transform: lowercase;
font-weight: bold;
}
.id {
font-style: italic;
}
.class-list {
font-style: italic;
opacity: 0.75;
font-size: 0.75rem;
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.dimensions {
color: #473c85;
}
}
}
}
}
</style>

View File

@ -96,6 +96,9 @@ class PlayerData {
this.invalid = false;
this.element = this.getPlayer();
this.eventBus.subscribe('get-player-tree', {function: () => this.handlePlayerTreeRequest()});
this.eventBus.subscribe('set-mark-element', {function: (data) => this.markElement(data)});
// this.notificationService = new PlayerNotificationUi(this.element, this.settings, this.eventBus);
this.ui = new UI('ultrawidifyUi', {parentElement: this.element, eventBus: this.eventBus});
// this.ui.init();
@ -413,6 +416,10 @@ class PlayerData {
}
return false;
}
equalish(a,b, tolerance) {
return a > b - tolerance && a < b + tolerance;
}
//#endregion
/**
@ -427,7 +434,10 @@ class PlayerData {
const elementStack: any[] = [{
element: this.video,
type: 'video'
type: 'video',
tagName: 'video',
classList: this.video.classList,
id: this.video.id,
}];
// first pass to generate the element stack and translate it into array
@ -456,7 +466,7 @@ class PlayerData {
// if 'verbose' option is passed, we also populate the elementStack
// with heuristics data for auto player detection.
if (playerCandidate && !options?.verbose) {
return playerCandidate;
return playerCandidate.element;
}
}
@ -464,9 +474,12 @@ class PlayerData {
// remember — we're only populating elementStack. If we found a player
// element using manual methods, we will still return that element.
this.getPlayerAuto(elementStack, videoWidth, videoHeight);
return playerCandidate;
playerCandidate.heuristics['activePlayer'] = true;
return playerCandidate.element;
} else {
return this.getPlayerAuto(elementStack, videoWidth, videoHeight);
const playerCandidate = this.getPlayerAuto(elementStack, videoWidth, videoHeight);
playerCandidate.heuristics['activePlayer'] = true;
return playerCandidate.element;
}
}
@ -545,7 +558,7 @@ class PlayerData {
if (bestCandidate.initialValue) {
bestCandidate = null;
} else {
bestCandidate = bestCandidate.element;
bestCandidate.heuristics['autoMatch'] = true;
}
return bestCandidate;
@ -587,7 +600,7 @@ class PlayerData {
if (bestCandidate.initialValue) {
bestCandidate = null;
} else {
bestCandidate = bestCandidate.element;
bestCandidate.heuristics['qsMatch'] = true;
}
return bestCandidate;
@ -596,11 +609,21 @@ class PlayerData {
private getPlayerParentIndex(elementStack: any[]) {
const host = window.location.hostname;
elementStack[this.settings.active.sites[host].DOM.player.videoAncestor].heuristics['manualElementByParentIndex'] = true;
return elementStack[this.settings.active.sites[host].DOM.player.videoAncestor].element;
return elementStack[this.settings.active.sites[host].DOM.player.videoAncestor];
}
equalish(a,b, tolerance) {
return a > b - tolerance && a < b + tolerance;
private handlePlayerTreeRequest() {
// this populates this.elementStack fully
this.getPlayer({verbose: true});
console.info('player-tree: emitting stack:', this.elementStack);
this.eventBus.send('uw-config-broadcast', {type: 'player-tree', config: JSON.parse(JSON.stringify(this.elementStack))});
}
private markElement(data: {parentIndex: number, enable: boolean}) {
console.log('mark element: got request to do border around this:', data);
this.elementStack[data.parentIndex].element.style.outline = data.enable ? '5px dashed #fa6' : null;
this.elementStack[data.parentIndex].element.style.filter = data.enable ? 'sepia(1) brightness(2) contrast(0.5)' : null;
}
forceRefreshPlayerElement() {

View File

@ -94,6 +94,7 @@ class VideoData {
this.eventBus.setUpstreamBus(pageInfo.eventBus);
}
this.setupStageOne();
}
@ -618,7 +619,7 @@ class VideoData {
return heightCompensationFactor;
}
//#region AARD handlers
//#region AARD handlers — TODO: remove, AARD handlers shouldn't be here
initArDetection() {
if(this.destroyed || this.invalid) {
// throw {error: 'VIDEO_DATA_DESTROYED', data: {videoData: this}};
@ -748,6 +749,16 @@ class VideoData {
return false;
}
/**
* Returns:
* * number of parent elements on route from <video> to <body>
* * parent index of automatically detected player element
* * index of current player element
*/
getPageOutline() {
}
}
export default VideoData;