attempt to get player selector to work

This commit is contained in:
Tamius Han 2023-07-15 04:03:32 +02:00
parent 9cb9a6607b
commit 3180063fe3
7 changed files with 162 additions and 45 deletions

View File

@ -48,7 +48,15 @@ export interface CommandInterface {
actionId?: string, actionId?: string,
} }
export type SettingsReloadComponent = 'PlayerData' | 'VideoData';
export type SettingsReloadFlags = true | SettingsReloadComponent;
interface SettingsInterface { interface SettingsInterface {
_updateFlags?: {
requireReload?: SettingsReloadFlags,
forSite?: string
}
arDetect: { arDetect: {
disabledReason: string, // if automatic aspect ratio has been disabled, show reason disabledReason: string, // if automatic aspect ratio has been disabled, show reason
allowedMisaligned: number, // top and bottom letterbox thickness can differ by this much. allowedMisaligned: number, // top and bottom letterbox thickness can differ by this much.
@ -384,7 +392,7 @@ export interface SiteSettingsInterface {
} }
export interface SiteDOMSettingsInterface { export interface SiteDOMSettingsInterface {
type: 'official' | 'community' | 'user-defined' | undefined; type: 'official' | 'community' | 'user-defined' | 'modified' | undefined;
elements?: { elements?: {
player?: SiteDOMElementSettingsInterface, player?: SiteDOMElementSettingsInterface,
video?: SiteDOMElementSettingsInterface, video?: SiteDOMElementSettingsInterface,
@ -403,6 +411,7 @@ export interface SiteDOMElementSettingsInterface {
manual?: boolean; manual?: boolean;
querySelectors?: string; querySelectors?: string;
index?: number; // previously: useRelativeAncestor + videoAncestor index?: number; // previously: useRelativeAncestor + videoAncestor
mode?: 'index' | 'qs';
nodeCss?: {[x: string]: string}; nodeCss?: {[x: string]: string};
} }

View File

@ -34,13 +34,6 @@
<script> <script>
import PlayerUIWindow from './src/PlayerUIWindow.vue' import PlayerUIWindow from './src/PlayerUIWindow.vue'
import BaseExtensionSettings from './src/PlayerUiPanels/BaseExtensionSettings.vue'
import DebugPanel from './src/PlayerUiPanels/DebugPanel.vue'
import VideoSettings from './src/PlayerUiPanels/VideoSettings.vue'
import AutodetectionSettingsPanel from './src/PlayerUiPanels/AutodetectionSettingsPanel.vue'
import PlayerDetectionPanel from './src/PlayerUiPanels/PlayerDetectionPanel.vue'
// import Icon from '../common/components/Icon';
import ResizerDebugPanel from './src/PlayerUiPanels/ResizerDebugPanelComponent';
import BrowserDetect from '../ext/conf/BrowserDetect'; import BrowserDetect from '../ext/conf/BrowserDetect';
import Logger from '../ext/lib/Logger'; import Logger from '../ext/lib/Logger';
import Settings from '../ext/lib/Settings'; import Settings from '../ext/lib/Settings';
@ -49,13 +42,6 @@ import UIProbeMixin from './src/utils/UIProbeMixin';
export default { export default {
components: { components: {
// Icon,
ResizerDebugPanel,
VideoSettings,
PlayerDetectionPanel,
AutodetectionSettingsPanel,
DebugPanel,
BaseExtensionSettings,
PlayerUIWindow PlayerUIWindow
}, },
mixins: [ mixins: [

View File

@ -93,7 +93,6 @@
></VideoSettings> ></VideoSettings>
<PlayerDetectionPanel <PlayerDetectionPanel
v-if="selectedTab === 'playerDetection'" v-if="selectedTab === 'playerDetection'"
:settings="settings"
:siteSettings="siteSettings" :siteSettings="siteSettings"
:eventBus="eventBus" :eventBus="eventBus"
:site="site" :site="site"

View File

@ -343,22 +343,15 @@ export default {
}, },
getCommandValue(availableCommands, command) { getCommandValue(availableCommands, command) {
console.log('command:', command, 'from available commands', availableCommands);
for (const cmd of availableCommands) { for (const cmd of availableCommands) {
console.log('——— processing command:', cmd)
console.log('comparing', JSON.stringify(command), 'to', JSON.stringify(cmd.arguments));
if (JSON.stringify(cmd.arguments) === JSON.stringify(command)) { if (JSON.stringify(cmd.arguments) === JSON.stringify(command)) {
return cmd.label; return cmd.label;
} }
} }
return 'Unknown command'; return 'Unknown command';
}, },
getAlignmentLabel(alignment) { getAlignmentLabel(alignment) {
console.log('alignment for site. ----------------------------', alignment);
// in case default settings don't have this set // in case default settings don't have this set
if (!alignment) { if (!alignment) {
return 'Center' return 'Center'

View File

@ -73,7 +73,8 @@
</div> </div>
</th> </th>
<th>Element</th> <th>Element</th>
<th>Quick fixes</th> <th>Actions</th>
<!-- <th>Quick fixes</th> -->
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -137,6 +138,11 @@
</div> </div>
</td> </td>
<td> <td>
<div class="flex flex-row">
<!-- <div @click="designatePlayer(index)">Set as player {{ index }}</div> -->
</div>
</td>
<!-- <td>
<div <div
class="css-fixes" class="css-fixes"
> >
@ -318,7 +324,7 @@
</span> </span>
</div> </div>
</div> </div>
</td> </td> -->
</tr> </tr>
</tbody> </tbody>
</table> </table>
@ -352,7 +358,7 @@ export default({
}, },
mixins: [], mixins: [],
props: [ props: [
'settings', 'siteSettings',
'frame', 'frame',
'eventBus', 'eventBus',
'site' 'site'
@ -375,18 +381,22 @@ export default({
this.eventBus.sendToTunnel('set-mark-element', {parentIndex, enable}); this.eventBus.sendToTunnel('set-mark-element', {parentIndex, enable});
}, },
async setPlayer(index) { async setPlayer(index) {
// yup.
this.siteSettings.getDOMConfig('modified', 'original');
await this.siteSettings.setUpdateFlags(['PlayerData']);
await this.siteSettings.set('DOMConfig.modified.type', 'modified', {noSave: true});
await this.siteSettings.set('activeDOMConfig', 'modified', {noSave: true});
// if user agrees with ultrawidify on what element player should be, // if user agrees with ultrawidify on what element player should be,
// we just unset our settings for this site // we just unset our settings for this site
if (this.elementStack[index].heuristics?.autoMatch) { if (this.elementStack[index].heuristics?.autoMatch) {
this.settings.setSiteOption(['DOM', 'player', 'manual'], false, this.site); await this.siteSettings.set('DOMConfig.modified.player.manual', false);
await this.settings.save();
this.eventBus.sendToTunnel('get-player-tree'); this.eventBus.sendToTunnel('get-player-tree');
} else { } else {
// ensure settings exist: // ensure settings exist:
this.settings.setSiteOption(['DOM', 'player', 'manual'], true, this.site); await this.siteSettings.set('DOMConfig.modified.player.manual', true, {noSave: true});
this.settings.setSiteOption(['DOM', 'player', 'useRelativeAncestor'], true, this.site); await this.siteSettings.set('DOMConfig.modified.player.mode', 'index', {noSave: true});
this.settings.setSiteOption(['DOM', 'player', 'videoAncestor'], index, this.site); await this.siteSettings.set('DOMConfig.modified.player.index', index, true);
await this.settings.save();
this.eventBus.sendToTunnel('get-player-tree'); this.eventBus.sendToTunnel('get-player-tree');
} }
}, },
@ -428,7 +438,6 @@ export default({
//TODO: update settings! //TODO: update settings!
} }
} }
}) })
</script> </script>

View File

@ -1,6 +1,6 @@
import CropModePersistence from '../../../common/enums/CropModePersistence.enum'; import CropModePersistence from '../../../common/enums/CropModePersistence.enum';
import ExtensionMode from '../../../common/enums/ExtensionMode.enum'; import ExtensionMode from '../../../common/enums/ExtensionMode.enum';
import { SiteSettingsInterface } from '../../../common/interfaces/SettingsInterface'; import { SettingsReloadComponent, SettingsReloadFlags, SiteSettingsInterface } from '../../../common/interfaces/SettingsInterface';
import { _cp } from '../../../common/js/utils'; import { _cp } from '../../../common/js/utils';
import Settings from '../Settings'; import Settings from '../Settings';
import { browser } from 'webextension-polyfill-ts'; import { browser } from 'webextension-polyfill-ts';
@ -24,6 +24,8 @@ export class SiteSettings {
sessionData: SiteSettingsInterface; sessionData: SiteSettingsInterface;
readonly defaultSettings: SiteSettingsInterface; readonly defaultSettings: SiteSettingsInterface;
storageChangeSubscriptions: {[x: string]: ((newSiteConf, changes, area) => void)[]} = {};
//#region lifecycle //#region lifecycle
constructor(settings: Settings, site: string) { constructor(settings: Settings, site: string) {
this.settings = settings; this.settings = settings;
@ -114,12 +116,53 @@ export class SiteSettings {
} }
const parsedSettings = JSON.parse(changes.uwSettings.newValue); const parsedSettings = JSON.parse(changes.uwSettings.newValue);
this.data = parsedSettings.active.sites[this.site]; this.data = parsedSettings.sites[this.site];
// we ignore 'readonly' property this once // we ignore 'readonly' property this once
(this as any).defaultSettings = parsedSettings.active.sites['@global']; (this as any).defaultSettings = parsedSettings.sites['@global'];
this.compileSettingsObject(); this.compileSettingsObject();
console.log('changes:', parsedSettings);
// trigger any subscriptions on change
if (parsedSettings._updateFlags) {
console.log('update flags yay!')
if (parsedSettings._updateFlags?.forSite === this.site) {
if (parsedSettings._updateFlags?.requireReload === true) {
for (const key in this.storageChangeSubscriptions) {
for (const fn of this.storageChangeSubscriptions[key]) {
fn(this, changes, area);
}
}
}
else if (parsedSettings._updateFlags?.requireReload) {
for (const key of parsedSettings._updateFlags?.requireReload) {
console.log('reload required for:', key, this.storageChangeSubscriptions)
for (const fn of this.storageChangeSubscriptions[key]) {
fn(this, changes, area);
}
}
}
}
// we aren't stepping on any other toes by doing this, since everyone
// gets the first change
this.settings.active._updateFlags = undefined;
this.settings.saveWithoutReload();
}
}
subscribeToStorageChange(component: SettingsReloadComponent, fn: (newSiteConf, changes, area) => void) {
if (!this.storageChangeSubscriptions[component]) {
this.storageChangeSubscriptions[component] = [];
}
this.storageChangeSubscriptions[component].push(fn);
}
unsubscribeToStorageChange(component: SettingsReloadComponent, fn: (newSiteConf, changes, area) => void) {
if (this.storageChangeSubscriptions[component]) {
this.storageChangeSubscriptions[component] = this.storageChangeSubscriptions[component].filter(x => x != fn);
}
} }
//#endregion //#endregion
@ -206,6 +249,23 @@ export class SiteSettings {
//#endregion //#endregion
//#region get
/**
* Gets DOMConfig. If DOMConfig with given name doesn't exist, we create a new one.
* @param configName We want to fetch this DOM config
* @param copyFrom If DOMConfig data doesn't exist, we copy things from DOMConfig with
* this name. If DOMConfig with this name doesn't exist, we copy last
* active DOMConfig. If that fails, we copy original DOMConfig.
* @returns Current DOMConfig object for this site
*/
getDOMConfig(configName: string, copyFrom?: string) {
if (! this.data.DOMConfig[configName]) {
this.data.DOMConfig[configName] = _cp(this.data.DOMConfig[copyFrom ?? this.data.activeDOMConfig ?? 'original']);
}
return this.data.currentDOMConfig[configName];
}
//#endregion
//#region set shit //#region set shit
/** /**
* Sets option value. * Sets option value.
@ -213,7 +273,7 @@ export class SiteSettings {
* @param optionValue new value of option * @param optionValue new value of option
* @param reload whether we should trigger a reload in components that require it * @param reload whether we should trigger a reload in components that require it
*/ */
async set(optionPath: string, optionValue: any, reload: boolean = false) { async set(optionPath: string, optionValue: any, options: {reload?: boolean, noSave?: boolean} = {reload: false}) {
// if no settings exist for this site, create an empty object // if no settings exist for this site, create an empty object
if (!this.settings.active.sites[this.site]) { if (!this.settings.active.sites[this.site]) {
this.settings.active.sites[this.site] = _cp(this.settings.active.sites['@empty']); this.settings.active.sites[this.site] = _cp(this.settings.active.sites['@empty']);
@ -226,22 +286,38 @@ export class SiteSettings {
} else { } else {
let iterator = this.settings.active.sites[this.site]; let iterator = this.settings.active.sites[this.site];
let i; let i;
let iterated = '';
for (i = 0; i < pathParts.length - 1; i++) { for (i = 0; i < pathParts.length - 1; i++) {
iterated = `${iterated}.${pathParts[i]}`
if (!iterator[pathParts[i]]) { // some optional paths may still be undefined, even after cloning empty object if (!iterator[pathParts[i]]) { // some optional paths may still be undefined, even after cloning empty object
iterator[pathParts[i]] = {}; iterator[pathParts[i]] = {};
} }
iterator = iterator[pathParts[i]]; iterator = iterator[pathParts[i]];
} }
iterated = `${iterated}.${pathParts[i]}`
iterator[pathParts[i]] = optionValue; iterator[pathParts[i]] = optionValue;
} }
if (reload) { if (! options.noSave) {
this.settings.save(); if (options.reload) {
} else { await this.settings.save();
this.settings.saveWithoutReload(); } else {
await this.settings.saveWithoutReload();
}
} }
} }
async setUpdateFlags(flags: SettingsReloadFlags) {
this.settings.active._updateFlags = {
requireReload: flags,
forSite: this.site
};
}
/** /**
* Sets temporary option value (for Persistence.UntilReload) * Sets temporary option value (for Persistence.UntilReload)
* @param optionPath path to value in object notation (dot separated) * @param optionPath path to value in object notation (dot separated)

View File

@ -146,12 +146,33 @@ class PlayerData {
this.startChangeDetection(); this.startChangeDetection();
document.addEventListener('fullscreenchange', this.trackDimensionChanges); document.addEventListener('fullscreenchange', this.trackDimensionChanges);
// we want to reload on storage changes
this.siteSettings.subscribeToStorageChange('PlayerData', () => this.reloadPlayerDataConfig());
} catch (e) { } catch (e) {
console.error('[Ultrawidify::PlayerData::ctor] There was an error setting up player data. You should be never seeing this message. Error:', e); console.error('[Ultrawidify::PlayerData::ctor] There was an error setting up player data. You should be never seeing this message. Error:', e);
this.invalid = true; this.invalid = true;
} }
} }
private reloadPlayerDataConfig() {
console.log('reloading config ...')
this.element = this.getPlayer();
console.log('got player:', this.element);
this.periodicallyRefreshPlayerElement = false;
try {
this.periodicallyRefreshPlayerElement = this.siteSettings.data.currentDOMConfig.periodicallyRefreshPlayerElement;
} catch (e) {
// no biggie — that means we don't have any special settings for this site.
}
// because this is often caused by the UI
console.log('tree request:');
this.handlePlayerTreeRequest();
}
private initEventBus() { private initEventBus() {
for (const action in this.eventBusCommands) { for (const action in this.eventBusCommands) {
for (const command of this.eventBusCommands[action]) { for (const command of this.eventBusCommands[action]) {
@ -474,10 +495,32 @@ class PlayerData {
const playerQs = this.siteSettings.getCustomDOMQuerySelector('player'); const playerQs = this.siteSettings.getCustomDOMQuerySelector('player');
const playerIndex = this.siteSettings.getPlayerIndex(); const playerIndex = this.siteSettings.getPlayerIndex();
if (playerQs) { // on verbose, get both qs and index player
playerCandidate = this.getPlayerQs(playerQs, elementStack, videoWidth, videoHeight); if (options.verbose) {
} else if (playerIndex) { // btw 0 is not a valid index for player if (playerIndex) {
playerCandidate = elementStack[playerIndex]; playerCandidate = elementStack[playerIndex];
playerCandidate.heuristics['manualElementByParentIndex'] = true;
}
if (playerQs) {
playerCandidate = this.getPlayerQs(playerQs, elementStack, videoWidth, videoHeight);
}
}
// if mode is given, we follow the preference
if (this.siteSettings.data.currentDOMConfig?.elements?.player?.mode) {
if (this.siteSettings.data.currentDOMConfig?.elements?.player?.mode === 'qs') {
playerCandidate = this.getPlayerQs(playerQs, elementStack, videoWidth, videoHeight);
} else {
playerCandidate = elementStack[playerIndex];
playerCandidate.heuristics['manualElementByParentIndex'] = true;
}
} else {
// try to figure it out based on what we have, with playerQs taking priority
if (playerQs) {
playerCandidate = this.getPlayerQs(playerQs, elementStack, videoWidth, videoHeight);
} else if (playerIndex) { // btw 0 is not a valid index for player
playerCandidate = elementStack[playerIndex];
playerCandidate.heuristics['manualElementByParentIndex'] = true;
}
} }
if (playerCandidate) { if (playerCandidate) {
@ -644,8 +687,10 @@ class PlayerData {
* Lists elements between video and DOM root for display in player selector (UI) * Lists elements between video and DOM root for display in player selector (UI)
*/ */
private handlePlayerTreeRequest() { private handlePlayerTreeRequest() {
console.log('aya')
// this populates this.elementStack fully // this populates this.elementStack fully
this.getPlayer({verbose: true}); this.getPlayer({verbose: true});
console.log('tree:', JSON.parse(JSON.stringify(this.elementStack)));
this.eventBus.send('uw-config-broadcast', {type: 'player-tree', config: JSON.parse(JSON.stringify(this.elementStack))}); this.eventBus.send('uw-config-broadcast', {type: 'player-tree', config: JSON.parse(JSON.stringify(this.elementStack))});
} }