Compare commits

..

No commits in common. "925a9fdea3987659cd8f661020dc5619cea6c631" and "8a4985e6a362fdb0b3ae34d90939e9b767429cd2" have entirely different histories.

11 changed files with 96 additions and 255 deletions

View File

@ -1,5 +1,3 @@
import { InPlayerUIOptions } from '@src/common/interfaces/SettingsInterface';
export interface MenuItemConfig { export interface MenuItemConfig {
label: string; label: string;
subitems?: MenuItemConfig[]; subitems?: MenuItemConfig[];
@ -22,7 +20,7 @@ export enum MenuPosition {
export interface MenuConfig { export interface MenuConfig {
isGlobal?: boolean; isGlobal?: boolean;
ui: InPlayerUIOptions;
menuPosition: MenuPosition; menuPosition: MenuPosition;
activationRadius?: number;
items: MenuItemConfig[]; items: MenuItemConfig[];
} }

View File

@ -308,23 +308,6 @@ interface DevSettings {
loadFromSnapshot: boolean, loadFromSnapshot: boolean,
} }
export interface InPlayerUIOptions {
activatorAlignment: 'left' | 'right',
minEnabledWidth: number, // don't show UI if player is narrower than % of screen width
minEnabledHeight: number, // don't show UI if player is narrower than % of screen height
activation: 'player' | 'player-ctrl' | 'trigger-zone' | 'distance' | 'none', // what needs to be hovered in order for UI to be visible
activationDistance: number,
activationDistanceUnits: '%' | 'px',
activatorPadding: 10,
activatorPaddingUnit: '%' | 'px',
triggerZoneDimensions: { // how large the trigger zone is (relative to player size)
width: number
height: number,
offsetX: number, // fed to translateX(offsetX + '%'). Valid range [-100, 0]
offsetY: number // fed to translateY(offsetY + '%'). Valid range [-100, 100]
},
};
interface SettingsInterface { interface SettingsInterface {
_updateFlags?: { _updateFlags?: {
requireReload?: SettingsReloadFlags, requireReload?: SettingsReloadFlags,
@ -336,7 +319,18 @@ interface SettingsInterface {
aard: AardSettings, aard: AardSettings,
ui: { ui: {
inPlayer: InPlayerUIOptions, inPlayer: {
popupAlignment: 'left' | 'right',
minEnabledWidth: number, // don't show UI if player is narrower than % of screen width
minEnabledHeight: number, // don't show UI if player is narrower than % of screen height
activation: 'player' | 'trigger-zone' | 'distance' | 'none', // what needs to be hovered in order for UI to be visible
triggerZoneDimensions: { // how large the trigger zone is (relative to player size)
width: number
height: number,
offsetX: number, // fed to translateX(offsetX + '%'). Valid range [-100, 0]
offsetY: number // fed to translateY(offsetY + '%'). Valid range [-100, 100]
},
},
devMode?: boolean, devMode?: boolean,
dev: DevUiConfig, dev: DevUiConfig,
} }

View File

@ -264,11 +264,7 @@ const ExtensionConf: SettingsInterface = {
minEnabledWidth: 0.75, minEnabledWidth: 0.75,
minEnabledHeight: 0.75, minEnabledHeight: 0.75,
activation: 'player', activation: 'player',
activationDistance: 100, popupAlignment: 'left',
activationDistanceUnits: '%',
activatorAlignment: 'left',
activatorPadding: 10,
activatorPaddingUnit: '%',
triggerZoneDimensions: { triggerZoneDimensions: {
width: 0.5, width: 0.5,
height: 0.5, height: 0.5,

View File

@ -89,7 +89,6 @@ export default class EventBus {
} }
send(command: string, commandData: any, context: EventBusContext = {}) { send(command: string, commandData: any, context: EventBusContext = {}) {
context.visitedBusses = [...context.visitedBusses ?? [], this.uuid];
// execute commands we have subscriptions for // execute commands we have subscriptions for
if (this.commands?.[command]) { if (this.commands?.[command]) {
@ -112,12 +111,13 @@ export default class EventBus {
} catch (e) { } catch (e) {
if (command !== 'reload-required') { if (command !== 'reload-required') {
// We shouldn't let reload-required command to trigger new reload-required commands. // We shouldn't let reload-required command to trigger new reload-required commands.
this.send('reload-required', {}, {visitedBusses: [this.uuid]}); this.send('reload-required', {});
} }
} }
}; };
// call forwarding functions if they exist // call forwarding functions if they exist
if (!context?.borderCrossings?.iframe) {
for (const forwarding of this.iframeForwardingList) { for (const forwarding of this.iframeForwardingList) {
forwarding.fn( forwarding.fn(
command, command,
@ -126,12 +126,15 @@ export default class EventBus {
...context, ...context,
borderCrossings: { borderCrossings: {
...context?.borderCrossings, ...context?.borderCrossings,
// iframe: true // we actually no longer check this prop, we should instead rely on visitedBusses iframe: true
} }
} }
); );
} }
this.sendToTunnel(command, commandData, context); this.sendToTunnel(command, commandData, context);
} else {
console.warn('message was already sent to iframe, doing nothing ...')
}
if (context?.stopPropagation) { if (context?.stopPropagation) {
return; return;
@ -145,10 +148,6 @@ export default class EventBus {
* @param config * @param config
*/ */
sendToTunnel(command: string, config: any, context: EventBusContext = {}) { sendToTunnel(command: string, config: any, context: EventBusContext = {}) {
if (!context.visitedBusses) {
console.error('Visited busses is missing from contextn. This is illegal.');
return;
}
context.visitedBusses = [...context.visitedBusses ?? [], this.uuid]; context.visitedBusses = [...context.visitedBusses ?? [], this.uuid];
if (!this.disableTunnel && typeof window !== 'undefined') { if (!this.disableTunnel && typeof window !== 'undefined') {
@ -206,7 +205,7 @@ export default class EventBus {
const payload = event.data.payload as EventBusMessage; const payload = event.data.payload as EventBusMessage;
console.info(this.name, 'received message from iframe. command:', payload); console.info(this.name, 'received message from iframe. command:', payload);
if (!payload.context?.visitedBusses) { if (!payload.context) {
console.warn('Received iframe message without context. Doing nothing in order to avoid infinite loop. Event:', event); console.warn('Received iframe message without context. Doing nothing in order to avoid infinite loop. Event:', event);
return; return;
} }

View File

@ -12,7 +12,6 @@ export class ClientMenu {
public get root(): HTMLDivElement { public get root(): HTMLDivElement {
return this._root; return this._root;
} }
private trigger: HTMLDivElement;
private visible = false; private visible = false;
private menuPositionClasses: string[] = []; private menuPositionClasses: string[] = [];
@ -23,8 +22,6 @@ export class ClientMenu {
private lastMouseMove = performance.now(); private lastMouseMove = performance.now();
private idleTimer?: number; private idleTimer?: number;
private onDocumentMouseMove?: (e: MouseEvent) => void; private onDocumentMouseMove?: (e: MouseEvent) => void;
private onDocumentMouseLeave?: () => void; private onDocumentMouseLeave?: () => void;
private idleIntervalId?: number; private idleIntervalId?: number;
@ -78,19 +75,16 @@ export class ClientMenu {
} }
private getActivationRadius(anchorEl: HTMLElement): number | null { private getActivationRadius(anchorEl: HTMLElement): number | null {
if (this.config.ui.activation !== 'distance') { if (this.config.activationRadius == null) return null;
return undefined;
}
if (this.config.ui.activationDistanceUnits === 'px') { if (typeof this.config.activationRadius === 'number') {
return +this.config.ui.activationDistance; return this.config.activationRadius;
} }
// percentage string // percentage string
const rect = anchorEl.getBoundingClientRect(); const rect = anchorEl.getBoundingClientRect();
const percent = +this.config.ui.activationDistance; const pct = parseFloat(this.config.activationRadius);
return Math.max(rect.width, rect.height) * (pct / 100);
return Math.max(rect.width, rect.height) * (percent / 100);
} }
private injectStyles() { private injectStyles() {
@ -160,6 +154,8 @@ export class ClientMenu {
pointerEvents: 'none', pointerEvents: 'none',
background: 'transparent', background: 'transparent',
}); });
console.log('UI host created:', this.host);
} }
private createShadow() { private createShadow() {
@ -212,9 +208,7 @@ export class ClientMenu {
const trigger = document.createElement('div'); const trigger = document.createElement('div');
trigger.classList = 'uw-menu-trigger uw-trigger'; trigger.classList = 'uw-menu-trigger uw-trigger';
trigger.style = `margin: ${this.config.ui.activatorPadding ?? 10} ${this.config.ui.activatorPaddingUnit ?? '%'}`;
trigger.textContent = 'Ultrawidify'; trigger.textContent = 'Ultrawidify';
this.trigger = trigger;
const submenu = this.buildSubmenu(this.config.items); const submenu = this.buildSubmenu(this.config.items);
@ -287,38 +281,24 @@ export class ClientMenu {
} }
private bindGlobalMouse(anchorEl: HTMLElement) { private bindGlobalMouse(anchorEl: HTMLElement) {
const playerRect = anchorEl.getBoundingClientRect(); const rect = anchorEl.getBoundingClientRect();
const cx = rect.left + rect.width / 2;
let menuActivatorRect, cx, cy; const cy = rect.top + rect.height / 2;
const activationRadius = this.getActivationRadius(anchorEl); const activationRadius = this.getActivationRadius(anchorEl);
const recalculateActivator = () => {
menuActivatorRect = this.trigger.getBoundingClientRect();
cx = menuActivatorRect.left + menuActivatorRect.width / 2;
cy = menuActivatorRect.top + menuActivatorRect.height / 2;
}
recalculateActivator();
this.onDocumentMouseMove = (e: MouseEvent) => { this.onDocumentMouseMove = (e: MouseEvent) => {
this.lastMouseMove = performance.now(); this.lastMouseMove = performance.now();
if (activationRadius != null) { if (activationRadius != null) {
if (! menuActivatorRect.width) {
recalculateActivator();
}
const d = Math.hypot(e.clientX - cx, e.clientY - cy); const d = Math.hypot(e.clientX - cx, e.clientY - cy);
this.isWithinActivation = d <= activationRadius; this.isWithinActivation = d <= activationRadius;
} else { } else {
this.isWithinActivation = this.isWithinActivation =
e.clientX >= playerRect.left && e.clientX >= rect.left &&
e.clientX <= playerRect.right && e.clientX <= rect.right &&
e.clientY >= playerRect.top && e.clientY >= rect.top &&
e.clientY <= playerRect.bottom && e.clientY <= rect.bottom;
(this.config.ui.activation !== 'player-ctrl' || e.ctrlKey);
} }
this.updateVisibility(); this.updateVisibility();
@ -339,7 +319,7 @@ export class ClientMenu {
private startIdleWatcher() { private startIdleWatcher() {
this.idleIntervalId = window.setInterval(() => { this.idleIntervalId = window.setInterval(() => {
const idle = performance.now() - this.lastMouseMove > 1000; const idle = performance.now() - this.lastMouseMove > 1000;
if (idle && !this.isHovered) { if (idle) {
this.hide(); this.hide();
} }
}, 200); }, 200);

View File

@ -184,7 +184,7 @@ class UI {
if (this.uiConfig.parentElement) { if (this.uiConfig.parentElement) {
const menuConfig = { const menuConfig = {
isGlobal: this.isGlobal, isGlobal: this.isGlobal,
ui: this.settings.active.ui.inPlayer, menuPosition: MenuPosition.Left,
items: [ items: [
{ {
customClassList: 'uw-site-info', customClassList: 'uw-site-info',

View File

@ -88,8 +88,7 @@ export default class IframeManager {
* @param context * @param context
*/ */
private handleIframeRegister(data, context) { private handleIframeRegister(data, context) {
console.log('handling iframe register:', {data, context}); const existingIndex = this.iframeList.findIndex(x => x.frameId === context.comms.sourceFrame.frameId);
const existingIndex = this.iframeList.findIndex(x => x.frameId && x.frameId === context.comms?.sourceFrame?.frameId);
if (existingIndex !== -1) { if (existingIndex !== -1) {
this.iframeList[existingIndex] = { this.iframeList[existingIndex] = {

View File

@ -37,7 +37,7 @@
v-for="suboption of tab.children" v-for="suboption of tab.children"
:key="suboption.id" :key="suboption.id"
class="suboption" class="suboption"
:class="{'active': suboption.id === selectedTab, 'disabled': suboption.disabled, 'hidden': suboption.visible === false }" :class="{'active': suboption.id === selectedTab, 'disabled': suboption.disabled }"
@click="selectTab(suboption.id)" @click="selectTab(suboption.id)"
> >
<div class="label"> <div class="label">
@ -60,8 +60,8 @@
</div> </div>
</div> </div>
<div class="grow content flex flex-col overflow-auto pr-4 pb-12"> <div class="grow content flex flex-col overflow-auto pr-4 pb-12">
<!-- autodetection warning --> <!-- autodetection warning -->
<div class="warning-area"> <div class="warning-area">
<div <div
v-if="statusFlags.hasDrm" v-if="statusFlags.hasDrm"
@ -72,19 +72,7 @@
</div> </div>
<div> <div>
This site is blocking automatic aspect ratio detection. You will have to adjust aspect ratio manually.<br/> This site is blocking automatic aspect ratio detection. You will have to adjust aspect ratio manually.<br/>
<!-- <a>Learn more ...</a> --> <a>Learn more ...</a>
</div>
</div>
<div
v-if="settings.active.preventReload"
class="info-box"
>
<div class="icon-container">
<mdicon name="information" :size="24" />
</div>
<div>
Some settings will only reply after page reload.
</div> </div>
</div> </div>
</div> </div>
@ -98,19 +86,6 @@
:site="site" :site="site"
></VideoSettings> ></VideoSettings>
<template v-if="[
'site-extension-settings',
'window.site-extension-settings',
'embedded-extension-settings',
].includes(selectedTab)">
<template v-if="!settings || !siteSettings">
Loading settings ...
<pre> site: {{site}}</pre>
<pre> settings: {{!!settings}}</pre>
<pre>site settings: {{!!siteSettings}}</pre>
</template>
<template v-else>
<template v-if="settings && selectedTab === 'site-extension-settings'" > <template v-if="settings && selectedTab === 'site-extension-settings'" >
<h3>Settings for {{site?.host}}</h3> <h3>Settings for {{site?.host}}</h3>
<SiteExtensionSettings <SiteExtensionSettings
@ -137,14 +112,8 @@
:settings="settings" :settings="settings"
></FrameSiteSettings> ></FrameSiteSettings>
</template> </template>
</template>
</template>
<template v-if="selectedTab === 'default-extension-settings'" > <template v-if="settings && selectedTab === 'default-extension-settings'" >
<template v-if="!settings">
Loading settings ...
</template>
<template v-else>
<h3>Default settings</h3> <h3>Default settings</h3>
<SiteExtensionSettings <SiteExtensionSettings
:settings="settings" :settings="settings"
@ -152,7 +121,6 @@
:isDefaultConfiguration="true" :isDefaultConfiguration="true"
></SiteExtensionSettings> ></SiteExtensionSettings>
</template> </template>
</template>
<OtherSiteSettings <OtherSiteSettings
v-if="selectedTab === 'website-extension-settings'" v-if="selectedTab === 'website-extension-settings'"
@ -268,8 +236,7 @@ const AVAILABLE_TABS = {
id: 'window.site-extension-settings', label: 'Site and Extension options', icon: 'cogs', id: 'window.site-extension-settings', label: 'Site and Extension options', icon: 'cogs',
children: [ children: [
{ id: 'window.site-extension-settings', label: 'For this site', }, { id: 'window.site-extension-settings', label: 'For this site', },
{ id: 'window.parent-site-extension-settings', label: 'For parent page', visible: false,}, { id: 'embedded-extension-settings', label: 'For embedded sites', disabled: true, badgeCount: 0, },
{ id: 'embedded-extension-settings', label: 'For embedded sites', disabled: true, visible: true, badgeCount: 0, },
{ id: 'default-extension-settings', label: 'Default settings' }, { id: 'default-extension-settings', label: 'Default settings' },
{ id: 'website-extension-settings', label: 'Website exceptions' }, { id: 'website-extension-settings', label: 'Website exceptions' },
] ]
@ -440,6 +407,7 @@ export default defineComponent({
const tabs = []; const tabs = [];
for (const tab of TAB_LOADOUT[this.role]) { for (const tab of TAB_LOADOUT[this.role]) {
if (!AVAILABLE_TABS[tab]) { if (!AVAILABLE_TABS[tab]) {
console.warn('[uw:SettingsWindowContent] tab', tab, 'is not present in available tabs:', AVAILABLE_TABS, '— tabs for role', this.role, TAB_LOADOUT[this.role]);
continue; continue;
} else { } else {
if (tab === 'site-extension-settings') { if (tab === 'site-extension-settings') {

View File

@ -5,32 +5,17 @@
<!-- 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 v-if="settings" class="flex flex-col" style="width: 100%"> <div v-if="settings" class="flex flex-col" style="width: 100%">
<div class="flex flex-col gap-2"> <div class="flex flex-col compact-form">
<div <div
class="flex flex-col field-group compact-form gap-2" class="flex flex-col field-group compact-form"
> >
<div class="field"> <div class="field disabled">
<div class="label"> <div class="label">
Popup activator position: Popup activator position:
</div> </div>
<div class="select"> <div class="select">
<select <select
v-model="settings.active.ui.inPlayer.activatorAlignment" v-model="settings.active.ui.inPlayer.popupAlignment"
@change="saveSettings()"
>
<option value="left">Left</option>
<option value="right">Right</option>
</select>
</div>
</div>
<div class="field">
<div class="label">
Popup activator padding:
</div>
<div class="select">
<select
v-model="settings.active.ui.inPlayer.activatorAlignment"
@change="saveSettings()" @change="saveSettings()"
> >
<option value="left">Left</option> <option value="left">Left</option>
@ -49,47 +34,11 @@
@change="saveSettings()" @change="saveSettings()"
> >
<option value="player"> <option value="player">
When mouse moves over player, always When mouse hovers over player
</option> </option>
<option value="player-ctrl"> <option value="trigger-zone">
When mouse moves over player, while holding CTRL key When mouse hovers over trigger zone
</option> </option>
<option value="distance">
When mouse is close to the menu activator
</option>
<!-- <option value="trigger-zone">
When mouse moves over trigger zone
</option> -->
</select>
</div>
</div>
<div v-show="settings.active.ui.inPlayer.activation === 'distance'" class="field">
<div class="label">
Show menu when mouse is closer than:
</div>
<div class="input range-input">
<input
v-model="settings.active.ui.inPlayer.activationDistance"
class="slider"
type="range"
min="10"
max="100"
step="1"
@change="(event) => saveSettings()"
>
<input
style="margin-right: 0.6rem;"
v-model="settings.active.ui.inPlayer.activationDistance"
@change="(event) => saveSettings(true)"
>
<select
class="unit-select !min-w-[72px]"
v-model="settings.active.ui.inPlayer.activationDistanceUnit"
@change="(event) => saveSettings(true)"
>
<option value="%">%</option>
<option value="px">px</option>
</select> </select>
</div> </div>
</div> </div>

View File

@ -14,16 +14,6 @@
class="w-full h-[100dvh] overflow-hidden flex flex-col" class="w-full h-[100dvh] overflow-hidden flex flex-col"
:class="{'max-w-[1920px]': !isDebugging && role !== 'ui'}" :class="{'max-w-[1920px]': !isDebugging && role !== 'ui'}"
> >
<div class="flex flex-row font-mono text-[0.8rem] text-stone-500 border-stone-500">
<!-- <pre>
url: {{getUrl}}
site: <pre>{{JSON.stringify(site, null, 2)}}</pre>
</pre> -->
</div>
<PopupHead <PopupHead
v-if="role === 'popup' && settings && siteSettings && eventBus" v-if="role === 'popup' && settings && siteSettings && eventBus"
:settings="settings" :settings="settings"
@ -32,7 +22,9 @@
:eventBus="eventBus" :eventBus="eventBus"
> >
</PopupHead> </PopupHead>
<div v-else-if="role === 'ui'" class="flex flex-row font-mono text-[0.8rem] text-stone-500 border-stone-500">
url: {{getUrl}}
</div>
<div v-else> <div v-else>
<h1 class="text-[3em] grow-0 shrink-0">Ultrawidify settings</h1> <h1 class="text-[3em] grow-0 shrink-0">Ultrawidify settings</h1>
</div> </div>

View File

@ -42,39 +42,6 @@
top: 0; top: 0;
transform: translateY(69%); transform: translateY(69%);
} }
.unit-select {
@apply bg-stone-950 text-white px-4 py-1 border border-transparent border-l-stone-600 border-dotted;
flex-grow: 1;
flex-shrink: 1;
min-width: 12px;
max-width: 24rem;
outline: none;
font: inherit;
font-size: inherit;
option {
@apply bg-stone-950 text-white;
&:checked {
@apply text-primary-400;
}
&:before {
content: ">";
display: none;
background-color: #f41 !important;
font-size: 5rem;;
}
&:hover {
@apply text-black bg-primary-300;
}
}
}
} }
.range-input { .range-input {
@ -128,7 +95,6 @@
flex-direction: column; flex-direction: column;
} }
.select { .select {
flex-grow: 1; flex-grow: 1;
flex-shrink: 1; flex-shrink: 1;