Migrate DOMConfig in preparation for new settings page

This commit is contained in:
Tamius Han 2025-12-26 21:39:34 +01:00
parent 2a42c3e715
commit 3dbec85269
9 changed files with 247 additions and 152 deletions

View File

@ -1,5 +1,5 @@
export enum PlayerDetectionMode {
Auto = 0,
AncestorIndex = 1,
querySelectors = 2,
QuerySelectors = 2,
};

View File

@ -1,3 +1,4 @@
import { SiteSupportLevel } from './../enums/SiteSupportLevel.enum';
import { Action } from '../../../node_modules/vuex/types/index'
import { AardPollingOptions } from '../../ext/lib/aard/enums/aard-polling-options.enum'
import { AardSubtitleCropMode } from '../../ext/lib/aard/enums/aard-subtitle-crop-mode.enum'
@ -9,6 +10,7 @@ import ExtensionMode from '../enums/ExtensionMode.enum'
import { SiteSupportLevel } from '../enums/SiteSupportLevel.enum'
import StretchType from '../enums/StretchType.enum'
import VideoAlignmentType from '../enums/VideoAlignmentType.enum'
import { PlayerDetectionMode } from '../enums/PlayerDetectionMode.enum';
export enum ExtensionEnvironment {
Normal = ExtensionMode.All,
@ -443,8 +445,8 @@ export interface SiteSettingsInterface {
enableKeyboard: ExtensionMode;
enableUI: ExtensionMode;
applyToEmbeddedContent: EmbeddedContentSettingsOverridePolicy; // presumed to be 'Always' if not defined
overrideWhenEmbedded?: boolean;
applyToEmbeddedContent: EmbeddedContentSettingsOverridePolicy; // presumed to be 'Use as default' if not defined
overrideWhenEmbedded?: EmbeddedContentSettingsOverridePolicy;
autocreated?: boolean;
@ -484,11 +486,10 @@ export interface PlayerAutoConfigInterface {
}
export interface SiteDOMSettingsInterface {
type: 'official' | 'community' | 'user-defined' | 'modified' | undefined;
type: SiteSupportLevel; // 'official' | 'community' | 'user-defined' | 'modified' | undefined;
elements?: {
player?: SiteDOMElementSettingsInterface,
video?: SiteDOMElementSettingsInterface,
other?: { [x: number]: SiteDOMElementSettingsInterface }
player?: PlayerDOMSettingsInterface,
video?: PlayerDOMSettingsInterface,
};
customCss?: string;
periodicallyRefreshPlayerElement?: boolean;
@ -499,12 +500,19 @@ export interface SiteDOMSettingsInterface {
anchorElement?: HTMLElement;
}
export interface PlayerDOMSettingsInterface {
playerDetectionMode: PlayerDetectionMode,
allowAutoFallback: boolean,
ancestorIndex?: number,
querySelectors?: string,
customCSS?: string,
}
export interface SiteDOMElementSettingsInterface {
manual?: boolean;
querySelectors?: string;
index?: number; // previously: useRelativeAncestor + videoAncestor
mode?: 'index' | 'qs';
nodeCss?: {[x: string]: string};
}
export default SettingsInterface;

View File

@ -12,6 +12,7 @@ import { update } from 'lodash';
import EmbeddedContentSettingsOverridePolicy from '../../common/enums/EmbeddedContentSettingsOverridePolicy.enum';
import LegacyExtensionMode from '../../common/enums/LegacyExtensionMode.enum';
import ExtensionMode from '../../common/enums/ExtensionMode.enum';
import { PlayerDetectionMode } from '../../common/enums/PlayerDetectionMode.enum';
const ExtensionConfPatch = Object.freeze([
@ -316,6 +317,53 @@ const ExtensionConfPatch = Object.freeze([
userOptions.ui = defaultOptions.ui
};
}
}, {
forVersion: '6.3.996',
updateFn: (userOptions: SettingsInterface, defaultOptions: SettingsInterface, logger?) => {
for (const site in userOptions.sites) {
for (const domConf in userOptions.sites.DOMConfig) {
const oldConf = userOptions.sites[site].DOMConfig[domConf] as any;
const newConf: any = {
type: oldConf.type ?? userOptions.sites[site].type,
elements: {}
};
if (oldConf.elements.player) {
newConf.elements['player'] = {
playerDetectionMode: oldConf?.elements?.player?.manual ? (
oldConf?.elements?.player?.querySelectors.trim() ? PlayerDetectionMode.QuerySelectors : PlayerDetectionMode.AncestorIndex
) : PlayerDetectionMode.Auto,
allowAutoFallback: true,
ancestorIndex: oldConf?.elements?.player?.parentIndex,
querySelectors: oldConf?.elements?.player?.querySelectors,
customCSS: oldConf?.elements?.player?.customCss,
}
} else {
newConf.elements['player'] = {
playerDetectionMode: PlayerDetectionMode.Auto,
allowAutoFallback: true,
}
}
if (oldConf.elements.video) {
newConf.elements['video'] = {
type: oldConf.type ?? userOptions.sites[site].type,
elements: {
video: {
playerDetectionMode: oldConf?.elements?.video?.manual ? PlayerDetectionMode.QuerySelectors : PlayerDetectionMode.Auto,
allowAutoFallback: true,
querySelectors: oldConf?.elements?.video?.querySelectors,
customCSS: oldConf?.elements?.video?.customCss,
}
}
}
}
userOptions.sites[site].DOMConfig[domConf] = newConf;
}
}
}
}
]);

View File

@ -13,6 +13,7 @@ import EmbeddedContentSettingsOverridePolicy from '../../common/enums/EmbeddedCo
import { AardPollingOptions } from '../lib/aard/enums/aard-polling-options.enum';
import { AardSubtitleCropMode } from '../lib/aard/enums/aard-subtitle-crop-mode.enum';
import { SiteSupportLevel } from '../../common/enums/SiteSupportLevel.enum';
import { PlayerDetectionMode } from '../../common/enums/PlayerDetectionMode.enum';
if(Debug.debug)
console.log("Loading: ExtensionConf.js");
@ -820,26 +821,66 @@ const ExtensionConf: SettingsInterface = {
crop: {type: AspectRatioType.Automatic},
stretch: {type: StretchType.NoStretch},
alignment: {x: VideoAlignmentType.Center, y: VideoAlignmentType.Center},
},
activeDOMConfig: 'blank',
DOMConfig: {
'blank': {
type: SiteSupportLevel.Unknown,
elements: {
player: {
playerDetectionMode: PlayerDetectionMode.Auto,
allowAutoFallback: true,
// ancestorIndex: 1, // we leave those on undefined,
// querySelectors: '',
// customCSS: ''
}
}
}
}
},
"@empty": { // placeholder settings object with fallbacks to @global
"@empty": {
defaultType: SiteSupportLevel.Unknown,
enable: ExtensionMode.Default,
enableAard: ExtensionMode.Default,
enableKeyboard: ExtensionMode.Default,
enableUI: ExtensionMode.Default,
applyToEmbeddedContent: EmbeddedContentSettingsOverridePolicy.Default,
overrideWhenEmbedded: EmbeddedContentSettingsOverridePolicy.Default,
applyToEmbeddedContent: EmbeddedContentSettingsOverridePolicy.Always,
type: SiteSupportLevel.UserDefined,
defaultType: SiteSupportLevel.UserDefined,
persistCSA: CropModePersistence.Default,
defaults: {
crop: null,
crop: {type: AspectRatioType.Default},
stretch: {type: StretchType.Default},
alignment: {x: VideoAlignmentType.Default, y: VideoAlignmentType.Default},
alignment: {x: VideoAlignmentType.Default, y: VideoAlignmentType.Default}
},
persistCSA: CropModePersistence.Default,
activeDOMConfig: 'empty',
DOMConfig: {
'empty': {
type: SiteSupportLevel.UserDefined,
elements: {
player: {
playerDetectionMode: PlayerDetectionMode.Auto,
allowAutoFallback: true,
// ancestorIndex: 1,
// querySelectors: '',
// customCSS: ''
},
video: {
playerDetectionMode: PlayerDetectionMode.Auto,
allowAutoFallback: true,
// ancestorIndex: 1,
// querySelectors: '',
// customCSS: ''
}
},
"www.youtube.com" : {
}
}
},
"www.youtube.com": {
enable: ExtensionMode.All,
enableAard: ExtensionMode.All,
enableKeyboard: ExtensionMode.All,
@ -858,7 +899,8 @@ const ExtensionConf: SettingsInterface = {
type: SiteSupportLevel.OfficialSupport,
elements: {
player: {
manual: true,
playerDetectionMode: PlayerDetectionMode.QuerySelectors,
allowAutoFallback: true,
querySelectors: "#movie_player, #player, #c4-player",
}
}
@ -885,7 +927,8 @@ const ExtensionConf: SettingsInterface = {
type: SiteSupportLevel.OfficialSupport,
elements: {
player: {
manual: true,
playerDetectionMode: PlayerDetectionMode.QuerySelectors,
allowAutoFallback: true,
querySelectors: "#movie_player, #player, #c4-player",
}
}
@ -901,6 +944,21 @@ const ExtensionConf: SettingsInterface = {
override: false,
type: SiteSupportLevel.CommunitySupport,
defaultType: SiteSupportLevel.CommunitySupport,
DOMConfig: {
'community': {
type: SiteSupportLevel.CommunitySupport,
elements: {
player: {
playerDetectionMode: PlayerDetectionMode.Auto,
allowAutoFallback: true,
// ancestorIndex: 1,
// querySelectors: '',
// customCSS: ''
}
}
}
}
},
"www.disneyplus.com" : {
enable: ExtensionMode.Theater,
@ -917,11 +975,13 @@ const ExtensionConf: SettingsInterface = {
type: SiteSupportLevel.OfficialSupport,
elements: {
player: {
manual: true,
playerDetectionMode: PlayerDetectionMode.QuerySelectors,
allowAutoFallback: true,
querySelectors: ".btm-media-player",
},
video: {
manual: true,
playerDetectionMode: PlayerDetectionMode.QuerySelectors,
allowAutoFallback: true,
querySelectors: ".btm-media-client-element"
}
},
@ -972,19 +1032,6 @@ const ExtensionConf: SettingsInterface = {
applyToEmbeddedContent: EmbeddedContentSettingsOverridePolicy.Never,
type: SiteSupportLevel.OfficialBlacklist,
defaultType: SiteSupportLevel.OfficialBlacklist,
activeDOMConfig: 'official',
DOMConfig: {
'official': {
type: SiteSupportLevel.OfficialSupport,
// customCss: 'video {\n width: 100% !important;\n height: 100% !important;\n}',
elements: {
player: {
manual: false,
querySelectors: '.reddit-video-player-root, .media-preview-content'
}
}
}
},
},
"imgur.com": {
enable: ExtensionMode.Disabled,
@ -1011,7 +1058,8 @@ const ExtensionConf: SettingsInterface = {
type: SiteSupportLevel.CommunitySupport,
elements: {
player: {
manual: true,
playerDetectionMode: PlayerDetectionMode.QuerySelectors,
allowAutoFallback: true,
querySelectors: "#jwplayer-container"
}
}
@ -1027,13 +1075,6 @@ const ExtensionConf: SettingsInterface = {
applyToEmbeddedContent: EmbeddedContentSettingsOverridePolicy.UseAsDefault,
type: SiteSupportLevel.CommunitySupport,
defaultType: SiteSupportLevel.CommunitySupport,
activeDOMConfig: 'community',
DOMConfig: {
'community': {
type: SiteSupportLevel.CommunitySupport,
// customCss: "body {\n background-color: #000;\n}\n\n.application {\n background-color: #000;\n}"
}
}
},
"metaivi.com": {
enable: ExtensionMode.Theater,
@ -1043,17 +1084,6 @@ const ExtensionConf: SettingsInterface = {
applyToEmbeddedContent: EmbeddedContentSettingsOverridePolicy.UseAsDefault,
type: SiteSupportLevel.CommunitySupport,
defaultType: SiteSupportLevel.CommunitySupport,
activeDOMConfig: 'community',
DOMConfig: {
'community': {
type: SiteSupportLevel.CommunitySupport,
elements: {
video: {
nodeCss: {'position': 'absolute !important'}
}
}
}
},
},
"piped.kavin.rocks": {
enable: ExtensionMode.Theater,
@ -1064,13 +1094,6 @@ const ExtensionConf: SettingsInterface = {
applyToEmbeddedContent: EmbeddedContentSettingsOverridePolicy.UseAsDefault,
type: SiteSupportLevel.CommunitySupport,
defaultType: SiteSupportLevel.CommunitySupport,
activeDOMConfig: 'community',
DOMConfig: {
'community': {
type: SiteSupportLevel.CommunitySupport,
// customCss: ".shaka-video-container {\n flex-direction: column !important;\n}"
}
}
},
}
}

View File

@ -39,6 +39,7 @@ export class SiteSettings {
temporaryData: SiteSettingsInterface;
sessionData: SiteSettingsInterface;
readonly defaultSettings: SiteSettingsInterface;
readonly blankSettings: SiteSettingsInterface;
storageChangeSubscriptions: {[x: string]: ((newSiteConf, changes, area) => void)[]} = {};
@ -50,6 +51,7 @@ export class SiteSettings {
this.settings = settings;
this.raw = settings.active.sites[this.site];
this.defaultSettings = settings.active.sites['@global'];
this.blankSettings = settings.active.sites['@empty'];
this.compileSettingsObject();
@ -472,7 +474,7 @@ export class SiteSettings {
// If this function is not being called in response to user actin,
// create fake settings object.
if (options.scripted && !this.settings.active.sites[targetSite]) {
this.settings.active.sites[targetSite] = _cp(this.settings.active.sites['@global']);
this.settings.active.sites[targetSite] = _cp(this.blankSettings);
this.settings.active.sites[targetSite].autocreated = true;
this.settings.active.sites[targetSite].type = SiteSupportLevel.Unknown;
} else {

View File

@ -1,10 +1,12 @@
<template>
<!-- ADVANCED OPTIONS -->
<div v-if="DOMConfigData" class="flex flex-col gap-2">
<div class="flex flex-col gap-2">
<div class="flex flex-row gap-2 justify-end">
<button>Load existing config</button>
<button>Import from file</button>
</div>
<template v-if="DOMConfigData" >
<div class="field">
<div class="label">Player detection:</div>
<div class="select">
@ -49,12 +51,18 @@
<div class="field">
<div class="label">Additional CSS for the page</div>
<div class="input">
<textbox v-model="DOMConfigData.customCss" />
<textarea v-model="DOMConfigData.customCSS" />
</div>
<div class="hint">
You should be at least somewhat proficient with CSS in order to use this option.
</div>
</div>
</template>
<template v-else>
No DOM config for this site.
</template>
</div>
<div class="w-full flex flex-row gap-2 justify-end">
@ -75,6 +83,7 @@ import { SiteSettings } from '@src/ext/lib/settings/SiteSettings';
import { PlayerDetectionMode } from '@src/common/enums/PlayerDetectionMode.enum';
import Popup from '@components/common/Popup.vue';
import { _cp } from '../../../../../common/js/utils';
export default({
@ -88,6 +97,7 @@ export default({
],
data() {
return {
PlayerDetectionMode,
DOMConfigData: undefined as any,
selectSnapshotDialog: {visible: false},
}
@ -104,7 +114,11 @@ export default({
},
methods: {
loadSiteSettings(siteSettings: SiteSettings) {
if (siteSettings.data.DOMConfig) {
this.DOMConfigData = siteSettings.data.DOMConfig[siteSettings.data.activeDOMConfig];
} else {
this.DOMConfigData = _cp(siteSettings.blankSettings.DOMConfig.blank)
}
}
}

View File

@ -200,23 +200,23 @@ export default defineComponent({
},
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});
// 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) {
await this.siteSettings.set('DOMConfig.modified.elements.player.manual', false);
this.getPlayerTree();
} else {
// ensure settings exist:
await this.siteSettings.set('DOMConfig.modified.elements.player.manual', true, {noSave: true});
await this.siteSettings.set('DOMConfig.modified.elements.player.mode', 'index', {noSave: true});
await this.siteSettings.set('DOMConfig.modified.elements.player.index', index, true);
this.getPlayerTree();
}
// // 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) {
// await this.siteSettings.set('DOMConfig.modified.elements.player.manual', false);
// this.getPlayerTree();
// } else {
// // ensure settings exist:
// await this.siteSettings.set('DOMConfig.modified.elements.player.manual', true, {noSave: true});
// await this.siteSettings.set('DOMConfig.modified.elements.player.mode', 'index', {noSave: true});
// await this.siteSettings.set('DOMConfig.modified.elements.player.index', index, true);
// this.getPlayerTree();
// }
},
/**
* Toggles active CSS for element of certain parent index.

View File

@ -56,23 +56,23 @@ export default({
},
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});
// 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) {
await this.siteSettings.set('DOMConfig.modified.elements.player.manual', false);
this.getPlayerTree();
} else {
// ensure settings exist:
await this.siteSettings.set('DOMConfig.modified.elements.player.manual', true, {noSave: true});
await this.siteSettings.set('DOMConfig.modified.elements.player.mode', 'index', {noSave: true});
await this.siteSettings.set('DOMConfig.modified.elements.player.index', index, true);
this.getPlayerTree();
}
// // 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) {
// await this.siteSettings.set('DOMConfig.modified.elements.player.manual', false);
// this.getPlayerTree();
// } else {
// // ensure settings exist:
// await this.siteSettings.set('DOMConfig.modified.elements.player.manual', true, {noSave: true});
// await this.siteSettings.set('DOMConfig.modified.elements.player.mode', 'index', {noSave: true});
// await this.siteSettings.set('DOMConfig.modified.elements.player.index', index, true);
// this.getPlayerTree();
// }
},
edit() {

View File

@ -156,23 +156,23 @@ export default({
},
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});
// 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) {
await this.siteSettings.set('DOMConfig.modified.elements.player.manual', false);
this.getPlayerTree();
} else {
// ensure settings exist:
await this.siteSettings.set('DOMConfig.modified.elements.player.manual', true, {noSave: true});
await this.siteSettings.set('DOMConfig.modified.elements.player.mode', 'index', {noSave: true});
await this.siteSettings.set('DOMConfig.modified.elements.player.index', index, true);
this.getPlayerTree();
}
// // 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) {
// await this.siteSettings.set('DOMConfig.modified.elements.player.manual', false);
// this.getPlayerTree();
// } else {
// // ensure settings exist:
// await this.siteSettings.set('DOMConfig.modified.elements.player.manual', true, {noSave: true});
// await this.siteSettings.set('DOMConfig.modified.elements.player.mode', 'index', {noSave: true});
// await this.siteSettings.set('DOMConfig.modified.elements.player.index', index, true);
// this.getPlayerTree();
// }
},
/**
* Toggles active CSS for element of certain parent index.