Try to detect when UI is not clickable
This commit is contained in:
parent
55c0e7e8c5
commit
ad1e73d0cc
@ -329,6 +329,7 @@ export interface SiteSettingsInterface {
|
||||
stretchModePersistence?: CropModePersistence;
|
||||
alignmentPersistence?: CropModePersistence;
|
||||
|
||||
playerAutoConfig?: PlayerAutoConfigInterface;
|
||||
|
||||
activeDOMConfig?: string;
|
||||
DOMConfig?: { [x: string]: SiteDOMSettingsInterface };
|
||||
@ -341,6 +342,12 @@ export interface SiteSettingsInterface {
|
||||
override?: boolean; // whether settings for this site will be overwritten by extension upgrade script
|
||||
}
|
||||
|
||||
export interface PlayerAutoConfigInterface {
|
||||
modified: boolean;
|
||||
initialIndex: number;
|
||||
currentIndex: number;
|
||||
}
|
||||
|
||||
export interface SiteDOMSettingsInterface {
|
||||
type: 'official' | 'community' | 'user-defined' | 'modified' | undefined;
|
||||
elements?: {
|
||||
|
@ -24,7 +24,17 @@
|
||||
@mouseleave="allowContextMenuHide()"
|
||||
>
|
||||
<template v-slot:activator>
|
||||
<div class="context-item uw-clickable uw-menu-trigger">
|
||||
<div class="context-item uw-clickable uw-menu-trigger relative">
|
||||
<div v-if="hoverStats.isOverTriggerMenu && !hoverStats.hasMouse" class="absolute ui-warning">
|
||||
<b>Video player is not being detected correctly</b><br/>
|
||||
<p>
|
||||
That's why this menu doesn't work correctly.
|
||||
</p>
|
||||
<p>
|
||||
It may start working if you move your mouse over the button a few times. If it doesn't, open the UI from the extension popup.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
Ultrawidify
|
||||
</div>
|
||||
</template>
|
||||
@ -327,7 +337,6 @@ export default {
|
||||
(data) => {
|
||||
switch (data.type) {
|
||||
case 'drm-status':
|
||||
console.log('got DRM status!');
|
||||
this.statusFlags.hasDrm = data.hasDrm;
|
||||
break;
|
||||
case 'aard-error':
|
||||
@ -619,6 +628,22 @@ export default {
|
||||
block-size: fit-content;
|
||||
}
|
||||
|
||||
.ui-warning {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
transform: translateY(-100%);
|
||||
|
||||
max-width: 16rem;
|
||||
width: 16rem;
|
||||
|
||||
overflow: hidden;
|
||||
overflow-wrap: break-word;
|
||||
|
||||
white-space: normal;
|
||||
word-break: break-word;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
|
||||
.context-spawn {
|
||||
position: absolute;
|
||||
|
@ -26,6 +26,12 @@ export default {
|
||||
width: '50dvw',
|
||||
transform: 'translateX(-50%)'
|
||||
},
|
||||
hoverStats: {
|
||||
isOverTriggerZone: false,
|
||||
isOverMenuTrigger: false,
|
||||
isOverUIArea: false,
|
||||
hasMouse: false,
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@ -75,6 +81,10 @@ export default {
|
||||
let isOverMenuTrigger = false;
|
||||
const elements = document.elementsFromPoint(eventData.coords.x, eventData.coords.y);
|
||||
|
||||
if (!elements.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const element of elements) {
|
||||
if (element.classList?.contains('uw-clickable')) {
|
||||
isClickable = true;
|
||||
@ -90,6 +100,7 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.triggerZoneActive = isOverTriggerZone;
|
||||
|
||||
// show ultrawidify trigger zone and set it to vanish after 250ms
|
||||
@ -112,15 +123,22 @@ export default {
|
||||
// this.uwTriggerZoneVisible = false;
|
||||
}
|
||||
|
||||
const hasMouse = !!document.querySelector(':hover');
|
||||
|
||||
this.hoverStats.isOverTriggerZone = isOverTriggerZone;
|
||||
this.hoverStats.isOverMenuTrigger = isOverMenuTrigger;
|
||||
this.hoverStats.isOverUIArea = isOverUIArea;
|
||||
this.hoverStats.hasMouse = hasMouse
|
||||
|
||||
window.parent.postMessage(
|
||||
{
|
||||
action: 'uwui-clickable',
|
||||
clickable: isClickable,
|
||||
hoverStats: {
|
||||
isOverTriggerZone,
|
||||
isOverMenuTrigger,
|
||||
isOverUIArea,
|
||||
hasMouse: !!document.querySelector(':hover'),
|
||||
isOverTriggerZone: isOverTriggerZone,
|
||||
isOverMenuTrigger: isOverMenuTrigger,
|
||||
isOverUIArea: isOverUIArea,
|
||||
hasMouse: hasMouse
|
||||
},
|
||||
ts: +new Date()
|
||||
},
|
||||
|
@ -184,7 +184,9 @@ export class SiteSettings {
|
||||
* @returns parent element index if possible, undefined otherwise
|
||||
*/
|
||||
getPlayerIndex(): number | undefined {
|
||||
return this.data.currentDOMConfig?.elements?.player?.manual && this.data.currentDOMConfig?.elements?.player?.index || undefined;
|
||||
return this.data.currentDOMConfig?.elements?.player?.manual && this.data.currentDOMConfig?.elements?.player?.index
|
||||
|| this.data.playerAutoConfig?.modified && this.data.playerAutoConfig?.currentIndex
|
||||
|| undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -47,6 +47,7 @@ class UI {
|
||||
|
||||
this.iframeErrorCount = 0;
|
||||
this.iframeConfirmed = false;
|
||||
this.iframeRejected = false;
|
||||
}
|
||||
|
||||
async init() {
|
||||
@ -305,15 +306,17 @@ class UI {
|
||||
this.uiIframe.style.pointerEvents === 'auto'
|
||||
) {
|
||||
if (
|
||||
event.data.hoverStats.isOverTriggerZone
|
||||
event.data.hoverStats.isOverMenuTrigger
|
||||
&& !event.data.hoverStats.hasMouse
|
||||
) {
|
||||
if (!this.iframeConfirmed) {
|
||||
if (this.iframeErrorCount++ > MAX_IFRAME_ERROR_COUNT) {
|
||||
// this.
|
||||
if (this.iframeErrorCount++ > MAX_IFRAME_ERROR_COUNT && !this.iframeRejected) {
|
||||
this.iframeRejected = true;
|
||||
this.eventBus.send('change-player-element');
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
} else if (event.data.hoverStats.isOverMenuTrigger && event.data.hoverStats.hasMouse) {
|
||||
this.iframeConfirmed = true;
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,16 @@ interface PlayerDimensions {
|
||||
fullscreen?: boolean;
|
||||
}
|
||||
|
||||
interface ElementData {
|
||||
element: HTMLElement,
|
||||
type: string,
|
||||
tagName?: string,
|
||||
classList?: any,
|
||||
id?: string
|
||||
}
|
||||
|
||||
type ElementStack = ElementData[];
|
||||
|
||||
/**
|
||||
* accepts <video> tag (element) and list of names that can appear in id or class
|
||||
* returns player dimensions (width, height)
|
||||
@ -67,9 +77,8 @@ class PlayerData {
|
||||
//#endregion
|
||||
|
||||
//#region HTML objects
|
||||
videoElement: any;
|
||||
element: any;
|
||||
overlayNode: any;
|
||||
videoElement: HTMLVideoElement;
|
||||
element: HTMLElement;
|
||||
//#endregion
|
||||
|
||||
//#region flags
|
||||
@ -93,7 +102,7 @@ class PlayerData {
|
||||
|
||||
private ui: UI;
|
||||
|
||||
elementStack: any[] = [];
|
||||
elementStack: ElementStack = [] as ElementStack;
|
||||
//#endregion
|
||||
|
||||
//#region event bus configuration
|
||||
@ -103,7 +112,7 @@ class PlayerData {
|
||||
}],
|
||||
'get-player-dimensions': [{
|
||||
function: () => {
|
||||
this.eventBus.send('—————————————————————————— uw-config-broadcast', {
|
||||
this.eventBus.send('uw-config-broadcast', {
|
||||
type: 'player-dimensions',
|
||||
data: this.dimensions
|
||||
});
|
||||
@ -117,6 +126,10 @@ class PlayerData {
|
||||
}],
|
||||
'set-run-level': [{
|
||||
function: (runLevel) => this.setRunLevel(runLevel)
|
||||
}],
|
||||
'change-player-element': [{
|
||||
function: () => {
|
||||
this.nextPlayerElement();
|
||||
}]
|
||||
}
|
||||
//#endregion
|
||||
@ -169,7 +182,6 @@ class PlayerData {
|
||||
// this happens in trackDimensionChanges!
|
||||
|
||||
this.dimensions = undefined;
|
||||
this.overlayNode = undefined;
|
||||
|
||||
this.periodicallyRefreshPlayerElement = false;
|
||||
try {
|
||||
@ -504,16 +516,7 @@ class PlayerData {
|
||||
}
|
||||
//#endregion
|
||||
|
||||
/**
|
||||
* Finds and returns HTML element of the player
|
||||
*/
|
||||
getPlayer(options?: {verbose?: boolean}) {
|
||||
const host = window.location.hostname;
|
||||
let element = this.videoElement.parentNode;
|
||||
const videoWidth = this.videoElement.offsetWidth;
|
||||
const videoHeight = this.videoElement.offsetHeight;
|
||||
let playerCandidate;
|
||||
|
||||
private getElementStack(): ElementStack {
|
||||
const elementStack: any[] = [{
|
||||
element: this.videoElement,
|
||||
type: 'video',
|
||||
@ -521,6 +524,7 @@ class PlayerData {
|
||||
classList: this.videoElement.classList,
|
||||
id: this.videoElement.id,
|
||||
}];
|
||||
let element = this.videoElement.parentNode as HTMLElement;
|
||||
|
||||
// first pass to generate the element stack and translate it into array
|
||||
while (element) {
|
||||
@ -535,8 +539,23 @@ class PlayerData {
|
||||
});
|
||||
element = element.parentElement;
|
||||
}
|
||||
|
||||
this.elementStack = elementStack;
|
||||
|
||||
return this.elementStack;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds and returns HTML element of the player
|
||||
*/
|
||||
getPlayer(options?: {verbose?: boolean}): HTMLElement {
|
||||
const host = window.location.hostname;
|
||||
let element = this.videoElement.parentNode;
|
||||
const videoWidth = this.videoElement.offsetWidth;
|
||||
const videoHeight = this.videoElement.offsetHeight;
|
||||
let playerCandidate;
|
||||
|
||||
const elementStack = this.getElementStack();
|
||||
const playerQs = this.siteSettings.getCustomDOMQuerySelector('player');
|
||||
const playerIndex = this.siteSettings.getPlayerIndex();
|
||||
|
||||
@ -583,6 +602,35 @@ class PlayerData {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private nextPlayerElement() {
|
||||
const currentIndex = this.siteSettings.data.playerAutoConfig?.currentIndex ?? this.siteSettings.data.playerAutoConfig?.initialIndex;
|
||||
|
||||
if (!currentIndex) {
|
||||
// console.warn('Player Element not valid.');
|
||||
return;
|
||||
}
|
||||
|
||||
const nextIndex = currentIndex + 1;
|
||||
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)
|
||||
) {
|
||||
this.siteSettings.set('playerAutoConfig.initialIndex', this.siteSettings.data.playerAutoConfig.initialIndex + 1, {noSave: true});
|
||||
this.siteSettings.set('playerAutoConfig.modified', true);
|
||||
console.log('updated site settings:', this.siteSettings.data.playerAutoConfig);
|
||||
this.videoData.settings.saveWithoutReload();
|
||||
|
||||
this.ui?.destroy();
|
||||
this.ui = undefined;
|
||||
|
||||
this.element = elementStack[nextIndex].element;
|
||||
this.trackDimensionChanges();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets player based on some assumptions, without us defining shit.
|
||||
* @param elementStack
|
||||
@ -595,7 +643,8 @@ class PlayerData {
|
||||
const sizePenaltyMultiplier = 0.1;
|
||||
const perLevelScorePenalty = 10;
|
||||
|
||||
for (const element of elementStack) {
|
||||
for (const [index, element] of elementStack.entries()) {
|
||||
element.index = index;
|
||||
|
||||
// ignore weird elements, those would break our stuff
|
||||
if (element.width == 0 || element.height == 0) {
|
||||
@ -666,6 +715,9 @@ class PlayerData {
|
||||
bestCandidate = null;
|
||||
} else {
|
||||
bestCandidate.heuristics['autoMatch'] = true;
|
||||
if (this.siteSettings.data.playerAutoConfig?.initialIndex !== bestCandidate.index) {
|
||||
this.siteSettings.set('playerAutoConfig.initialIndex', bestCandidate.index, {reload: false});
|
||||
}
|
||||
}
|
||||
|
||||
return bestCandidate;
|
||||
@ -776,6 +828,8 @@ class PlayerData {
|
||||
}
|
||||
|
||||
forceRefreshPlayerElement() {
|
||||
this.ui?.destroy();
|
||||
this.ui = undefined;
|
||||
this.element = this.getPlayer();
|
||||
// this.notificationService?.replace(this.element);
|
||||
this.trackDimensionChanges();
|
||||
|
Loading…
Reference in New Issue
Block a user