Add global page (not loaded by extension yet), put mousemove probes in a separate file

This commit is contained in:
Tamius Han 2023-01-04 18:09:01 +01:00
parent a94092ac78
commit 3c324aa1b2
6 changed files with 187 additions and 64 deletions

69
src/csui/GlobalFrame.vue Normal file
View File

@ -0,0 +1,69 @@
<template>
<div class="uw-clickthrough relative w-100 h-100">
<template v-for="rectangle of drawnRectangles" :key="rectangle.id ?? rectangle">
<!-- Player element overlays -->
<div class="absolute z-index-overlay"
:style="rectangle.style"
>
<!-- used for drawing player element overlay rectangles - keep this section empty -->
</div>
<!-- Notification overlay -->
<div class="absolute z-index-notification notification-area">
<template v-for="notification of displayedNotifications" :key="notification.id">
<div class="notification d-flex flex-row">
<div class="notification-icon">
<mdicon :name="notification.icon ?? 'alert'" :size="128"></mdicon>
</div>
<div class="notification-text">
<h3 class="notification-title">{{ notification.title }}</h3>
<p class="notification-verbose">{{ notification.text }}</p>
</div>
</div>
</template>
</div>
</template>
</div>
</template>
<script>
import UIProbeMixin from './src/utils/UIProbeMixin';
export default {
components: {
},
mixins: [
UIProbeMixin
],
data() {
return {
drawnRectangles: [],
displayedNotifications: [],
}
},
async created() {
this.logger = new Logger();
// this prolly needs to be taken out
await this.logger.init({
allowLogging: true,
});
/**
* Setup the "companion" onMouseMove handler to the one in the content script.
* We can handle events with the same function we use to handle events from
* the content script.
*/
document.addEventListener('mousemove', (event) => {
this.handleProbe({
coords: {
x: event.clientX,
y: event.clientY
}
}, this.origin);
});
}
}
</script>

View File

