Compare commits

...

7 Commits

14 changed files with 545 additions and 241 deletions

View File

@ -1,12 +1,12 @@
<template> <template>
<div <div
class="context-spawn uw-ui-trigger" class="context-spawn uw-ui-area"
style="z-index: 1000" style="z-index: 1000;"
v-if="!triggerZoneEditorVisible"
> >
<div <div
class="spawn-container uw-trigger" class="spawn-container uw-ui-trigger debug-2"
:style="triggerZoneStyles" :style="triggerZoneStyles"
@mouseenter="(ev) => setTriggerZoneActive(true, ev)"
> >
&nbsp; &nbsp;
</div> </div>
@ -14,14 +14,14 @@
<div <div
v-if="contextMenuActive || settingsInitialized && uwTriggerZoneVisible && !isGlobal" v-if="contextMenuActive || settingsInitialized && uwTriggerZoneVisible && !isGlobal"
class="context-spawn uw-clickable" class="context-spawn uw-clickable uw-ui-area"
style="z-index: 1001" style="z-index: 1001"
@mouseenter="preventContextMenuHide()"
@mouseleave="allowContextMenuHide()"
> >
<GhettoContextMenu <GhettoContextMenu
alignment="right" class="uw-menu" alignment="right" class="uw-menu"
@mouseenter="newFeatureViewUpdate('uw6.ui-popup')" @mouseenter="() => {preventContextMenuHide(); newFeatureViewUpdate('uw6.ui-popup')}"
@mouseleave="allowContextMenuHide()"
> >
<template v-slot:activator> <template v-slot:activator>
<div class="context-item"> <div class="context-item">
@ -151,7 +151,7 @@
<div <div
v-if="settingsInitialized && uwWindowVisible" v-if="settingsInitialized && uwWindowVisible"
class="uw-window flex flex-col uw-clickable" class="uw-window flex flex-col uw-clickable uw-ui-area"
:class="{'fade-out': uwWindowFadeOut}" :class="{'fade-out': uwWindowFadeOut}"
> >
<PlayerUIWindow <PlayerUIWindow
@ -167,17 +167,17 @@
</div> </div>
<div <div
class="context-spawn uw-ui-trigger" v-if="triggerZoneEditorVisible"
style="z-index: 1000;" class="context-spawn uw-ui-area"
style="z-index: 1000; border: 2px dashed red; overflow: hidden;"
> >
<TriggerZoneEditor <TriggerZoneEditor
class="uw-clickable"
:settings="settings" :settings="settings"
:eventBus="eventBus"
:playerDimensions="playerDimensions" :playerDimensions="playerDimensions"
> >
</TriggerZoneEditor> </TriggerZoneEditor>
</div> </div>
</template> </template>
<script> <script>
@ -228,6 +228,7 @@ export default {
uwWindowFadeOut: false, uwWindowFadeOut: false,
uwWindowCloseTimeout: undefined, uwWindowCloseTimeout: undefined,
uwWindowVisible: false, uwWindowVisible: false,
triggerZoneEditorVisible: false,
// component properties // component properties
settings: {}, settings: {},
@ -387,6 +388,26 @@ export default {
} }
}); });
this.eventBus.subscribe(
'start-trigger-zone-edit',
{
function: () => {
this.triggerZoneEditorVisible = true;
this.uwWindowVisible = false;
}
}
);
this.eventBus.subscribe(
'finish-trigger-zone-edit',
{
function: () => {
this.triggerZoneEditorVisible = false;
this.showUwWindow('playerUiSettings');
}
}
);
this.sendToParentLowLevel('uwui-get-role', null); this.sendToParentLowLevel('uwui-get-role', null);
this.sendToParentLowLevel('uwui-get-theme', null); this.sendToParentLowLevel('uwui-get-theme', null);
@ -531,13 +552,11 @@ export default {
background-color: rgba(0,0,0,0.85) !important; background-color: rgba(0,0,0,0.85) !important;
} }
</style> </style>
<style lang="scss" src="./src/res-common/panels.scss" scoped module></style>
<style lang="scss" src="./src/res-common/common.scss" scoped module></style>
<style lang="scss" scoped> <style lang="scss" scoped>
@import 'res/css/uwui-base.scss';
@import 'res/css/colors.scss';
@import 'res/css/font/overpass.css';
@import 'res/css/font/overpass-mono.css';
@import 'res/css/common.scss';
@import './src/res-common/_variables';
.uw-hover { .uw-hover {
position: absolute; position: absolute;
@ -560,7 +579,7 @@ export default {
} }
.uw-window { .uw-window {
position: absolute; position: fixed;
top: 10%; top: 10%;
left: 10%; left: 10%;
@ -595,9 +614,15 @@ export default {
.context-spawn { .context-spawn {
position: absolute; position: absolute;
top: 50%; top: 0;
left: 0; left: 0;
transform: translateY(-50%);
width: 100dvw;
height: 100dvh;
box-sizing: border-box;
overflow: hidden;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-content: center; align-content: center;
@ -605,8 +630,6 @@ export default {
// width: 100%; // width: 100%;
// height: 100%; // height: 100%;
padding: 2rem;
color: #fff; color: #fff;
// .context-item { // .context-item {
@ -653,4 +676,18 @@ export default {
border: 4px solid #fa4; border: 4px solid #fa4;
} }
.debug-1 {
border: 1px solid yellow;
&:hover {
background-color: rbba(255,255,0,0.5);
}
}
.debug-2 {
border: 1px solid blue;
&:hover {
background-color: rbba(0,0,255,.5);
}
}
</style> </style>

View File

@ -1,5 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en"; style="position: relative">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="color-scheme" content="light dark"> <meta name="color-scheme" content="light dark">

View File

@ -1,12 +1,12 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en" style="position: relative">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="color-scheme" content="dark"> <meta name="color-scheme" content="dark">
<title>Ultrawidify - Content Script User Interface (in-player overlay)</title> <title>Ultrawidify - Content Script User Interface (in-player overlay)</title>
<!-- <link rel="stylesheet" href="csui.css"> --> <!-- <link rel="stylesheet" href="csui.css"> -->
</head> </head>
<body class="uw-ultrawidify-container-root" style="background-color: transparent"> <body class="uw-ultrawidify-container-root" style="background-color: transparent;">
<div id="app"></div> <div id="app"></div>
<script src="csui.js"></script> <script src="csui.js"></script>
</body> </body>

View File

@ -1,12 +1,12 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en" style="position: relative">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="color-scheme" content="light"> <meta name="color-scheme" content="light">
<title>Ultrawidify - Content Script User Interface (in-player overlay)</title> <title>Ultrawidify - Content Script User Interface (in-player overlay)</title>
<!-- <link rel="stylesheet" href="csui.css"> --> <!-- <link rel="stylesheet" href="csui.css"> -->
</head> </head>
<body class="uw-ultrawidify-container-root" style="background-color: transparent"> <body class="uw-ultrawidify-container-root" style="background-color: transparent;">
<div id="app"></div> <div id="app"></div>
<script src="csui.js"></script> <script src="csui.js"></script>
</body> </body>

View File

@ -1,11 +1,11 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en" style="position: relative">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>Ultrawidify - Content Script User Interface (in-player overlay)</title> <title>Ultrawidify - Content Script User Interface (in-player overlay)</title>
<!-- <link rel="stylesheet" href="csui.css"> --> <!-- <link rel="stylesheet" href="csui.css"> -->
</head> </head>
<body class="uw-ultrawidify-container-root" style="background-color: transparent"> <body class="uw-ultrawidify-container-root" style="background-color: transparent;">
<div id="app"></div> <div id="app"></div>
<script src="csui.js"></script> <script src="csui.js"></script>
</body> </body>

View File

@ -1,5 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en" style="position: relative">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>Title</title> <title>Title</title>

View File

@ -117,11 +117,11 @@
v-if="selectedTab === 'about'" v-if="selectedTab === 'about'"
> >
</AboutPanel> </AboutPanel>
<ResetBackupPanel <!-- <ResetBackupPanel
v-if="selectedTab === 'resetBackup'" v-if="selectedTab === 'resetBackup'"
:settings="settings" :settings="settings"
> >
</ResetBackupPanel> </ResetBackupPanel> -->
</div> </div>
</div> </div>
</div> </div>
@ -164,14 +164,14 @@ export default {
tabs: [ tabs: [
// {id: 'videoSettings', label: 'Video settings', icon: 'crop'}, // {id: 'videoSettings', label: 'Video settings', icon: 'crop'},
{id: 'extensionSettings', label: 'Site and Extension options', icon: 'cogs' }, {id: 'extensionSettings', label: 'Site and Extension options', icon: 'cogs' },
{id: 'playerUiSettings', label: 'In-player interface', icon: 'movie-cog-outline' }, {id: 'playerUiSettings', label: 'UI and keyboard', icon: 'movie-cog-outline' },
{id: 'playerDetection', label: 'Player detection', icon: 'television-play'}, {id: 'playerDetection', label: 'Player detection', icon: 'television-play'},
{id: 'autodetectionSettings', label: 'Autodetection options', icon: 'auto-fix'}, {id: 'autodetectionSettings', label: 'Autodetection options', icon: 'auto-fix'},
// {id: 'advancedOptions', label: 'Advanced options', icon: 'cogs' }, // {id: 'advancedOptions', label: 'Advanced options', icon: 'cogs' },
// {id: 'debugging', label: 'Debugging', icon: 'bug-outline' } // {id: 'debugging', label: 'Debugging', icon: 'bug-outline' }
{id: 'changelog', label: 'What\'s new', icon: 'alert-decagram' }, {id: 'changelog', label: 'What\'s new', icon: 'alert-decagram' },
{id: 'about', label: 'About', icon: 'information-outline'}, {id: 'about', label: 'About', icon: 'information-outline'},
{id: 'resetBackup', label: 'Reset and backup', icon: 'file-restore-outline'}, // {id: 'resetBackup', label: 'Reset and backup', icon: 'file-restore-outline'},
], ],
selectedTab: 'extensionSettings', selectedTab: 'extensionSettings',
BrowserDetect: BrowserDetect, BrowserDetect: BrowserDetect,

View File

@ -1,9 +1,6 @@
<template> <template>
<!-- <div class="flex flex-row">
<mdicon name="crop" :size="32" />
<h1>Crop video:</h1>
</div> -->
<div class="sub-panel-content flex flex-row flex-wrap"> <div class="sub-panel-content flex flex-row flex-wrap">
<ShortcutButton <ShortcutButton
v-for="(command, index) of settings?.active.commands.crop" v-for="(command, index) of settings?.active.commands.crop"
class="flex b3 button" class="flex b3 button"
@ -114,7 +111,7 @@
</div> </div>
</div> </div>
<div class="edit-action-area"> <div v-if="siteSettings" class="edit-action-area">
<div class="field"> <div class="field">
<div class="label">Default for this site</div> <div class="label">Default for this site</div>
<div class="select"> <div class="select">
@ -176,11 +173,19 @@ export default {
}, },
computed: { computed: {
siteDefaultCrop() { siteDefaultCrop() {
if (!this.siteSettings) {
return null;
}
return JSON.stringify( return JSON.stringify(
this.siteSettings.data.defaults.crop this.siteSettings.data.defaults.crop
); );
}, },
}, },
created() {
if (this.isEditing) {
this.enableEditMode();
}
},
watch: { watch: {
isEditing(newValue, oldValue) { isEditing(newValue, oldValue) {
if (newValue) { if (newValue) {
@ -195,6 +200,9 @@ export default {
* Sets default crop, for either site or global * Sets default crop, for either site or global
*/ */
setDefaultCrop($event, scope) { setDefaultCrop($event, scope) {
if (!this.siteSettings) {
return;
}
const commandArguments = JSON.parse($event.target.value); const commandArguments = JSON.parse($event.target.value);
this.siteSettings.set('defaults.crop', commandArguments); this.siteSettings.set('defaults.crop', commandArguments);
@ -205,7 +213,7 @@ export default {
* Determines whether a given crop command is the currently active one * Determines whether a given crop command is the currently active one
*/ */
isActiveCrop(cropCommand) { isActiveCrop(cropCommand) {
if (! this.resizerConfig.crop) { if (! this.resizerConfig.crop || !this.siteSettings) {
return false; return false;
} }

View File

@ -127,7 +127,7 @@
</div> </div>
</div> </div>
<div class="edit-action-area"> <div v-if="siteSettings" class="edit-action-area">
<div class="field"> <div class="field">
<div class="label">Default for this site:</div> <div class="label">Default for this site:</div>
<div class="select"> <div class="select">
@ -191,11 +191,19 @@ export default {
}, },
computed: { computed: {
siteDefaultStretch() { siteDefaultStretch() {
if (!this.siteSettings) {
return null;
}
return JSON.stringify( return JSON.stringify(
this.siteSettings.data.defaults.stretch this.siteSettings.data.defaults.stretch
); );
}, },
}, },
created() {
if (this.isEditing) {
this.enableEditMode();
}
},
watch: { watch: {
isEditing(newValue, oldValue) { isEditing(newValue, oldValue) {
if (newValue) { if (newValue) {
@ -210,6 +218,9 @@ export default {
* Sets default stretching mode, for either site or global * Sets default stretching mode, for either site or global
*/ */
setDefaultStretchingMode($event, globalOrSite) { setDefaultStretchingMode($event, globalOrSite) {
if (!this.siteSettings) {
return;
}
const commandArguments = JSON.parse($event.target.value); const commandArguments = JSON.parse($event.target.value);
this.siteSettings.set('defaults.stretch', commandArguments); this.siteSettings.set('defaults.stretch', commandArguments);
}, },
@ -218,7 +229,7 @@ export default {
* Determines whether a given stretch command is the currently active one * Determines whether a given stretch command is the currently active one
*/ */
isActiveStretch(stretchCommand) { isActiveStretch(stretchCommand) {
if (! this.resizerConfig.stretch) { if (! this.resizerConfig.stretch || !this.siteSettings) {
return false; return false;
} }

View File

@ -2,17 +2,16 @@
<div class="flex flex-col" style="position: relative; width: 100%;"> <div class="flex flex-col" style="position: relative; width: 100%;">
<!-- The rest of the tab is under 'edit ratios and shortcuts' row --> <!-- The rest of the tab is under 'edit ratios and shortcuts' row -->
<div class="flex flex-col" style="width: 100%"> <div class="flex flex-col" style="width: 100%">
<h2>Player UI options</h2> <h2>Player UI options</h2>
<div class="flex flex-col compact-form">
<div class="field"> <div class="field">
<div class="label">Enable in-player UI</div> <div class="label">Enable in-player UI</div>
<input type="checkbox" v-model="settings.active.ui.inPlayer.enabled" /> <input type="checkbox" v-model="settings.active.ui.inPlayer.enabled" />
</div> </div>
<div <div
class="flex flex-col" class="flex flex-col field-group compact-form"
:class="{disabled: settings.active.ui.inPlayer.enabled}" :class="{disabled: !settings.active.ui.inPlayer.enabled}"
> >
<div class="field"> <div class="field">
<div class="label">Enable only in full screen</div> <div class="label">Enable only in full screen</div>
@ -53,90 +52,9 @@
</div> </div>
</div> </div>
<div class="field"> <div class="field" :class="{disabled: settings.active.ui.inPlayer.activation !== 'trigger-zone'}">
<div class="label">Edit trigger zone:</div> <div class="label">Edit trigger zone:</div>
<button>Edit</button> <button @click="startTriggerZoneEdit()">Edit</button>
</div>
<div v-if="settings.active.ui.inPlayer.activation === 'trigger-zone'">
<div class="trigger-zone-editor">
<div class="heading">
<h3>Trigger zone editor</h3>
</div>
<div class="field">
<div class="label">Trigger zone width:</div>
<div class="input range-input">
<input
v-model="settings.active.ui.inPlayer.triggerZoneDimensions.width"
class="slider"
type="range"
min="0.1"
max="1"
step="0.01"
>
<input
:value="(settings.active.ui.inPlayer.triggerZoneDimensions.width * 100).toFixed(2)"
@input="(event) => setTriggerZoneSize('width', event.target.value)"
>
</div>
<div class="hint">
Width of the trigger zone (% of player area).
</div>
</div>
<div class="field">
<div class="label">Trigger zone height:</div>
<div class="input range-input">
<input
v-model="settings.active.ui.inPlayer.triggerZoneDimensions.height"
type="range"
min="0.1"
max="1"
step="0.01"
>
<input
:value="(settings.active.ui.inPlayer.triggerZoneDimensions.height * 100).toFixed(2)"
@input="(event) => setTriggerZoneSize('width', event.target.value)"
>
</div>
<div class="hint">
Height of the trigger zone (% of player area).
</div>
</div>
<div class="field">
<div class="label">Trigger zone horizontal offset:</div>
<div class="input range-input">
<input
v-model="settings.active.ui.inPlayer.triggerZoneDimensions.offsetX"
type="range"
min="-100"
max="100"
>
<input
v-model="settings.active.ui.inPlayer.triggerZoneDimensions.offsetX"
>
</div>
<div class="hint">
By default, trigger zone is centered around the button. This option moves trigger zone left and right.
</div>
</div>
<div class="field">
<div class="label">Trigger zone vertical offset:</div>
<div class="input range-input">
<input
v-model="settings.active.ui.inPlayer.triggerZoneDimensions.offsetY"
type="range"
min="-100"
max="100"
>
<input
v-model="settings.active.ui.inPlayer.triggerZoneDimensions.offsetY"
>
</div>
<div class="hint">
By default, trigger zone is centered around the button. This option moves trigger zone up and down.
</div>
</div>
</div>
</div> </div>
<div class="field"> <div class="field">
@ -146,6 +64,40 @@
<div>TODO: slider</div> <div>TODO: slider</div>
</div> </div>
</div> </div>
</div>
<h2 class="mt2r">Menu options and keyboard shortcuts</h2>
<div>
Click 'add new' to add a new option. Click a button to edit or remove the keyboard shortcut.
</div>
<div class="keyboard-settings">
<!-- CROP OPTIONS -->
<div>
<div class="flex flex-row">
<h3 class="mth3">CROP OPTIONS</h3>
</div>
<CropOptionsPanel
:settings="settings"
:eventBus="eventBus"
:isEditing="true"
>
</CropOptionsPanel>
</div>
<!-- STRETCH OPTIONS -->
<div>
<div class="flex flex-row">
<h3 class="mth3">STRETCH OPTIONS</h3>
</div>
<StretchOptionsPanel
:settings="settings"
:eventBus="eventBus"
:isEditing="true"
></StretchOptionsPanel>
</div>
</div>
</div> </div>
</div> </div>
@ -154,8 +106,15 @@
<script> <script>
import Button from '../components/Button.vue' import Button from '../components/Button.vue'
import BrowserDetect from '../../../ext/conf/BrowserDetect'; import BrowserDetect from '../../../ext/conf/BrowserDetect';
import CropOptionsPanel from './PanelComponents/VideoSettings/CropOptionsPanel.vue'
import StretchOptionsPanel from './PanelComponents/VideoSettings/StretchOptionsPanel.vue'
export default { export default {
components: {
Button,
CropOptionsPanel,
StretchOptionsPanel
},
data() { data() {
return { return {
@ -171,32 +130,14 @@ export default {
}, },
mounted() { mounted() {
}, },
components: {
Button,
},
methods: { methods: {
setUiPage(key, event) { setUiPage(key, event) {
}, },
forceNumber(value) {
// Change EU format to US if needed startTriggerZoneEdit() {
// | remove everything after second period if necessary this.eventBus.send('start-trigger-zone-edit');
// | | | remove non-numeric characters
// | | | |
return value.replaceAll(',', '.').split('.', 2).join('.').replace(/[^0-9.]/g, '');
}, },
setTriggerZoneSize(key, value) {
let size = (+this.forceNumber(value) / 100);
if (isNaN(+size)) {
size = 0.5;
}
this.settings.active.ui.inPlayer.triggerZoneDimensions[key] = size;
this.settings.saveWithoutReload();
},
async openOptionsPage() { async openOptionsPage() {
BrowserDetect.runtime.openOptionsPage(); BrowserDetect.runtime.openOptionsPage();
}, },
@ -249,6 +190,39 @@ export default {
.field { .field {
margin-bottom: -1em; margin-bottom: -1em;
} }
}
.disabled {
pointer-events: none;
/* color: #666; */
filter: contrast(50%) brightness(40%) grayscale(100%);
}
.compact-form {
> .field, > .field-group {
margin-top: 0;
margin-bottom: 0;
}
}
.keyboard-settings {
display: flex;
flex-direction: row;
flex-wrap: wrap;
gap: 1rem;
> * {
width: calc(50% - 0.5rem);
}
}
.mt2r {
margin-top: 2rem;
margin-bottom: 0.5rem;
}
.mth3 {
margin-top: 1.5rem;
} }
</style> </style>

View File

@ -1,4 +1,6 @@
<template> <template>
<!-- Preview + editor -->
<div <div
v-if="settings?.active?.ui" v-if="settings?.active?.ui"
class="active-trigger-area uw-clickable" class="active-trigger-area uw-clickable"
@ -8,28 +10,137 @@
@mousedown="(event) => handleMouseDown('offset', event)" @mousedown="(event) => handleMouseDown('offset', event)"
> >
<div <div
class="uw-clickable tl" class="uw-clickable corner tl"
@mousedown.stop="(event) => handleMouseDown('tl', event)" @mousedown.stop="(event) => handleMouseDown('tl', event)"
> >
XX
</div> </div>
<div <div
class="uw-clickable tr" class="uw-clickable corner tr"
@mousedown.stop="(event) => handleMouseDown('tr', event)" @mousedown.stop="(event) => handleMouseDown('tr', event)"
> >
XX
</div> </div>
<div <div
class="uw-clickable bl" class="uw-clickable corner bl"
@mousedown.stop="(event) => handleMouseDown('bl', event)" @mousedown.stop="(event) => handleMouseDown('bl', event)"
> >
XX
</div> </div>
<div <div
class="uw-clickable br" class="uw-clickable corner br"
@mousedown.stop="(event) => handleMouseDown('br', event)" @mousedown.stop="(event) => handleMouseDown('br', event)"
> >
XX </div>
</div>
</div>
<!-- Sliders -->
<div
class="trigger-zone-editor-sliders-container"
>
<div class="panel uw-clickable">
<div class="trigger-zone-editor-window">
<div class="heading">
<h2>Trigger zone editor</h2>
</div>
<div>
<p>
Trigger zone is represented by this very obvious gold grid. Ultrawidify menu button will only show when mouse enters the area marked by the grid.
</p>
<p>
Note that interacting with the grid area is slightly broken. The distance dragged doesn't correspond with the amount of resizing. I don't plan on
fixing that because the amount of effort required to get it working perfectly doesn't correspond with the amount of utility this part of the UI will
see. Like, it works well enough and I want to enjoy some of my end-of-year PTO.
</p>
<p>
Sliders work as they should.
</p>
</div>
<div class="field">
<div class="label">Trigger zone width:</div>
<div class="input range-input">
<input
:value="settings.active.ui.inPlayer.triggerZoneDimensions.width"
class="slider"
type="range"
min="0.1"
max="1"
step="0.01"
@input="(event) => setTriggerZoneOffset('width', event.target.value, true)"
>
<input
:value="triggerZoneWidth"
@input="(event) => setTriggerZoneSize('width', event.target.value)"
@change="(event) => updateSettings()"
>
</div>
<div class="hint">
Width of the trigger zone (% of player area).
</div>
</div>
<div class="field">
<div class="label">Trigger zone height:</div>
<div class="input range-input">
<input
:value="settings.active.ui.inPlayer.triggerZoneDimensions.height"
type="range"
min="0.1"
max="1"
step="0.01"
@input="(event) => setTriggerZoneOffset('height', event.target.value, true)"
>
<input
:value="triggerZoneHeight"
@input="(event) => setTriggerZoneSize('height', event.target.value)"
@change="(event) => updateSettings()"
>
</div>
<div class="hint">
Height of the trigger zone (% of player area).
</div>
</div>
<div class="field">
<div class="label">Trigger zone horizontal offset:</div>
<div class="input range-input">
<input
v-model="settings.active.ui.inPlayer.triggerZoneDimensions.offsetX"
type="range"
min="-100"
max="100"
@input="(event) => setTriggerZoneOffset('offsetX', event.target.value, true)"
>
<input
:value="settings.active.ui.inPlayer.triggerZoneDimensions.offsetX"
@input="(event) => setTriggerZoneOffset('offsetX', event.target.value)"
@change="(event) => updateSettings()"
>
</div>
<div class="hint">
By default, trigger zone is centered around the button. This option moves trigger zone left and right.
</div>
</div>
<div class="field">
<div class="label">Trigger zone vertical offset:</div>
<div class="input range-input">
<input
v-model="settings.active.ui.inPlayer.triggerZoneDimensions.offsetY"
type="range"
min="-100"
max="100"
@input="(event) => setTriggerZoneOffset('offsetY', event.target.value, true)"
>
<input
:value="settings.active.ui.inPlayer.triggerZoneDimensions.offsetY"
@input="(event) => setTriggerZoneOffset('offsetY', event.target.value)"
@change="(event) => updateSettings()"
>
</div>
<div class="hint">
By default, trigger zone is centered around the button. This option moves trigger zone up and down.
</div>
</div>
<div class="action-row">
<button @click="finishTriggerZoneEdit">Finish editing</button>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -39,11 +150,11 @@
export default { export default {
props: [ props: [
'settings', 'settings',
'eventBus',
'playerDimensions', 'playerDimensions',
], ],
watch: { watch: {
playerDimensions(newVal, oldVal) { playerDimensions(newVal, oldVal) {
console.log('triggerzone -- dimensions changed!', this.playerDimensions, newVal, oldVal);
this.updateTriggerZones(); this.updateTriggerZones();
} }
}, },
@ -58,9 +169,26 @@ export default {
created() { created() {
document.addEventListener("mouseup", this.handleMouseUp); document.addEventListener("mouseup", this.handleMouseUp);
document.addEventListener("mousemove", this.handleMouseMove); document.addEventListener("mousemove", this.handleMouseMove);
this.updateTriggerZones(false);
},
computed: {
triggerZoneWidth() {
const v = this.settings.active.ui.inPlayer.triggerZoneDimensions.width * 100;
return this.optionalToFixed(v, 2);
},
triggerZoneHeight() {
const v = this.settings.active.ui.inPlayer.triggerZoneDimensions.height * 100;
return this.optionalToFixed(v, 2);
}
}, },
methods: { methods: {
updateTriggerZones() { optionalToFixed(v, n) {
if ((`${v}`.split('.')[1]?.length ?? 0) > n) {
return v.toFixed(2);
}
return v;
},
updateTriggerZones(forceRefresh = true) {
if (this.playerDimensions && this.settings?.active?.ui?.inPlayer?.triggerZoneDimensions) { if (this.playerDimensions && this.settings?.active?.ui?.inPlayer?.triggerZoneDimensions) {
this.triggerZoneStyles = { this.triggerZoneStyles = {
width: `${Math.round(this.playerDimensions.width * this.settings.active.ui.inPlayer.triggerZoneDimensions.width)}px`, width: `${Math.round(this.playerDimensions.width * this.settings.active.ui.inPlayer.triggerZoneDimensions.width)}px`,
@ -68,6 +196,9 @@ export default {
transform: `translate(${(this.settings.active.ui.inPlayer.triggerZoneDimensions.offsetX)}%, ${this.settings.active.ui.inPlayer.triggerZoneDimensions.offsetY}%)`, transform: `translate(${(this.settings.active.ui.inPlayer.triggerZoneDimensions.offsetX)}%, ${this.settings.active.ui.inPlayer.triggerZoneDimensions.offsetY}%)`,
}; };
} }
// if (forceRefresh) {
// this.$forceUpdate();
// }
}, },
handleMouseDown(corner, event) { handleMouseDown(corner, event) {
this.activeCornerDrag = corner; this.activeCornerDrag = corner;
@ -134,8 +265,8 @@ export default {
} }
// ensure everything is properly limited // ensure everything is properly limited
const cw = Math.min(0.95, Math.max(0.125, nw)); const cw = Math.min(1, Math.max(0.125, nw));
const ch = Math.min(0.95, Math.max(0.125, nh)); const ch = Math.min(1, Math.max(0.125, nh));
// // update properties // // update properties
this.settings.active.ui.inPlayer.triggerZoneDimensions.width = cw; this.settings.active.ui.inPlayer.triggerZoneDimensions.width = cw;
@ -161,14 +292,63 @@ export default {
this.settings.active.ui.inPlayer.triggerZoneDimensions.offsetX = cx; this.settings.active.ui.inPlayer.triggerZoneDimensions.offsetX = cx;
this.settings.active.ui.inPlayer.triggerZoneDimensions.offsetY = cy; this.settings.active.ui.inPlayer.triggerZoneDimensions.offsetY = cy;
},
//#region slider window
forceNumber(value) {
// Change EU format to US if needed
// | remove everything after second period if necessary
// | | | remove non-numeric characters
// | | | |
return value.replaceAll(',', '.').split('.', 2).join('.').replace(/[^0-9.\-]/g, '');
},
setTriggerZoneSize(key, value, instantUpdate) {
console.log('setting trigger zone size:', key, value);
let size = (+this.forceNumber(value) / 100);
if (isNaN(+size)) {
size = 0.5;
} }
this.settings.active.ui.inPlayer.triggerZoneDimensions[key] = size;
if (instantUpdate) {
this.updateSettings();
}
},
setTriggerZoneOffset(key, value, instantUpdate) {
let offset = +this.forceNumber(value);
this.settings.active.ui.inPlayer.triggerZoneDimensions[key] = offset;
if (instantUpdate) {
this.updateSettings();
}
},
updateSettings() {
this.settings.saveWithoutReload();
this.updateTriggerZones();
},
//#endregion
finishTriggerZoneEdit() {
this.eventBus.send('finish-trigger-zone-edit');
},
} }
} }
</script> </script>
<style lang="scss" src="../res-common/panels.scss" scoped module></style>
<style lang="scss" src="../res-common/common.scss" scoped module></style>
<style lang="scss" scoped> <style lang="scss" scoped>
.active-trigger-area { .active-trigger-area {
background-image: url('/res/img/grid_512.webp'); background-image: url('/res/img/grid_512.webp');
background-position: center;
background-attachment: fixed;
} }
.trigger-zone-editor { .trigger-zone-editor {
@ -176,8 +356,14 @@ export default {
height: 100%; height: 100%;
position: relative; position: relative;
> * { > .corner {
position: absolute; position: absolute;
width: 32px;
height: 32px;
background-color: #000;
background-image: url('/res/img/corner-marker_64.webp');
background-size: cover;
} }
.tr, .tl { .tr, .tl {
top: 0; top: 0;
@ -191,6 +377,86 @@ export default {
.tr, .br { .tr, .br {
right: 0; right: 0;
} }
.br {
transform: rotate(90deg);
}
.bl {
transform: rotate(180deg);
}
.tl {
transform: rotate(-90deg);
}
}
.trigger-zone-editor-window {
max-width: 69rem;
}
.trigger-zone-editor-sliders-container {
position: fixed;
width: 100dvw;
height: 100dvh;
top: 0;
left: 0;
z-index: 2000;
pointer-events: none;
display: flex;
align-items: center;
justify-content: center;
.panel {
backdrop-filter: blur(0.5rem) brightness(0.5);
color: #ccc;
pointer-events: all;
padding: 1rem;
}
.range-input {
display: flex;
flex-direction: row;
* {
margin-left: 0.5rem;
margin-right: 0.5rem;
}
input {
max-width: 5rem;
}
input[type=range] {
max-width: none;
}
}
.trigger-zone-editor {
padding-bottom: 2rem;
.field {
margin-bottom: -1em;
}
}
}
.range-input {
display: flex;
flex-direction: row;
* {
margin-left: 0.5rem;
margin-right: 0.5rem;
}
input {
max-width: 5rem;
}
input[type=range] {
max-width: none;
}
} }
</style> </style>

View File

@ -6,12 +6,16 @@ export default {
* the content script. * the content script.
*/ */
document.addEventListener('mousemove', (event) => { document.addEventListener('mousemove', (event) => {
this.handleProbe({ this.handleProbe(
{
coords: { coords: {
x: event.clientX, x: event.clientX,
y: event.clientY y: event.clientY
} },
}, this.origin); isCompanion: true,
},
this.origin
);
}); });
}, },
data() { data() {
@ -74,6 +78,7 @@ export default {
*/ */
let isClickable = false; let isClickable = false;
let isOverTriggerZone = false; let isOverTriggerZone = false;
let isOverUIArea = false;
const elements = document.elementsFromPoint(eventData.coords.x, eventData.coords.y); const elements = document.elementsFromPoint(eventData.coords.x, eventData.coords.y);
for (const element of elements) { for (const element of elements) {
@ -83,6 +88,9 @@ export default {
if (element.classList?.contains('uw-ui-trigger')) { if (element.classList?.contains('uw-ui-trigger')) {
isOverTriggerZone = true; isOverTriggerZone = true;
} }
if (element.classList?.contains('uw-ui-area')) {
isOverUIArea = true;
}
} }
this.triggerZoneActive = isOverTriggerZone; this.triggerZoneActive = isOverTriggerZone;
@ -91,18 +99,22 @@ export default {
// but don't show the trigger zone behind an active popup // but don't show the trigger zone behind an active popup
if ( if (
eventData.canShowUI eventData.canShowUI
&& (this.settings.active.ui.inPlayer.activation !== 'player' || isOverTriggerZone) && (this.settings.active.ui.inPlayer.activation === 'player' ? isOverUIArea : isOverTriggerZone)
) { ) {
if (! this.uwWindowVisible) { if (! this.uwWindowVisible) {
this.uwTriggerZoneVisible = true; this.uwTriggerZoneVisible = true;
clearTimeout(this.uwTriggerZoneTimeout); clearTimeout(this.uwTriggerZoneTimeout);
this.uwTriggerZoneTimeout = setTimeout( this.uwTriggerZoneTimeout = setTimeout(
() => this.uwTriggerZoneVisible = false, () => {
250 this.uwTriggerZoneVisible = false;
// this.$forceRefresh();
},
750
); );
} }
} else { } else {
this.uwTriggerZoneVisible = false; // console.log('[UI] hiding UI because conditions were not met. canShowUI:', eventData.canShowUI, 'isOverTriggerZone', isOverTriggerZone);
// this.uwTriggerZoneVisible = false;
} }
window.parent.postMessage( window.parent.postMessage(

View File

@ -106,9 +106,17 @@ class UI {
return; return;
} }
const rect = this.uiIframe.getBoundingClientRect();
const offsets = {
top: window.scrollY + rect.top,
left: window.scrollX + rect.left
};
const coords = { const coords = {
x: event.pageX - this.uiIframe.offsetLeft, x: event.pageX - offsets.left,
y: event.pageY - this.uiIframe.offsetTop y: event.pageY - offsets.top,
frameOffset: offsets,
}; };
const playerData = this.canShowUI(coords); const playerData = this.canShowUI(coords);
@ -223,12 +231,12 @@ class UI {
* * player element () * * player element ()
* * uwui-clickable element * * uwui-clickable element
*/ */
canShowUI(coords) { canShowUI() {
const playerCssClass = 'uw-ultrawidify-player-css'; const playerCssClass = 'uw-ultrawidify-player-css';
const result = { const result = {
playerDimensions: undefined, playerDimensions: undefined,
canShowUI: false canShowUI: false,
} }
if (this.playerData?.dimensions) { if (this.playerData?.dimensions) {
@ -243,24 +251,12 @@ class UI {
// fullscreen mode unless watching videos) // fullscreen mode unless watching videos)
result.playerDimensions.width < window.screen.width * (this.uiSettings.inPlayer.minEnabledWidth ?? 0) result.playerDimensions.width < window.screen.width * (this.uiSettings.inPlayer.minEnabledWidth ?? 0)
) { ) {
result.canShowUI = false;
return result; return result;
} }
const elements = document.elementsFromPoint(coords.x, coords.y);
for (const element of elements) {
if (
element instanceof HTMLVideoElement
|| element.classList.contains(playerCssClass)
) {
result.canShowUI = true; result.canShowUI = true;
return result; return result;
} }
}
return result;
}
/** /**
* Handles events received from the iframe. * Handles events received from the iframe.

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB