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

View File

@ -34,13 +34,6 @@
<script>
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 Logger from '../ext/lib/Logger';
import Settings from '../ext/lib/Settings';
@ -49,13 +42,6 @@ import UIProbeMixin from './src/utils/UIProbeMixin';
export default {
components: {
// Icon,
ResizerDebugPanel,
VideoSettings,
PlayerDetectionPanel,
AutodetectionSettingsPanel,
DebugPanel,
BaseExtensionSettings,
PlayerUIWindow
},
mixins: [

View File

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

View File

@ -343,22 +343,15 @@ export default {
},
getCommandValue(availableCommands, command) {
console.log('command:', command, 'from available commands', 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)) {
return cmd.label;
}
}
return 'Unknown command';
},
getAlignmentLabel(alignment) {
console.log('alignment for site. ----------------------------', alignment);
// in case default settings don't have this set
if (!alignment) {
return 'Center'

View File

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

View File

@ -1,6 +1,6 @@
import CropModePersistence from '../../../common/enums/CropModePersistence.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 Settings from '../Settings';
import { browser } from 'webextension-polyfill-ts';
@ -24,6 +24,8 @@ export class SiteSettings {
sessionData: SiteSettingsInterface;
readonly defaultSettings: SiteSettingsInterface;
storageChangeSubscriptions: {[x: string]: ((newSiteConf, changes, area) => void)[]} = {};
//#region lifecycle
constructor(settings: Settings, site: string) {
this.settings = settings;
@ -114,12 +116,53 @@ export class SiteSettings {
}
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
(this as any).defaultSettings = parsedSettings.active.sites['@global'];
(this as any).defaultSettings = parsedSettings.sites['@global'];
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
@ -206,6 +249,23 @@ export class SiteSettings {
//#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
/**
* Sets option value.
@ -213,7 +273,7 @@ export class SiteSettings {
* @param optionValue new value of option
* @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 (!this.settings.active.sites[this.site]) {
this.settings.active.sites[this.site] = _cp(this.settings.active.sites['@empty']);
@ -226,22 +286,38 @@ export class SiteSettings {
} else {
let iterator = this.settings.active.sites[this.site];
let i;
let iterated = '';
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
iterator[pathParts[i]] = {};
}
iterator = iterator[pathParts[i]];
}
iterated = `${iterated}.${pathParts[i]}`
iterator[pathParts[i]] = optionValue;
}
if (reload) {
this.settings.save();
} else {
this.settings.saveWithoutReload();
if (! options.noSave) {
if (options.reload) {
await this.settings.save();
} 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)
* @param optionPath path to value in object notation (dot separated)

View File

@ -146,12 +146,33 @@ class PlayerData {
this.startChangeDetection();
document.addEventListener('fullscreenchange', this.trackDimensionChanges);
// we want to reload on storage changes
this.siteSettings.subscribeToStorageChange('PlayerData', () => this.reloadPlayerDataConfig());
} catch (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;
}
}
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() {
for (const action in this.eventBusCommands) {
for (const command of this.eventBusCommands[action]) {
@ -474,10 +495,32 @@ class PlayerData {
const playerQs = this.siteSettings.getCustomDOMQuerySelector('player');
const playerIndex = this.siteSettings.getPlayerIndex();
if (playerQs) {
playerCandidate = this.getPlayerQs(playerQs, elementStack, videoWidth, videoHeight);
} else if (playerIndex) { // btw 0 is not a valid index for player
playerCandidate = elementStack[playerIndex];
// on verbose, get both qs and index player
if (options.verbose) {
if (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) {
@ -644,8 +687,10 @@ class PlayerData {
* Lists elements between video and DOM root for display in player selector (UI)
*/
private handlePlayerTreeRequest() {
console.log('aya')
// this populates this.elementStack fully
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))});
}