@ -149,6 +149,7 @@ import ExecAction from './src/ui-libs/ExecAction';
import Logger from '../ext/lib/Logger'; import Logger from '../ext/lib/Logger';
import Settings from '../ext/lib/Settings'; import Settings from '../ext/lib/Settings';
import EventBus from '../ext/lib/EventBus'; import EventBus from '../ext/lib/EventBus';
import UIProbeMixin from './src/utils/UIProbeMixin';
export default { export default {
components: { components: {
@ -158,6 +159,9 @@ export default {
PlayerDetectionPanel, PlayerDetectionPanel,
AutodetectionSettingsPanel, DebugPanel, BaseExtensionSettings AutodetectionSettingsPanel, DebugPanel, BaseExtensionSettings
}, },
mixins: [
UIProbeMixin
],
data() { data() {
return { return {
uwTriggerZoneVisible: false, uwTriggerZoneVisible: false,
@ -246,6 +250,8 @@ export default {
async created() { async created() {
this.logger = new Logger(); this.logger = new Logger();
// this prolly needs to be taken out
await this.logger.init({ await this.logger.init({
allowLogging: true, allowLogging: true,
}); });
@ -264,14 +270,18 @@ export default {
* We can handle events with the same function we use to handle events from * We can handle events with the same function we use to handle events from
* the content script. * the content script.
*/ */
document.addEventListener('mousemove', (event) => {
this.handleProbe({ // this is handled in UIProbeMixin.js now if UIProbeMixin works, then
coords: { // this can be safely removed. Note to self leave the comment explaining
x: event.clientX, // UI probes are set in the mixin.
y: event.clientY // document.addEventListener('mousemove', (event) => {
} // this.handleProbe({
}, this.origin); // coords: {
}); // x: event.clientX,
// y: event.clientY
// }
// }, this.origin);
// });
this.eventBus.subscribe('uw-config-broadcast', {function: (data) => { this.eventBus.subscribe('uw-config-broadcast', {function: (data) => {
if (data.type === 'drm-status') { if (data.type === 'drm-status') {
@ -299,66 +309,12 @@ export default {
this.origin = event.origin; this.origin = event.origin;
this.site = event.origin.split('//')[1]; this.site = event.origin.split('//')[1];
} }
this.handleProbe(event.data, event.origin); this.handleProbe(event.data, event.origin); // handleProbe is defined in UIProbeMixin
} else if (event.data.action === 'uw-bus-tunnel') { } else if (event.data.action === 'uw-bus-tunnel') {
this.handleBusTunnelIn(event.data.payload); this.handleBusTunnelIn(event.data.payload);
} }
}, },
/**
* Handles 'uwui-probe' events. It checks whether there's a clickable element under
* cursor, and sends a reply to the content scripts that indicates whether pointer-events
* property of the iframe should be set to capture or ignore the clicks.
*/
handleProbe(eventData, origin) {
if (eventData.ts < this.lastProbeTs) {
return; // i don't know if events can arrive out-of-order. Prolly not. We still check.
}
this.lastProbeTs = eventData.ts;
// show ultrawidify trigger zone and set it to vanish after 250ms
// but don't show the trigger zone behind an active popup
if (! this.uwWindowVisible) {
this.uwTriggerZoneVisible = true;
clearTimeout(this.uwTriggerZoneTimeout);
this.uwTriggerZoneTimeout = setTimeout(
() => this.uwTriggerZoneVisible = false,
250
);
}
/* we check if our mouse is hovering over an element.
*
* gentleman's agreement: elements with uw-clickable inside the iframe will
* toggle pointerEvents on the iframe from 'none' to 'auto'
* Children of uw-clickable events should also do that.
*
* TODO: rename uw-clickable to something else, since we pretty much need that on
* our top-level element.
*/
let isClickable = false;
let element = document.elementFromPoint(eventData.coords.x, eventData.coords.y);
while (element) {
if (element?.classList.contains('uw-clickable')) {
// we could set 'pointerEvents' here and now & simply use return, but that
// might cause us a problem if we ever try to add more shit to this function
isClickable = true;
break;
}
element = element.parentElement;
}
window.parent.postMessage(
{
action: 'uwui-clickable',
clickable: isClickable,
ts: +new Date()
},
origin
);
},
showUwWindow() { showUwWindow() {
this.uwWindowFadeOut = false; this.uwWindowFadeOut = false;
this.uwWindowVisible = true; this.uwWindowVisible = true;

15
src/csui/csui-global.html Normal file
View File

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Ultrawidify - Content Script User Interface (global overlay)</title>
<!-- <link rel="stylesheet" href="csui.css"> -->
<% if (NODE_ENV === 'development') { %>
<!-- Load some resources only in development environment -->
<% } %>
</head>
<body class="uw-ultrawidify-container-root">
<div id="app"></div>
<script src="csui-global.js"></script>
</body>
</html>

11
src/csui/csui-global.js Normal file
View File

@ -0,0 +1,11 @@
import { createApp } from 'vue';
import GlobalFrame from './GlobalFrame';
import mdiVue from 'mdi-vue/v3';
import * as mdijs from '@mdi/js';
// NOTE — this is in-player interface for ultrawidify
// it is injected into the page in UI.init()
createApp(GlobalFrame)
.use(mdiVue, {icons: mdijs})
.mount('#app');

View File

@ -2,7 +2,7 @@
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>Ultravidify - Content Script User Interface</title> <title>Ultrawidify - Content Script User Interface (in-player overlay)</title>
<!-- <link rel="stylesheet" href="csui.css"> --> <!-- <link rel="stylesheet" href="csui.css"> -->
<% if (NODE_ENV === 'development') { %> <% if (NODE_ENV === 'development') { %>
<!-- Load some resources only in development environment --> <!-- Load some resources only in development environment -->

View File

@ -0,0 +1,72 @@
export default {
created() {
/**
* Setup the "companion" onMouseMove handler to the one in the content script.
* We can handle events with the same function we use to handle events from
* the content script.
*/
document.addEventListener('mousemove', (event) => {
this.handleProbe({
coords: {
x: event.clientX,
y: event.clientY
}
}, this.origin);
});
},
methods: {
/**
* Handles 'uwui-probe' events. It checks whether there's a clickable element under
* cursor, and sends a reply to the content scripts that indicates whether pointer-events
* property of the iframe should be set to capture or ignore the clicks.
*/
handleProbe(eventData, origin) {
if (eventData.ts < this.lastProbeTs) {
return; // i don't know if events can arrive out-of-order. Prolly not. We still check.
}
this.lastProbeTs = eventData.ts;
// show ultrawidify trigger zone and set it to vanish after 250ms
// but don't show the trigger zone behind an active popup
if (! this.uwWindowVisible) {
this.uwTriggerZoneVisible = true;
clearTimeout(this.uwTriggerZoneTimeout);
this.uwTriggerZoneTimeout = setTimeout(
() => this.uwTriggerZoneVisible = false,
250
);
}
/* we check if our mouse is hovering over an element.
*
* gentleman's agreement: elements with uw-clickable inside the iframe will
* toggle pointerEvents on the iframe from 'none' to 'auto'
* Children of uw-clickable events should also do that.
*
* TODO: rename uw-clickable to something else, since we pretty much need that on
* our top-level element.
*/
let isClickable = false;
let element = document.elementFromPoint(eventData.coords.x, eventData.coords.y);
while (element) {
if (element?.classList.contains('uw-clickable')) {
// we could set 'pointerEvents' here and now & simply use return, but that
// might cause us a problem if we ever try to add more shit to this function
isClickable = true;
break;
}
element = element.parentElement;
}
window.parent.postMessage(
{
action: 'uwui-clickable',
clickable: isClickable,
ts: +new Date()
},
origin
);
},
}
}