migration to site settings mostly done. TODO: check if things still work
This commit is contained in:
parent
a58edad8ea
commit
9503003a4a
6
src/common/interfaces/ArInterface.ts
Normal file
6
src/common/interfaces/ArInterface.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import AspectRatioType from '../enums/AspectRatioType.enum';
|
||||||
|
|
||||||
|
export interface Ar {
|
||||||
|
type: AspectRatioType,
|
||||||
|
ratio?: number
|
||||||
|
}
|
@ -366,7 +366,7 @@ export interface SiteSettingsInterface {
|
|||||||
defaults?: { // must be defined in @global and @empty
|
defaults?: { // must be defined in @global and @empty
|
||||||
crop?: {type: AspectRatioType, [x: string]: any},
|
crop?: {type: AspectRatioType, [x: string]: any},
|
||||||
stretch?: StretchType,
|
stretch?: StretchType,
|
||||||
alignment?: any,
|
alignment?: {x: VideoAlignmentType, y: VideoAlignmentType},
|
||||||
}
|
}
|
||||||
|
|
||||||
cropModePersistence?: CropModePersistence;
|
cropModePersistence?: CropModePersistence;
|
||||||
|
@ -39,11 +39,9 @@ import DebugPanel from './src/PlayerUiPanels/DebugPanel.vue'
|
|||||||
import VideoSettings from './src/PlayerUiPanels/VideoSettings.vue'
|
import VideoSettings from './src/PlayerUiPanels/VideoSettings.vue'
|
||||||
import AutodetectionSettingsPanel from './src/PlayerUiPanels/AutodetectionSettingsPanel.vue'
|
import AutodetectionSettingsPanel from './src/PlayerUiPanels/AutodetectionSettingsPanel.vue'
|
||||||
import PlayerDetectionPanel from './src/PlayerUiPanels/PlayerDetectionPanel.vue'
|
import PlayerDetectionPanel from './src/PlayerUiPanels/PlayerDetectionPanel.vue'
|
||||||
import { mapState } from 'vuex';
|
|
||||||
// import Icon from '../common/components/Icon';
|
// import Icon from '../common/components/Icon';
|
||||||
import ResizerDebugPanel from './src/PlayerUiPanels/ResizerDebugPanelComponent';
|
import ResizerDebugPanel from './src/PlayerUiPanels/ResizerDebugPanelComponent';
|
||||||
import BrowserDetect from '../ext/conf/BrowserDetect';
|
import BrowserDetect from '../ext/conf/BrowserDetect';
|
||||||
import ExecAction from './src/ui-libs/ExecAction';
|
|
||||||
import Logger from '../ext/lib/Logger';
|
import Logger from '../ext/lib/Logger';
|
||||||
import Settings from '../ext/lib/Settings';
|
import Settings from '../ext/lib/Settings';
|
||||||
import EventBus from '../ext/lib/EventBus';
|
import EventBus from '../ext/lib/EventBus';
|
||||||
@ -85,7 +83,6 @@ export default {
|
|||||||
settings: {},
|
settings: {},
|
||||||
BrowserDetect: BrowserDetect,
|
BrowserDetect: BrowserDetect,
|
||||||
settingsInitialized: false,
|
settingsInitialized: false,
|
||||||
execAction: new ExecAction(),
|
|
||||||
eventBus: new EventBus(),
|
eventBus: new EventBus(),
|
||||||
logger: null,
|
logger: null,
|
||||||
|
|
||||||
|
@ -154,6 +154,7 @@ export default {
|
|||||||
selectedTab: 'videoSettings',
|
selectedTab: 'videoSettings',
|
||||||
BrowserDetect: BrowserDetect,
|
BrowserDetect: BrowserDetect,
|
||||||
preventClose: false,
|
preventClose: false,
|
||||||
|
siteSettings: null,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
props: [
|
props: [
|
||||||
@ -168,9 +169,12 @@ export default {
|
|||||||
// IS SUPER HARAM
|
// IS SUPER HARAM
|
||||||
// THINGS WILL NOT WORK IF YOU USE ARROWS
|
// THINGS WILL NOT WORK IF YOU USE ARROWS
|
||||||
siteSupportLevel() {
|
siteSupportLevel() {
|
||||||
return (this.site && this.settings?.active) ? this.settings.active.sites[this.site]?.type || 'no-support' : 'waiting';
|
return (this.site && this.siteSettings) ? this.siteSettings.data.type || 'no-support' : 'waiting';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
created() {
|
||||||
|
this.siteSettings = this.settings.getSiteSettings(this.site);
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
/**
|
/**
|
||||||
* Gets URL of the browser settings page (i think?)
|
* Gets URL of the browser settings page (i think?)
|
||||||
|
@ -262,7 +262,6 @@ import Button from '../../../common/components/Button.vue'
|
|||||||
import KeyboardShortcutParser from '../../../common/js/KeyboardShortcutParser';
|
import KeyboardShortcutParser from '../../../common/js/KeyboardShortcutParser';
|
||||||
import ShortcutButton from '../../../common/components/ShortcutButton';
|
import ShortcutButton from '../../../common/components/ShortcutButton';
|
||||||
import EditShortcutButton from '../../../common/components/EditShortcutButton';
|
import EditShortcutButton from '../../../common/components/EditShortcutButton';
|
||||||
import ExecAction from '../ui-libs/ExecAction';
|
|
||||||
import BrowserDetect from '../../../ext/conf/BrowserDetect';
|
import BrowserDetect from '../../../ext/conf/BrowserDetect';
|
||||||
import AspectRatioType from '../../../common/enums/AspectRatioType.enum';
|
import AspectRatioType from '../../../common/enums/AspectRatioType.enum';
|
||||||
import StretchType from '../../../common/enums/StretchType.enum';
|
import StretchType from '../../../common/enums/StretchType.enum';
|
||||||
@ -286,7 +285,6 @@ export default {
|
|||||||
'site'
|
'site'
|
||||||
],
|
],
|
||||||
created() {
|
created() {
|
||||||
this.exec = new ExecAction(this.settings, window.location.hostname);
|
|
||||||
this.eventBus.subscribe('uw-config-broadcast', {function: (config) => this.handleConfigBroadcast(config)});
|
this.eventBus.subscribe('uw-config-broadcast', {function: (config) => this.handleConfigBroadcast(config)});
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
@ -191,26 +191,7 @@ export default {
|
|||||||
commandArguments = $event.target.value;
|
commandArguments = $event.target.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.settings.active.sites[this.site]) {
|
this.siteSettings.set(option, commandArguments);
|
||||||
this.settings.active.sites[this.site] = this.settings.getDefaultSiteConfiguration();
|
|
||||||
}
|
|
||||||
|
|
||||||
const optionPath = option.split('.');
|
|
||||||
if (optionPath.length < 2) {
|
|
||||||
this.settings.active.sites[this.site][option] = commandArguments;
|
|
||||||
} else {
|
|
||||||
let currentOptionObject = this.settings.active.sites[this.site][optionPath[0]];
|
|
||||||
let i;
|
|
||||||
for (i = 1; i < optionPath.length - 1; i++) {
|
|
||||||
if (currentOptionObject[optionPath[i]] === undefined) {
|
|
||||||
currentOptionObject[optionPath[i]] = {};
|
|
||||||
}
|
|
||||||
currentOptionObject = currentOptionObject[optionPath[i]];
|
|
||||||
}
|
|
||||||
currentOptionObject[optionPath[optionPath.length - 1]] = commandArguments;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.settings.saveWithoutReload();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,23 +132,6 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
|
||||||
<div class="label">Extension default</div>
|
|
||||||
<div class="select">
|
|
||||||
<select
|
|
||||||
:value="extensionDefaultCrop"
|
|
||||||
@click="setDefaultCrop($event, 'global')"
|
|
||||||
>
|
|
||||||
<option
|
|
||||||
v-for="(command, index) of settings?.active.commands.crop"
|
|
||||||
:key="index"
|
|
||||||
:value="JSON.stringify(command.arguments)"
|
|
||||||
>
|
|
||||||
{{command.label}}
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -220,23 +203,7 @@ export default {
|
|||||||
setDefaultCrop($event, scope) {
|
setDefaultCrop($event, scope) {
|
||||||
const commandArguments = JSON.parse($event.target.value);
|
const commandArguments = JSON.parse($event.target.value);
|
||||||
|
|
||||||
if (scope === 'site') {
|
this.siteSettings.set('defaults.crop', commandArguments);
|
||||||
if (!this.settings.active.sites[this.site]) {
|
|
||||||
this.settings.active.sites[this.site] = this.settings.getDefaultSiteConfiguration();
|
|
||||||
}
|
|
||||||
this.settings.active.sites[this.site].defaultCrop = commandArguments;
|
|
||||||
} else {
|
|
||||||
// eventually, this 'if' will be safe to remove (and we'll be able to only
|
|
||||||
// get away with the 'else' section) Maybe in 6 months or so.
|
|
||||||
if (!this.settings.active.crop) {
|
|
||||||
this.settings.active['crop'] = {
|
|
||||||
default: commandArguments
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.settings.active.crop.default = commandArguments;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.settings.saveWithoutReload();
|
this.settings.saveWithoutReload();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -235,16 +235,7 @@ export default {
|
|||||||
*/
|
*/
|
||||||
setDefaultStretchingMode($event, globalOrSite) {
|
setDefaultStretchingMode($event, globalOrSite) {
|
||||||
const commandArguments = JSON.parse($event.target.value);
|
const commandArguments = JSON.parse($event.target.value);
|
||||||
|
this.siteSettings.set('defaults.stretch', commandArguments);
|
||||||
if (globalOrSite === 'site') {
|
|
||||||
if (!this.settings.active.sites[this.site]) {
|
|
||||||
this.settings.active.sites[this.site] = this.settings.getDefaultSiteConfiguration();
|
|
||||||
}
|
|
||||||
this.settings.active.sites[this.site].defaultStretch = commandArguments;
|
|
||||||
} else {
|
|
||||||
this.settings.active.stretch.default = commandArguments;
|
|
||||||
}
|
|
||||||
this.settings.saveWithoutReload();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -117,7 +117,6 @@ import Button from '../../../common/components/Button.vue'
|
|||||||
import ShortcutButton from '../../../common/components/ShortcutButton';
|
import ShortcutButton from '../../../common/components/ShortcutButton';
|
||||||
import EditShortcutButton from '../../../common/components/EditShortcutButton';
|
import EditShortcutButton from '../../../common/components/EditShortcutButton';
|
||||||
import ComputeActionsMixin from '../../../common/mixins/ComputeActionsMixin';
|
import ComputeActionsMixin from '../../../common/mixins/ComputeActionsMixin';
|
||||||
import ExecAction from '../ui-libs/ExecAction';
|
|
||||||
import BrowserDetect from '../../../ext/conf/BrowserDetect';
|
import BrowserDetect from '../../../ext/conf/BrowserDetect';
|
||||||
import AlignmentOptionsControlComponent from './AlignmentOptionsControlComponent.vue';
|
import AlignmentOptionsControlComponent from './AlignmentOptionsControlComponent.vue';
|
||||||
import CommsMixin from '../utils/CommsMixin';
|
import CommsMixin from '../utils/CommsMixin';
|
||||||
@ -149,7 +148,6 @@ export default {
|
|||||||
'site'
|
'site'
|
||||||
],
|
],
|
||||||
created() {
|
created() {
|
||||||
this.exec = new ExecAction(this.settings, window.location.hostname);
|
|
||||||
this.eventBus.subscribe('uw-config-broadcast', {function: (config) => this.handleConfigBroadcast(config)});
|
this.eventBus.subscribe('uw-config-broadcast', {function: (config) => this.handleConfigBroadcast(config)});
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
@ -1,94 +0,0 @@
|
|||||||
import Comms from '../../../ext/lib/comms/Comms';
|
|
||||||
|
|
||||||
class ExecAction {
|
|
||||||
constructor(settings, site) {
|
|
||||||
this.settings = settings;
|
|
||||||
this.site = site;
|
|
||||||
}
|
|
||||||
|
|
||||||
setSettings(settings) {
|
|
||||||
this.settings = settings;
|
|
||||||
}
|
|
||||||
setSite(site) {
|
|
||||||
this.site = site;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
async exec(action, scope, frame, useBus) {
|
|
||||||
for (var cmd of action.cmd) {
|
|
||||||
if (!scope || scope === 'page') {
|
|
||||||
const message = {
|
|
||||||
forwardToContentScript: true,
|
|
||||||
targetFrame: frame,
|
|
||||||
frame: frame,
|
|
||||||
cmd: cmd.action,
|
|
||||||
arg: cmd.arg,
|
|
||||||
customArg: cmd.customArg
|
|
||||||
}
|
|
||||||
if (useBus) {
|
|
||||||
// todo: postMessage out of the iframe!
|
|
||||||
// window.ultrawidify.bus.sendMessage(message.cmd, message);
|
|
||||||
window.parent.sendMessage(message.cmd, message);
|
|
||||||
} else {
|
|
||||||
Comms.sendMessage(message);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// set-ar-persistence sends stuff to content scripts as well (!)
|
|
||||||
// it's important to do that BEFORE the save step
|
|
||||||
if (cmd.action === 'set-ar-persistence') {
|
|
||||||
// even when setting global defaults, we only send message to the current tab in
|
|
||||||
// order to avoid problems related to
|
|
||||||
const message = {
|
|
||||||
forwardToActive: true,
|
|
||||||
targetFrame: frame,
|
|
||||||
frame: frame,
|
|
||||||
cmd: cmd.action,
|
|
||||||
arg: cmd.arg,
|
|
||||||
}
|
|
||||||
// this hopefully delays settings.save() until current crops are saved on the site
|
|
||||||
// and thus avoid any fucky-wuckies
|
|
||||||
if (useBus) {
|
|
||||||
// todo: postMessage out of the iframe!
|
|
||||||
// window.ultrawidify.bus.sendMessage(message.cmd, message);
|
|
||||||
window.parent.sendMessage(message.cmd, message);
|
|
||||||
} else {
|
|
||||||
await Comms.sendMessage(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let site = this.site;
|
|
||||||
if (scope === 'global') {
|
|
||||||
site = '@global';
|
|
||||||
} else if (!this.site) {
|
|
||||||
site = window.location.hostname;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (scope === 'site' && !this.settings.active.sites[site]) {
|
|
||||||
this.settings.active.sites[site] = this.settings.getDefaultOption();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cmd.action === "set-stretch") {
|
|
||||||
this.settings.active.sites[site].stretch = cmd.arg;
|
|
||||||
} else if (cmd.action === "set-alignment") {
|
|
||||||
this.settings.active.sites[site].videoAlignment = cmd.arg;
|
|
||||||
} else if (cmd.action === "set-extension-mode") {
|
|
||||||
this.settings.active.sites[site].mode = cmd.arg;
|
|
||||||
} else if (cmd.action === "set-autoar-mode") {
|
|
||||||
this.settings.active.sites[site].autoar = cmd.arg;
|
|
||||||
} else if (cmd.action === 'set-keyboard') {
|
|
||||||
this.settings.active.sites[site].keyboardShortcutsEnabled = cmd.arg;
|
|
||||||
} else if (cmd.action === 'set-ar-persistence') {
|
|
||||||
this.settings.active.sites[site]['cropModePersistence'] = cmd.arg;
|
|
||||||
this.settings.saveWithoutReload();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cmd.action !== 'set-ar-persistence') {
|
|
||||||
this.settings.save();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default ExecAction;
|
|
@ -8,11 +8,13 @@ import Logger, { baseLoggingOptions } from './lib/Logger';
|
|||||||
import UWGlobals from './lib/UWGlobals';
|
import UWGlobals from './lib/UWGlobals';
|
||||||
import EventBus from './lib/EventBus';
|
import EventBus from './lib/EventBus';
|
||||||
import KeyboardHandler from './lib/kbm/KeyboardHandler';
|
import KeyboardHandler from './lib/kbm/KeyboardHandler';
|
||||||
|
import { SiteSettings } from './lib/settings/SiteSettings';
|
||||||
|
|
||||||
export default class UWContent {
|
export default class UWContent {
|
||||||
pageInfo: PageInfo;
|
pageInfo: PageInfo;
|
||||||
comms: CommsClient;
|
comms: CommsClient;
|
||||||
settings: Settings;
|
settings: Settings;
|
||||||
|
siteSettings: SiteSettings;
|
||||||
keyboardHandler: KeyboardHandler;
|
keyboardHandler: KeyboardHandler;
|
||||||
logger: Logger;
|
logger: Logger;
|
||||||
eventBus: EventBus;
|
eventBus: EventBus;
|
||||||
@ -90,6 +92,7 @@ export default class UWContent {
|
|||||||
logger: this.logger
|
logger: this.logger
|
||||||
});
|
});
|
||||||
await this.settings.init();
|
await this.settings.init();
|
||||||
|
this.siteSettings = this.settings.getSiteSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.eventBus = new EventBus();
|
this.eventBus = new EventBus();
|
||||||
@ -109,42 +112,25 @@ export default class UWContent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// we always initialize extension, even if it's disabled.
|
||||||
initPhase2() {
|
initPhase2() {
|
||||||
// If extension is soft-disabled, don't do shit
|
|
||||||
var extensionMode = this.settings.getExtensionMode();
|
|
||||||
|
|
||||||
this.logger.log('info', 'debug', "[uw::init] Extension mode:" + (extensionMode < 0 ? "disabled" : extensionMode == '1' ? 'basic' : 'full'));
|
|
||||||
|
|
||||||
const isSiteDisabled = extensionMode === ExtensionMode.Disabled
|
|
||||||
|
|
||||||
if (isSiteDisabled) {
|
|
||||||
this.destroy();
|
|
||||||
if (this.settings.getExtensionMode('@global') === ExtensionMode.Disabled) {
|
|
||||||
this.logger.log('info', 'debug', "[uw::init] EXTENSION DISABLED, THEREFORE WONT BE STARTED")
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (this.pageInfo) {
|
if (this.pageInfo) {
|
||||||
this.logger.log('info', 'debug', '[uw.js::setup] An instance of pageInfo already exists and will be destroyed.');
|
this.logger.log('info', 'debug', '[uw.js::setup] An instance of pageInfo already exists and will be destroyed.');
|
||||||
this.pageInfo.destroy();
|
this.pageInfo.destroy();
|
||||||
}
|
}
|
||||||
this.pageInfo = new PageInfo(this.eventBus, this.settings, this.logger, extensionMode, isSiteDisabled);
|
this.pageInfo = new PageInfo(this.eventBus, this.siteSettings, this.settings, this.logger);
|
||||||
this.logger.log('info', 'debug', "[uw.js::setup] pageInfo initialized.");
|
this.logger.log('info', 'debug', "[uw.js::setup] pageInfo initialized.");
|
||||||
|
|
||||||
this.logger.log('info', 'debug', "[uw.js::setup] will try to initate KeyboardHandler.");
|
this.logger.log('info', 'debug', "[uw.js::setup] will try to initate KeyboardHandler.");
|
||||||
|
|
||||||
// start action handler only if extension is enabled for this site
|
|
||||||
if (!isSiteDisabled) {
|
|
||||||
if (this.keyboardHandler) {
|
if (this.keyboardHandler) {
|
||||||
this.keyboardHandler.destroy();
|
this.keyboardHandler.destroy();
|
||||||
}
|
}
|
||||||
this.keyboardHandler = new KeyboardHandler(this.eventBus, this.settings, this.logger);
|
this.keyboardHandler = new KeyboardHandler(this.eventBus, this.siteSettings, this.settings, this.logger);
|
||||||
this.keyboardHandler.init();
|
this.keyboardHandler.init();
|
||||||
|
|
||||||
this.logger.log('info', 'debug', "[uw.js::setup] KeyboardHandler initiated.");
|
this.logger.log('info', 'debug', "[uw.js::setup] KeyboardHandler initiated.");
|
||||||
}
|
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Ultrawidify: failed to start extension. Error:', e)
|
console.error('Ultrawidify: failed to start extension. Error:', e)
|
||||||
|
@ -12,6 +12,7 @@ import Logger from './Logger';
|
|||||||
import SettingsInterface from '../../common/interfaces/SettingsInterface';
|
import SettingsInterface from '../../common/interfaces/SettingsInterface';
|
||||||
import { browser } from 'webextension-polyfill-ts';
|
import { browser } from 'webextension-polyfill-ts';
|
||||||
import AspectRatioType from '../../common/enums/AspectRatioType.enum';
|
import AspectRatioType from '../../common/enums/AspectRatioType.enum';
|
||||||
|
import { SiteSettings } from './settings/SiteSettings';
|
||||||
|
|
||||||
if(process.env.CHANNEL !== 'stable'){
|
if(process.env.CHANNEL !== 'stable'){
|
||||||
console.info("Loading Settings");
|
console.info("Loading Settings");
|
||||||
@ -348,189 +349,6 @@ class Settings {
|
|||||||
return JSON.parse(JSON.stringify(this.default));
|
return JSON.parse(JSON.stringify(this.default));
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------
|
|
||||||
// Config for a given page:
|
|
||||||
//
|
|
||||||
// <hostname> : {
|
|
||||||
// status: <option> // should extension work on this site?
|
|
||||||
// arStatus: <option> // should we do autodetection on this site?
|
|
||||||
// statusEmbedded: <option> // reserved for future... maybe
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Valid values for options:
|
|
||||||
//
|
|
||||||
// status, arStatus, statusEmbedded:
|
|
||||||
//
|
|
||||||
// * enabled — always allow
|
|
||||||
// * basic — only allow fullscreen
|
|
||||||
// * default — allow if default is to allow, block if default is to block
|
|
||||||
// * disabled — never allow
|
|
||||||
|
|
||||||
|
|
||||||
getActionsForSite(site) {
|
|
||||||
if (!site) {
|
|
||||||
return this.active.actions;
|
|
||||||
}
|
|
||||||
if (this.active.sites[site] && this.active.sites[site].actions && this.active.sites[site].actions.length > 0) {
|
|
||||||
return this.active.sites[site].actions;
|
|
||||||
}
|
|
||||||
return this.active.actions;
|
|
||||||
}
|
|
||||||
|
|
||||||
getSettingsForSite(site?) {
|
|
||||||
if (!site) {
|
|
||||||
site = window.location.hostname;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.active.sites[site];
|
|
||||||
}
|
|
||||||
|
|
||||||
getExtensionMode(site?: string) {
|
|
||||||
if (!site) {
|
|
||||||
site = window.location.hostname;
|
|
||||||
|
|
||||||
if (!site) {
|
|
||||||
this.logger?.log('info', 'settings', `[Settings::canStartExtension] window.location.hostname is null or undefined: ${window.location.hostname} \nactive settings:`, this.active);
|
|
||||||
return ExtensionMode.Disabled;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
// if site-specific settings don't exist for the site, we use default mode:
|
|
||||||
if (! this.active.sites[site]) {
|
|
||||||
return this.getExtensionMode('@global');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.active.sites[site].mode === ExtensionMode.Enabled) {
|
|
||||||
return ExtensionMode.Enabled;
|
|
||||||
} else if (this.active.sites[site].mode === ExtensionMode.Basic) {
|
|
||||||
return ExtensionMode.Basic;
|
|
||||||
} else if (this.active.sites[site].mode === ExtensionMode.Disabled) {
|
|
||||||
return ExtensionMode.Disabled;
|
|
||||||
} else {
|
|
||||||
if (site !== '@global') {
|
|
||||||
return this.getExtensionMode('@global');
|
|
||||||
} else {
|
|
||||||
return ExtensionMode.Disabled;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch(e){
|
|
||||||
this.logger?.log('error', 'settings', "[Settings.js::canStartExtension] Something went wrong — are settings defined/has init() been called?\n\nerror:", e, "\n\nSettings object:", this)
|
|
||||||
|
|
||||||
return ExtensionMode.Disabled;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether extension can start on a given site or not.
|
|
||||||
* @param site — default value fof this argument is window.location.hostname
|
|
||||||
* @returns true if extension can run on this site, false otherwise
|
|
||||||
*/
|
|
||||||
isEnabledForSite(site = window.location.hostname) {
|
|
||||||
if (!site) {
|
|
||||||
this.logger?.log('info', 'settings', `[Settings::canStartExtension] window.location.hostname is null or undefined: ${window.location.hostname} \nactive settings:`, this.active);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if (Debug.debug) {
|
|
||||||
// // let's just temporarily disable debugging while recursively calling
|
|
||||||
// // this function to get extension status on current site without duplo
|
|
||||||
// // console logs (and without endless recursion)
|
|
||||||
// Debug.debug = false;
|
|
||||||
// const cse = this.canStartExtension(site);
|
|
||||||
// Debug.debug = true;
|
|
||||||
// }
|
|
||||||
try{
|
|
||||||
// if site is not defined, we use default mode:
|
|
||||||
if (! this.active.sites[site] || this.active.sites[site].mode === ExtensionMode.Default) {
|
|
||||||
return this.active.sites['@global'].mode === ExtensionMode.Enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.active.sites['@global'].mode === ExtensionMode.Enabled) {
|
|
||||||
return this.active.sites[site].mode !== ExtensionMode.Disabled;
|
|
||||||
} else if (this.active.sites['@global'].mode === ExtensionMode.Whitelist) {
|
|
||||||
return this.active.sites[site].mode === ExtensionMode.Enabled;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} catch(e) {
|
|
||||||
this.logger?.log('error', 'settings', "[Settings.js::canStartExtension] Something went wrong — are settings defined/has init() been called?\nSettings object:", this);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
keyboardShortcutsEnabled(site) {
|
|
||||||
if (!site) {
|
|
||||||
site = window.location.hostname;
|
|
||||||
}
|
|
||||||
if (!site) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (!this.active.sites[site]
|
|
||||||
|| this.active.sites[site].keyboardShortcutsEnabled === undefined
|
|
||||||
|| this.active.sites[site].keyboardShortcutsEnabled === ExtensionMode.Default) {
|
|
||||||
return this.keyboardShortcutsEnabled('@global');
|
|
||||||
} else {
|
|
||||||
return this.active.sites[site].keyboardShortcutsEnabled === ExtensionMode.Enabled;
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
this.logger?.log('info', 'settings',"[Settings.js::keyboardDisabled] something went wrong:", e);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extensionEnabled(){
|
|
||||||
return this.active.sites['@global'].mode !== ExtensionMode.Disabled
|
|
||||||
}
|
|
||||||
|
|
||||||
canStartAutoAr(site?: string) {
|
|
||||||
// 'site' argument is only ever used when calling this function recursively for debugging
|
|
||||||
if (!site) {
|
|
||||||
site = window.location.hostname;
|
|
||||||
|
|
||||||
if (!site) {
|
|
||||||
this.logger?.log('warn', ['settings', 'init', 'debug'], `[Settings::canStartAutoAr] No site — even window.location.hostname returned nothing!: ${window.location.hostname}`);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if (Debug.debug) {
|
|
||||||
// let's just temporarily disable debugging while recursively calling
|
|
||||||
// this function to get extension status on current site without duplo
|
|
||||||
// console logs (and without endless recursion)
|
|
||||||
// Debug.debug = false;
|
|
||||||
// const csar = this.canStartAutoAr(site);
|
|
||||||
// Debug.debug = true;
|
|
||||||
|
|
||||||
this.logger?.log('info', ['settings', 'init', 'debug'], "[Settings::canStartAutoAr] ----------------\nCAN WE START AUTOAR ON SITE", site,
|
|
||||||
"?\n\nsettings.active.sites[site]=", this.active.sites[site], "settings.active.sites[@global]=", this.active.sites['@global'],
|
|
||||||
"\nAutoar mode (global)?", this.active.sites['@global'].autoar,
|
|
||||||
`\nAutoar mode (${site})`, this.active.sites[site] ? this.active.sites[site].autoar : '<not defined>',
|
|
||||||
// "\nCan autoar be started?", csar
|
|
||||||
);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if site is not defined, we use default mode:
|
|
||||||
if (! this.active.sites[site]) {
|
|
||||||
this.logger?.log('info', ['settings', 'aard', 'init', 'debug'], "[Settings::canStartAutoAr] Settings not defined for this site, returning defaults.", site, this.active.sites[site], this.active.sites);
|
|
||||||
return this.active.sites['@global'].autoar === ExtensionMode.Enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.active.sites['@global'].autoar === ExtensionMode.Enabled) {
|
|
||||||
this.logger?.log('info', ['settings', 'aard', 'init', 'debug'], `[Settings::canStartAutoAr] Aard is enabled by default. Extension can run unless disabled for this site.`, this.active.sites[site].autoar);
|
|
||||||
return this.active.sites[site].autoar !== ExtensionMode.Disabled;
|
|
||||||
} else if (this.active.sites['@global'].autoar === ExtensionMode.Whitelist) {
|
|
||||||
this.logger?.log('info', ['settings', 'init', 'debug'], "canStartAutoAr — can(not) start aard because extension is in whitelist mode, and this site is (not) equal to", ExtensionMode.Enabled)
|
|
||||||
return this.active.sites[site].autoar === ExtensionMode.Enabled;
|
|
||||||
} else {
|
|
||||||
this.logger?.log('info', ['settings', 'init', 'debug'], "canStartAutoAr — cannot start aard because extension is globally disabled")
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getDefaultOption(option?) {
|
getDefaultOption(option?) {
|
||||||
const allDefault = {
|
const allDefault = {
|
||||||
mode: ExtensionMode.Default,
|
mode: ExtensionMode.Default,
|
||||||
@ -547,40 +365,6 @@ class Settings {
|
|||||||
return allDefault[option];
|
return allDefault[option];
|
||||||
}
|
}
|
||||||
|
|
||||||
getDefaultAr(site) {
|
|
||||||
// site = this.getSiteSettings(site);
|
|
||||||
|
|
||||||
// if (site.defaultAr) {
|
|
||||||
// return site.defaultAr;
|
|
||||||
// }
|
|
||||||
return this.active.miscSettings.defaultAr;
|
|
||||||
}
|
|
||||||
|
|
||||||
getDefaultStretchMode_legacy(site) {
|
|
||||||
if (site && (this.active.sites[site]?.stretch ?? StretchType.Default) !== StretchType.Default) {
|
|
||||||
return this.active.sites[site].stretch;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.active.sites['@global'].stretch;
|
|
||||||
}
|
|
||||||
|
|
||||||
getDefaultCropPersistenceMode(site) {
|
|
||||||
if (site && (this.active.sites[site]?.cropModePersistence ?? StretchType.Default) !== StretchType.Default) {
|
|
||||||
return this.active.sites[site].cropModePersistence;
|
|
||||||
}
|
|
||||||
|
|
||||||
// persistence mode thing is missing from settings by default
|
|
||||||
return this.active.sites['@global'].cropModePersistence || CropModePersistence.Disabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
getDefaultVideoAlignment(site) {
|
|
||||||
if ( (this.active.sites[site]?.videoAlignment ?? VideoAlignmentType.Default) !== VideoAlignmentType.Default) {
|
|
||||||
return this.active.sites[site].videoAlignment;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.active.sites['@global'].videoAlignment;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets default site configuration. Only returns essential settings.
|
* Gets default site configuration. Only returns essential settings.
|
||||||
* @returns
|
* @returns
|
||||||
@ -597,48 +381,8 @@ class Settings {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
getSiteSettings(site: string = window.location.hostname): SiteSettings {
|
||||||
* Gets default cropping mode for extension.
|
return new SiteSettings(this, site);
|
||||||
* Returns site default if defined, otherwise it returns extension default.
|
|
||||||
* If extension default is not defined because extension updated but the
|
|
||||||
* settings didn't port over, we return automatic.
|
|
||||||
*/
|
|
||||||
getDefaultCrop(site?: string) {
|
|
||||||
return this.active.sites[site ?? window.location.hostname]?.defaultCrop ?? this.active.crop?.default ?? {type: AspectRatioType.Automatic};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets default stretching mode for extension.
|
|
||||||
* Returns site default if defined, otherwise it returns extension default.
|
|
||||||
* If extension default is not defined because extension updated but the
|
|
||||||
* settings didn't port over, we return automatic.
|
|
||||||
*/
|
|
||||||
getDefaultStretchMode(site?: string) {
|
|
||||||
return this.active.sites[site ?? window.location.hostname]?.defaultStretch ?? this.active.stretch.default ?? {type: StretchType.NoStretch};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets a site option and initializes values if empty.
|
|
||||||
* Does not save settings.
|
|
||||||
* @param path
|
|
||||||
* @param value
|
|
||||||
* @param site
|
|
||||||
*/
|
|
||||||
setSiteOption(path: string[], value: any, site?: string) {
|
|
||||||
site = site ?? window.location.hostname;
|
|
||||||
|
|
||||||
if (!this.active.sites[site]) {
|
|
||||||
this.active.sites[site] = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
let object = this.active.sites[site];
|
|
||||||
for (let i = 0; i < path.length - 1; i++) {
|
|
||||||
if (!object[path[i]]) {
|
|
||||||
object[path[i]] = {};
|
|
||||||
}
|
|
||||||
object = object[path[i]];
|
|
||||||
}
|
|
||||||
object[path[path.length - 1]] = value;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,7 +252,7 @@ class ArDetector {
|
|||||||
this.resetBlackLevel();
|
this.resetBlackLevel();
|
||||||
|
|
||||||
// if we're restarting ArDetect, we need to do this in order to force-recalculate aspect ratio
|
// if we're restarting ArDetect, we need to do this in order to force-recalculate aspect ratio
|
||||||
this.conf.resizer.setLastAr({type: AspectRatioType.AutomaticUpdate, ratio: this.defaultAr});
|
this.conf.resizer.lastAr = {type: AspectRatioType.AutomaticUpdate, ratio: this.defaultAr};
|
||||||
|
|
||||||
this.canvasImageDataRowLength = cwidth << 2;
|
this.canvasImageDataRowLength = cwidth << 2;
|
||||||
|
|
||||||
@ -277,7 +277,7 @@ class ArDetector {
|
|||||||
start() {
|
start() {
|
||||||
if (this.conf.resizer.lastAr.type === AspectRatioType.AutomaticUpdate) {
|
if (this.conf.resizer.lastAr.type === AspectRatioType.AutomaticUpdate) {
|
||||||
// ensure first autodetection will run in any case
|
// ensure first autodetection will run in any case
|
||||||
this.conf.resizer.setLastAr({type: AspectRatioType.AutomaticUpdate, ratio: this.defaultAr});
|
this.conf.resizer.lastAr = {type: AspectRatioType.AutomaticUpdate, ratio: this.defaultAr};
|
||||||
}
|
}
|
||||||
|
|
||||||
// start autodetection
|
// start autodetection
|
||||||
@ -781,7 +781,7 @@ class ArDetector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check if aspect ratio is changed:
|
// check if aspect ratio is changed:
|
||||||
let lastAr = this.conf.resizer.getLastAr();
|
let lastAr = this.conf.resizer.lastAr;
|
||||||
if (lastAr.type === AspectRatioType.AutomaticUpdate && lastAr.ratio !== null && lastAr.ratio !== undefined){
|
if (lastAr.type === AspectRatioType.AutomaticUpdate && lastAr.ratio !== null && lastAr.ratio !== undefined){
|
||||||
// we can only deny aspect ratio changes if we use automatic mode and if aspect ratio was set from here.
|
// we can only deny aspect ratio changes if we use automatic mode and if aspect ratio was set from here.
|
||||||
|
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
import EventBus, { EventBusCommand } from '../EventBus';
|
import EventBus, { EventBusCommand } from '../EventBus';
|
||||||
import Logger from '../Logger';
|
import Logger from '../Logger';
|
||||||
import Settings from '../Settings';
|
import Settings from '../Settings';
|
||||||
|
import { SiteSettings } from '../settings/SiteSettings';
|
||||||
|
|
||||||
export class KbmBase {
|
export class KbmBase {
|
||||||
listenFor: string[] = [];
|
listenFor: string[] = [];
|
||||||
logger: Logger;
|
logger: Logger;
|
||||||
settings: Settings;
|
settings: Settings;
|
||||||
|
siteSettings: SiteSettings;
|
||||||
eventBus: EventBus;
|
eventBus: EventBus;
|
||||||
|
|
||||||
eventBusCommands: { [x: string]: EventBusCommand } = {
|
eventBusCommands: { [x: string]: EventBusCommand } = {
|
||||||
@ -26,7 +28,7 @@ export class KbmBase {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(eventBus: EventBus, settings: Settings, logger: Logger) {
|
constructor(eventBus: EventBus, siteSettings: SiteSettings, settings: Settings, logger: Logger) {
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.settings = settings;
|
this.settings = settings;
|
||||||
this.eventBus = eventBus;
|
this.eventBus = eventBus;
|
||||||
@ -90,9 +92,10 @@ export class KbmBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
load() {
|
load() {
|
||||||
if (! (this.settings.isEnabledForSite() && this.settings.active.kbm.enabled)) {
|
// if (! (this.settings.isEnabledForSite() && this.settings.active.kbm.enabled)) {
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
// todo: detect if this is enabled or not
|
||||||
this.addListener();
|
this.addListener();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ import Settings from '../Settings';
|
|||||||
import VideoData from '../video-data/VideoData';
|
import VideoData from '../video-data/VideoData';
|
||||||
import EventBus, { EventBusCommand } from '../EventBus';
|
import EventBus, { EventBusCommand } from '../EventBus';
|
||||||
import KbmBase from './KbmBase';
|
import KbmBase from './KbmBase';
|
||||||
|
import { SiteSettings } from '../settings/SiteSettings';
|
||||||
|
|
||||||
if(process.env.CHANNEL !== 'stable'){
|
if(process.env.CHANNEL !== 'stable'){
|
||||||
console.info("Loading KeyboardHandler");
|
console.info("Loading KeyboardHandler");
|
||||||
@ -24,6 +25,7 @@ export class KeyboardHandler extends KbmBase {
|
|||||||
listenFor: string[] = ['keyup'];
|
listenFor: string[] = ['keyup'];
|
||||||
logger: Logger;
|
logger: Logger;
|
||||||
settings: Settings;
|
settings: Settings;
|
||||||
|
siteSettings: SiteSettings;
|
||||||
eventBus: EventBus;
|
eventBus: EventBus;
|
||||||
|
|
||||||
playerElements: HTMLElement[] = [];
|
playerElements: HTMLElement[] = [];
|
||||||
@ -43,8 +45,8 @@ export class KeyboardHandler extends KbmBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//#region lifecycle
|
//#region lifecycle
|
||||||
constructor(eventBus: EventBus, settings: Settings, logger: Logger) {
|
constructor(eventBus: EventBus, siteSettings: SiteSettings, settings: Settings, logger: Logger) {
|
||||||
super(eventBus, settings, logger);
|
super(eventBus, siteSettings, settings, logger);
|
||||||
|
|
||||||
this.init();
|
this.init();
|
||||||
}
|
}
|
||||||
@ -124,7 +126,7 @@ export class KeyboardHandler extends KbmBase {
|
|||||||
"\nis type === 'text'? (yes -> prevent):", activeElement.getAttribute("type") === "text",
|
"\nis type === 'text'? (yes -> prevent):", activeElement.getAttribute("type") === "text",
|
||||||
"\nevent.target.isContentEditable? (yes -> prevent):", event.target.isContentEditable,
|
"\nevent.target.isContentEditable? (yes -> prevent):", event.target.isContentEditable,
|
||||||
"\nis keyboard local disabled? (yes -> prevent):", this.keyboardLocalDisabled,
|
"\nis keyboard local disabled? (yes -> prevent):", this.keyboardLocalDisabled,
|
||||||
"\nis keyboard enabled in settings? (no -> prevent)", this.settings.keyboardShortcutsEnabled(window.location.hostname),
|
// "\nis keyboard enabled in settings? (no -> prevent)", this.settings.keyboardShortcutsEnabled(window.location.hostname),
|
||||||
"\nwill the action be prevented? (yes -> prevent)", preventAction,
|
"\nwill the action be prevented? (yes -> prevent)", preventAction,
|
||||||
"\n-----------------{ extra debug info }-------------------",
|
"\n-----------------{ extra debug info }-------------------",
|
||||||
"\ntag name? (lowercase):", activeElement.tagName, activeElement.tagName.toLocaleLowerCase(),
|
"\ntag name? (lowercase):", activeElement.tagName, activeElement.tagName.toLocaleLowerCase(),
|
||||||
@ -139,9 +141,9 @@ export class KeyboardHandler extends KbmBase {
|
|||||||
if (this.keyboardLocalDisabled) {
|
if (this.keyboardLocalDisabled) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (!this.settings.keyboardShortcutsEnabled(window.location.hostname)) {
|
// if (!this.settings.keyboardShortcutsEnabled(window.location.hostname)) {
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
if (this.inputs.indexOf(activeElement.tagName.toLocaleLowerCase()) !== -1) {
|
if (this.inputs.indexOf(activeElement.tagName.toLocaleLowerCase()) !== -1) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import EventBus, { EventBusCommand } from '../EventBus';
|
import EventBus, { EventBusCommand } from '../EventBus';
|
||||||
import Logger from '../Logger';
|
import Logger from '../Logger';
|
||||||
import Settings from '../Settings';
|
import Settings from '../Settings';
|
||||||
|
import { SiteSettings } from '../settings/SiteSettings';
|
||||||
import KbmBase from './KbmBase';
|
import KbmBase from './KbmBase';
|
||||||
|
|
||||||
if(process.env.CHANNEL !== 'stable'){
|
if(process.env.CHANNEL !== 'stable'){
|
||||||
@ -35,11 +36,12 @@ export class MouseHandler extends KbmBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//#region lifecycle
|
//#region lifecycle
|
||||||
constructor(playerElement: HTMLElement, eventBus: EventBus, settings: Settings, logger: Logger) {
|
constructor(playerElement: HTMLElement, eventBus: EventBus, siteSettings: SiteSettings, settings: Settings, logger: Logger) {
|
||||||
super(eventBus, settings, logger);
|
super(eventBus, siteSettings, settings, logger);
|
||||||
|
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.settings = settings;
|
this.settings = settings;
|
||||||
|
this.siteSettings = siteSettings;
|
||||||
this.eventBus = eventBus;
|
this.eventBus = eventBus;
|
||||||
this.playerElement = playerElement;
|
this.playerElement = playerElement;
|
||||||
|
|
||||||
@ -52,10 +54,7 @@ export class MouseHandler extends KbmBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
load() {
|
load() {
|
||||||
if (!this.settings.isEnabledForSite() || this.settings.active.kbm.enabled) {
|
// todo: process whether mouse movement should be enabled or disabled
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.addListener();
|
this.addListener();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,10 +4,12 @@ import { SiteSettingsInterface } from '../../../common/interfaces/SettingsInterf
|
|||||||
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';
|
||||||
|
import StretchType from '../../../common/enums/StretchType.enum';
|
||||||
|
import VideoAlignmentType from '../../../common/enums/VideoAlignmentType.enum';
|
||||||
|
|
||||||
export class SiteSettings {
|
export class SiteSettings {
|
||||||
private settings: Settings;
|
private settings: Settings;
|
||||||
private site: string;;
|
private site: string;
|
||||||
|
|
||||||
data: SiteSettingsInterface;
|
data: SiteSettingsInterface;
|
||||||
temporaryData: SiteSettingsInterface;
|
temporaryData: SiteSettingsInterface;
|
||||||
@ -45,8 +47,24 @@ export class SiteSettings {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.data.defaultCrop = this.data.defaultCrop ?? _cp(this.defaultSettings.defaultCrop);
|
|
||||||
this.data.defaultStretch = this.data.defaultStretch ?? _cp(this.defaultSettings.defaultStretch);
|
// 'undefined' default here means use default
|
||||||
|
this.data.defaults.crop = this.data.defaults.crop ?? _cp(this.defaultSettings.defaults.crop);
|
||||||
|
|
||||||
|
// these can contain default options, but can also be undefined
|
||||||
|
if (this.data.defaults?.stretch === StretchType.Default || this.data.defaults?.stretch === undefined) {
|
||||||
|
this.data.defaults.stretch = _cp(this.defaultSettings.defaults.stretch);
|
||||||
|
}
|
||||||
|
if (this.data.defaults?.alignment === undefined) { // distinguish between undefined and 0!
|
||||||
|
this.data.defaults.alignment = _cp(this.defaultSettings.defaults.alignment);
|
||||||
|
} else {
|
||||||
|
if (this.data.defaults?.alignment.x === VideoAlignmentType.Default) {
|
||||||
|
this.data.defaults.alignment.x = _cp(this.defaultSettings.defaults.alignment.x);
|
||||||
|
}
|
||||||
|
if (this.data.defaults.alignment.y === VideoAlignmentType.Default) {
|
||||||
|
this.data.defaults.alignment.y = _cp(this.defaultSettings.defaults.alignment.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
for (const enableSegment of ['enable', 'enableAard', 'enableKeyboard']) {
|
for (const enableSegment of ['enable', 'enableAard', 'enableKeyboard']) {
|
||||||
@ -97,8 +115,9 @@ export class SiteSettings {
|
|||||||
}
|
}
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
|
//#region get shit
|
||||||
/**
|
/**
|
||||||
* Gets custom query selector for player or video, if element exists, is manually defined, and has querySelectors property.
|
* Gets custom query selector for player or video, if configuration for it exists, is manually defined, and has querySelectors property.
|
||||||
* @param element player or video
|
* @param element player or video
|
||||||
* @returns querySelector if possible, undefined otherwise
|
* @returns querySelector if possible, undefined otherwise
|
||||||
*/
|
*/
|
||||||
@ -106,6 +125,80 @@ export class SiteSettings {
|
|||||||
return this.data.currentDOMConfig?.elements?.[element]?.manual && this.data.currentDOMConfig?.elements?.[element]?.querySelectors || undefined;
|
return this.data.currentDOMConfig?.elements?.[element]?.manual && this.data.currentDOMConfig?.elements?.[element]?.querySelectors || undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets custom element index for player, if configuration for player exists, is manually defined, and has index property defined.
|
||||||
|
* NOTE: while querySelector should take priority over index, this function does NOT take that into account.
|
||||||
|
* @returns parent element index if possible, undefined otherwise
|
||||||
|
*/
|
||||||
|
getPlayerIndex(): number | undefined {
|
||||||
|
return this.data.currentDOMConfig?.elements?.player?.manual && this.data.currentDOMConfig?.elements?.player?.index || undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets default crop mode for extension, while taking persistence settings into account
|
||||||
|
*/
|
||||||
|
getDefaultOption(option: 'crop' | 'stretch' | 'alignment') {
|
||||||
|
const persistenceLevel = this.data.persistOption[option];
|
||||||
|
|
||||||
|
switch (persistenceLevel) {
|
||||||
|
case CropModePersistence.UntilPageReload:
|
||||||
|
return this.temporaryData.defaults[option];
|
||||||
|
case CropModePersistence.CurrentSession:
|
||||||
|
return this.sessionData.defaults[option];
|
||||||
|
case CropModePersistence.Disabled:
|
||||||
|
case CropModePersistence.Default:
|
||||||
|
case CropModePersistence.Forever:
|
||||||
|
default:
|
||||||
|
return this.data.defaults[option];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _getEnvironment(isTheater: boolean, isFullscreen: boolean): 'fullscreen' | 'theater' | 'normal' {
|
||||||
|
if (isFullscreen) {
|
||||||
|
return 'fullscreen';
|
||||||
|
}
|
||||||
|
if (isTheater) {
|
||||||
|
return 'theater';
|
||||||
|
}
|
||||||
|
return 'normal';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is extension allowed to run in current environment
|
||||||
|
* @param isTheater
|
||||||
|
* @param isFullscreen
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
isEnabledForEnvironment(isTheater: boolean, isFullscreen: boolean) {
|
||||||
|
const env = this._getEnvironment(isTheater, isFullscreen);
|
||||||
|
return this.data.enable[env];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is autodetection allowed to run, given current environment
|
||||||
|
* @param isTheater
|
||||||
|
* @param isFullscreen
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
isAardEnabledForEnvironment(isTheater: boolean, isFullscreen: boolean) {
|
||||||
|
const env = this._getEnvironment(isTheater, isFullscreen);
|
||||||
|
return this.data.enableAard[env];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether keyboard interactions are enabled in current environment
|
||||||
|
* @param isTheater
|
||||||
|
* @param isFullscreen
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
isKeyboardEnabledForEnvironment(isTheater: boolean, isFullscreen: boolean) {
|
||||||
|
const env = this._getEnvironment(isTheater, isFullscreen);
|
||||||
|
return this.data.enableKeyboard[env];
|
||||||
|
}
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
//#region set shit
|
||||||
/**
|
/**
|
||||||
* Sets option value.
|
* Sets option value.
|
||||||
* @param optionPath path to value in object notation (dot separated)
|
* @param optionPath path to value in object notation (dot separated)
|
||||||
@ -123,6 +216,9 @@ export class SiteSettings {
|
|||||||
let iterator = this.settings.active.sites[this.site];
|
let iterator = this.settings.active.sites[this.site];
|
||||||
let i;
|
let i;
|
||||||
for (i = 0; i < pathParts.length - 1; i++) {
|
for (i = 0; i < pathParts.length - 1; i++) {
|
||||||
|
if (!iterator[pathParts[i]]) { // some optional paths may still be undefined, even after cloning empty object
|
||||||
|
iterator[pathParts[i]] = {};
|
||||||
|
}
|
||||||
iterator = iterator[pathParts[i]];
|
iterator = iterator[pathParts[i]];
|
||||||
}
|
}
|
||||||
iterator[pathParts[i]] = optionValue;
|
iterator[pathParts[i]] = optionValue;
|
||||||
@ -168,25 +264,6 @@ export class SiteSettings {
|
|||||||
sessionStorage.setItem('uw-session-defaults', JSON.stringify(this.sessionData));
|
sessionStorage.setItem('uw-session-defaults', JSON.stringify(this.sessionData));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets default crop mode for extension, while taking persistence settings into account
|
|
||||||
*/
|
|
||||||
getDefaultOption(option: 'crop' | 'stretch' | 'alignment') {
|
|
||||||
const persistenceLevel = this.data.persistOption[option];
|
|
||||||
|
|
||||||
switch (persistenceLevel) {
|
|
||||||
case CropModePersistence.UntilPageReload:
|
|
||||||
return this.temporaryData.defaults[option];
|
|
||||||
case CropModePersistence.CurrentSession:
|
|
||||||
return this.sessionData.defaults[option];
|
|
||||||
case CropModePersistence.Disabled:
|
|
||||||
case CropModePersistence.Default:
|
|
||||||
case CropModePersistence.Forever:
|
|
||||||
default:
|
|
||||||
return this.data.defaults[option];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates options while accounting for persistence settings
|
* Updates options while accounting for persistence settings
|
||||||
* @param option
|
* @param option
|
||||||
@ -209,5 +286,6 @@ export class SiteSettings {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//#endregion
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,6 @@ class PageInfo {
|
|||||||
|
|
||||||
//#region misc stuff
|
//#region misc stuff
|
||||||
lastUrl: string;
|
lastUrl: string;
|
||||||
extensionMode: ExtensionMode;
|
|
||||||
defaultCrop: any;
|
defaultCrop: any;
|
||||||
currentCrop: any;
|
currentCrop: any;
|
||||||
keyboardHandlerInitQueue: any[] = [];
|
keyboardHandlerInitQueue: any[] = [];
|
||||||
@ -70,14 +69,12 @@ class PageInfo {
|
|||||||
keyboardHandler: any;
|
keyboardHandler: any;
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
constructor(eventBus: EventBus, settings: Settings, logger: Logger, extensionMode, readOnly = false){
|
constructor(eventBus: EventBus, siteSettings: SiteSettings, settings: Settings, logger: Logger, readOnly = false){
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.settings = settings;
|
this.settings = settings;
|
||||||
|
this.siteSettings = siteSettings;
|
||||||
this.siteSettings = new SiteSettings(settings, window.location.hostname);
|
|
||||||
|
|
||||||
this.lastUrl = window.location.href;
|
this.lastUrl = window.location.href;
|
||||||
this.extensionMode = extensionMode;
|
|
||||||
this.readOnly = readOnly;
|
this.readOnly = readOnly;
|
||||||
|
|
||||||
this.isFullscreen = !!document.fullscreenElement;
|
this.isFullscreen = !!document.fullscreenElement;
|
||||||
|
@ -10,6 +10,7 @@ import Settings from '../Settings';
|
|||||||
import Logger from '../Logger';
|
import Logger from '../Logger';
|
||||||
import EventBus from '../EventBus';
|
import EventBus from '../EventBus';
|
||||||
import UI from '../uwui/UI';
|
import UI from '../uwui/UI';
|
||||||
|
import { SiteSettings } from '../settings/SiteSettings';
|
||||||
|
|
||||||
if (process.env.CHANNEL !== 'stable'){
|
if (process.env.CHANNEL !== 'stable'){
|
||||||
console.info("Loading: PlayerData.js");
|
console.info("Loading: PlayerData.js");
|
||||||
@ -41,7 +42,7 @@ class PlayerData {
|
|||||||
//#region helper objects
|
//#region helper objects
|
||||||
logger: Logger;
|
logger: Logger;
|
||||||
videoData: VideoData;
|
videoData: VideoData;
|
||||||
settings: Settings;
|
siteSettings: SiteSettings;
|
||||||
notificationService: PlayerNotificationUi;
|
notificationService: PlayerNotificationUi;
|
||||||
eventBus: EventBus;
|
eventBus: EventBus;
|
||||||
//#endregion
|
//#endregion
|
||||||
@ -90,7 +91,7 @@ class PlayerData {
|
|||||||
*/
|
*/
|
||||||
get aspectRatio() {
|
get aspectRatio() {
|
||||||
try {
|
try {
|
||||||
if (this.isFullscreen && !this.settings.getSettingsForSite()?.usePlayerArInFullscreen) {
|
if (this.isFullscreen) {
|
||||||
return window.innerWidth / window.innerHeight;
|
return window.innerWidth / window.innerHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,7 +107,7 @@ class PlayerData {
|
|||||||
this.logger = videoData.logger;
|
this.logger = videoData.logger;
|
||||||
this.videoData = videoData;
|
this.videoData = videoData;
|
||||||
this.video = videoData.video;
|
this.video = videoData.video;
|
||||||
this.settings = videoData.settings;
|
this.siteSettings = videoData.siteSettings;
|
||||||
this.eventBus = videoData.eventBus;
|
this.eventBus = videoData.eventBus;
|
||||||
this.extensionMode = videoData.extensionMode;
|
this.extensionMode = videoData.extensionMode;
|
||||||
this.invalid = false;
|
this.invalid = false;
|
||||||
@ -122,7 +123,7 @@ class PlayerData {
|
|||||||
|
|
||||||
this.periodicallyRefreshPlayerElement = false;
|
this.periodicallyRefreshPlayerElement = false;
|
||||||
try {
|
try {
|
||||||
this.periodicallyRefreshPlayerElement = this.settings.active.sites[window.location.hostname].DOM.player.periodicallyRefreshPlayerElement;
|
this.periodicallyRefreshPlayerElement = this.siteSettings.data.currentDOMConfig.periodicallyRefreshPlayerElement;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// no biggie — that means we don't have any special settings for this site.
|
// no biggie — that means we don't have any special settings for this site.
|
||||||
}
|
}
|
||||||
@ -225,30 +226,28 @@ class PlayerData {
|
|||||||
private handleSizeConstraints(currentPlayerDimensions: PlayerDimensions) {
|
private handleSizeConstraints(currentPlayerDimensions: PlayerDimensions) {
|
||||||
|
|
||||||
// never disable ultrawidify in full screen
|
// never disable ultrawidify in full screen
|
||||||
if (this.isFullscreen) {
|
// if (this.isFullscreen) {
|
||||||
this.enable();
|
// this.enable();
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
|
||||||
const restrictions = this.settings.getSettingsForSite()?.restrictions ?? this.settings.active?.restrictions;
|
|
||||||
|
|
||||||
// if 'disable on small players' option is not enabled, the extension will run in any case
|
// if 'disable on small players' option is not enabled, the extension will run in any case
|
||||||
if (!restrictions?.disableOnSmallPlayers) {
|
// if (!restrictions?.disableOnSmallPlayers) {
|
||||||
this.enable();
|
// this.enable();
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
|
||||||
// If we only allow ultrawidify in full screen, we disable it when not in full screen
|
// If we only allow ultrawidify in full screen, we disable it when not in full screen
|
||||||
if (restrictions.onlyAllowInFullscreen && !currentPlayerDimensions.fullscreen) {
|
// if (restrictions.onlyAllowInFullscreen && !currentPlayerDimensions.fullscreen) {
|
||||||
this.disable();
|
// this.disable();
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
|
||||||
// if current width or height are smaller than the minimum, the extension will not run
|
// if current width or height are smaller than the minimum, the extension will not run
|
||||||
if (restrictions.minAllowedHeight > currentPlayerDimensions?.height || restrictions.minAllowedWidth > currentPlayerDimensions?.width) {
|
// if (restrictions.minAllowedHeight > currentPlayerDimensions?.height || restrictions.minAllowedWidth > currentPlayerDimensions?.width) {
|
||||||
this.disable();
|
// this.disable();
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
|
||||||
// in this case, the player is big enough to warrant enabling Ultrawidify
|
// in this case, the player is big enough to warrant enabling Ultrawidify
|
||||||
this.enable();
|
this.enable();
|
||||||
@ -483,26 +482,20 @@ class PlayerData {
|
|||||||
}
|
}
|
||||||
this.elementStack = elementStack;
|
this.elementStack = elementStack;
|
||||||
|
|
||||||
if (this.settings.active.sites[host]?.DOM?.player?.manual) {
|
const playerQs = this.siteSettings.getCustomDOMQuerySelector('player');
|
||||||
if (this.settings.active.sites[host]?.DOM?.player?.useRelativeAncestor
|
const playerIndex = this.siteSettings.getPlayerIndex();
|
||||||
&& this.settings.active.sites[host]?.DOM?.player?.videoAncestor) {
|
|
||||||
playerCandidate = this.getPlayerParentIndex(elementStack);
|
if (playerQs) {
|
||||||
} else if (this.settings.active.sites[host]?.DOM?.player?.querySelectors) {
|
playerCandidate = this.getPlayerQs(playerQs, elementStack, videoWidth, videoHeight);
|
||||||
playerCandidate = this.getPlayerQs(elementStack, videoWidth, videoHeight);
|
} else if (playerIndex) { // btw 0 is not a valid index for player
|
||||||
|
playerCandidate = elementStack[playerIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
// if 'verbose' option is passed, we also populate the elementStack
|
if (playerCandidate) {
|
||||||
// with heuristics data for auto player detection.
|
if (options?.verbose) {
|
||||||
if (playerCandidate && !options?.verbose) {
|
|
||||||
return playerCandidate.element;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options?.verbose && playerCandidate) {
|
|
||||||
// remember — we're only populating elementStack. If we found a player
|
|
||||||
// element using manual methods, we will still return that element.
|
|
||||||
this.getPlayerAuto(elementStack, videoWidth, videoHeight);
|
this.getPlayerAuto(elementStack, videoWidth, videoHeight);
|
||||||
playerCandidate.heuristics['activePlayer'] = true;
|
playerCandidate.heuristics['activePlayer'] = true;
|
||||||
|
}
|
||||||
return playerCandidate.element;
|
return playerCandidate.element;
|
||||||
} else {
|
} else {
|
||||||
const playerCandidate = this.getPlayerAuto(elementStack, videoWidth, videoHeight);
|
const playerCandidate = this.getPlayerAuto(elementStack, videoWidth, videoHeight);
|
||||||
@ -511,6 +504,13 @@ class PlayerData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets player based on some assumptions, without us defining shit.
|
||||||
|
* @param elementStack
|
||||||
|
* @param videoWidth
|
||||||
|
* @param videoHeight
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
private getPlayerAuto(elementStack: any[], videoWidth, videoHeight) {
|
private getPlayerAuto(elementStack: any[], videoWidth, videoHeight) {
|
||||||
let penaltyMultiplier = 1;
|
let penaltyMultiplier = 1;
|
||||||
const sizePenaltyMultiplier = 0.1;
|
const sizePenaltyMultiplier = 0.1;
|
||||||
@ -592,12 +592,29 @@ class PlayerData {
|
|||||||
return bestCandidate;
|
return bestCandidate;
|
||||||
}
|
}
|
||||||
|
|
||||||
private getPlayerQs(elementStack: any[], videoWidth, videoHeight) {
|
/**
|
||||||
const host = window.location.hostname;
|
* Gets player element based on a query string.
|
||||||
|
*
|
||||||
|
* Since query string does not necessarily uniquely identify an element, this function also
|
||||||
|
* tries to evaluate which candidate of element that match the query selector is the most
|
||||||
|
* likely the one element we're looking for.
|
||||||
|
*
|
||||||
|
* Function prefers elements that are:
|
||||||
|
* 1. closer to the video
|
||||||
|
* 2. about the same size as the video
|
||||||
|
* 3. they must appear between video and root of the DOM hierarchy
|
||||||
|
*
|
||||||
|
* @param queryString query string for player element
|
||||||
|
* @param elementStack branch of DOM hierarchy that ends with a video
|
||||||
|
* @param videoWidth width of the video
|
||||||
|
* @param videoHeight height of the video
|
||||||
|
* @returns best candidate or null, if nothing in elementStack matches our query selector
|
||||||
|
*/
|
||||||
|
private getPlayerQs(queryString: string, elementStack: any[], videoWidth, videoHeight) {
|
||||||
const perLevelScorePenalty = 10;
|
const perLevelScorePenalty = 10;
|
||||||
let penaltyMultiplier = 0;
|
let penaltyMultiplier = 0;
|
||||||
|
|
||||||
const allSelectors = document.querySelectorAll(this.settings.active.sites[host].DOM.player.querySelectors);
|
const allSelectors = document.querySelectorAll(queryString);
|
||||||
|
|
||||||
for (const element of elementStack) {
|
for (const element of elementStack) {
|
||||||
if (this.collectionHas(allSelectors, element.element)) {
|
if (this.collectionHas(allSelectors, element.element)) {
|
||||||
@ -634,17 +651,12 @@ class PlayerData {
|
|||||||
return bestCandidate;
|
return bestCandidate;
|
||||||
}
|
}
|
||||||
|
|
||||||
private getPlayerParentIndex(elementStack: any[]) {
|
/**
|
||||||
const host = window.location.hostname;
|
* Lists elements between video and DOM root for display in player selector (UI)
|
||||||
elementStack[this.settings.active.sites[host].DOM.player.videoAncestor].heuristics['manualElementByParentIndex'] = true;
|
*/
|
||||||
return elementStack[this.settings.active.sites[host].DOM.player.videoAncestor];
|
|
||||||
}
|
|
||||||
|
|
||||||
private handlePlayerTreeRequest() {
|
private handlePlayerTreeRequest() {
|
||||||
// this populates this.elementStack fully
|
// this populates this.elementStack fully
|
||||||
this.getPlayer({verbose: true});
|
this.getPlayer({verbose: true});
|
||||||
|
|
||||||
console.info('player-tree: emitting stack:', 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))});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ import { sleep } from '../../../common/js/utils';
|
|||||||
import { hasDrm } from '../ar-detect/DrmDetecor';
|
import { hasDrm } from '../ar-detect/DrmDetecor';
|
||||||
import EventBus from '../EventBus';
|
import EventBus from '../EventBus';
|
||||||
import { SiteSettings } from '../settings/SiteSettings';
|
import { SiteSettings } from '../settings/SiteSettings';
|
||||||
|
import { Ar } from '../../../common/interfaces/ArInterface';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* VideoData — handles CSS for the video element.
|
* VideoData — handles CSS for the video element.
|
||||||
@ -226,7 +227,7 @@ class VideoData {
|
|||||||
// after we receive a "please crop" or "please stretch".
|
// after we receive a "please crop" or "please stretch".
|
||||||
|
|
||||||
// Time to apply any crop from address of crop mode persistence
|
// Time to apply any crop from address of crop mode persistence
|
||||||
const defaultCrop = this.siteSettings.getDefaultOption('crop');
|
const defaultCrop = this.siteSettings.getDefaultOption('crop') as Ar;
|
||||||
const defaultStretch = this.siteSettings.getDefaultOption('stretch');
|
const defaultStretch = this.siteSettings.getDefaultOption('stretch');
|
||||||
|
|
||||||
this.resizer.setAr(defaultCrop);
|
this.resizer.setAr(defaultCrop);
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { SiteSettings } from './../settings/SiteSettings';
|
||||||
import Debug from '../../conf/Debug';
|
import Debug from '../../conf/Debug';
|
||||||
import Scaler, { CropStrategy, VideoDimensions } from './Scaler';
|
import Scaler, { CropStrategy, VideoDimensions } from './Scaler';
|
||||||
import Stretcher from './Stretcher';
|
import Stretcher from './Stretcher';
|
||||||
@ -10,9 +11,12 @@ import AspectRatioType from '../../../common/enums/AspectRatioType.enum';
|
|||||||
import CropModePersistance from '../../../common/enums/CropModePersistence.enum';
|
import CropModePersistance from '../../../common/enums/CropModePersistence.enum';
|
||||||
import { sleep } from '../Util';
|
import { sleep } from '../Util';
|
||||||
import Logger from '../Logger';
|
import Logger from '../Logger';
|
||||||
import Settings from '../Settings';
|
import siteSettings from '../Settings';
|
||||||
import VideoData from '../video-data/VideoData';
|
import VideoData from '../video-data/VideoData';
|
||||||
import EventBus from '../EventBus';
|
import EventBus from '../EventBus';
|
||||||
|
import { _cp } from '../../../common/js/utils';
|
||||||
|
import Settings from '../Settings';
|
||||||
|
import { Ar } from '../../../common/interfaces/ArInterface';
|
||||||
|
|
||||||
if(Debug.debug) {
|
if(Debug.debug) {
|
||||||
console.log("Loading: Resizer.js");
|
console.log("Loading: Resizer.js");
|
||||||
@ -28,6 +32,7 @@ class Resizer {
|
|||||||
//#region helper objects
|
//#region helper objects
|
||||||
logger: Logger;
|
logger: Logger;
|
||||||
settings: Settings;
|
settings: Settings;
|
||||||
|
siteSettings: SiteSettings;
|
||||||
scaler: Scaler;
|
scaler: Scaler;
|
||||||
stretcher: Stretcher;
|
stretcher: Stretcher;
|
||||||
zoom: Zoom;
|
zoom: Zoom;
|
||||||
@ -47,8 +52,8 @@ class Resizer {
|
|||||||
currentCssValidFor: any;
|
currentCssValidFor: any;
|
||||||
currentVideoSettings: any;
|
currentVideoSettings: any;
|
||||||
|
|
||||||
_lastAr: {type: any, ratio?: number} = {type: AspectRatioType.Initial};
|
_lastAr: Ar = {type: AspectRatioType.Initial};
|
||||||
set lastAr(x: {type: any, ratio?: number}) {
|
set lastAr(x: Ar) {
|
||||||
this._lastAr = x;
|
this._lastAr = x;
|
||||||
// emit updates for UI when setting lastAr
|
// emit updates for UI when setting lastAr
|
||||||
this.eventBus.send('uw-config-broadcast', {type: 'ar', config: x})
|
this.eventBus.send('uw-config-broadcast', {type: 'ar', config: x})
|
||||||
@ -101,6 +106,7 @@ class Resizer {
|
|||||||
this.logger = videoData.logger;
|
this.logger = videoData.logger;
|
||||||
this.video = videoData.video;
|
this.video = videoData.video;
|
||||||
this.settings = videoData.settings;
|
this.settings = videoData.settings;
|
||||||
|
this.siteSettings = videoData.siteSettings;
|
||||||
this.eventBus = videoData.eventBus;
|
this.eventBus = videoData.eventBus;
|
||||||
this.initEventBus();
|
this.initEventBus();
|
||||||
|
|
||||||
@ -108,18 +114,15 @@ class Resizer {
|
|||||||
this.stretcher = new Stretcher(this.conf);
|
this.stretcher = new Stretcher(this.conf);
|
||||||
this.zoom = new Zoom(this.conf);
|
this.zoom = new Zoom(this.conf);
|
||||||
|
|
||||||
this.videoAlignment = {
|
this.videoAlignment = this.siteSettings.getDefaultOption('alignment') as {x: VideoAlignmentType, y: VideoAlignmentType} // this is initial video alignment
|
||||||
x: this.settings.getDefaultVideoAlignment(window.location.hostname),
|
|
||||||
y: VideoAlignmentType.Center
|
|
||||||
}; // this is initial video alignment
|
|
||||||
|
|
||||||
this.destroyed = false;
|
this.destroyed = false;
|
||||||
|
|
||||||
if (this.settings.active.pan) {
|
// if (this.siteSettings.active.pan) {
|
||||||
this.canPan = this.settings.active.miscSettings.mousePan.enabled;
|
// this.canPan = this.siteSettings.active.miscSettings.mousePan.enabled;
|
||||||
} else {
|
// } else {
|
||||||
this.canPan = false;
|
// this.canPan = false;
|
||||||
}
|
// }
|
||||||
|
|
||||||
this.userCssClassName = videoData.userCssClassName;
|
this.userCssClassName = videoData.userCssClassName;
|
||||||
}
|
}
|
||||||
@ -215,7 +218,7 @@ class Resizer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async setAr(ar: {type: any, ratio?: number}, lastAr?: {type: any, ratio?: number}) {
|
async setAr(ar: Ar, lastAr?: Ar) {
|
||||||
if (this.destroyed) {
|
if (this.destroyed) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -253,7 +256,6 @@ class Resizer {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const siteSettings = this.settings.active.sites[window.location.hostname];
|
|
||||||
let stretchFactors: {xFactor: number, yFactor: number, arCorrectionFactor?: number, ratio?: number} | any;
|
let stretchFactors: {xFactor: number, yFactor: number, arCorrectionFactor?: number, ratio?: number} | any;
|
||||||
|
|
||||||
// reset zoom, but only on aspect ratio switch. We also know that aspect ratio gets converted to
|
// reset zoom, but only on aspect ratio switch. We also know that aspect ratio gets converted to
|
||||||
@ -271,8 +273,7 @@ class Resizer {
|
|||||||
// this means here's the optimal place to set or forget aspect ratio. Saving of current crop ratio
|
// this means here's the optimal place to set or forget aspect ratio. Saving of current crop ratio
|
||||||
// is handled in pageInfo.updateCurrentCrop(), which also makes sure to persist aspect ratio if ar
|
// is handled in pageInfo.updateCurrentCrop(), which also makes sure to persist aspect ratio if ar
|
||||||
// is set to persist between videos / through current session / until manual reset.
|
// is set to persist between videos / through current session / until manual reset.
|
||||||
if (ar.type === AspectRatioType.Automatic ||
|
if (ar.type === AspectRatioType.Reset ||
|
||||||
ar.type === AspectRatioType.Reset ||
|
|
||||||
ar.type === AspectRatioType.Initial ) {
|
ar.type === AspectRatioType.Initial ) {
|
||||||
// reset/undo default
|
// reset/undo default
|
||||||
this.conf.pageInfo.updateCurrentCrop(undefined);
|
this.conf.pageInfo.updateCurrentCrop(undefined);
|
||||||
@ -391,13 +392,6 @@ class Resizer {
|
|||||||
this.lastAr = {type: AspectRatioType.Initial};
|
this.lastAr = {type: AspectRatioType.Initial};
|
||||||
}
|
}
|
||||||
|
|
||||||
setLastAr(override){
|
|
||||||
this.lastAr = override;
|
|
||||||
}
|
|
||||||
|
|
||||||
getLastAr(){
|
|
||||||
return this.lastAr;
|
|
||||||
}
|
|
||||||
|
|
||||||
setStretchMode(stretchMode, fixedStretchRatio?){
|
setStretchMode(stretchMode, fixedStretchRatio?){
|
||||||
this.stretcher.setStretchMode(stretchMode, fixedStretchRatio);
|
this.stretcher.setStretchMode(stretchMode, fixedStretchRatio);
|
||||||
@ -481,7 +475,7 @@ class Resizer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
reset(){
|
reset(){
|
||||||
this.setStretchMode(this.settings.active.sites[window.location.hostname]?.stretch ?? this.settings.active.sites['@global'].stretch);
|
this.setStretchMode(this.siteSettings.getDefaultOption('stretch'));
|
||||||
this.zoom.setZoom(1);
|
this.zoom.setZoom(1);
|
||||||
this.resetPan();
|
this.resetPan();
|
||||||
this.setAr({type: AspectRatioType.Reset});
|
this.setAr({type: AspectRatioType.Reset});
|
||||||
@ -647,7 +641,7 @@ class Resizer {
|
|||||||
|
|
||||||
private _computeOffsetsRecursionGuard: boolean = false;
|
private _computeOffsetsRecursionGuard: boolean = false;
|
||||||
computeOffsets(stretchFactors: VideoDimensions){
|
computeOffsets(stretchFactors: VideoDimensions){
|
||||||
this.logger.log('info', 'debug', "[Resizer::computeOffsets] <rid:"+this.resizerId+"> video will be aligned to ", this.settings.active.sites['@global'].videoAlignment);
|
this.logger.log('info', 'debug', "[Resizer::computeOffsets] <rid:"+this.resizerId+"> video will be aligned to ", this.videoAlignment);
|
||||||
|
|
||||||
const {realVideoWidth, realVideoHeight, marginX, marginY} = this.computeVideoDisplayedDimensions();
|
const {realVideoWidth, realVideoHeight, marginX, marginY} = this.computeVideoDisplayedDimensions();
|
||||||
|
|
||||||
@ -831,7 +825,7 @@ class Resizer {
|
|||||||
|
|
||||||
let extraStyleString;
|
let extraStyleString;
|
||||||
try {
|
try {
|
||||||
extraStyleString = this.settings.active.sites[window.location.hostname].DOM.video.additionalCss;
|
extraStyleString = this.siteSettings.data.currentDOMConfig.customCss;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// do nothing. It's ok if no special settings are defined for this site, we'll just do defaults
|
// do nothing. It's ok if no special settings are defined for this site, we'll just do defaults
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { SiteSettings } from './../settings/SiteSettings';
|
||||||
import StretchType from '../../../common/enums/StretchType.enum';
|
import StretchType from '../../../common/enums/StretchType.enum';
|
||||||
import BrowserDetect from '../../conf/BrowserDetect';
|
import BrowserDetect from '../../conf/BrowserDetect';
|
||||||
import AspectRatioType from '../../../common/enums/AspectRatioType.enum';
|
import AspectRatioType from '../../../common/enums/AspectRatioType.enum';
|
||||||
@ -19,6 +20,7 @@ class Stretcher {
|
|||||||
conf: VideoData;
|
conf: VideoData;
|
||||||
logger: Logger;
|
logger: Logger;
|
||||||
settings: Settings;
|
settings: Settings;
|
||||||
|
siteSettings: SiteSettings;
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
//#region misc data
|
//#region misc data
|
||||||
@ -30,14 +32,15 @@ class Stretcher {
|
|||||||
constructor(videoData) {
|
constructor(videoData) {
|
||||||
this.conf = videoData;
|
this.conf = videoData;
|
||||||
this.logger = videoData.logger;
|
this.logger = videoData.logger;
|
||||||
|
this.siteSettings = videoData.siteSettings;
|
||||||
this.settings = videoData.settings;
|
this.settings = videoData.settings;
|
||||||
this.mode = this.settings.getDefaultStretchMode_legacy(window.location.hostname);
|
this.mode = this.siteSettings.data.defaults.stretch;
|
||||||
this.fixedStretchRatio = undefined;
|
this.fixedStretchRatio = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
setStretchMode(stretchMode, fixedStretchRatio?) {
|
setStretchMode(stretchMode, fixedStretchRatio?) {
|
||||||
if (stretchMode === StretchType.Default) {
|
if (stretchMode === StretchType.Default) {
|
||||||
this.mode = this.settings.getDefaultStretchMode_legacy(window.location.hostname);
|
this.mode = this.siteSettings.data.defaults.stretch;
|
||||||
} else {
|
} else {
|
||||||
if (stretchMode === StretchType.Fixed || stretchMode == StretchType.FixedSource) {
|
if (stretchMode === StretchType.Fixed || stretchMode == StretchType.FixedSource) {
|
||||||
this.fixedStretchRatio = fixedStretchRatio;
|
this.fixedStretchRatio = fixedStretchRatio;
|
||||||
|
@ -72,7 +72,6 @@ export default {
|
|||||||
performance: {},
|
performance: {},
|
||||||
site: null,
|
site: null,
|
||||||
currentZoom: 1,
|
currentZoom: 1,
|
||||||
execAction: new ExecAction(),
|
|
||||||
settings: {},
|
settings: {},
|
||||||
settingsInitialized: false,
|
settingsInitialized: false,
|
||||||
logger: {},
|
logger: {},
|
||||||
|
@ -73,7 +73,6 @@ export default {
|
|||||||
performance: {},
|
performance: {},
|
||||||
site: null,
|
site: null,
|
||||||
currentZoom: 1,
|
currentZoom: 1,
|
||||||
execAction: new ExecAction(),
|
|
||||||
settings: {},
|
settings: {},
|
||||||
settingsInitialized: false,
|
settingsInitialized: false,
|
||||||
logger: {},
|
logger: {},
|
||||||
|
@ -1,152 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div class="label">
|
this component is deprecated.
|
||||||
Enable this extension:
|
|
||||||
</div>
|
|
||||||
<div class="flex flex-row button-box">
|
|
||||||
<Button label="Always"
|
|
||||||
:selected="settings.active.sites['@global'].mode === ExtensionMode.Enabled"
|
|
||||||
@click.native="setDefaultExtensionMode(ExtensionMode.Enabled)"
|
|
||||||
>
|
|
||||||
</Button>
|
|
||||||
<Button label="On whitelisted sites"
|
|
||||||
:selected="settings.active.sites['@global'].mode === ExtensionMode.Whitelist"
|
|
||||||
@click.native="setDefaultExtensionMode(ExtensionMode.Whitelist)"
|
|
||||||
>
|
|
||||||
</Button>
|
|
||||||
<Button label="Never"
|
|
||||||
:selected="settings.active.sites['@global'].mode === ExtensionMode.Disabled"
|
|
||||||
@click.native="setDefaultExtensionMode(ExtensionMode.Disabled)"
|
|
||||||
>
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
<div class="description">
|
|
||||||
<b>Always</b> enables this extension on every site you visit that you didn't blacklist.<br/>
|
|
||||||
<b>On whitelisted sites</b> enables this extension only on sites you explicitly whitelisted.<br/>
|
|
||||||
<b>Never</b> disables extension on all sites, even on those you whitelisted.
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="label">
|
|
||||||
Enable autodetection:
|
|
||||||
</div>
|
|
||||||
<div class="flex flex-row button-box">
|
|
||||||
<Button label="Always"
|
|
||||||
:selected="settings.active.sites['@global'].autoar === ExtensionMode.Enabled"
|
|
||||||
@click.native="setDefaultAutodetectionMode(ExtensionMode.Enabled)">
|
|
||||||
</Button>
|
|
||||||
<Button label="On whitelisted sites"
|
|
||||||
:selected="settings.active.sites['@global'].autoar === ExtensionMode.Whitelist"
|
|
||||||
@click.native="setDefaultAutodetectionMode(ExtensionMode.Whitelist)">
|
|
||||||
</Button>
|
|
||||||
<Button label="Never"
|
|
||||||
:selected="settings.active.sites['@global'].autoar === ExtensionMode.Disabled"
|
|
||||||
@click.native="setDefaultAutodetectionMode(ExtensionMode.Disabled)">
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
<div class="description">
|
|
||||||
<b>Always</b> enables autodetection on every site this extension is enabled for, unless blacklisted.<br/>
|
|
||||||
<b>On whitelisted sites</b> enables autodetection only for sites that you explicitly enabled.<br/>
|
|
||||||
<b>Never</b> disables autodetection on all sites, even on those you whitelisted.<br/>
|
|
||||||
<!-- <br/> -->
|
|
||||||
<!-- For more settings related to autodetection, please check the 'Autodetection' tab. -->
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="label">
|
|
||||||
Default video alignment:
|
|
||||||
</div>
|
|
||||||
<div class="flex flex-row button-box">
|
|
||||||
<Button label="Left"
|
|
||||||
:selected="settings.active.sites['@global'].videoAlignment === VideoAlignmentType.Left"
|
|
||||||
@click.native="setDefaultvideoAlignment(VideoAlignmentType.Left)">
|
|
||||||
</Button>
|
|
||||||
<Button label="Center"
|
|
||||||
:selected="settings.active.sites['@global'].videoAlignment === VideoAlignmentType.Center"
|
|
||||||
@click.native="setDefaultvideoAlignment(VideoAlignmentType.Center)">
|
|
||||||
</Button>
|
|
||||||
<Button label="Right"
|
|
||||||
:selected="settings.active.sites['@global'].videoAlignment === VideoAlignmentType.Right"
|
|
||||||
@click.native="setDefaultvideoAlignment(VideoAlignmentType.Right)">
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="label">
|
|
||||||
Default stretch mode:
|
|
||||||
</div>
|
|
||||||
<div class="flex flex-row button-box">
|
|
||||||
<Button label="Don't stretch"
|
|
||||||
:selected="settings.active.sites['@global'].stretch === StretchType.NoStretch"
|
|
||||||
@click.native="setDefaultStretchingMode(StretchType.NoStretch)">
|
|
||||||
</Button>
|
|
||||||
<Button label="Basic stretch"
|
|
||||||
:selected="settings.active.sites['@global'].stretch === StretchType.Basic"
|
|
||||||
@click.native="setDefaultStretchingMode(StretchType.Basic)">
|
|
||||||
</Button>
|
|
||||||
<Button label="Hybrid stretch"
|
|
||||||
:selected="settings.active.sites['@global'].stretch === StretchType.Hybrid"
|
|
||||||
@click.native="setDefaultStretchingMode(StretchType.Hybrid)">
|
|
||||||
</Button>
|
|
||||||
<Button label="Thin borders only"
|
|
||||||
:selected="settings.active.sites['@global'].stretch === StretchType.Conditional"
|
|
||||||
@click.native="setDefaultStretchingMode(StretchType.Conditional)"
|
|
||||||
>
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
<div class="description">
|
|
||||||
<b>None:</b> do not stretch the video at all. This is the default option, for men of culture.<br/>
|
|
||||||
<b>Basic:</b> stretches video to fit the player or screen unconditionally. If video has letterbox encoded, this option <i>will not</i> try to remove letterbox before stretching. You probably shouldn't be using this option.<br/>
|
|
||||||
<b>Hybrid:</b> stretches the video to fit the player, but only if cropping didn't completely remove the black bars.<br/>
|
|
||||||
<b>Thin borders:</b> stretches only if the width of black borders after cropping is thin.
|
|
||||||
<br/>
|
|
||||||
Threshold for thin borders can be defined below.
|
|
||||||
</div>
|
|
||||||
<div class="indent">
|
|
||||||
<div class="flex flex-row row-padding">
|
|
||||||
<div class="flex label-secondary">
|
|
||||||
Thin border threshold:
|
|
||||||
</div>
|
|
||||||
<div class="flex flex-input">
|
|
||||||
<input type="number"
|
|
||||||
step="any"
|
|
||||||
:value="settings.active.stretch.conditionalDifferencePercent"
|
|
||||||
@input="updateStretchThreshold($event.target.value)"
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="label">
|
|
||||||
Import, export, reset settings
|
|
||||||
</div>
|
|
||||||
<div class="flex flex-column">
|
|
||||||
<div v-if="downloadPermissionError"
|
|
||||||
class="w100 center-text warning-lite"
|
|
||||||
>
|
|
||||||
Exporting settings requires the 'downloads' permission. (If you want to export settings without granting 'downloads' permission, you can copy-paste settings from 'Super advanced settings' tab)
|
|
||||||
</div>
|
|
||||||
<div v-if="corruptedSettingsError"
|
|
||||||
class="w100 center-text warning-lite"
|
|
||||||
>
|
|
||||||
Settings import failed. The settings file is probably corrupted.
|
|
||||||
</div>
|
|
||||||
<div class="flex flex-row button-box">
|
|
||||||
<div class="button center-text flex flex-auto">
|
|
||||||
<label for="file-upload" class="w100 h100 block">
|
|
||||||
Import settings
|
|
||||||
</label>
|
|
||||||
<input id="file-upload"
|
|
||||||
type="file"
|
|
||||||
@input="importSettings"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<Button label="Export settings"
|
|
||||||
@click.native="exportSettings()"
|
|
||||||
/>
|
|
||||||
<Button label="Reset settings"
|
|
||||||
@click.native="resetSettings()"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -166,110 +20,13 @@ export default {
|
|||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
StretchType: StretchType,
|
|
||||||
ExtensionMode: ExtensionMode,
|
|
||||||
VideoAlignmentType: VideoAlignmentType,
|
|
||||||
stretchThreshold: 0,
|
|
||||||
corruptedSettingsError: false,
|
|
||||||
downloadPermissionError: false,
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created () {
|
created () {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
setDefaultAutodetectionMode(mode) {
|
|
||||||
this.settings.active.sites['@global'].autoar = mode;
|
|
||||||
this.settings.save();
|
|
||||||
},
|
|
||||||
setDefaultExtensionMode(mode) {
|
|
||||||
this.settings.active.sites['@global'].mode = mode;
|
|
||||||
this.settings.save();
|
|
||||||
|
|
||||||
},
|
|
||||||
setDefaultvideoAlignment(mode) {
|
|
||||||
this.settings.active.sites['@global'].videoAlignment = mode;
|
|
||||||
this.settings.save();
|
|
||||||
},
|
|
||||||
setDefaultStretchingMode(mode) {
|
|
||||||
this.settings.active.sites['@global'].stretch = mode;
|
|
||||||
this.settings.save();
|
|
||||||
},
|
|
||||||
updateStretchThreshold(newThreshold) {
|
|
||||||
if (!newThreshold || isNaN(newThreshold)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.settings.active.stretch.conditionalDifferencePercent = newThreshold;
|
|
||||||
this.settings.save();
|
|
||||||
},
|
|
||||||
resetSettings() {
|
|
||||||
this.settings.active = JSON.parse(JSON.stringify(this.settings.default));
|
|
||||||
this.settings.save();
|
|
||||||
},
|
|
||||||
async exportSettings() {
|
|
||||||
this.downloadPermissionError = false;
|
|
||||||
|
|
||||||
const blob = new Blob([JSON.stringify(this.settings.active)], {type: 'application/json'});
|
|
||||||
const fileUrl = URL.createObjectURL(blob);
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (BrowserDetect.firefox) {
|
|
||||||
// reminder — webextension-polyfill doesn't seem to work in vue!
|
|
||||||
await browser.permissions.request({permissions: ['downloads']});
|
|
||||||
browser.downloads.download({saveAs: true, filename: 'ultrawidify-settings.json', url: fileUrl});
|
|
||||||
} else if (BrowserDetect.anyChromium) {
|
|
||||||
const ths = this;
|
|
||||||
|
|
||||||
chrome.permissions.request(
|
|
||||||
{permissions: ['downloads']},
|
|
||||||
(granted) => {
|
|
||||||
if (granted) {
|
|
||||||
ths.exportSettingsChrome(fileUrl);
|
|
||||||
} else {
|
|
||||||
ths.downloadPermissionError = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
this.downloadPermissionError = true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
exportSettingsChrome(fileUrl){
|
|
||||||
chrome.downloads.download({saveAs: true, filename: 'ultrawidify-settings.json', url: fileUrl});
|
|
||||||
},
|
|
||||||
async importSettings($event) {
|
|
||||||
let file, text, settingsObj;
|
|
||||||
this.corruptedSettingsError = false;
|
|
||||||
|
|
||||||
try {
|
|
||||||
file = $event.target.files[0];
|
|
||||||
} catch (e) {
|
|
||||||
console.error("error grabbing a file!");
|
|
||||||
this.corruptedSettingsError = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
text = await file.text();
|
|
||||||
settingsObj = JSON.parse(text);
|
|
||||||
} catch (e) {
|
|
||||||
console.error("error parsing file to json");
|
|
||||||
this.corruptedSettingsError = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// validate settings
|
|
||||||
for (const key in this.settings.default) {
|
|
||||||
if (!settingsObj[key]) {
|
|
||||||
console.error("corrupted settings!")
|
|
||||||
this.corruptedSettingsError = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.settings.active = settingsObj;
|
|
||||||
this.settings.save();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -67,7 +67,6 @@
|
|||||||
import ZoomOptionsPanel from '../../csui/src/PlayerUiPanels/PanelComponents/VideoSettings/ZoomOptionsPanel.vue'
|
import ZoomOptionsPanel from '../../csui/src/PlayerUiPanels/PanelComponents/VideoSettings/ZoomOptionsPanel.vue'
|
||||||
import StretchOptionsPanel from '../../csui/src/PlayerUiPanels/PanelComponents/VideoSettings/StretchOptionsPanel.vue'
|
import StretchOptionsPanel from '../../csui/src/PlayerUiPanels/PanelComponents/VideoSettings/StretchOptionsPanel.vue'
|
||||||
import CropOptionsPanel from '../../csui/src/PlayerUiPanels/PanelComponents/VideoSettings/CropOptionsPanel.vue'
|
import CropOptionsPanel from '../../csui/src/PlayerUiPanels/PanelComponents/VideoSettings/CropOptionsPanel.vue'
|
||||||
import ExecAction from '../../csui/src/ui-libs/ExecAction';
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
@ -88,7 +87,6 @@ export default {
|
|||||||
CropOptionsPanel, StretchOptionsPanel, ZoomOptionsPanel
|
CropOptionsPanel, StretchOptionsPanel, ZoomOptionsPanel
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.exec = new ExecAction(this.settings, window.location.hostname);
|
|
||||||
this.eventBus.subscribe('uw-config-broadcast', {function: (config) => this.handleConfigBroadcast(config)});
|
this.eventBus.subscribe('uw-config-broadcast', {function: (config) => this.handleConfigBroadcast(config)});
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
@ -250,23 +250,23 @@ export default {
|
|||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
site: String,
|
site: String,
|
||||||
settings: Object,
|
siteSettings: Object,
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
try {
|
try {
|
||||||
this.videoManualQs = this.settings.active.sites[this.site]?.DOM?.video?.manual ?? this.videoManualQs;
|
this.videoManualQs = this.siteSettings.data.currentDOMConfig?.elements?.video?.manual ?? this.videoManualQs;
|
||||||
this.videoQs = this.settings.active.sites[this.site]?.DOM?.video?.querySelectors;
|
this.videoQs = this.siteSettings.data.currentDOMConfig?.elements?.video?.querySelectors;
|
||||||
this.videoCss = this.settings.active.sites[this.site]?.DOM?.video?.additionalCss;
|
this.videoCss = this.siteSettings.data.currentDOMConfig?.elements?.video?.nodeCss;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// that's here just in case relevant settings for this site don't exist yet
|
// that's here just in case relevant settings for this site don't exist yet
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.playerManualQs = this.settings.active.sites[this.site]?.DOM?.player?.manual ?? this.playerManualQs;
|
this.playerManualQs = this.siteSettings.data.currentDOMConfig?.elements?.player?.manual ?? this.playerManualQs;
|
||||||
this.playerQs = this.settings.active.sites[this.site]?.DOM?.player?.querySelectors;
|
this.playerQs = this.siteSettings.data.currentDOMConfig?.elements?.player?.querySelectors;
|
||||||
this.playerByNodeIndex = this.settings.active.sites[this.site]?.DOM?.player?.useRelativeAncestor ?? this.playerByNodeIndex;
|
this.playerByNodeIndex = !this.siteSettings.data.currentDOMConfig?.elements?.player?.querySelectors || this.playerByNodeIndex;
|
||||||
this.playerParentNodeIndex = this.settings.active.sites[this.site]?.DOM?.player?.videoAncestor;
|
this.playerParentNodeIndex = this.siteSettings.data.currentDOMConfig?.elements?.player?.index;
|
||||||
this.usePlayerAr = this.settings.active.sites[this.site]?.usePlayerArInFullscreen;
|
// this.usePlayerAr = this.settings.active.sites[this.site]?.usePlayerArInFullscreen;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// that's here just in case relevant settings for this site don't exist yet
|
// that's here just in case relevant settings for this site don't exist yet
|
||||||
}
|
}
|
||||||
@ -295,32 +295,8 @@ export default {
|
|||||||
|
|
||||||
observer.observe(saveButtonBait);
|
observer.observe(saveButtonBait);
|
||||||
},
|
},
|
||||||
ensureSettings(scope) {
|
|
||||||
if (! this.settings.active.sites[this.site]) {
|
|
||||||
this.settings.active.sites[this.site] = {
|
|
||||||
mode: ExtensionMode.Default,
|
|
||||||
autoar: ExtensionMode.Default,
|
|
||||||
type: 'user-added',
|
|
||||||
stretch: StretchType.Default,
|
|
||||||
videoAlignment: VideoAlignmentType.Default,
|
|
||||||
keyboardShortcutsEnabled: ExtensionMode.Default,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (! this.settings.active.sites[this.site].DOM) {
|
|
||||||
this.settings.active.sites[this.site].DOM = {};
|
|
||||||
}
|
|
||||||
if (! this.settings.active.sites[this.site].DOM[scope]) {
|
|
||||||
this.settings.active.sites[this.site].DOM[scope] = {
|
|
||||||
manual: false,
|
|
||||||
querySelectors: '',
|
|
||||||
additionalCss: '',
|
|
||||||
useRelativeAncestor: scope === 'player' ? false : undefined,
|
|
||||||
videoAncestor: undefined,
|
|
||||||
playerNodeCss: scope === 'player' ? '' : undefined,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
updateVideoQuerySelector() {
|
updateVideoQuerySelector() {
|
||||||
|
this.siteSettings.set('currentDOMConfig')
|
||||||
this.ensureSettings('video');
|
this.ensureSettings('video');
|
||||||
this.settings.active.sites[this.site].DOM.video.querySelectors = this.videoQs;
|
this.settings.active.sites[this.site].DOM.video.querySelectors = this.videoQs;
|
||||||
this.settings.save();
|
this.settings.save();
|
||||||
|
Loading…
Reference in New Issue
Block a user