Compare commits
No commits in common. "ca751a660fb66181f4de07fa07210b5a29e18f5c" and "877fc96da10d9b105dd0a7e5ac13b0b8e427a5f7" have entirely different histories.
ca751a660f
...
877fc96da1
19
.vscode/settings.json
vendored
19
.vscode/settings.json
vendored
@ -10,8 +10,6 @@
|
||||
"blackframe",
|
||||
"canvas",
|
||||
"clickthrough",
|
||||
"cmpa",
|
||||
"cmpb",
|
||||
"com",
|
||||
"comms",
|
||||
"csui",
|
||||
@ -25,37 +23,26 @@
|
||||
"fith",
|
||||
"fitw",
|
||||
"fuckup",
|
||||
"fucky",
|
||||
"geoblocked",
|
||||
"geoblocking",
|
||||
"gfycat",
|
||||
"gmail",
|
||||
"guardline",
|
||||
"han",
|
||||
"haram",
|
||||
"Heebo",
|
||||
"hoverable",
|
||||
"iframe",
|
||||
"imgur",
|
||||
"insta",
|
||||
"jsoneditor",
|
||||
"jwplayer",
|
||||
"kavin",
|
||||
"letterboxed",
|
||||
"manjaro",
|
||||
"mdicon",
|
||||
"mdijs",
|
||||
"metaivi",
|
||||
"minification",
|
||||
"mitigations",
|
||||
"mstefan",
|
||||
"nogrow",
|
||||
"noshrink",
|
||||
"outro",
|
||||
"PILLARBOX",
|
||||
"PILLARBOXED",
|
||||
"polyfill",
|
||||
"problemo",
|
||||
"recursing",
|
||||
"reddit",
|
||||
"rescan",
|
||||
@ -64,7 +51,6 @@
|
||||
"scrollbar",
|
||||
"shitiness",
|
||||
"smallcaps",
|
||||
"spaghettified",
|
||||
"suboption",
|
||||
"subscan",
|
||||
"tabitem",
|
||||
@ -75,7 +61,6 @@
|
||||
"ultrawidify",
|
||||
"unmark",
|
||||
"unmarking",
|
||||
"unsets",
|
||||
"unshift",
|
||||
"uwid",
|
||||
"uwui",
|
||||
@ -83,12 +68,8 @@
|
||||
"vids",
|
||||
"vuejs",
|
||||
"vuex",
|
||||
"wakanim",
|
||||
"webextension",
|
||||
"webextensions",
|
||||
"wuckies",
|
||||
"wucky",
|
||||
"ycenter",
|
||||
"youtube"
|
||||
],
|
||||
"cSpell.ignoreWords": [
|
||||
|
||||
14
package-lock.json
generated
14
package-lock.json
generated
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "ultrawidify",
|
||||
"version": "6.3.994",
|
||||
"version": "6.3.993",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "ultrawidify",
|
||||
"version": "6.3.994",
|
||||
"version": "6.3.993",
|
||||
"dependencies": {
|
||||
"@babel/plugin-proposal-class-properties": "^7.18.6",
|
||||
"@mdi/font": "^7.4.47",
|
||||
@ -16,7 +16,6 @@
|
||||
"fs-extra": "^11.3.2",
|
||||
"gl-matrix": "^3.4.4",
|
||||
"json-cyclic": "1.0.2",
|
||||
"json-difference": "^1.16.1",
|
||||
"lodash": "^4.17.21",
|
||||
"mdi-vue": "^3.0.13",
|
||||
"typescript": "^5.9.3",
|
||||
@ -13497,15 +13496,6 @@
|
||||
"integrity": "sha512-K0Y9wQnrc13Ef+P8KY8SjFyVAz941CTrTVmu3oyQPExhaFFYXXLXnEuRi1tqYOS1B8WtFIxIwA7nHRJ64Uvf5Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/json-difference": {
|
||||
"version": "1.16.1",
|
||||
"resolved": "https://registry.npmjs.org/json-difference/-/json-difference-1.16.1.tgz",
|
||||
"integrity": "sha512-tNVUzBKn2I4BB4Cjn+j+Kq/BfLNwqtEvxhnlyuX5XJmKn9VlfV5MvaTbB/ure/toFgLaD6XglOUt+dd4iMQ3dA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.17.x"
|
||||
}
|
||||
},
|
||||
"node_modules/json-parse-better-errors": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ultrawidify",
|
||||
"version": "6.3.994",
|
||||
"version": "6.3.993",
|
||||
"description": "Aspect ratio fixer for youtube and other sites, with automatic aspect ratio detection. Supports ultrawide and other ratios.",
|
||||
"author": "Tamius Han <tamius.han@gmail.com>",
|
||||
"scripts": {
|
||||
@ -33,7 +33,6 @@
|
||||
"fs-extra": "^11.3.2",
|
||||
"gl-matrix": "^3.4.4",
|
||||
"json-cyclic": "1.0.2",
|
||||
"json-difference": "^1.16.1",
|
||||
"lodash": "^4.17.21",
|
||||
"mdi-vue": "^3.0.13",
|
||||
"typescript": "^5.9.3",
|
||||
|
||||
@ -1,11 +0,0 @@
|
||||
const path = require('path')
|
||||
|
||||
module.exports = {
|
||||
'@src': path.resolve(__dirname, 'src'),
|
||||
'@csui': path.resolve(__dirname, 'src/csui'),
|
||||
'@ui': path.resolve(__dirname, 'src/ui'),
|
||||
'@components': path.resolve(__dirname, 'src/ui/components'),
|
||||
'@res': path.resolve(__dirname, 'src/ui/res'),
|
||||
'@': path.resolve(__dirname, 'src'),
|
||||
};
|
||||
|
||||
@ -1,22 +1,5 @@
|
||||
const path = require('path');
|
||||
const aliases = require('./paths.config');
|
||||
|
||||
module.exports = {
|
||||
plugins: [
|
||||
require('postcss-import')({
|
||||
resolve(id) {
|
||||
for (const alias in aliases) {
|
||||
if (id === alias || id.startsWith(alias + '/')) {
|
||||
return path.resolve(
|
||||
aliases[alias],
|
||||
id.slice(alias.length + 1)
|
||||
)
|
||||
}
|
||||
}
|
||||
return id
|
||||
},
|
||||
}),
|
||||
|
||||
require('@tailwindcss/postcss'),
|
||||
require('postcss-nested'),
|
||||
require('autoprefixer'),
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
enum ExtensionMode {
|
||||
AutoDisabled = -2,
|
||||
Disabled = -1,
|
||||
Default = 0,
|
||||
FullScreen = 1,
|
||||
Theater = 2,
|
||||
All = 3
|
||||
}
|
||||
Whitelist = 1,
|
||||
Basic = 2,
|
||||
Enabled = 3,
|
||||
};
|
||||
|
||||
export default ExtensionMode;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
enum LegacyExtensionMode {
|
||||
enum ExtensionMode {
|
||||
AutoDisabled = -2,
|
||||
Disabled = -1,
|
||||
Default = 0,
|
||||
@ -7,4 +7,4 @@ enum LegacyExtensionMode {
|
||||
Enabled = 3,
|
||||
};
|
||||
|
||||
export default LegacyExtensionMode;
|
||||
export default ExtensionMode;
|
||||
|
||||
@ -1,9 +0,0 @@
|
||||
export enum SiteSupportLevel {
|
||||
OfficialSupport = 'official',
|
||||
CommunitySupport = 'community',
|
||||
UserDefined = 'user-defined',
|
||||
BetaSupport = 'testing',
|
||||
OfficialBlacklist = 'officially-disabled',
|
||||
Unknown = 'unknown',
|
||||
UserModified = 'modified',
|
||||
}
|
||||
@ -6,14 +6,13 @@ import AspectRatioType from '../enums/AspectRatioType.enum'
|
||||
import CropModePersistence from '../enums/CropModePersistence.enum'
|
||||
import EmbeddedContentSettingsOverridePolicy from '../enums/EmbeddedContentSettingsOverridePolicy.enum'
|
||||
import ExtensionMode from '../enums/ExtensionMode.enum'
|
||||
import { SiteSupportLevel } from '../enums/SiteSupportLevel.enum'
|
||||
import StretchType from '../enums/StretchType.enum'
|
||||
import VideoAlignmentType from '../enums/VideoAlignmentType.enum'
|
||||
|
||||
export enum ExtensionEnvironment {
|
||||
Normal = ExtensionMode.All,
|
||||
Theater = ExtensionMode.Theater,
|
||||
Fullscreen = ExtensionMode.FullScreen,
|
||||
Normal = 'normal',
|
||||
Theater = 'theater',
|
||||
Fullscreen = 'fullscreen',
|
||||
}
|
||||
|
||||
export interface DevUiConfig {
|
||||
@ -49,6 +48,12 @@ interface RestrictionsSettings {
|
||||
onlyAllowAutodetectionInFullScreen?: boolean; // if enabled, autodetection will only start once in full screen
|
||||
}
|
||||
|
||||
interface ExtensionEnvironmentSettingsInterface {
|
||||
normal: ExtensionMode,
|
||||
theater: ExtensionMode,
|
||||
fullscreen: ExtensionMode,
|
||||
}
|
||||
|
||||
export interface CommandInterface {
|
||||
action: string,
|
||||
label: string,
|
||||
@ -320,6 +325,8 @@ interface SettingsInterface {
|
||||
|
||||
ui: {
|
||||
inPlayer: {
|
||||
enabled: boolean, // Deprecated — moved to site settings
|
||||
enabledFullscreenOnly: boolean, // Deprecated — moved to site settings
|
||||
popupAlignment: 'left' | 'right',
|
||||
minEnabledWidth: number, // don't show UI if player is narrower than % of screen width
|
||||
minEnabledHeight: number, // don't show UI if player is narrower than % of screen height
|
||||
@ -438,18 +445,18 @@ interface SettingsInterface {
|
||||
}
|
||||
|
||||
export interface SiteSettingsInterface {
|
||||
enable: ExtensionMode;
|
||||
enableAard: ExtensionMode;
|
||||
enableKeyboard: ExtensionMode;
|
||||
enableUI: ExtensionMode;
|
||||
enable: ExtensionEnvironmentSettingsInterface;
|
||||
enableAard: ExtensionEnvironmentSettingsInterface;
|
||||
enableKeyboard: ExtensionEnvironmentSettingsInterface;
|
||||
enableUI: ExtensionEnvironmentSettingsInterface; // Lies! enableUI doesn't use 'theater' property (but uses the other two)
|
||||
|
||||
applyToEmbeddedContent: EmbeddedContentSettingsOverridePolicy; // presumed to be 'Always' if not defined
|
||||
overrideWhenEmbedded?: boolean;
|
||||
|
||||
|
||||
autocreated?: boolean;
|
||||
type?: SiteSupportLevel;
|
||||
defaultType: SiteSupportLevel;
|
||||
type?: 'official' | 'community' | 'user-defined' | 'testing' | 'officially-disabled' | 'unknown' | 'modified';
|
||||
defaultType: 'official' | 'community' | 'user-defined' | 'testing' | 'officially-disabled' | 'unknown' | 'modified';
|
||||
|
||||
// must be defined in @global and @empty
|
||||
persistCSA?: CropModePersistence, // CSA - crop, stretch, alignment
|
||||
|
||||
@ -1,40 +1,42 @@
|
||||
<template>
|
||||
<div>
|
||||
<!-- Enable extension -->
|
||||
|
||||
<pre>{{simpleExtensionSettings}}</pre>
|
||||
|
||||
<div class="field">
|
||||
<div class="label">
|
||||
Enable <span class="color-emphasis">extension</span>
|
||||
<span class="sub-label"><br/>under the following conditions:</span>
|
||||
</div>
|
||||
<pre>{{simpleExtensionSettings}}</pre>
|
||||
<div class="select">
|
||||
<select
|
||||
:value="simpleExtensionSettings.enable"
|
||||
@click="setExtensionMode('enable', $event)"
|
||||
>
|
||||
<option
|
||||
v-if="simpleExtensionSettings.enable === 'complex'"
|
||||
value="complex"
|
||||
>
|
||||
(Site uses advanced settings)
|
||||
</option>
|
||||
<template v-if="isDefaultConfiguration">
|
||||
<option :value="ExtensionMode.Disabled">
|
||||
<option value="disabled">
|
||||
Disabled by default
|
||||
</option>
|
||||
</template>
|
||||
<template v-else>
|
||||
<option :value="ExtensionMode.Default">
|
||||
Use default ({{simpleDefaultSettings.enableAard}})
|
||||
<option value="default">
|
||||
Use default ({{simpleDefaultSettings.enable}})
|
||||
</option>
|
||||
<option :value="ExtensionMode.Disabled">
|
||||
<option value="disabled">
|
||||
Never
|
||||
</option>
|
||||
</template>
|
||||
<option :value="ExtensionMode.FullScreen">
|
||||
<option value="fs">
|
||||
Fullscreen only
|
||||
</option>
|
||||
<option :value="ExtensionMode.Theater">
|
||||
<option value="theater">
|
||||
Fullscreen and theater mode
|
||||
</option>
|
||||
<option :value="ExtensionMode.All">
|
||||
<option value="enabled">
|
||||
Always
|
||||
</option>
|
||||
</select>
|
||||
@ -54,26 +56,32 @@
|
||||
:value="simpleExtensionSettings.enableAard"
|
||||
@click="setExtensionMode('enableAard', $event)"
|
||||
>
|
||||
<option
|
||||
v-if="simpleExtensionSettings.enable === 'complex'"
|
||||
value="complex"
|
||||
>
|
||||
(Site uses advanced settings)
|
||||
</option>
|
||||
<template v-if="isDefaultConfiguration">
|
||||
<option :value="ExtensionMode.Disabled">
|
||||
<option value="disabled">
|
||||
Disabled by default
|
||||
</option>
|
||||
</template>
|
||||
<template v-else>
|
||||
<option :value="ExtensionMode.Default">
|
||||
<option value="default">
|
||||
Use default ({{simpleDefaultSettings.enableAard}})
|
||||
</option>
|
||||
<option :value="ExtensionMode.Disabled">
|
||||
<option value="disabled">
|
||||
Never
|
||||
</option>
|
||||
</template>
|
||||
<option :value="ExtensionMode.FullScreen">
|
||||
<option value="fs">
|
||||
Fullscreen only
|
||||
</option>
|
||||
<option :value="ExtensionMode.Theater">
|
||||
<option value="theater">
|
||||
Fullscreen and theater mode
|
||||
</option>
|
||||
<option :value="ExtensionMode.All">
|
||||
<option value="enabled">
|
||||
Always
|
||||
</option>
|
||||
</select>
|
||||
@ -91,26 +99,32 @@
|
||||
:value="simpleExtensionSettings.enableKeyboard"
|
||||
@click="setExtensionMode('enableKeyboard', $event)"
|
||||
>
|
||||
<option
|
||||
v-if="simpleExtensionSettings.enable === 'complex'"
|
||||
value="complex"
|
||||
>
|
||||
(Site uses advanced settings)
|
||||
</option>
|
||||
<template v-if="isDefaultConfiguration">
|
||||
<option :value="ExtensionMode.Disabled">
|
||||
<option value="disabled">
|
||||
Disabled by default
|
||||
</option>
|
||||
</template>
|
||||
<template v-else>
|
||||
<option :value="ExtensionMode.Default">
|
||||
Use default ({{simpleDefaultSettings.enableAard}})
|
||||
<option value="default">
|
||||
Use default ({{simpleDefaultSettings.enableKeyboard}})
|
||||
</option>
|
||||
<option :value="ExtensionMode.Disabled">
|
||||
<option value="disabled">
|
||||
Never
|
||||
</option>
|
||||
</template>
|
||||
<option :value="ExtensionMode.FullScreen">
|
||||
<option value="fs">
|
||||
Fullscreen only
|
||||
</option>
|
||||
<option :value="ExtensionMode.Theater">
|
||||
<option value="theater">
|
||||
Fullscreen and theater mode
|
||||
</option>
|
||||
<option :value="ExtensionMode.All">
|
||||
<option value="enabled">
|
||||
Always
|
||||
</option>
|
||||
</select>
|
||||
@ -129,26 +143,23 @@
|
||||
@click="setExtensionMode('enableUI', $event)"
|
||||
>
|
||||
<template v-if="isDefaultConfiguration">
|
||||
<option :value="ExtensionMode.Disabled">
|
||||
<option value="disabled">
|
||||
Disabled by default
|
||||
</option>
|
||||
</template>
|
||||
<template v-else>
|
||||
<option :value="ExtensionMode.Default">
|
||||
Use default ({{simpleDefaultSettings.enableAard}})
|
||||
<option value="default">
|
||||
Use default ({{simpleDefaultSettings.enableUI}})
|
||||
</option>
|
||||
<option :value="ExtensionMode.Disabled">
|
||||
<option value="disabled">
|
||||
Never
|
||||
</option>
|
||||
</template>
|
||||
<option :value="ExtensionMode.FullScreen">
|
||||
<option value="fs">
|
||||
Fullscreen only
|
||||
</option>
|
||||
<option :value="ExtensionMode.Theater">
|
||||
Fullscreen and theater mode
|
||||
</option>
|
||||
<option :value="ExtensionMode.All">
|
||||
Always
|
||||
<option value="theater">
|
||||
Always where possible
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
@ -285,7 +296,7 @@
|
||||
v-if="!isDefaultConfiguration"
|
||||
:value="CropModePersistence.Default"
|
||||
>
|
||||
Use default ({{defaultPersistenceLabel}})
|
||||
Use default ({{defaultPersistanceLabel}})
|
||||
</option>
|
||||
<option :value="CropModePersistence.Disabled">Disabled</option>
|
||||
<option :value="CropModePersistence.UntilPageReload">Until page reload</option>
|
||||
@ -377,7 +388,7 @@ export default {
|
||||
siteDefaultCropPersistence() {
|
||||
return this.siteSettings.raw?.persistCSA ?? undefined;
|
||||
},
|
||||
defaultPersistenceLabel() {
|
||||
defaultPersistanceLabel() {
|
||||
switch (this.siteSettings.defaultSettings.persistCSA) {
|
||||
case CropModePersistence.CurrentSession:
|
||||
return 'current session';
|
||||
@ -414,12 +425,64 @@ export default {
|
||||
break;
|
||||
}
|
||||
|
||||
return settingsData[component];
|
||||
|
||||
try {
|
||||
if (
|
||||
( settingsData?.[component]?.normal === ExtensionMode.Disabled || component === 'enableUI')
|
||||
&& settingsData?.[component]?.theater === ExtensionMode.Disabled
|
||||
&& settingsData?.[component]?.fullscreen === ExtensionMode.Disabled
|
||||
) {
|
||||
return 'disabled';
|
||||
}
|
||||
if (
|
||||
( settingsData?.[component]?.normal === ExtensionMode.Default || component === 'enableUI')
|
||||
&& settingsData?.[component]?.theater === ExtensionMode.Default
|
||||
&& settingsData?.[component]?.fullscreen === ExtensionMode.Default
|
||||
) {
|
||||
// console.log(
|
||||
// component, 'is set to default because:\n',
|
||||
// `\nsettingsData[${component}].normal: ${settingsData?.[component]?.normal} || component is enableUI?`, component,
|
||||
// `\nsettingsData[${component}].theater: ${settingsData?.[component]?.normal}`,
|
||||
// `\nsettingsData[${component}].fullscreen: ${settingsData?.[component]?.normal}`,
|
||||
|
||||
// `\n\n(expected values:`, ExtensionMode.Default
|
||||
// )
|
||||
return 'default';
|
||||
}
|
||||
if (
|
||||
( settingsData?.[component]?.normal === ExtensionMode.Disabled || component === 'enableUI')
|
||||
&& settingsData?.[component]?.theater === ExtensionMode.Disabled
|
||||
&& settingsData?.[component]?.fullscreen === ExtensionMode.Enabled
|
||||
) {
|
||||
return 'fs';
|
||||
}
|
||||
if (
|
||||
( settingsData?.[component]?.normal === ExtensionMode.Disabled || component === 'enableUI')
|
||||
&& settingsData?.[component]?.theater === ExtensionMode.Enabled
|
||||
&& settingsData?.[component]?.fullscreen === ExtensionMode.Enabled
|
||||
) {
|
||||
return 'theater';
|
||||
}
|
||||
if (
|
||||
( settingsData?.[component]?.normal === ExtensionMode.Enabled || component === 'enableUI')
|
||||
&& settingsData?.[component]?.theater === ExtensionMode.Enabled
|
||||
&& settingsData?.[component]?.fullscreen === ExtensionMode.Enabled
|
||||
) {
|
||||
return 'enabled';
|
||||
}
|
||||
|
||||
return 'complex';
|
||||
} catch (e) {
|
||||
return 'loading';
|
||||
}
|
||||
},
|
||||
|
||||
getDefaultOptionLabel(component) {
|
||||
const componentValue = this.compileSimpleSettings(component, 'default');
|
||||
|
||||
if (componentValue === 'loading') {
|
||||
return componentValue;
|
||||
}
|
||||
if (component === 'enableUI') {
|
||||
switch (componentValue) {
|
||||
case 'fs':
|
||||
@ -517,7 +580,7 @@ export default {
|
||||
this._computedWatchers?.siteDefaultStretch?.run();
|
||||
this._computedWatchers?.siteDefaultAlignment?.run();
|
||||
this._computedWatchers?.siteDefaultCropPersistence?.run();
|
||||
this._computedWatchers?.defaultPersistenceLabel?.run();
|
||||
this._computedWatchers?.defaultPersistanceLabel?.run();
|
||||
|
||||
this.$nextTick( () => this.$forceUpdate());
|
||||
},
|
||||
|
||||
@ -274,7 +274,7 @@ export default {
|
||||
this.eventBus?.sendToTunnel('set-zoom', {zoom: 1});
|
||||
},
|
||||
changeZoom(newZoom, axis) {
|
||||
// we store zoom logarithmically on this component
|
||||
// we store zoom logarithmically on this compnent
|
||||
if (!axis) {
|
||||
this.zoom.x = newZoom;
|
||||
} else {
|
||||
|
||||
@ -110,7 +110,7 @@ export default class UWContent {
|
||||
this.pageInfo = new PageInfo(this.eventBus, this.siteSettings, this.settings, this.logAggregator);
|
||||
this.logger.debug('setup', "pageInfo initialized.");
|
||||
|
||||
this.logger.debug('setup', "will try to initiate KeyboardHandler.");
|
||||
this.logger.debug('setup', "will try to initate KeyboardHandler.");
|
||||
|
||||
if (this.keyboardHandler) {
|
||||
this.keyboardHandler.destroy();
|
||||
|
||||
@ -1,44 +1,41 @@
|
||||
// How to use:
|
||||
// version: {ExtensionConf object, but only properties that get overwritten}
|
||||
import StretchType from '../../common/enums/StretchType.enum';
|
||||
// import ExtensionMode from '../../common/enums/ExtensionMode.enum';
|
||||
import ExtensionMode from '../../common/enums/ExtensionMode.enum';
|
||||
import VideoAlignmentType from '../../common/enums/VideoAlignmentType.enum';
|
||||
import BrowserDetect from './BrowserDetect';
|
||||
import SettingsInterface, { SiteSettingsInterface } from '../../common/interfaces/SettingsInterface';
|
||||
import SettingsInterface from '../../common/interfaces/SettingsInterface';
|
||||
import { _cp } from '../../common/js/utils';
|
||||
import CropModePersistence from '../../common/enums/CropModePersistence.enum';
|
||||
import AspectRatioType from '../../common/enums/AspectRatioType.enum';
|
||||
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';
|
||||
|
||||
|
||||
const ExtensionConfPatch = Object.freeze([
|
||||
{
|
||||
forVersion: '6.2.4',
|
||||
updateFn: (userOptions: any, defaultOptions, logger?) => {
|
||||
updateFn: (userOptions: SettingsInterface, defaultOptions) => {
|
||||
for (const site in userOptions.sites) {
|
||||
(userOptions as any).sites[site].enableUI = {
|
||||
fullscreen: LegacyExtensionMode.Default,
|
||||
theater: LegacyExtensionMode.Default,
|
||||
normal: LegacyExtensionMode.Default,
|
||||
userOptions.sites[site].enableUI = {
|
||||
fullscreen: ExtensionMode.Default,
|
||||
theater: ExtensionMode.Default,
|
||||
normal: ExtensionMode.Default,
|
||||
}
|
||||
}
|
||||
userOptions.sites['@global'].enableUI = {
|
||||
fullscreen: userOptions.ui.inPlayer.enabled ? LegacyExtensionMode.Enabled : LegacyExtensionMode.Disabled,
|
||||
theater: LegacyExtensionMode.Enabled,
|
||||
normal: (userOptions.ui.inPlayer.enabled && !userOptions.ui.inPlayer.enabledFullscreenOnly) ? LegacyExtensionMode.Enabled : LegacyExtensionMode.Disabled
|
||||
fullscreen: userOptions.ui.inPlayer.enabled ? ExtensionMode.Enabled : ExtensionMode.Disabled,
|
||||
theater: ExtensionMode.Enabled,
|
||||
normal: (userOptions.ui.inPlayer.enabled && !userOptions.ui.inPlayer.enabledFullscreenOnly) ? ExtensionMode.Enabled : ExtensionMode.Disabled
|
||||
}
|
||||
userOptions.sites['@empty'].enableUI = {
|
||||
fullscreen: LegacyExtensionMode.Default,
|
||||
theater: LegacyExtensionMode.Default,
|
||||
normal: LegacyExtensionMode.Default,
|
||||
fullscreen: ExtensionMode.Default,
|
||||
theater: ExtensionMode.Default,
|
||||
normal: ExtensionMode.Default,
|
||||
}
|
||||
}
|
||||
}, {
|
||||
forVersion: '6.2.6',
|
||||
updateFn: (userOptions: any, defaultOptions, logger?) => {
|
||||
updateFn: (userOptions: SettingsInterface, defaultOptions) => {
|
||||
console.log('[ultrawidify] Migrating settings — applying patches for version 6.2.6');
|
||||
|
||||
if (!userOptions.commands) {
|
||||
@ -244,7 +241,7 @@ const ExtensionConfPatch = Object.freeze([
|
||||
}
|
||||
}, {
|
||||
forVersion: '6.3.92',
|
||||
updateFn: (userOptions: any) => {
|
||||
updateFn: (userOptions: SettingsInterface) => {
|
||||
// applyToEmbeddedContent is now an enum, and also no longer optional
|
||||
for (const site in userOptions.sites) {
|
||||
if (userOptions.sites[site].applyToEmbeddedContent === undefined) {
|
||||
@ -273,41 +270,11 @@ const ExtensionConfPatch = Object.freeze([
|
||||
},
|
||||
{
|
||||
forVersion: '6.3.98',
|
||||
updateFn: (userOptions: SettingsInterface, defaultOptions: SettingsInterface) => {
|
||||
upgradeFn: (userOptions: SettingsInterface, defaultOptions: SettingsInterface) => {
|
||||
userOptions.aard = defaultOptions.aard;
|
||||
userOptions.aardLegacy = defaultOptions.aardLegacy;
|
||||
delete (userOptions as any).arDetect;
|
||||
}
|
||||
},
|
||||
{
|
||||
forVersion: '6.3.994',
|
||||
updateFn: (userOptions: SettingsInterface, defaultOptions: SettingsInterface, logger?) => {
|
||||
const convertLegacyExtensionMode = (option: {normal: LegacyExtensionMode, theater: LegacyExtensionMode, fullscreen: LegacyExtensionMode}) => {
|
||||
logger.log('updateFn', 'converting option', option);
|
||||
if (option.normal === LegacyExtensionMode.Enabled) {
|
||||
return ExtensionMode.All;
|
||||
}
|
||||
if (option.theater === LegacyExtensionMode.Enabled) {
|
||||
return ExtensionMode.Theater;
|
||||
}
|
||||
if (option.fullscreen === LegacyExtensionMode.Enabled) {
|
||||
return ExtensionMode.FullScreen;
|
||||
}
|
||||
if (option.fullscreen === LegacyExtensionMode.Disabled) {
|
||||
return ExtensionMode.Disabled;
|
||||
}
|
||||
return ExtensionMode.Default;
|
||||
}
|
||||
|
||||
for (const key in userOptions.sites) {
|
||||
userOptions.sites[key].enable = convertLegacyExtensionMode(userOptions.sites[key].enable as any);
|
||||
userOptions.sites[key].enableAard = convertLegacyExtensionMode(userOptions.sites[key].enable as any);
|
||||
userOptions.sites[key].enableKeyboard = convertLegacyExtensionMode(userOptions.sites[key].enable as any);
|
||||
userOptions.sites[key].enableUI = convertLegacyExtensionMode(userOptions.sites[key].enable as any);
|
||||
|
||||
logger.log('migrated site', key, userOptions.sites[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
]);
|
||||
|
||||
@ -12,7 +12,6 @@ import { Extension } from 'typescript';
|
||||
import EmbeddedContentSettingsOverridePolicy from '../../common/enums/EmbeddedContentSettingsOverridePolicy.enum';
|
||||
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';
|
||||
|
||||
if(Debug.debug)
|
||||
console.log("Loading: ExtensionConf.js");
|
||||
@ -263,6 +262,8 @@ const ExtensionConf: SettingsInterface = {
|
||||
|
||||
ui: {
|
||||
inPlayer: {
|
||||
enabled: true, // enable by default on new installs
|
||||
enabledFullscreenOnly: false,
|
||||
minEnabledWidth: 0.75,
|
||||
minEnabledHeight: 0.75,
|
||||
activation: 'player',
|
||||
@ -756,6 +757,65 @@ const ExtensionConf: SettingsInterface = {
|
||||
arguments: {
|
||||
arPersistence: CropModePersistence.Default
|
||||
}
|
||||
}, {
|
||||
action: 'set-extension-enabled',
|
||||
label: 'Enable extension',
|
||||
arguments: {
|
||||
mode: ExtensionMode.Enabled,
|
||||
},
|
||||
internalOnly: true,
|
||||
}, {
|
||||
action: 'set-extension-enabled',
|
||||
label: 'Whitelist',
|
||||
arguments: {
|
||||
mode: ExtensionMode.Whitelist,
|
||||
},
|
||||
internalOnly: true,
|
||||
}, {
|
||||
action: 'set-extension-enabled',
|
||||
label: 'Disable',
|
||||
arguments: {
|
||||
mode: ExtensionMode.Disabled
|
||||
},
|
||||
internalOnly: true,
|
||||
}, {
|
||||
action: 'set-extension-enabled',
|
||||
label: 'Use default option',
|
||||
arguments: {
|
||||
mode: ExtensionMode.Default
|
||||
},
|
||||
internalOnly: true
|
||||
}, {
|
||||
action: 'set-autoar-enabled',
|
||||
label: 'Enabled',
|
||||
comment: 'Enable automatic aspect ratio detection if possible',
|
||||
arguments: {
|
||||
mode: ExtensionMode.Enabled
|
||||
},
|
||||
internalOnly: true
|
||||
}, {
|
||||
action: 'set-autoar-enabled',
|
||||
label: 'Whitelist',
|
||||
comment: 'Enable automatic aspect ratio detection if possible, but only on whitelisted sites',
|
||||
arguments: {
|
||||
mode: ExtensionMode.Whitelist,
|
||||
},
|
||||
internalOnly: true,
|
||||
}, {
|
||||
action: 'set-autoar-enabled',
|
||||
label: 'Disable',
|
||||
comment: 'Disable aspect ratio detection',
|
||||
arguments: {
|
||||
mode: ExtensionMode.Disabled
|
||||
},
|
||||
internalOnly: true,
|
||||
}, {
|
||||
action: 'set-autoar-enabled',
|
||||
label: 'Use default option',
|
||||
arguments: {
|
||||
mode: ExtensionMode.Default
|
||||
},
|
||||
internalOnly: true
|
||||
}]
|
||||
},
|
||||
mitigations: {
|
||||
@ -802,14 +862,29 @@ const ExtensionConf: SettingsInterface = {
|
||||
// to avoid writing this multiple times. Tags:
|
||||
// #g — only available in @global
|
||||
// #s — only available for specific site
|
||||
enable: ExtensionMode.Disabled,
|
||||
enableAard: ExtensionMode.Disabled,
|
||||
enableKeyboard: ExtensionMode.Disabled,
|
||||
enableUI: ExtensionMode.FullScreen,
|
||||
|
||||
enable: { // How should extension work:
|
||||
fullscreen: ExtensionMode.Disabled, // 'enabled' - work everywhere except blacklist
|
||||
theater: ExtensionMode.Disabled, //
|
||||
normal: ExtensionMode.Disabled, // 'disabled' - work nowhere
|
||||
}, // 'default' - follow global rules (#s)
|
||||
enableAard: { // Should we try to automatically detect aspect ratio?
|
||||
fullscreen: ExtensionMode.Disabled, // Options: 'enabled', 'default' (#s), 'disabled'
|
||||
theater: ExtensionMode.Disabled,
|
||||
normal: ExtensionMode.Disabled,
|
||||
},
|
||||
enableKeyboard: {
|
||||
fullscreen: ExtensionMode.Disabled,
|
||||
theater: ExtensionMode.Disabled,
|
||||
normal: ExtensionMode.Disabled
|
||||
},
|
||||
enableUI: {
|
||||
fullscreen: ExtensionMode.Disabled,
|
||||
theater: ExtensionMode.Disabled, // Lies! means 'theater-ish'
|
||||
normal: ExtensionMode.Disabled // Not actually used.
|
||||
},
|
||||
applyToEmbeddedContent: EmbeddedContentSettingsOverridePolicy.Always,
|
||||
|
||||
defaultType: SiteSupportLevel.Unknown,
|
||||
defaultType: 'unknown',
|
||||
persistCSA: CropModePersistence.Disabled,
|
||||
|
||||
defaults: {
|
||||
@ -819,15 +894,30 @@ const ExtensionConf: SettingsInterface = {
|
||||
}
|
||||
},
|
||||
"@empty": { // placeholder settings object with fallbacks to @global
|
||||
enable: ExtensionMode.Default,
|
||||
enableAard: ExtensionMode.Default,
|
||||
enableKeyboard: ExtensionMode.Default,
|
||||
enableUI: ExtensionMode.Default,
|
||||
|
||||
enable: {
|
||||
fullscreen: ExtensionMode.Default,
|
||||
theater: ExtensionMode.Default,
|
||||
normal: ExtensionMode.Default,
|
||||
},
|
||||
enableAard: {
|
||||
fullscreen: ExtensionMode.Default,
|
||||
theater: ExtensionMode.Default,
|
||||
normal: ExtensionMode.Default,
|
||||
},
|
||||
enableKeyboard: {
|
||||
fullscreen: ExtensionMode.Default,
|
||||
theater: ExtensionMode.Default,
|
||||
normal: ExtensionMode.Default
|
||||
},
|
||||
enableUI: {
|
||||
fullscreen: ExtensionMode.Default,
|
||||
theater: ExtensionMode.Default,
|
||||
normal: ExtensionMode.Disabled
|
||||
},
|
||||
applyToEmbeddedContent: EmbeddedContentSettingsOverridePolicy.Always,
|
||||
|
||||
type: SiteSupportLevel.UserDefined,
|
||||
defaultType: SiteSupportLevel.UserDefined,
|
||||
type: 'user-defined',
|
||||
defaultType: 'user-defined',
|
||||
persistCSA: CropModePersistence.Default,
|
||||
defaults: {
|
||||
crop: null,
|
||||
@ -836,22 +926,37 @@ const ExtensionConf: SettingsInterface = {
|
||||
}
|
||||
},
|
||||
"www.youtube.com" : {
|
||||
enable: ExtensionMode.All,
|
||||
enableAard: ExtensionMode.All,
|
||||
enableKeyboard: ExtensionMode.All,
|
||||
enableUI: ExtensionMode.All,
|
||||
|
||||
enable: {
|
||||
fullscreen: ExtensionMode.Enabled,
|
||||
theater: ExtensionMode.Enabled,
|
||||
normal: ExtensionMode.Enabled,
|
||||
},
|
||||
enableAard: {
|
||||
fullscreen: ExtensionMode.Enabled,
|
||||
theater: ExtensionMode.Enabled,
|
||||
normal: ExtensionMode.Enabled,
|
||||
},
|
||||
enableKeyboard: {
|
||||
fullscreen: ExtensionMode.Enabled,
|
||||
theater: ExtensionMode.Enabled,
|
||||
normal: ExtensionMode.Enabled
|
||||
},
|
||||
enableUI: {
|
||||
fullscreen: ExtensionMode.Enabled,
|
||||
theater: ExtensionMode.Enabled,
|
||||
normal: ExtensionMode.Disabled
|
||||
},
|
||||
applyToEmbeddedContent: EmbeddedContentSettingsOverridePolicy.Always,
|
||||
overrideWhenEmbedded: true,
|
||||
override: false, // ignore value localStorage in favour of this
|
||||
type: SiteSupportLevel.OfficialSupport, // is officially supported? (Alternatives are 'community' and 'user-defined')
|
||||
defaultType: SiteSupportLevel.OfficialSupport, // if user mucks around with settings, type changes to 'user-defined'.
|
||||
type: 'official', // is officially supported? (Alternatives are 'community' and 'user-defined')
|
||||
defaultType: 'official', // if user mucks around with settings, type changes to 'user-defined'.
|
||||
// We still want to know what the original type was, hence defaultType
|
||||
|
||||
activeDOMConfig: 'official',
|
||||
DOMConfig: {
|
||||
'official': {
|
||||
type: SiteSupportLevel.OfficialSupport,
|
||||
type: 'official',
|
||||
elements: {
|
||||
player: {
|
||||
manual: true,
|
||||
@ -862,23 +967,38 @@ const ExtensionConf: SettingsInterface = {
|
||||
}
|
||||
},
|
||||
"www.youtube-nocookie.com": {
|
||||
enable: ExtensionMode.All,
|
||||
enableAard: ExtensionMode.All,
|
||||
enableKeyboard: ExtensionMode.All,
|
||||
enableUI: ExtensionMode.FullScreen,
|
||||
|
||||
enable: {
|
||||
fullscreen: ExtensionMode.Enabled,
|
||||
theater: ExtensionMode.Enabled,
|
||||
normal: ExtensionMode.Enabled,
|
||||
},
|
||||
enableAard: {
|
||||
fullscreen: ExtensionMode.Enabled,
|
||||
theater: ExtensionMode.Enabled,
|
||||
normal: ExtensionMode.Enabled,
|
||||
},
|
||||
enableKeyboard: {
|
||||
fullscreen: ExtensionMode.Enabled,
|
||||
theater: ExtensionMode.Enabled,
|
||||
normal: ExtensionMode.Enabled
|
||||
},
|
||||
enableUI: {
|
||||
fullscreen: ExtensionMode.Enabled,
|
||||
theater: ExtensionMode.Enabled,
|
||||
normal: ExtensionMode.Disabled
|
||||
},
|
||||
applyToEmbeddedContent: EmbeddedContentSettingsOverridePolicy.Always,
|
||||
overrideWhenEmbedded: true,
|
||||
|
||||
override: false, // ignore value localStorage in favour of this
|
||||
type: SiteSupportLevel.OfficialSupport, // is officially supported? (Alternatives are 'community' and 'user-defined')
|
||||
defaultType: SiteSupportLevel.OfficialSupport, // if user mucks around with settings, type changes to 'user-defined'.
|
||||
type: 'official', // is officially supported? (Alternatives are 'community' and 'user-defined')
|
||||
defaultType: 'official', // if user mucks around with settings, type changes to 'user-defined'.
|
||||
// We still want to know what the original type was, hence defaultType
|
||||
|
||||
activeDOMConfig: 'official',
|
||||
DOMConfig: {
|
||||
'official': {
|
||||
type: SiteSupportLevel.OfficialSupport,
|
||||
type: 'official',
|
||||
elements: {
|
||||
player: {
|
||||
manual: true,
|
||||
@ -889,28 +1009,59 @@ const ExtensionConf: SettingsInterface = {
|
||||
}
|
||||
},
|
||||
"www.netflix.com" : {
|
||||
enable: ExtensionMode.Theater,
|
||||
enableAard: ExtensionMode.Disabled,
|
||||
enableKeyboard: ExtensionMode.All,
|
||||
enableUI: ExtensionMode.All,
|
||||
enable: {
|
||||
fullscreen: ExtensionMode.Enabled,
|
||||
theater: ExtensionMode.Enabled,
|
||||
normal: ExtensionMode.Default,
|
||||
},
|
||||
enableAard: {
|
||||
fullscreen: ExtensionMode.Disabled,
|
||||
theater: ExtensionMode.Disabled,
|
||||
normal: ExtensionMode.Disabled,
|
||||
},
|
||||
enableKeyboard: {
|
||||
fullscreen: ExtensionMode.Enabled,
|
||||
theater: ExtensionMode.Enabled,
|
||||
normal: ExtensionMode.Enabled
|
||||
},
|
||||
enableUI: {
|
||||
fullscreen: ExtensionMode.Enabled,
|
||||
theater: ExtensionMode.Enabled,
|
||||
normal: ExtensionMode.Disabled
|
||||
},
|
||||
applyToEmbeddedContent: EmbeddedContentSettingsOverridePolicy.Always,
|
||||
override: false,
|
||||
type: SiteSupportLevel.CommunitySupport,
|
||||
defaultType: SiteSupportLevel.CommunitySupport,
|
||||
type: 'community',
|
||||
defaultType: 'community',
|
||||
},
|
||||
"www.disneyplus.com" : {
|
||||
enable: ExtensionMode.Theater,
|
||||
enableAard: ExtensionMode.Theater,
|
||||
enableKeyboard: ExtensionMode.All,
|
||||
enableUI: ExtensionMode.FullScreen,
|
||||
|
||||
enable: {
|
||||
fullscreen: ExtensionMode.Enabled,
|
||||
theater: ExtensionMode.Enabled,
|
||||
normal: ExtensionMode.Default,
|
||||
},
|
||||
enableAard: {
|
||||
fullscreen: ExtensionMode.Enabled,
|
||||
theater: ExtensionMode.Enabled,
|
||||
normal: ExtensionMode.Default,
|
||||
},
|
||||
enableKeyboard: {
|
||||
fullscreen: ExtensionMode.Enabled,
|
||||
theater: ExtensionMode.Enabled,
|
||||
normal: ExtensionMode.Default
|
||||
},
|
||||
enableUI: {
|
||||
fullscreen: ExtensionMode.Enabled,
|
||||
theater: ExtensionMode.Enabled,
|
||||
normal: ExtensionMode.Default
|
||||
},
|
||||
applyToEmbeddedContent: EmbeddedContentSettingsOverridePolicy.Always,
|
||||
type: SiteSupportLevel.CommunitySupport,
|
||||
defaultType: SiteSupportLevel.CommunitySupport,
|
||||
type: 'community',
|
||||
defaultType: 'community',
|
||||
activeDOMConfig: 'community-mstefan99',
|
||||
DOMConfig: {
|
||||
'community-mstefan99': {
|
||||
type: SiteSupportLevel.OfficialSupport,
|
||||
type: 'official',
|
||||
elements: {
|
||||
player: {
|
||||
manual: true,
|
||||
@ -926,28 +1077,58 @@ const ExtensionConf: SettingsInterface = {
|
||||
}
|
||||
},
|
||||
"www.twitch.tv": {
|
||||
enable: ExtensionMode.All,
|
||||
enableAard: ExtensionMode.All,
|
||||
enableKeyboard: ExtensionMode.All,
|
||||
enableUI: ExtensionMode.FullScreen,
|
||||
|
||||
enable: {
|
||||
fullscreen: ExtensionMode.Enabled,
|
||||
theater: ExtensionMode.Enabled,
|
||||
normal: ExtensionMode.Enabled,
|
||||
},
|
||||
enableAard: {
|
||||
fullscreen: ExtensionMode.Enabled,
|
||||
theater: ExtensionMode.Enabled,
|
||||
normal: ExtensionMode.Enabled,
|
||||
},
|
||||
enableKeyboard: {
|
||||
fullscreen: ExtensionMode.Enabled,
|
||||
theater: ExtensionMode.Enabled,
|
||||
normal: ExtensionMode.Enabled
|
||||
},
|
||||
enableUI: {
|
||||
fullscreen: ExtensionMode.Enabled,
|
||||
theater: ExtensionMode.Enabled,
|
||||
normal: ExtensionMode.Enabled
|
||||
},
|
||||
applyToEmbeddedContent: EmbeddedContentSettingsOverridePolicy.Always,
|
||||
type: SiteSupportLevel.OfficialSupport,
|
||||
defaultType: SiteSupportLevel.OfficialSupport,
|
||||
type: 'official',
|
||||
defaultType: 'official',
|
||||
},
|
||||
"old.reddit.com" : {
|
||||
enable: ExtensionMode.Disabled,
|
||||
enableAard: ExtensionMode.Disabled,
|
||||
enableKeyboard: ExtensionMode.Disabled,
|
||||
enableUI: ExtensionMode.Disabled,
|
||||
|
||||
enable: {
|
||||
fullscreen: ExtensionMode.Disabled,
|
||||
theater: ExtensionMode.Disabled,
|
||||
normal: ExtensionMode.Disabled,
|
||||
},
|
||||
enableAard: {
|
||||
fullscreen: ExtensionMode.Disabled,
|
||||
theater: ExtensionMode.Disabled,
|
||||
normal: ExtensionMode.Disabled,
|
||||
},
|
||||
enableKeyboard: {
|
||||
fullscreen: ExtensionMode.Disabled,
|
||||
theater: ExtensionMode.Disabled,
|
||||
normal: ExtensionMode.Disabled,
|
||||
},
|
||||
enableUI: {
|
||||
fullscreen: ExtensionMode.Disabled,
|
||||
theater: ExtensionMode.Disabled,
|
||||
normal: ExtensionMode.Disabled
|
||||
},
|
||||
applyToEmbeddedContent: EmbeddedContentSettingsOverridePolicy.Never,
|
||||
type: SiteSupportLevel.OfficialBlacklist,
|
||||
defaultType: SiteSupportLevel.OfficialBlacklist,
|
||||
type: 'officially-disabled',
|
||||
defaultType: 'officially-disabled',
|
||||
activeDOMConfig: 'official',
|
||||
DOMConfig: {
|
||||
'official': {
|
||||
type: SiteSupportLevel.OfficialSupport,
|
||||
type: 'official',
|
||||
// customCss: 'video {\n width: 100% !important;\n height: 100% !important;\n}',
|
||||
elements: {
|
||||
player: {
|
||||
@ -959,18 +1140,33 @@ const ExtensionConf: SettingsInterface = {
|
||||
},
|
||||
},
|
||||
"www.reddit.com" : {
|
||||
enable: ExtensionMode.Disabled,
|
||||
enableAard: ExtensionMode.Disabled,
|
||||
enableKeyboard: ExtensionMode.Disabled,
|
||||
enableUI: ExtensionMode.Disabled,
|
||||
|
||||
enable: {
|
||||
fullscreen: ExtensionMode.Disabled,
|
||||
theater: ExtensionMode.Disabled,
|
||||
normal: ExtensionMode.Disabled,
|
||||
},
|
||||
enableAard: {
|
||||
fullscreen: ExtensionMode.Disabled,
|
||||
theater: ExtensionMode.Disabled,
|
||||
normal: ExtensionMode.Disabled,
|
||||
},
|
||||
enableKeyboard: {
|
||||
fullscreen: ExtensionMode.Disabled,
|
||||
theater: ExtensionMode.Disabled,
|
||||
normal: ExtensionMode.Disabled,
|
||||
},
|
||||
enableUI: {
|
||||
fullscreen: ExtensionMode.Disabled,
|
||||
theater: ExtensionMode.Disabled,
|
||||
normal: ExtensionMode.Disabled
|
||||
},
|
||||
applyToEmbeddedContent: EmbeddedContentSettingsOverridePolicy.Never,
|
||||
type: SiteSupportLevel.OfficialBlacklist,
|
||||
defaultType: SiteSupportLevel.OfficialBlacklist,
|
||||
type: 'officially-disabled',
|
||||
defaultType: 'officially-disabled',
|
||||
activeDOMConfig: 'official',
|
||||
DOMConfig: {
|
||||
'official': {
|
||||
type: SiteSupportLevel.OfficialSupport,
|
||||
type: 'official',
|
||||
// customCss: 'video {\n width: 100% !important;\n height: 100% !important;\n}',
|
||||
elements: {
|
||||
player: {
|
||||
@ -982,28 +1178,58 @@ const ExtensionConf: SettingsInterface = {
|
||||
},
|
||||
},
|
||||
"imgur.com": {
|
||||
enable: ExtensionMode.Disabled,
|
||||
enableAard: ExtensionMode.Disabled,
|
||||
enableKeyboard: ExtensionMode.Disabled,
|
||||
enableUI: ExtensionMode.Disabled,
|
||||
|
||||
enable: {
|
||||
fullscreen: ExtensionMode.Disabled,
|
||||
theater: ExtensionMode.Disabled,
|
||||
normal: ExtensionMode.Disabled,
|
||||
},
|
||||
enableAard: {
|
||||
fullscreen: ExtensionMode.Disabled,
|
||||
theater: ExtensionMode.Disabled,
|
||||
normal: ExtensionMode.Disabled,
|
||||
},
|
||||
enableKeyboard: {
|
||||
fullscreen: ExtensionMode.Disabled,
|
||||
theater: ExtensionMode.Disabled,
|
||||
normal: ExtensionMode.Disabled,
|
||||
},
|
||||
enableUI: {
|
||||
fullscreen: ExtensionMode.Disabled,
|
||||
theater: ExtensionMode.Disabled,
|
||||
normal: ExtensionMode.Disabled
|
||||
},
|
||||
applyToEmbeddedContent: EmbeddedContentSettingsOverridePolicy.Never,
|
||||
type: SiteSupportLevel.OfficialBlacklist,
|
||||
defaultType: SiteSupportLevel.OfficialBlacklist,
|
||||
type: 'officially-disabled',
|
||||
defaultType: 'officially-disabled',
|
||||
},
|
||||
"www.wakanim.tv": {
|
||||
enable: ExtensionMode.All,
|
||||
enableAard: ExtensionMode.All,
|
||||
enableKeyboard: ExtensionMode.All,
|
||||
enableUI: ExtensionMode.FullScreen,
|
||||
|
||||
enable: {
|
||||
fullscreen: ExtensionMode.Enabled,
|
||||
theater: ExtensionMode.Enabled,
|
||||
normal: ExtensionMode.Enabled,
|
||||
},
|
||||
enableAard: {
|
||||
fullscreen: ExtensionMode.Enabled,
|
||||
theater: ExtensionMode.Enabled,
|
||||
normal: ExtensionMode.Enabled,
|
||||
},
|
||||
enableKeyboard: {
|
||||
fullscreen: ExtensionMode.Enabled,
|
||||
theater: ExtensionMode.Enabled,
|
||||
normal: ExtensionMode.Enabled
|
||||
},
|
||||
enableUI: {
|
||||
fullscreen: ExtensionMode.Enabled,
|
||||
theater: ExtensionMode.Enabled,
|
||||
normal: ExtensionMode.Enabled
|
||||
},
|
||||
applyToEmbeddedContent: EmbeddedContentSettingsOverridePolicy.Always,
|
||||
type: SiteSupportLevel.CommunitySupport,
|
||||
defaultType: SiteSupportLevel.CommunitySupport,
|
||||
type: 'community',
|
||||
defaultType: 'community',
|
||||
activeDOMConfig: 'community',
|
||||
DOMConfig: {
|
||||
'community': {
|
||||
type: SiteSupportLevel.CommunitySupport,
|
||||
type: 'community',
|
||||
elements: {
|
||||
player: {
|
||||
manual: true,
|
||||
@ -1014,34 +1240,65 @@ const ExtensionConf: SettingsInterface = {
|
||||
},
|
||||
},
|
||||
"app.plex.tv": {
|
||||
enable: ExtensionMode.Theater,
|
||||
enableAard: ExtensionMode.Theater,
|
||||
enableKeyboard: ExtensionMode.Theater,
|
||||
enableUI: ExtensionMode.FullScreen,
|
||||
|
||||
enable: {
|
||||
fullscreen: ExtensionMode.Enabled,
|
||||
theater: ExtensionMode.Enabled,
|
||||
normal: ExtensionMode.Disabled,
|
||||
},
|
||||
enableAard: {
|
||||
fullscreen: ExtensionMode.Enabled,
|
||||
theater: ExtensionMode.Enabled,
|
||||
normal: ExtensionMode.Disabled,
|
||||
},
|
||||
enableKeyboard: {
|
||||
fullscreen: ExtensionMode.Enabled,
|
||||
theater: ExtensionMode.Enabled,
|
||||
normal: ExtensionMode.Disabled
|
||||
},
|
||||
enableUI: {
|
||||
fullscreen: ExtensionMode.Enabled,
|
||||
theater: ExtensionMode.Enabled,
|
||||
normal: ExtensionMode.Disabled
|
||||
},
|
||||
applyToEmbeddedContent: EmbeddedContentSettingsOverridePolicy.Always,
|
||||
type: SiteSupportLevel.CommunitySupport,
|
||||
defaultType: SiteSupportLevel.CommunitySupport,
|
||||
type: 'community',
|
||||
defaultType: 'community',
|
||||
activeDOMConfig: 'community',
|
||||
DOMConfig: {
|
||||
'community': {
|
||||
type: SiteSupportLevel.CommunitySupport,
|
||||
type: 'community',
|
||||
// customCss: "body {\n background-color: #000;\n}\n\n.application {\n background-color: #000;\n}"
|
||||
}
|
||||
}
|
||||
},
|
||||
"metaivi.com": {
|
||||
enable: ExtensionMode.Theater,
|
||||
enableAard: ExtensionMode.Theater,
|
||||
enableKeyboard: ExtensionMode.Theater,
|
||||
enableUI: ExtensionMode.FullScreen,
|
||||
enable: {
|
||||
fullscreen: ExtensionMode.Enabled,
|
||||
theater: ExtensionMode.Enabled,
|
||||
normal: ExtensionMode.Disabled,
|
||||
},
|
||||
enableAard: {
|
||||
fullscreen: ExtensionMode.Enabled,
|
||||
theater: ExtensionMode.Enabled,
|
||||
normal: ExtensionMode.Disabled,
|
||||
},
|
||||
enableKeyboard: {
|
||||
fullscreen: ExtensionMode.Enabled,
|
||||
theater: ExtensionMode.Enabled,
|
||||
normal: ExtensionMode.Disabled
|
||||
},
|
||||
enableUI: {
|
||||
fullscreen: ExtensionMode.Enabled,
|
||||
theater: ExtensionMode.Enabled,
|
||||
normal: ExtensionMode.Disabled
|
||||
},
|
||||
applyToEmbeddedContent: EmbeddedContentSettingsOverridePolicy.Always,
|
||||
type: SiteSupportLevel.CommunitySupport,
|
||||
defaultType: SiteSupportLevel.CommunitySupport,
|
||||
type: "community",
|
||||
defaultType: "community",
|
||||
activeDOMConfig: 'community',
|
||||
DOMConfig: {
|
||||
'community': {
|
||||
type: SiteSupportLevel.CommunitySupport,
|
||||
type: 'community',
|
||||
elements: {
|
||||
video: {
|
||||
nodeCss: {'position': 'absolute !important'}
|
||||
@ -1051,18 +1308,33 @@ const ExtensionConf: SettingsInterface = {
|
||||
},
|
||||
},
|
||||
"piped.kavin.rocks": {
|
||||
enable: ExtensionMode.Theater,
|
||||
enableAard: ExtensionMode.Theater,
|
||||
enableKeyboard: ExtensionMode.Theater,
|
||||
enableUI: ExtensionMode.FullScreen,
|
||||
|
||||
enable: {
|
||||
fullscreen: ExtensionMode.Enabled,
|
||||
theater: ExtensionMode.Enabled,
|
||||
normal: ExtensionMode.Disabled,
|
||||
},
|
||||
enableAard: {
|
||||
fullscreen: ExtensionMode.Enabled,
|
||||
theater: ExtensionMode.Enabled,
|
||||
normal: ExtensionMode.Disabled,
|
||||
},
|
||||
enableKeyboard: {
|
||||
fullscreen: ExtensionMode.Enabled,
|
||||
theater: ExtensionMode.Enabled,
|
||||
normal: ExtensionMode.Disabled
|
||||
},
|
||||
enableUI: {
|
||||
fullscreen: ExtensionMode.Enabled,
|
||||
theater: ExtensionMode.Enabled,
|
||||
normal: ExtensionMode.Disabled
|
||||
},
|
||||
applyToEmbeddedContent: EmbeddedContentSettingsOverridePolicy.Always,
|
||||
type: SiteSupportLevel.CommunitySupport,
|
||||
defaultType: SiteSupportLevel.CommunitySupport,
|
||||
type: "community",
|
||||
defaultType: "community",
|
||||
activeDOMConfig: 'community',
|
||||
DOMConfig: {
|
||||
'community': {
|
||||
type: SiteSupportLevel.CommunitySupport,
|
||||
type: 'community',
|
||||
// customCss: ".shaka-video-container {\n flex-direction: column !important;\n}"
|
||||
}
|
||||
}
|
||||
|
||||
@ -263,7 +263,7 @@ export class Aard {
|
||||
// console.log('--- video data: ---\n', this.videoData);
|
||||
return;
|
||||
}
|
||||
if (this.siteSettings.data.enableAard <= this.videoData.player.environment) {
|
||||
if (this.siteSettings.data.enableAard[this.videoData.player.environment] === ExtensionMode.Enabled) {
|
||||
this.start();
|
||||
} else {
|
||||
this.stop();
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import AspectRatioType from '@src/common/enums/AspectRatioType.enum';
|
||||
import ExtensionMode from '@src/common/enums/ExtensionMode.enum';
|
||||
import { ArVariant } from '@src/common/interfaces/ArInterface';
|
||||
import { ExtensionEnvironment } from '@src/common/interfaces/SettingsInterface';
|
||||
import EventBus from '../EventBus';
|
||||
@ -15,10 +16,15 @@ import { GlDebugCanvas, GlDebugType } from './gl/GlDebugCanvas';
|
||||
import { AardCanvasStore } from './interfaces/aard-canvas-store.interface';
|
||||
import { AardDetectionSample, generateSampleArray, resetSamples } from './interfaces/aard-detection-sample.interface';
|
||||
import { AardStatus, initAardStatus } from './interfaces/aard-status.interface';
|
||||
import { AardTestResult_SubtitleRegion, AardTestResults, resetSubtitleScanResults } from './interfaces/aard-test-results.interface';
|
||||
import { AardTimers, initAardTimers } from './interfaces/aard-timers.interface';
|
||||
import { ComponentLogger } from '../logging/ComponentLogger';
|
||||
import { AardPollingOptions } from './enums/aard-polling-options.enum';
|
||||
import { AardSubtitleCropMode } from './enums/aard-subtitle-crop-mode.enum';
|
||||
import { LetterboxOrientation } from './enums/letterbox-orientation.enum';
|
||||
import { Edge } from './enums/edge.enum';
|
||||
import { AardUncertainReason } from './enums/aard-letterbox-uncertain-reason.enum';
|
||||
import { result } from 'lodash';
|
||||
import { AardLegacyTestResults, initAardTestResults, resetAardTestResults, resetGuardLine } from './interfaces/aard-legacy-test-results.interface';
|
||||
|
||||
|
||||
@ -433,7 +439,7 @@ export class AardLegacy {
|
||||
// console.log('--- video data: ---\n', this.videoData);
|
||||
return;
|
||||
}
|
||||
if (this.videoData.player.environment <= this.siteSettings.data.enableAard) {
|
||||
if (this.siteSettings.data.enableAard[this.videoData.player.environment] === ExtensionMode.Enabled) {
|
||||
this.start();
|
||||
} else {
|
||||
this.stop();
|
||||
|
||||
@ -24,6 +24,10 @@ const BASE_LOGGING_STYLES = {
|
||||
*/
|
||||
export class KeyboardHandler extends KbmBase {
|
||||
listenFor: string[] = ['keyup'];
|
||||
settings: Settings;
|
||||
siteSettings: SiteSettings;
|
||||
eventBus: EventBus;
|
||||
|
||||
playerElements: HTMLElement[] = [];
|
||||
|
||||
|
||||
@ -103,8 +107,8 @@ export class KeyboardHandler extends KbmBase {
|
||||
}
|
||||
}
|
||||
|
||||
setKeyboardLocal(state: ExtensionMode) {
|
||||
if (state === ExtensionMode.All) {
|
||||
setKeyboardLocal(state) {
|
||||
if (state === ExtensionMode.Enabled) {
|
||||
this.keyboardLocalDisabled = false;
|
||||
} else if (state === ExtensionMode.Disabled) {
|
||||
this.keyboardLocalDisabled = true;
|
||||
|
||||
@ -113,6 +113,7 @@ export class LogAggregator {
|
||||
|
||||
private storageChangeListener(changes, area) {
|
||||
if (!changes[STORAGE_LOG_SETTINGS_KEY]) {
|
||||
// console.info('We dont have any logging settings, not processing frther', changes);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -6,10 +6,9 @@ import ExtensionConfPatch from '../../conf/ExtConfPatches';
|
||||
import SettingsInterface from '../../../common/interfaces/SettingsInterface';
|
||||
import AspectRatioType from '../../../common/enums/AspectRatioType.enum';
|
||||
import { GetSiteSettingsOptions, SiteSettings } from './SiteSettings';
|
||||
import { SettingsSnapshot, SettingsSnapshotManager } from './SettingsSnapshotManager';
|
||||
import { SettingsSnapshotManager } from './SettingsSnapshotManager';
|
||||
import { ComponentLogger } from '../logging/ComponentLogger';
|
||||
import { LogAggregator } from '../logging/LogAggregator';
|
||||
import { getDiff } from 'json-difference'
|
||||
|
||||
if(process.env.CHANNEL !== 'stable'){
|
||||
console.info("Loading Settings");
|
||||
@ -96,49 +95,28 @@ class Settings {
|
||||
if (!changes.uwSettings) {
|
||||
return;
|
||||
}
|
||||
console.log('new settings change.')
|
||||
this.logger?.info('storageOnChange', "Settings have been changed outside of here. Updating active settings. Changes:", changes, "storage area:", area);
|
||||
// if (changes['uwSettings'] && changes['uwSettings'].newValue) {
|
||||
// this.logger?.log('info', 'settings',"[Settings::<storage/on change>] new settings object:", JSON.parse(changes.uwSettings.newValue));
|
||||
// }
|
||||
const parsedSettings = JSON.parse(changes.uwSettings.newValue);
|
||||
|
||||
const diff = getDiff(this.active, parsedSettings, {isLodashLike: true});
|
||||
|
||||
const validChangeFn = (x: any) =>
|
||||
x[0] !== 'lastModified';
|
||||
|
||||
const validAdditions = diff.added.filter(validChangeFn);
|
||||
const validEdits = diff.edited.filter(validChangeFn);
|
||||
const validRemovals = diff.removed.filter(validChangeFn).filter(x => x[0] !== 'version');
|
||||
|
||||
this.logger?.info('storageOnChange', "Diff between current and changed settings:", diff, 'valid changes:', {validAdditions, validEdits, validRemovals});
|
||||
|
||||
if (
|
||||
validAdditions.length === 0
|
||||
&& validRemovals.length === 0
|
||||
&& validEdits.length === 0
|
||||
) {
|
||||
this.logger?.warn('storageOnChange', "storageChangeListener fired, but no changes were detected. Sus.\nchanges:", changes, "storage area:", area, 'current:', this.active, 'diff:', diff);
|
||||
return;
|
||||
}
|
||||
|
||||
this.setActive(parsedSettings);
|
||||
|
||||
this.logger?.info('storageOnChange', 'Does parsedSettings.preventReload exist?', parsedSettings.preventReload, "Does callback exist?", !!this.onSettingsChanged);
|
||||
|
||||
if (!parsedSettings.preventReload) {
|
||||
this.active.preventReload = true;
|
||||
try {
|
||||
for (const fn of this.onChangedCallbacks) {
|
||||
try {
|
||||
fn();
|
||||
} catch (e) {
|
||||
this.logger?.warn('storageOnChange', "afterSettingsChanged fallback failed. It's possible that a vue component got destroyed, and this function is nothing more than vestigial remains. It would be nice if we implemented something that allows us to remove callback functions from array, and remove vue callbacks from the callback array when their respective UI component gets destroyed. Or this could be an error with the function itself. IDK, here's the error.", e)
|
||||
this.logger?.warn('storageOnChange', "afterSettingsChanged fallback failed. It's possible that a vue component got destroyed, and this function is nothing more than vestigal remains. It would be nice if we implemented something that allows us to remove callback functions from array, and remove vue callbacks from the callback array when their respective UI component gets destroyed. Or this could be an error with the function itself. IDK, here's the error.", e)
|
||||
}
|
||||
}
|
||||
if (this.onSettingsChanged) {
|
||||
this.onSettingsChanged();
|
||||
}
|
||||
|
||||
this.logger?.info('storageOnChange', 'Update callback finished.')
|
||||
} catch (e) {
|
||||
this.logger?.error('storageOnChange', "CALLING UPDATE CALLBACK FAILED. Reason:", e)
|
||||
@ -148,7 +126,7 @@ class Settings {
|
||||
try {
|
||||
fn();
|
||||
} catch (e) {
|
||||
this.logger?.warn('storageOnChange', "afterSettingsChanged fallback failed. It's possible that a vue component got destroyed, and this function is nothing more than vestigial remains. It would be nice if we implemented something that allows us to remove callback functions from array, and remove vue callbacks from the callback array when their respective UI component gets destroyed. Or this could be an error with the function itself. IDK, here's the error.", e)
|
||||
this.logger?.warn('storageOnChange', "afterSettingsChanged fallback failed. It's possible that a vue component got destroyed, and this function is nothing more than vestigal remains. It would be nice if we implemented something that allows us to remove callback functions from array, and remove vue callbacks from the callback array when their respective UI component gets destroyed. Or this could be an error with the function itself. IDK, here's the error.", e)
|
||||
}
|
||||
}
|
||||
if (this.afterSettingsSaved) {
|
||||
@ -234,7 +212,7 @@ class Settings {
|
||||
private findFirstNecessaryPatch(version) {
|
||||
return ExtensionConfPatch.findIndex(x => this.compareExtensionVersions(x.forVersion, version) > 0);
|
||||
}
|
||||
private applySettingsPatches(currentSettings, oldVersion, options?: {skipSnapshot?: boolean}) {
|
||||
private applySettingsPatches(oldVersion) {
|
||||
let index = this.findFirstNecessaryPatch(oldVersion);
|
||||
|
||||
if (index === -1) {
|
||||
@ -243,30 +221,26 @@ class Settings {
|
||||
}
|
||||
|
||||
// save current settings object
|
||||
if (!options?.skipSnapshot) {
|
||||
this.snapshotManager.createSnapshot(
|
||||
JSON.parse(JSON.stringify(currentSettings)),
|
||||
{
|
||||
label: 'Pre-migration snapshot',
|
||||
isAutomatic: true
|
||||
}
|
||||
);
|
||||
}
|
||||
const currentSettings = this.active;
|
||||
|
||||
this.snapshotManager.createSnapshot(
|
||||
JSON.parse(JSON.stringify(currentSettings)),
|
||||
{
|
||||
label: 'Pre-migration snapshot',
|
||||
isAutomatic: true
|
||||
}
|
||||
);
|
||||
|
||||
// this.active.newFeatureTracker = {};
|
||||
|
||||
|
||||
// apply all remaining patches
|
||||
const pendingPatchesCount = ExtensionConfPatch.length - index;
|
||||
this.logger?.info('applySettingsPatches', `There are ${pendingPatchesCount} settings patches to apply`);
|
||||
const defaultSettings = this.getDefaultSettings();
|
||||
this.logger?.info('applySettingsPatches', `There are ${ExtensionConfPatch.length - index} settings patches to apply`);
|
||||
while (index < ExtensionConfPatch.length) {
|
||||
const updateFn = ExtensionConfPatch[index].updateFn;
|
||||
|
||||
this.logger.info('applySettingsPatches', `Processing patch ${index} / ${ExtensionConfPatch.length}. Patch ${!!updateFn ? 'has' : 'does NOT have'} an update function.`);
|
||||
|
||||
if (updateFn) {
|
||||
try {
|
||||
this.logger.log('applySettingsPatches', `Starting to update patch for version ${ExtensionConfPatch[index].forVersion} (${pendingPatchesCount - (ExtensionConfPatch.length - index)} / ${pendingPatchesCount}) | index: ${index}, patches length: ${ExtensionConfPatch.length}`);
|
||||
updateFn(currentSettings, defaultSettings, this.logger);
|
||||
this.logger.log('applySettingsPatches', `Patch for version ${ExtensionConfPatch[index].forVersion} applied. (${pendingPatchesCount - (ExtensionConfPatch.length - index)} / ${pendingPatchesCount})`);
|
||||
updateFn(this.active, this.getDefaultSettings());
|
||||
} catch (e) {
|
||||
this.logger?.error('applySettingsPatches', 'Failed to execute update function. Keeping settings object as-is. Error:', e);
|
||||
}
|
||||
@ -274,37 +248,30 @@ class Settings {
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
return currentSettings;
|
||||
}
|
||||
|
||||
async init(options?: {dryRun?: boolean, snapshot?: SettingsSnapshot, skipSnapshot?: boolean}) {
|
||||
let settings;
|
||||
async init() {
|
||||
let settings = await this.get();
|
||||
|
||||
if (options?.snapshot) {
|
||||
this.logger?.info('init', 'Snapshot was provided — will load settings from snapshot.', options.snapshot);
|
||||
settings = options.snapshot.settings;
|
||||
} else if (settings?.dev?.loadFromSnapshot) {
|
||||
if (settings?.dev?.loadFromSnapshot) {
|
||||
this.logger?.info('init', 'Dev mode is enabled, Loading settings from snapshot:', settings.dev.loadFromSnapshot);
|
||||
const snapshot = await this.snapshotManager.getSnapshot();
|
||||
if (snapshot) {
|
||||
settings = snapshot.settings;
|
||||
}
|
||||
} else {
|
||||
settings = await this.get();
|
||||
}
|
||||
|
||||
const currentVersion = this.getExtensionVersion();
|
||||
this.version = this.getExtensionVersion();
|
||||
|
||||
// |—> on first setup, settings is undefined & settings.version is haram
|
||||
// | since new installs ship with updates by default, no patching is
|
||||
// | needed. In this case, we assume we're on the current version
|
||||
const oldVersion = settings?.version ?? currentVersion;
|
||||
const oldVersion = settings?.version ?? this.version;
|
||||
|
||||
if (settings) {
|
||||
this.logger?.info('init', "Configuration fetched from storage:", settings,
|
||||
"\nlast saved with:", settings.version,
|
||||
"\ncurrent version:", currentVersion
|
||||
"\ncurrent version:", this.version
|
||||
);
|
||||
}
|
||||
|
||||
@ -317,57 +284,40 @@ class Settings {
|
||||
'\nsettings:',
|
||||
settings
|
||||
);
|
||||
this.active = this.getDefaultSettings();
|
||||
this.active.version = this.version;
|
||||
await this.save();
|
||||
|
||||
settings = this.getDefaultSettings();
|
||||
settings.version = currentVersion;
|
||||
|
||||
if (!options?.dryRun) {
|
||||
this.active = settings;
|
||||
this.version = currentVersion;
|
||||
await this.save();
|
||||
}
|
||||
|
||||
return settings;
|
||||
return this.active;
|
||||
}
|
||||
|
||||
// if there's settings, set saved object as active settings
|
||||
this.active = settings;
|
||||
|
||||
// if version number is undefined, we make it defined
|
||||
// this should only happen on first extension initialization
|
||||
if (!settings.version) {
|
||||
settings.version = currentVersion;
|
||||
|
||||
if (!options?.dryRun) {
|
||||
this.active = settings;
|
||||
this.version = currentVersion;
|
||||
await this.save();
|
||||
}
|
||||
return settings;
|
||||
if (!this.active.version) {
|
||||
this.active.version = this.version;
|
||||
await this.save();
|
||||
return this.active;
|
||||
}
|
||||
|
||||
// check if extension has been updated. If not, return settings as they were retrieved
|
||||
if (settings.version === currentVersion) {
|
||||
if (this.active.version === this.version) {
|
||||
this.logger?.info('init', "extension was saved with current version of ultrawidify. Returning object as-is.");
|
||||
if (!options?.dryRun) {
|
||||
this.active = settings;
|
||||
}
|
||||
return settings;
|
||||
return this.active;
|
||||
}
|
||||
|
||||
// in case settings in previous version contained a fucky wucky, we overwrite existing settings with a patch
|
||||
settings = this.applySettingsPatches(settings, oldVersion, {skipSnapshot: options?.dryRun || options?.skipSnapshot});
|
||||
this.applySettingsPatches(oldVersion);
|
||||
|
||||
// set 'whatsNewChecked' flag to false when updating, always
|
||||
settings.whatsNewChecked = false;
|
||||
this.active.whatsNewChecked = false;
|
||||
// update settings version to current
|
||||
settings.version = currentVersion;
|
||||
this.active.version = this.version;
|
||||
|
||||
if (!options?.dryRun) {
|
||||
this.active = settings;
|
||||
this.version = currentVersion;
|
||||
await this.save();
|
||||
}
|
||||
return settings;
|
||||
await this.save();
|
||||
return this.active;
|
||||
}
|
||||
|
||||
async get(): Promise<SettingsInterface | undefined> {
|
||||
@ -487,11 +437,6 @@ class Settings {
|
||||
removeAfterChangeListener(fn: () => void): void {
|
||||
this.afterSettingsChangedCallbacks = this.afterSettingsChangedCallbacks.filter(x => x !== fn);
|
||||
}
|
||||
|
||||
async testMigration(snapshot: SettingsSnapshot) {
|
||||
const afterMigrationSettings = await this.init({dryRun: true, snapshot});
|
||||
this.logger.log('testMigration', 'Settings migrated. Settings model after initialization:', afterMigrationSettings);
|
||||
}
|
||||
}
|
||||
|
||||
export default Settings;
|
||||
|
||||
@ -1,12 +1,11 @@
|
||||
import CropModePersistence from '../../../common/enums/CropModePersistence.enum';
|
||||
import ExtensionMode from '../../../common/enums/ExtensionMode.enum';
|
||||
import { ExtensionEnvironment, SettingsReloadComponent, SettingsReloadFlags, SiteSettingsInterface } from '../../../common/interfaces/SettingsInterface';
|
||||
import { SettingsReloadComponent, SettingsReloadFlags, SiteSettingsInterface } from '../../../common/interfaces/SettingsInterface';
|
||||
import { _cp } from '../../../common/js/utils';
|
||||
import Settings from './Settings';
|
||||
import StretchType from '../../../common/enums/StretchType.enum';
|
||||
import VideoAlignmentType from '../../../common/enums/VideoAlignmentType.enum';
|
||||
import EmbeddedContentSettingsOverridePolicy from '../../../common/enums/EmbeddedContentSettingsOverridePolicy.enum';
|
||||
import { SiteSupportLevel } from '../../../common/enums/SiteSupportLevel.enum';
|
||||
|
||||
|
||||
export interface GetSiteSettingsOptions {
|
||||
@ -183,8 +182,6 @@ export class SiteSettings {
|
||||
*/
|
||||
private compileSettingsObject() {
|
||||
const {siteSettings, usesSettingsFor} = this.getSettingsForSite(this.options);
|
||||
console.log('got settings for site:', siteSettings, usesSettingsFor)
|
||||
|
||||
this.data = _cp(siteSettings);
|
||||
this.usesSettingsFor = usesSettingsFor;
|
||||
|
||||
@ -216,10 +213,13 @@ export class SiteSettings {
|
||||
}
|
||||
|
||||
for (const enableSegment of ['enable', 'enableAard', 'enableKeyboard', 'enableUI']) {
|
||||
if (this.data[enableSegment] === undefined) {
|
||||
if (!this.data[enableSegment]) {
|
||||
this.data[enableSegment] = {};
|
||||
} else if (this.data[enableSegment] === ExtensionMode.Default) {
|
||||
this.data[enableSegment] = this.defaultSettings[enableSegment];
|
||||
}
|
||||
for (const environment of ['normal', 'theater', 'fullscreen']) {
|
||||
if (!this.data[enableSegment][environment] || this.data[enableSegment][environment] === ExtensionMode.Default) {
|
||||
this.data[enableSegment][environment] = _cp(this.defaultSettings[enableSegment][environment]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -339,14 +339,14 @@ export class SiteSettings {
|
||||
}
|
||||
}
|
||||
|
||||
private _getEnvironment(isTheater: boolean, isFullscreen: boolean): ExtensionEnvironment {
|
||||
private _getEnvironment(isTheater: boolean, isFullscreen: boolean): 'fullscreen' | 'theater' | 'normal' {
|
||||
if (isFullscreen) {
|
||||
return ExtensionEnvironment.Fullscreen;
|
||||
return 'fullscreen';
|
||||
}
|
||||
if (isTheater) {
|
||||
return ExtensionEnvironment.Theater;
|
||||
return 'theater';
|
||||
}
|
||||
return ExtensionEnvironment.Normal;
|
||||
return 'normal';
|
||||
}
|
||||
|
||||
/**
|
||||
@ -355,9 +355,9 @@ export class SiteSettings {
|
||||
* @param isFullscreen
|
||||
* @returns ExtensionMode
|
||||
*/
|
||||
isEnabledForEnvironment(isTheater: boolean, isFullscreen: boolean): boolean {
|
||||
isEnabledForEnvironment(isTheater: boolean, isFullscreen: boolean): ExtensionMode {
|
||||
const env = this._getEnvironment(isTheater, isFullscreen);
|
||||
return env <= this.data.enable;
|
||||
return this.data.enable[env];
|
||||
}
|
||||
|
||||
/**
|
||||
@ -366,9 +366,9 @@ export class SiteSettings {
|
||||
* @param isFullscreen
|
||||
* @returns
|
||||
*/
|
||||
isAardEnabledForEnvironment(isTheater: boolean, isFullscreen: boolean): boolean {
|
||||
isAardEnabledForEnvironment(isTheater: boolean, isFullscreen: boolean): ExtensionMode {
|
||||
const env = this._getEnvironment(isTheater, isFullscreen);
|
||||
return env <= this.data.enableAard;
|
||||
return this.data.enableAard[env];
|
||||
}
|
||||
|
||||
/**
|
||||
@ -377,9 +377,9 @@ export class SiteSettings {
|
||||
* @param isFullscreen
|
||||
* @returns
|
||||
*/
|
||||
isKeyboardEnabledForEnvironment(isTheater: boolean, isFullscreen: boolean): boolean {
|
||||
isKeyboardEnabledForEnvironment(isTheater: boolean, isFullscreen: boolean): ExtensionMode {
|
||||
const env = this._getEnvironment(isTheater, isFullscreen);
|
||||
return env <= this.data.enableKeyboard;
|
||||
return this.data.enableKeyboard[env];
|
||||
}
|
||||
|
||||
//#endregion
|
||||
@ -461,11 +461,11 @@ export class SiteSettings {
|
||||
if (options.scripted && !this.settings.active.sites[targetSite]) {
|
||||
this.settings.active.sites[targetSite] = _cp(this.settings.active.sites['@global']);
|
||||
this.settings.active.sites[targetSite].autocreated = true;
|
||||
this.settings.active.sites[targetSite].type = SiteSupportLevel.Unknown;
|
||||
this.settings.active.sites[targetSite].type = 'unknown';
|
||||
} else {
|
||||
if (!this.settings.active.sites[targetSite] || this.settings.active.sites[targetSite].autocreated) {
|
||||
this.settings.active.sites[targetSite] = _cp(this.data);
|
||||
this.settings.active.sites[targetSite].type = SiteSupportLevel.UserDefined;
|
||||
this.settings.active.sites[targetSite].type = 'user-defined';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -41,7 +41,7 @@ class UI {
|
||||
// TODO: at some point, UI should be different for global popup and in-player UI
|
||||
this.csuiScheme = this.getCsuiScheme();
|
||||
const csuiVersion = this.getCsuiVersion(this.csuiScheme.contentScheme);
|
||||
// this.uiURI = chrome.runtime.getURL(`/csui/${csuiVersion}.html`);
|
||||
this.uiURI = chrome.runtime.getURL(`/csui/${csuiVersion}.html`);
|
||||
this.extensionBase = chrome.runtime.getURL('').replace(/\/$/, "");
|
||||
|
||||
// UI will be initialized when setUiVisibility is called
|
||||
@ -53,13 +53,17 @@ class UI {
|
||||
return true;
|
||||
}
|
||||
|
||||
return this.siteSettings?.data.enableUI !== ExtensionMode.Disabled;
|
||||
return this.siteSettings?.data.enableUI.fullscreen === ExtensionMode.Enabled
|
||||
|| this.siteSettings?.data.enableUI.theater === ExtensionMode.Enabled
|
||||
|| this.siteSettings?.data.enableUI.normal === ExtensionMode.Enabled;
|
||||
}
|
||||
|
||||
async init() {
|
||||
if (!this.canRun()) {
|
||||
// console.log('ui config: canRun returned false', this.siteSettings?.data.enableUI.fullscreen === ExtensionMode.Enabled, this.siteSettings?.data.enableUI.theater === ExtensionMode.Enabled, this.siteSettings?.data.enableUI.normal === ExtensionMode.Enabled)
|
||||
return;
|
||||
}
|
||||
// console.log('ui config: canRun returned truie', this.siteSettings?.data.enableUI.fullscreen === ExtensionMode.Enabled, this.siteSettings?.data.enableUI.theater === ExtensionMode.Enabled, this.siteSettings?.data.enableUI.normal === ExtensionMode.Enabled)
|
||||
|
||||
|
||||
this.initUIContainer();
|
||||
@ -119,7 +123,6 @@ class UI {
|
||||
}
|
||||
|
||||
loadIframe() {
|
||||
return;
|
||||
// in onMouseMove, we currently can't access this because we didn't
|
||||
// do things the most properly
|
||||
const uiURI = this.uiURI;
|
||||
@ -339,7 +342,7 @@ class UI {
|
||||
canShowUI: false,
|
||||
}
|
||||
|
||||
if (this.playerData?.environment && this.playerData?.environment <= this.siteSettings.data.enableUI) {
|
||||
if (this.playerData?.environment && this.siteSettings.data.enableUI[this.playerData?.environment] !== ExtensionMode.Enabled) {
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -474,7 +477,7 @@ class UI {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends message to iframe. Messages sent with this function will be routed to eventBus.
|
||||
* Sends message to iframe. Messages sent with this function will be routed to eventbus.
|
||||
*/
|
||||
sendToIframe(action, actionConfig, routingData, uiURI = this.uiURI) {
|
||||
// if (routingData) {
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import ExtensionMode from '../../../common/enums/ExtensionMode.enum';
|
||||
import EventBus from '../EventBus';
|
||||
import { SiteSettings } from '../settings/SiteSettings';
|
||||
|
||||
@ -18,9 +19,9 @@ export class ExtensionStatus {
|
||||
return this.fsStatus.fullscreen;
|
||||
}
|
||||
|
||||
private enabled: boolean;
|
||||
private aardEnabled: boolean;
|
||||
private kbdEnabled: boolean;
|
||||
private enabled: ExtensionMode;
|
||||
private aardEnabled: ExtensionMode;
|
||||
private kbdEnabled: ExtensionMode;
|
||||
|
||||
constructor(siteSettings: SiteSettings, eventBus: EventBus, fsStatus: {fullscreen: boolean}){
|
||||
this.siteSettings = siteSettings;
|
||||
@ -32,20 +33,26 @@ export class ExtensionStatus {
|
||||
const canAard = this.siteSettings.isAardEnabledForEnvironment(this.isTheaterMode, this.isFullScreen);
|
||||
const canKbd = this.siteSettings.isKeyboardEnabledForEnvironment(this.isTheaterMode, this.isFullScreen);
|
||||
|
||||
if (canRun) {
|
||||
this.eventBus.send('set-extension-active', {});
|
||||
} else {
|
||||
this.eventBus.send('set-extension-inactive', {});
|
||||
if (canRun !== this.enabled) {
|
||||
if (canRun === ExtensionMode.Enabled) {
|
||||
this.eventBus.send('set-extension-active', {});
|
||||
} else {
|
||||
this.eventBus.send('set-extension-inactive', {});
|
||||
}
|
||||
}
|
||||
if (canAard) {
|
||||
this.eventBus.send('set-aard-active', {});
|
||||
} else {
|
||||
this.eventBus.send('set-aard-inactive', {});
|
||||
if (canAard !== this.aardEnabled) {
|
||||
if (canAard === ExtensionMode.Enabled) {
|
||||
this.eventBus.send('set-aard-active', {});
|
||||
} else {
|
||||
this.eventBus.send('set-aard-inactive', {});
|
||||
}
|
||||
}
|
||||
if (canKbd) {
|
||||
this.eventBus.send('set-kbd-active', {});
|
||||
} else {
|
||||
this.eventBus.send('set-kbd-inactive', {});
|
||||
if (canKbd !== this.kbdEnabled) {
|
||||
if (canKbd === ExtensionMode.Enabled) {
|
||||
this.eventBus.send('set-kbd-active', {});
|
||||
} else {
|
||||
this.eventBus.send('set-kbd-inactive', {});
|
||||
}
|
||||
}
|
||||
|
||||
this.enabled = canRun;
|
||||
|
||||
@ -269,14 +269,14 @@ class PlayerData {
|
||||
* @returns
|
||||
*/
|
||||
deferredUiInitialization(playerDimensions = this.dimensions) {
|
||||
if (this.ui || this.siteSettings.data.enableUI === ExtensionMode.Disabled) {
|
||||
if (this.ui || this.siteSettings.data.enableUI.fullscreen === ExtensionMode.Disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
this.isFullscreen
|
||||
|| (
|
||||
this.siteSettings.data.enableUI >= ExtensionMode.FullScreen
|
||||
this.siteSettings.data.enableUI.theater !== ExtensionMode.Disabled
|
||||
&& playerDimensions.width > 1208
|
||||
&& playerDimensions.height > 720
|
||||
)
|
||||
@ -478,7 +478,7 @@ class PlayerData {
|
||||
this.isTooSmall = this.checkIfTooSmall();
|
||||
}
|
||||
|
||||
const canEnable = this.siteSettings.isEnabledForEnvironment(this.isFullscreen, this.isTheaterMode);
|
||||
const canEnable = this.siteSettings.isEnabledForEnvironment(this.isFullscreen, this.isTheaterMode) === ExtensionMode.Enabled;
|
||||
|
||||
if (this.runLevel === RunLevel.Off && canEnable) {
|
||||
this.eventBus.send('restore-ar', null);
|
||||
|
||||
@ -408,7 +408,7 @@ class VideoData {
|
||||
this.logger.warn('onEnvironmentChanged', 'environment changed from:', this.currentEnvironment, 'to:', this.player.environment);
|
||||
|
||||
this.currentEnvironment = this.player.environment;
|
||||
if (this.player.environment <= this.siteSettings.data.enable) {
|
||||
if (this.siteSettings.data.enable[this.player.environment] === ExtensionMode.Disabled) {
|
||||
this.setRunLevel(RunLevel.Off);
|
||||
} else {
|
||||
this.restoreAr();
|
||||
@ -417,7 +417,7 @@ class VideoData {
|
||||
}
|
||||
|
||||
setRunLevel(runLevel: RunLevel, options?: {fromPlayer?: boolean}) {
|
||||
if (this.player && this.siteSettings.data.enable >= this.player.environment) {
|
||||
if (this.player && this.siteSettings.data.enable[this.player.environment] !== ExtensionMode.Enabled) {
|
||||
runLevel = RunLevel.Off;
|
||||
}
|
||||
|
||||
|
||||
24
src/main.css
24
src/main.css
@ -1,11 +1,27 @@
|
||||
@import "tailwindcss";
|
||||
@import "tailwindcss/utilities";
|
||||
|
||||
@import '@ui/res/styles/theme.css';
|
||||
@import '@ui/res/styles/forms.css';
|
||||
@import '@ui/res/styles/fonts.css';
|
||||
@import '@ui/res/styles/buttons.css';
|
||||
@theme {
|
||||
--breakpoint-popup: 640px;
|
||||
--breakpoint-window: 960px;
|
||||
|
||||
--color-primary: #ff872c;
|
||||
--color-primary-50: #ffddbe;
|
||||
--color-primary-100: #ffcda0;
|
||||
--color-primary-200: #ffbd83;
|
||||
--color-primary-300: #ffac66;
|
||||
--color-primary-400: #ff9a4a;
|
||||
--color-primary-500: #ff872c;
|
||||
--color-primary-600: #de7622;
|
||||
--color-primary-700: #be6518;
|
||||
--color-primary-800: #9f540e;
|
||||
--color-primary-900: #824406;
|
||||
--color-primary-950: #663400;
|
||||
}
|
||||
|
||||
@import './ui/res/styles/forms.css';
|
||||
@import './ui/res/styles/fonts.css';
|
||||
@import './ui/res/styles/buttons.css';
|
||||
|
||||
html, body {
|
||||
@apply bg-stone-950 text-stone-300;
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
"manifest_version": 3,
|
||||
"name": "Ultrawidify",
|
||||
"description": "Removes black bars on ultrawide videos and offers advanced options to fix aspect ratio.",
|
||||
"version": "6.3.994",
|
||||
"version": "6.3.993",
|
||||
"icons": {
|
||||
"32":"res/icons/uw-32.png",
|
||||
"64":"res/icons/uw-64.png"
|
||||
@ -19,8 +19,7 @@
|
||||
"common/lib/browser-polyfill.js",
|
||||
"ext/uw.js"
|
||||
],
|
||||
"all_frames": true,
|
||||
"type": "module"
|
||||
"all_frames": true
|
||||
}],
|
||||
|
||||
"minimum_chrome_version": "93",
|
||||
|
||||
@ -232,8 +232,8 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import BrowserDetect from '@src/ext/conf/BrowserDetect';
|
||||
import JsonEditor from '@components/common/JsonEditor.vue';
|
||||
import BrowserDetect from '../../../ext/conf/BrowserDetect';
|
||||
import JsonEditor from '@csui/src/components/JsonEditor';
|
||||
import {AardPollingOptions} from '@src/ext/lib/aard/enums/aard-polling-options.enum';
|
||||
import {AardSubtitleCropMode} from '@src/ext/lib/aard/enums/aard-subtitle-crop-mode.enum';
|
||||
import { defineComponent } from 'vue';
|
||||
103
src/ui/components/Debugging/Debugging.vue
Normal file
103
src/ui/components/Debugging/Debugging.vue
Normal file
@ -0,0 +1,103 @@
|
||||
<template>
|
||||
<div>
|
||||
|
||||
<div>
|
||||
<h1>{{loggerPanel.title}}<small><br/>{{loggerPanel.subtitle}}</small></h1>
|
||||
|
||||
<div>Logger configuration:</div>
|
||||
|
||||
<JsonEditor
|
||||
v-model="lastSettings"
|
||||
></JsonEditor>
|
||||
|
||||
<div class="flex flex-row flex-end">
|
||||
<div class="button" @click="getLoggerSettings()">
|
||||
Revert
|
||||
</div>
|
||||
<div class="button button-primary" @click="saveLoggerSettings()">
|
||||
Save
|
||||
</div>
|
||||
<div class="button button-primary" @click="startLogging()">
|
||||
Save and start logging
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { LogAggregator, BLANK_LOGGER_CONFIG } from '@src/ext/lib/logging/LogAggregator';
|
||||
import JsonEditor from '@csui/src/components/JsonEditor';
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
JsonEditor
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loggerPanelRotation: [{
|
||||
title: 'DEFORESTATOR 5000',
|
||||
subtitle: 'Iron Legion\'s finest logging tool'
|
||||
},{
|
||||
title: 'Astinus',
|
||||
subtitle: 'Ultrawidify logging tool'
|
||||
}, {
|
||||
title: 'Tracer',
|
||||
subtitle: "Maybe I'll be Tracer — I'm already printing stack traces."
|
||||
}, {
|
||||
title: 'Grûmsh',
|
||||
subtitle: "He who watches (all the things printed to the console)."
|
||||
}, {
|
||||
title: 'Situation Room/The Council',
|
||||
subtitle: 'We will always be watching.'
|
||||
}, {
|
||||
title: 'Isengard Land Management Services',
|
||||
subtitle: "#log4saruman"
|
||||
}, {
|
||||
title: 'Saw Hero',
|
||||
subtitle: 'Ultrawidify logging tool'
|
||||
}],
|
||||
|
||||
loggerPanel: {
|
||||
title: 'whoopsie daisy',
|
||||
subtitle: 'you broke the header choosing script',
|
||||
pasteConfMode: false,
|
||||
},
|
||||
lastSettings: undefined,
|
||||
parsedSettings: undefined,
|
||||
currentSettings: undefined
|
||||
};
|
||||
},
|
||||
props: [
|
||||
'settings',
|
||||
'eventBus',
|
||||
],
|
||||
created() {
|
||||
this.loggerPanel = {
|
||||
...this.loggerPanelRotation[Math.floor(Math.random() * this.loggerPanelRotation.length)],
|
||||
pasteConfMode: false,
|
||||
};
|
||||
this.getLoggerSettings();
|
||||
},
|
||||
methods: {
|
||||
loadDefaultConfig() {
|
||||
this.lastSettings = JSON.parse(JSON.stringify(BLANK_LOGGER_CONFIG));
|
||||
},
|
||||
async getLoggerSettings() {
|
||||
this.lastSettings = await LogAggregator.getConfig() || BLANK_LOGGER_CONFIG;
|
||||
},
|
||||
async saveLoggerSettings() {
|
||||
console.log('Saving logger settings', this.lastSettings);
|
||||
await LogAggregator.saveConfig({...this.lastSettings});
|
||||
console.log('[ok] logger settings saved');
|
||||
},
|
||||
async startLogging(){
|
||||
this.logStringified = undefined;
|
||||
await LogAggregator.saveConfig({...this.lastSettings});
|
||||
window.location.reload();
|
||||
},
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@ -2,27 +2,19 @@
|
||||
<p class="mb-4">Full changelog for older versions <a href="https://github.com/tamius-han/ultrawidify/blob/master/CHANGELOG.md" target="_blank">is available here</a>.</p>
|
||||
|
||||
<p>Changes in version <b class="font-semibold text-primary-400">6.4.0</b>:</p>
|
||||
|
||||
<b class="text-white">Potentially breaking:</b>
|
||||
<ul>
|
||||
<li>De-spaghettified the part of the settings that controls whether extension runs on a given site or not.</li>
|
||||
</ul>
|
||||
|
||||
<b class="text-white">Autodetection:</b>
|
||||
<ul>
|
||||
<li>In-player UI can now appear in full-screen for websites that put players into top layer (allegedly).</li>
|
||||
<li>Embedded sites now inherit settings of the parent frame. <small>However, this hasn't been tested for all edge cases and may contain bugs.</small></li>
|
||||
<li>Added validation to custom aspect ratio entry menu. Corrected parsing of aspect ratios given in the X:Y format, even though aspect ratios should be ideally given as a single number.</li>
|
||||
<li>Autodetection can be set to stop after first aspect ratio detection, or after a period of no changes.</li>
|
||||
<li>
|
||||
There is a new, experimental mode for autodetection. At this point, it can be manually enabled in the autodetection settings. It will become the default option in 2026.<br/>
|
||||
There is a new, experiental mode for autodetection. At this point, it can be manually enabled in the autodetection settings. It will become the default option in 2026.<br/>
|
||||
If you enable experimental mode, please consider reporting problems <a href="https://github.com/tamius-han/ultrawidify/issues/291" target="_blank">in this thread</a> on Github.
|
||||
</li>
|
||||
<li>
|
||||
Experimental autodetection can now detect hardcoded subtitles. You may change how extension handles subtitles in the settings.
|
||||
Autodetection can now detect hardcoded subtitles. You may change how extension handles subtitles in the settings.
|
||||
Use of new experimental autodetection is required for subtitle handling options to work.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<b class="text-white">UI</b>
|
||||
<ul>
|
||||
<li>In-player UI can now appear in full-screen for websites that put players into top layer (allegedly).</li>
|
||||
<li>
|
||||
Keyboard shortcut settings have been split from UI settings, and are now presented in list form on the settings page.
|
||||
</li>
|
||||
@ -31,12 +23,6 @@
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<b class="text-white">Other updates and fixes:</b>
|
||||
<ul>
|
||||
<li>Embedded sites now inherit settings of the parent frame. <small>However, this hasn't been tested for all edge cases and may contain bugs.</small></li>
|
||||
<li>Added validation to custom aspect ratio entry menu. Corrected parsing of aspect ratios given in the X:Y format, even though aspect ratios should be ideally given as a single number.</li>
|
||||
</ul>
|
||||
|
||||
</template>
|
||||
<script>
|
||||
import BrowserDetect from '@src/ext/conf/BrowserDetect';
|
||||
@ -153,9 +153,9 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SiteExtensionSettings from '@components/segments/ExtensionSettings/Panels/SiteExtensionSettings.vue';
|
||||
import FrameSiteSettings from '@components/segments/ExtensionSettings/Panels/FrameSiteSettings.vue';
|
||||
import OtherSiteSettings from '@components/segments/ExtensionSettings/Panels/OtherSiteSettings.vue';
|
||||
import SiteExtensionSettings from '@components/ExtensionSettings/Panels/SiteExtensionSettings.vue';
|
||||
import FrameSiteSettings from '@components/ExtensionSettings/Panels/FrameSiteSettings.vue';
|
||||
import OtherSiteSettings from '@components/ExtensionSettings/Panels/OtherSiteSettings.vue';
|
||||
import Popup from '@csui/src/components/Popup';
|
||||
import ConfirmButton from '@csui/src/components/ConfirmButton';
|
||||
import UploadJsonFileButton from '@csui/src/components/UploadJsonFileButton';
|
||||
@ -12,31 +12,31 @@
|
||||
@click="setExtensionMode('enable', $event)"
|
||||
>
|
||||
<option
|
||||
v-if="simpleExtensionSettings.enable === 'invalid'"
|
||||
:value="undefined"
|
||||
v-if="simpleExtensionSettings.enable === 'complex'"
|
||||
value="complex"
|
||||
>
|
||||
(Site uses advanced settings)
|
||||
</option>
|
||||
<template v-if="isDefaultConfiguration">
|
||||
<option :value="ExtensionMode.Disabled">
|
||||
<option value="disabled">
|
||||
Disabled by default
|
||||
</option>
|
||||
</template>
|
||||
<template v-else>
|
||||
<option :value="ExtensionMode.Default">
|
||||
<option value="default">
|
||||
Use default ({{simpleDefaultSettings.enable}})
|
||||
</option>
|
||||
<option :value="ExtensionMode.Disabled">
|
||||
<option value="disabled">
|
||||
Never
|
||||
</option>
|
||||
</template>
|
||||
<option :value="ExtensionMode.FullScreen">
|
||||
<option value="fs">
|
||||
Fullscreen only
|
||||
</option>
|
||||
<option :value="ExtensionMode.Theater">
|
||||
<option value="theater">
|
||||
Fullscreen and theater mode
|
||||
</option>
|
||||
<option :value="ExtensionMode.All">
|
||||
<option value="enabled">
|
||||
Always
|
||||
</option>
|
||||
</select>
|
||||
@ -63,25 +63,25 @@
|
||||
(Site uses advanced settings)
|
||||
</option>
|
||||
<template v-if="isDefaultConfiguration">
|
||||
<option :value="ExtensionMode.Disabled">
|
||||
<option value="disabled">
|
||||
Disabled by default
|
||||
</option>
|
||||
</template>
|
||||
<template v-else>
|
||||
<option :value="ExtensionMode.Default">
|
||||
<option value="default">
|
||||
Use default ({{simpleDefaultSettings.enableAard}})
|
||||
</option>
|
||||
<option :value="ExtensionMode.Disabled">
|
||||
<option value="disabled">
|
||||
Never
|
||||
</option>
|
||||
</template>
|
||||
<option :value="ExtensionMode.FullScreen">
|
||||
<option value="fs">
|
||||
Fullscreen only
|
||||
</option>
|
||||
<option :value="ExtensionMode.Theater">
|
||||
<option value="theater">
|
||||
Fullscreen and theater mode
|
||||
</option>
|
||||
<option :value="ExtensionMode.All">
|
||||
<option value="enabled">
|
||||
Always
|
||||
</option>
|
||||
</select>
|
||||
@ -106,25 +106,25 @@
|
||||
(Site uses advanced settings)
|
||||
</option>
|
||||
<template v-if="isDefaultConfiguration">
|
||||
<option :value="ExtensionMode.Disabled">
|
||||
<option value="disabled">
|
||||
Disabled by default
|
||||
</option>
|
||||
</template>
|
||||
<template v-else>
|
||||
<option :value="ExtensionMode.Default">
|
||||
<option value="default">
|
||||
Use default ({{simpleDefaultSettings.enableKeyboard}})
|
||||
</option>
|
||||
<option :value="ExtensionMode.Disabled">
|
||||
<option value="disabled">
|
||||
Never
|
||||
</option>
|
||||
</template>
|
||||
<option :value="ExtensionMode.FullScreen">
|
||||
<option value="fs">
|
||||
Fullscreen only
|
||||
</option>
|
||||
<option :value="ExtensionMode.Theater">
|
||||
<option value="theater">
|
||||
Fullscreen and theater mode
|
||||
</option>
|
||||
<option :value="ExtensionMode.All">
|
||||
<option value="enabled">
|
||||
Always
|
||||
</option>
|
||||
</select>
|
||||
@ -143,26 +143,23 @@
|
||||
@click="setExtensionMode('enableUI', $event)"
|
||||
>
|
||||
<template v-if="isDefaultConfiguration">
|
||||
<option :value="ExtensionMode.Disabled">
|
||||
<option value="disabled">
|
||||
Disabled by default
|
||||
</option>
|
||||
</template>
|
||||
<template v-else>
|
||||
<option :value="ExtensionMode.Default">
|
||||
<option value="default">
|
||||
Use default ({{simpleDefaultSettings.enableUI}})
|
||||
</option>
|
||||
<option :value="ExtensionMode.Disabled">
|
||||
<option value="disabled">
|
||||
Never
|
||||
</option>
|
||||
</template>
|
||||
<option :value="ExtensionMode.FullScreen">
|
||||
<option value="fs">
|
||||
Fullscreen only
|
||||
</option>
|
||||
<option :value="ExtensionMode.Theater">
|
||||
Fullscreen and theater
|
||||
</option>
|
||||
<option :value="ExtensionMode.Theater">
|
||||
Where possible
|
||||
<option value="theater">
|
||||
Always where possible
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
@ -299,7 +296,7 @@
|
||||
v-if="!isDefaultConfiguration"
|
||||
:value="CropModePersistence.Default"
|
||||
>
|
||||
Use default ({{defaultPersistenceLabel}})
|
||||
Use default ({{defaultPersistanceLabel}})
|
||||
</option>
|
||||
<option :value="CropModePersistence.Disabled">Disabled</option>
|
||||
<option :value="CropModePersistence.UntilPageReload">Until page reload</option>
|
||||
@ -309,14 +306,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<pre>
|
||||
SITE SETTINGS: raw
|
||||
{{JSON.stringify(siteSettings.raw)}}
|
||||
|
||||
SITE SETTINGS: data
|
||||
{{JSON.stringify(siteSettings.data)}}
|
||||
</pre>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -401,7 +390,7 @@ export default defineComponent({
|
||||
siteDefaultCropPersistence() {
|
||||
return this.siteSettings.raw?.persistCSA ?? undefined;
|
||||
},
|
||||
defaultPersistenceLabel() {
|
||||
defaultPersistanceLabel() {
|
||||
switch (this.siteSettings.defaultSettings.persistCSA) {
|
||||
case CropModePersistence.CurrentSession:
|
||||
return 'current session';
|
||||
@ -423,7 +412,7 @@ export default defineComponent({
|
||||
/**
|
||||
* Compiles our extension settings into more user-friendly options
|
||||
*/
|
||||
compileSimpleSettings(component, getFor = 'site'): ExtensionMode {
|
||||
compileSimpleSettings(component, getFor = 'site') {
|
||||
|
||||
let settingsData;
|
||||
switch (getFor) {
|
||||
@ -438,27 +427,86 @@ export default defineComponent({
|
||||
break;
|
||||
}
|
||||
|
||||
console.log('compiling simple settings;', settingsData, 'original settings:', this.siteSettings)
|
||||
|
||||
return settingsData?.[component];
|
||||
try {
|
||||
if (
|
||||
( settingsData?.[component]?.normal === ExtensionMode.Disabled || component === 'enableUI')
|
||||
&& settingsData?.[component]?.theater === ExtensionMode.Disabled
|
||||
&& settingsData?.[component]?.fullscreen === ExtensionMode.Disabled
|
||||
) {
|
||||
return 'disabled';
|
||||
}
|
||||
if (
|
||||
( settingsData?.[component]?.normal === ExtensionMode.Default || component === 'enableUI')
|
||||
&& settingsData?.[component]?.theater === ExtensionMode.Default
|
||||
&& settingsData?.[component]?.fullscreen === ExtensionMode.Default
|
||||
) {
|
||||
// console.log(
|
||||
// component, 'is set to default because:\n',
|
||||
// `\nsettingsData[${component}].normal: ${settingsData?.[component]?.normal} || component is enableUI?`, component,
|
||||
// `\nsettingsData[${component}].theater: ${settingsData?.[component]?.normal}`,
|
||||
// `\nsettingsData[${component}].fullscreen: ${settingsData?.[component]?.normal}`,
|
||||
|
||||
// `\n\n(expected values:`, ExtensionMode.Default
|
||||
// )
|
||||
return 'default';
|
||||
}
|
||||
if (
|
||||
( settingsData?.[component]?.normal === ExtensionMode.Disabled || component === 'enableUI')
|
||||
&& settingsData?.[component]?.theater === ExtensionMode.Disabled
|
||||
&& settingsData?.[component]?.fullscreen === ExtensionMode.Enabled
|
||||
) {
|
||||
return 'fs';
|
||||
}
|
||||
if (
|
||||
( settingsData?.[component]?.normal === ExtensionMode.Disabled || component === 'enableUI')
|
||||
&& settingsData?.[component]?.theater === ExtensionMode.Enabled
|
||||
&& settingsData?.[component]?.fullscreen === ExtensionMode.Enabled
|
||||
) {
|
||||
return 'theater';
|
||||
}
|
||||
if (
|
||||
( settingsData?.[component]?.normal === ExtensionMode.Enabled || component === 'enableUI')
|
||||
&& settingsData?.[component]?.theater === ExtensionMode.Enabled
|
||||
&& settingsData?.[component]?.fullscreen === ExtensionMode.Enabled
|
||||
) {
|
||||
return 'enabled';
|
||||
}
|
||||
|
||||
return 'complex';
|
||||
} catch (e) {
|
||||
return 'loading';
|
||||
}
|
||||
},
|
||||
|
||||
getDefaultOptionLabel(component) {
|
||||
const componentValue: ExtensionMode = this.compileSimpleSettings(component, 'default');
|
||||
const componentValue = this.compileSimpleSettings(component, 'default');
|
||||
|
||||
if (componentValue === 'loading') {
|
||||
return componentValue;
|
||||
}
|
||||
if (component === 'enableUI') {
|
||||
switch (componentValue) {
|
||||
case 'fs':
|
||||
return 'fullscreen only';
|
||||
case 'enabled':
|
||||
case 'theater':
|
||||
return 'where possible';
|
||||
case 'disabled':
|
||||
return 'disabled';
|
||||
}
|
||||
}
|
||||
switch (componentValue) {
|
||||
case ExtensionMode.Disabled:
|
||||
return 'disabled';
|
||||
case ExtensionMode.Default:
|
||||
return 'default';
|
||||
case ExtensionMode.FullScreen:
|
||||
return 'fullscreen only';
|
||||
case ExtensionMode.Theater:
|
||||
return 'fullscreen & theater';
|
||||
case ExtensionMode.All:
|
||||
case 'fs':
|
||||
return 'Fullscreen only';
|
||||
case 'theater':
|
||||
return 'theater & FS';
|
||||
case 'enabled':
|
||||
return 'always';
|
||||
default:
|
||||
return '<Invalid value>';
|
||||
case 'disabled':
|
||||
return 'disabled';
|
||||
case 'default':
|
||||
return 'complex'
|
||||
}
|
||||
},
|
||||
|
||||
@ -534,7 +582,7 @@ export default defineComponent({
|
||||
this._computedWatchers?.siteDefaultStretch?.run();
|
||||
this._computedWatchers?.siteDefaultAlignment?.run();
|
||||
this._computedWatchers?.siteDefaultCropPersistence?.run();
|
||||
this._computedWatchers?.defaultPersistenceLabel?.run();
|
||||
this._computedWatchers?.defaultPersistanceLabel?.run();
|
||||
|
||||
this.$nextTick( () => this.$forceUpdate());
|
||||
},
|
||||
@ -547,15 +595,10 @@ export default defineComponent({
|
||||
setExtensionMode(component, event) {
|
||||
const option = event.target.value;
|
||||
|
||||
console.log('set extension mode - we received option', option, 'for component', component);
|
||||
|
||||
return;
|
||||
if (option === 'complex') {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (component === 'enable' && !this.isDefaultConfiguration) {
|
||||
this.setExtensionMode('enableAard', event);
|
||||
this.setExtensionMode('enableKeyboard', event);
|
||||
@ -568,6 +611,41 @@ export default defineComponent({
|
||||
}
|
||||
}
|
||||
|
||||
if (option === 'default') {
|
||||
return this.siteSettings.set(component, {
|
||||
normal: ExtensionMode.Default,
|
||||
theater: ExtensionMode.Default,
|
||||
fullscreen: ExtensionMode.Default
|
||||
});
|
||||
}
|
||||
if (option === 'disabled') {
|
||||
return this.siteSettings.set(component, {
|
||||
normal: ExtensionMode.Disabled,
|
||||
theater: ExtensionMode.Disabled,
|
||||
fullscreen: ExtensionMode.Disabled
|
||||
});
|
||||
}
|
||||
if (option === 'enabled') {
|
||||
return this.siteSettings.set(component, {
|
||||
normal: ExtensionMode.Enabled,
|
||||
theater: ExtensionMode.Enabled,
|
||||
fullscreen: ExtensionMode.Enabled
|
||||
});
|
||||
}
|
||||
if (option === 'theater') {
|
||||
return this.siteSettings.set(component, {
|
||||
normal: ExtensionMode.Disabled,
|
||||
theater: ExtensionMode.Enabled,
|
||||
fullscreen: ExtensionMode.Enabled
|
||||
});
|
||||
}
|
||||
if (option === 'fs') {
|
||||
return this.siteSettings.set(component, {
|
||||
normal: ExtensionMode.Disabled,
|
||||
theater: ExtensionMode.Disabled,
|
||||
fullscreen: ExtensionMode.Enabled
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
@import '@src/main.css'; /** postcss processor doesn't support aliases */
|
||||
@import '../../../../main.css'; /** postcss processor doesn't support aliases */
|
||||
|
||||
.keyboard-shortcut-row {
|
||||
@apply py-2 px-4
|
||||
@ -30,7 +30,7 @@
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import KeyboardShortcutParserMixin from '@ui/utils/mixins/KeyboardShortcutParserMixin.vue';
|
||||
import KeyboardShortcutParserMixin from '../../../../csui/src/utils/KeyboardShortcutParserMixin';
|
||||
import EditShortcutButton from './EditShortcutButton.vue';
|
||||
|
||||
export default defineComponent({
|
||||
@ -155,6 +155,7 @@ import AspectRatioType from '@src/common/enums/AspectRatioType.enum';
|
||||
import StretchType from '@src/common/enums/StretchType.enum';
|
||||
import NewAspectRatioForm from './Components/NewAspectRatioForm.vue';
|
||||
|
||||
import BrowserDetect from '@src/ext/conf/BrowserDetect';
|
||||
import CropOptionsPanel from '@csui/src/PlayerUiPanels/PanelComponents/VideoSettings/CropOptionsPanel.vue'
|
||||
import StretchOptionsPanel from '@csui/src/PlayerUiPanels/PanelComponents/VideoSettings/StretchOptionsPanel.vue'
|
||||
import ZoomOptionsPanel from '@csui/src/PlayerUiPanels/PanelComponents/VideoSettings/ZoomOptionsPanel.vue'
|
||||
@ -65,7 +65,7 @@
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import BrowserDetect from '@src/ext/conf/BrowserDetect';
|
||||
import SupportLevelIndicator from '@components/common/SupportLevelIndicator.vue';
|
||||
import SupportLevelIndicator from '@components/common/components/SupportLevelIndicator.vue';
|
||||
|
||||
|
||||
export default defineComponent({
|
||||
@ -95,7 +95,7 @@ export default defineComponent({
|
||||
})
|
||||
</script>
|
||||
<style lang="postcss" scoped>
|
||||
@import '@src/main.css'; /** postcss processor doesn't support aliases */
|
||||
@import '../../../main.css'; /** postcss processor doesn't support aliases */
|
||||
|
||||
.open-settings-popup {
|
||||
width: 16rem;
|
||||
@ -76,23 +76,30 @@
|
||||
|
||||
<div class="flex flex-col panel-content">
|
||||
<!-- Panel section -->
|
||||
<VideoSettings v-if="selectedTab === 'video-settings'"
|
||||
<VideoSettings
|
||||
v-if="selectedTab === 'video-settings'"
|
||||
:settings="settings"
|
||||
:siteSettings="siteSettings"
|
||||
:eventBus="eventBus"
|
||||
:site="site"
|
||||
></VideoSettings>
|
||||
|
||||
<template v-if="settings && selectedTab === 'site-extension-settings'" >
|
||||
<template
|
||||
v-if="settings && selectedTab === 'site-extension-settings'"
|
||||
>
|
||||
<h3>Settings for {{site?.host}}</h3>
|
||||
<SiteExtensionSettings
|
||||
:settings="settings"
|
||||
:siteSettings="siteSettings"
|
||||
:isDefaultConfiguration="false"
|
||||
></SiteExtensionSettings>
|
||||
|
||||
<pre>{{JSON.stringify(siteSettings.data, null, 2)}}</pre>
|
||||
</template>
|
||||
|
||||
<template v-if="settings && selectedTab === 'embedded-extension-settings'" >
|
||||
<template
|
||||
v-if="settings && selectedTab === 'embedded-extension-settings'"
|
||||
>
|
||||
<h3>Settings for embedded sites</h3>
|
||||
<FrameSiteSettings
|
||||
:parentHost="site?.host"
|
||||
@ -102,7 +109,9 @@
|
||||
</template>
|
||||
|
||||
|
||||
<template v-if="settings && selectedTab === 'default-extension-settings'" >
|
||||
<template
|
||||
v-if="settings && selectedTab === 'default-extension-settings'"
|
||||
>
|
||||
<h3>Default settings</h3>
|
||||
<SiteExtensionSettings
|
||||
:settings="settings"
|
||||
@ -116,7 +125,6 @@
|
||||
:settings="settings"
|
||||
:enableSettingsEditor="true"
|
||||
></OtherSiteSettings>
|
||||
|
||||
<AutodetectionSettings
|
||||
v-if="selectedTab === 'autodetectionSettings'"
|
||||
:settings="settings"
|
||||
@ -160,17 +168,12 @@
|
||||
>
|
||||
</PlayerDetectionPanel>
|
||||
|
||||
<ImportExportSettings v-if="selectedTab === 'import-export-settings'"
|
||||
:settings="settings"
|
||||
>
|
||||
</ImportExportSettings>
|
||||
|
||||
<Debugging
|
||||
<DebugPanel
|
||||
v-if="selectedTab === 'debugging'"
|
||||
:settings="settings"
|
||||
:eventBus="eventBus"
|
||||
:site="site"
|
||||
></Debugging>
|
||||
></DebugPanel>
|
||||
|
||||
<!-- <ResetBackupPanel
|
||||
v-if="selectedTab === 'resetBackup'"
|
||||
@ -184,24 +187,24 @@
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import VideoSettings from '@components/segments/VideoSettings/VideoSettings.vue';
|
||||
import OtherSiteSettings from '@components/segments/ExtensionSettings/Panels/OtherSiteSettings.vue';
|
||||
import AutodetectionSettings from '@components/segments/AutodetectionSettings/AutodetectionSettings.vue';
|
||||
import UISettings from '@components/segments/UISettings/UISettings.vue';
|
||||
import KeyboardShortcutSettings from '@components/segments/KeyboardShortcuts/KeyboardShortcutSettings.vue';
|
||||
import SiteExtensionSettings from '@components/segments/ExtensionSettings/Panels/SiteExtensionSettings.vue';
|
||||
import FrameSiteSettings from '@components/segments/ExtensionSettings/Panels/FrameSiteSettings.vue';
|
||||
import Debugging from '@components/segments/Debugging/Debugging.vue';
|
||||
import ImportExportSettings from '@components/segments/ImportExportSettings/ImportExportSettings.vue';
|
||||
import VideoSettings from '@components/VideoSettings/VideoSettings.vue';
|
||||
import OtherSiteSettings from '@components/ExtensionSettings/Panels/OtherSiteSettings.vue';
|
||||
import AutodetectionSettings from '@components/AutodetectionSettings/AutodetectionSettings.vue';
|
||||
import UISettings from '@components/UISettings/UISettings.vue';
|
||||
import KeyboardShortcutSettings from '@components/KeyboardShortcuts/KeyboardShortcutSettings.vue';
|
||||
import SiteExtensionSettings from '@components/ExtensionSettings/Panels/SiteExtensionSettings.vue';
|
||||
import FrameSiteSettings from '@components/ExtensionSettings/Panels/FrameSiteSettings.vue';
|
||||
|
||||
import WhatsNew from '@components/segments/ExtensionInfo/WhatsNew.vue';
|
||||
import About from '@components/segments/ExtensionInfo/About.vue';
|
||||
import WhatsNew from '@components/ExtensionInfo/WhatsNew.vue';
|
||||
import About from '@components/ExtensionInfo/About.vue';
|
||||
|
||||
// to replace:
|
||||
import DebugPanel from '../../csui/src/PlayerUiPanels/DebugPanel.vue'
|
||||
import PlayerDetectionPanel from '../../csui/src/PlayerUiPanels/PlayerDetectionPanel.vue'
|
||||
|
||||
// not component:
|
||||
import BrowserDetect from '@src/ext/conf/BrowserDetect'
|
||||
import BrowserDetect from '../../ext/conf/BrowserDetect'
|
||||
import ChangelogPanel from '../../csui/src/PlayerUiPanels/ChangelogPanel.vue'
|
||||
import AboutPanel from '@csui/src/PlayerUiPanels/AboutPanel.vue'
|
||||
import ResetBackupPanel from '../../csui/src/PlayerUiPanels/ResetBackupPanel.vue'
|
||||
import SupportLevelIndicator from '@csui/src/components/SupportLevelIndicator.vue'
|
||||
|
||||
|
||||
const AVAILABLE_TABS = {
|
||||
@ -224,7 +227,6 @@ const AVAILABLE_TABS = {
|
||||
'playerDetection': {id: 'playerDetection', label: 'Player detection', icon: 'television-play'},
|
||||
'changelog': {id: 'changelog', label: 'What\'s new', icon: 'alert-decagram' },
|
||||
'about': {id: 'about', label: 'About', icon: 'information-outline'},
|
||||
'import-export-settings': { id: 'import-export-settings', label: 'Import & export settings', icon: 'file-export-outline'},
|
||||
'debugging': {id: 'debugging', label: 'Debugging', icon: 'bug-outline', hidden: true}
|
||||
};
|
||||
|
||||
@ -236,7 +238,6 @@ const TAB_LOADOUT = {
|
||||
'keyboardShortcuts',
|
||||
'changelog',
|
||||
'about',
|
||||
'import-export-settings',
|
||||
'debugging',
|
||||
],
|
||||
'popup': [
|
||||
@ -256,13 +257,16 @@ export default defineComponent({
|
||||
UISettings,
|
||||
SiteExtensionSettings,
|
||||
FrameSiteSettings,
|
||||
ImportExportSettings,
|
||||
Debugging,
|
||||
|
||||
WhatsNew,
|
||||
About,
|
||||
|
||||
PlayerDetectionPanel,
|
||||
DebugPanel,
|
||||
ChangelogPanel,
|
||||
AboutPanel,
|
||||
SupportLevelIndicator,
|
||||
ResetBackupPanel,
|
||||
},
|
||||
mixins: [],
|
||||
data() {
|
||||
@ -301,9 +305,6 @@ export default defineComponent({
|
||||
watch: {
|
||||
'initialPath': function (newVal) {
|
||||
this.setInitialPath(newVal);
|
||||
},
|
||||
'site': function (newVal) {
|
||||
this.updateSite(newVal);
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@ -324,9 +325,7 @@ export default defineComponent({
|
||||
changelogTab.highlight = !this.settings.active?.whatsNewChecked;
|
||||
}
|
||||
|
||||
if (this.site) {
|
||||
this.siteSettings = this.settings.getSiteSettings({site: this.site});
|
||||
}
|
||||
this.siteSettings = this.settings.getSiteSettings({site: this.site});
|
||||
this.eventBus?.subscribe(
|
||||
'uw-show-ui',
|
||||
{
|
||||
@ -345,13 +344,6 @@ export default defineComponent({
|
||||
this.eventBus?.unsubscribeAll(this);
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* Regenerates this.siteSettings
|
||||
*/
|
||||
updateSite(newSite: {host: string, hostnames: string[],}) {
|
||||
this.siteSettings = this.settings.getSiteSettings({site: newSite.host});
|
||||
this.$nextTick( () => this.$forceUpdate());
|
||||
},
|
||||
/**
|
||||
* Gets URL of the browser settings page (i think?)
|
||||
*/
|
||||
@ -374,13 +366,11 @@ export default defineComponent({
|
||||
console.log('setting initial path:', this.initialPath)
|
||||
if (path && path.length) {
|
||||
this.selectedTab = path[0];
|
||||
this.$emit('debugStatusChanged', this.selectedTab === 'debugging');
|
||||
}
|
||||
},
|
||||
selectTab(tab) {
|
||||
console.log("Selecting tab", tab);
|
||||
this.selectedTab = tab;
|
||||
this.$emit('debugStatusChanged', tab === 'debugging');
|
||||
window.location.hash = `#${this.role}/${this.selectedTab}`;
|
||||
},
|
||||
setPreventClose(bool) {
|
||||
@ -399,7 +389,7 @@ export default defineComponent({
|
||||
});
|
||||
</script>
|
||||
<style lang="postcss" scoped>
|
||||
@import '@src/main.css'; /** postcss processor doesn't support aliases */
|
||||
@import '../../main.css'; /** postcss processor doesn't support aliases */
|
||||
|
||||
.settings-categories {
|
||||
@apply
|
||||
|
||||
@ -113,12 +113,12 @@ import { defineComponent } from 'vue';
|
||||
import BrowserDetect from '@src/ext/conf/BrowserDetect';
|
||||
|
||||
import ShortcutButton from './components/ShortcutButton.vue';
|
||||
import CommsMixin from '@ui/utils/mixins/CommsMixin.vue';
|
||||
import KeyboardShortcutParserMixin from '@ui/utils/mixins/KeyboardShortcutParserMixin.vue';
|
||||
import CommsMixin from '@components/common/mixins/CommsMixin.vue';
|
||||
import KeyboardShortcutParserMixin from '@components/common/mixins/KeyboardShortcutParserMixin.vue';
|
||||
|
||||
import alignmentIndicatorSvg from '!!raw-loader!@ui/res/img/alignment-indicators.svg?raw';
|
||||
import {setupVideoAlignmentIndicatorInteraction, setVideoAlignmentIndicatorState} from '@ui/utils/video-alignment-indicator-handling';
|
||||
import VideoAlignmentType from '@src/common/enums/VideoAlignmentType.enum';
|
||||
import {setupVideoAlignmentIndicatorInteraction, setVideoAlignmentIndicatorState} from '@ui/utils/video-alignment-indicator-handling.ts';
|
||||
import VideoAlignmentType from '../../../common/enums/VideoAlignmentType.enum';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
@ -227,7 +227,7 @@ export default defineComponent({
|
||||
});
|
||||
</script>
|
||||
<style lang="postcss" scoped>
|
||||
@import '@src/main.css';
|
||||
@import '../../../main.css';
|
||||
|
||||
.button-container {
|
||||
@apply w-full pt-2
|
||||
@ -1,109 +0,0 @@
|
||||
|
||||
<template>
|
||||
<div v-if="popupVisible" class="popup">
|
||||
<div class="popup-window">
|
||||
<div
|
||||
class="header"
|
||||
:class="{
|
||||
'danger': dialogType === 'danger',
|
||||
'warning': dialogType === 'warning',
|
||||
'info': dialogType === 'info',
|
||||
'normal': dialogType === 'normal'
|
||||
}"
|
||||
>
|
||||
{{ dialogText || 'Confirm action' }}
|
||||
</div>
|
||||
<div class="body">
|
||||
{{ dialogText || 'Are you sure you want to do that?' }}
|
||||
</div>
|
||||
<div class="footer w-full flex row gap-2 justify-end">
|
||||
<button
|
||||
class="button confirm"
|
||||
:class="{
|
||||
'danger': dialogType === 'danger',
|
||||
'warning': dialogType === 'warning',
|
||||
'info': dialogType === 'info',
|
||||
'normal': dialogType === 'normal'
|
||||
}"
|
||||
@click="confirmAction"
|
||||
>
|
||||
{{ confirmText || 'Confirm' }}
|
||||
</button>
|
||||
<button class="button" @click="popupVisible = false">{{ cancelText || 'Cancel' }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
:class="[
|
||||
{
|
||||
'danger': dialogType === 'danger',
|
||||
'warning': dialogType === 'warning',
|
||||
},
|
||||
btnClass
|
||||
]"
|
||||
@click="popupVisible = true"
|
||||
>
|
||||
<slot></slot>
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
data() {
|
||||
return {
|
||||
popupVisible: false,
|
||||
}
|
||||
},
|
||||
props: [
|
||||
'btnClass',
|
||||
'dialogTitle',
|
||||
'dialogText',
|
||||
'confirmText',
|
||||
'cancelText',
|
||||
'dialogType'
|
||||
],
|
||||
methods: {
|
||||
confirmAction() {
|
||||
this.popupVisible = false;
|
||||
this.$emit('onConfirmed');
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="postcss" scoped>
|
||||
.popup {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
backdrop-filter: saturate(50%) brightness(50%) blur(1rem);
|
||||
z-index: 99999;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
.header {
|
||||
font-size: 1.33rem;
|
||||
|
||||
color: #fff;
|
||||
|
||||
&.danger {
|
||||
color: rgb(251, 107, 63);
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
.body {
|
||||
min-height: 5rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,120 +0,0 @@
|
||||
<template>
|
||||
<div class="flex flex-row w-full">
|
||||
<button
|
||||
v-if="editorMode === 'tree'"
|
||||
@click="() => setEditorMode('text')"
|
||||
>
|
||||
Edit as text
|
||||
</button>
|
||||
<button
|
||||
v-else
|
||||
@click="() => setEditorMode('tree')"
|
||||
>
|
||||
Show as tree
|
||||
</button>
|
||||
</div>
|
||||
<div ref="refContainer" class="w-full h-full"></div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { createJSONEditor, Mode } from "vanilla-jsoneditor";
|
||||
|
||||
export default {
|
||||
props: {
|
||||
modelValue: Object // v-model binding
|
||||
},
|
||||
emits: ["update:modelValue"],
|
||||
data() {
|
||||
return {
|
||||
refContainer: null,
|
||||
editor: null,
|
||||
editorMode: Mode.tree,
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
modelValue: {
|
||||
deep: true,
|
||||
handler(newValue) {
|
||||
if (this.editor) {
|
||||
this.editor.updateProps({ content: { json: newValue || {} } });
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (this.$refs.refContainer) {
|
||||
this.editor = createJSONEditor({
|
||||
target: this.$refs.refContainer,
|
||||
props: {
|
||||
mode: Mode.tree,
|
||||
content: { json: this.modelValue || {} },
|
||||
onChange: (updatedContent) => {
|
||||
this.$emit("update:modelValue", updatedContent.json);
|
||||
},
|
||||
onRenderContextMenu: false,
|
||||
navigationBar: false,
|
||||
statusBar: false,
|
||||
mainMenuBar: false
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
setEditorMode(mode) {
|
||||
this.editorMode = mode
|
||||
this.editor.updateProps({ mode });
|
||||
}
|
||||
},
|
||||
beforeUnmount() {
|
||||
if (this.editor) {
|
||||
this.editor.destroy();
|
||||
this.editor = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="postcss">
|
||||
:root {
|
||||
--jse-panel-background: #111;
|
||||
--jse-background-color: #000;
|
||||
--jse-text-color: #ccc;
|
||||
--jse-key-color: #8c8bef;
|
||||
--jse-selection-background-color: rgba(255, 171, 102, 0.177);
|
||||
--jse-context-menu-pointer-background: rgba(255, 171, 102, 0.177);
|
||||
--jse-delimiter-color: #fa6;
|
||||
--jse-value-color-boolean: rgb(132, 132, 137);
|
||||
}
|
||||
|
||||
.jse-boolean-toggle[role="checkbox"] {
|
||||
&[aria-checked="true"] {
|
||||
color: rgb(218, 244, 238);
|
||||
}
|
||||
|
||||
&[aria-checked="false"] {
|
||||
border: 0px transparent;
|
||||
outline: 0px transparent;
|
||||
color: rgb(241, 107, 25);
|
||||
background-color: rgb(241, 107, 25);
|
||||
|
||||
position: relative;
|
||||
|
||||
&:after {
|
||||
position: absolute;
|
||||
|
||||
content: '×';
|
||||
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
color: black;
|
||||
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
@ -1,111 +0,0 @@
|
||||
<template>
|
||||
<div
|
||||
v-if="title"
|
||||
class="popup-overlay"
|
||||
:class="{'dim': dimOverlay}"
|
||||
>
|
||||
<div class="popup-content p-4 border border-stone-700 max-h-[90dvh] max-w-[90dvw]" >
|
||||
<div class="h-full flex flex-col">
|
||||
<div v-if="title" class="header grow-0 shrink-0" :class="type">
|
||||
<h3 class="mb-4 mt-0">{{title}}</h3>
|
||||
</div>
|
||||
<p v-if="message">
|
||||
{{ message }}
|
||||
</p>
|
||||
<div v-else class="grow shrink overflow-auto">
|
||||
<slot></slot>
|
||||
</div>
|
||||
<div class="grow-0 shrink-0 flex row gap-2 justify-end w-full">
|
||||
<button
|
||||
class="primary"
|
||||
v-if="confirmButtonText"
|
||||
:class="type"
|
||||
@click="$emit('onConfirm')"
|
||||
>
|
||||
{{ confirmButtonText }}
|
||||
</button>
|
||||
<button
|
||||
:class="type"
|
||||
@click="$emit('onCancel')"
|
||||
>
|
||||
{{ cancelButtonText }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
props: {
|
||||
// onConfirm: {
|
||||
// type: Function,
|
||||
// required: false
|
||||
// },
|
||||
// onCancel: {
|
||||
// type: Function,
|
||||
// default: () => this.$emit('close')
|
||||
// },
|
||||
title: {
|
||||
type: String,
|
||||
required: false
|
||||
},
|
||||
message: {
|
||||
type: String,
|
||||
required: false, // technically prolly should be true, but we don't have to guard against skill issue
|
||||
},
|
||||
dimOverlay: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: 'info'
|
||||
},
|
||||
confirmButtonText: {
|
||||
type: String,
|
||||
required: false,
|
||||
},
|
||||
cancelButtonText: {
|
||||
type: String,
|
||||
default: 'Cancel'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="postcss" scoped>
|
||||
|
||||
.popup-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
backdrop-filter: saturate(50%) brightness(50%) blur(1rem);
|
||||
z-index: 99999;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
.header {
|
||||
font-size: 1.33rem;
|
||||
|
||||
color: #fff;
|
||||
|
||||
&.danger {
|
||||
color: rgb(251, 107, 63);
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
.body {
|
||||
min-height: 5rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,79 +0,0 @@
|
||||
<template>
|
||||
<button
|
||||
class="button drop-zone"
|
||||
:class="[{'drag-over': isDragOver}, className]"
|
||||
@click="onClick"
|
||||
@dragover="isDragOver = true"
|
||||
@dragleave="isDragOver = false"
|
||||
@drop="onDrop"
|
||||
>
|
||||
<slot></slot>
|
||||
<input type="file" ref="fileInput" @change="onFileChange" accept=".json" />
|
||||
</button>
|
||||
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
className: {
|
||||
type: String,
|
||||
default: ""
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isDragOver: false
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
onClick() {
|
||||
this.$refs.fileInput.click();
|
||||
},
|
||||
onDrop(event) {
|
||||
event.preventDefault();
|
||||
this.isDragOver = false;
|
||||
|
||||
if (event.dataTransfer.files.length > 0) {
|
||||
this.handleFile(event.dataTransfer.files[0]);
|
||||
}
|
||||
},
|
||||
onFileChange(event) {
|
||||
if (event.target.files.length > 0) {
|
||||
this.handleFile(event.target.files[0]);
|
||||
}
|
||||
},
|
||||
handleFile(file) {
|
||||
if (file.type !== "application/json") {
|
||||
this.$emit('error', 'NOT_JSON_FILE');
|
||||
return;
|
||||
}
|
||||
|
||||
const reader = new FileReader();
|
||||
reader.onload = async (event) => {
|
||||
try {
|
||||
const importedData = JSON.parse(event.target.result as string);
|
||||
this.$emit('importedJson', importedData);
|
||||
} catch (error) {
|
||||
this.$emit('error', 'INVALID_JSON');
|
||||
}
|
||||
};
|
||||
reader.readAsText(file);
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
<style lang="postcss" scoped>
|
||||
input {
|
||||
display: none;
|
||||
}
|
||||
.drop-zone {
|
||||
&.drag-over {
|
||||
background-color: #fa6;
|
||||
color: black;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -62,7 +62,7 @@ export default defineComponent({
|
||||
},
|
||||
computed: {
|
||||
computedSiteSupportLevel() {
|
||||
return this.siteSupportLevel ?? (this.siteSettings ? this.siteSettings.data.type ?? 'no-support' : 'waiting');
|
||||
return this.siteSupportLevel ?? this.siteSettings ? this.siteSettings.data.type || 'no-support' : 'waiting';
|
||||
}
|
||||
}
|
||||
|
||||
@ -70,7 +70,7 @@ export default defineComponent({
|
||||
</script>
|
||||
|
||||
<style lang="postcss" scoped>
|
||||
@import '@src/main.css'; /** postcss processor doesn't support aliases */
|
||||
@import '../../../../main.css'; /** postcss processor doesn't support aliases */
|
||||
|
||||
.site-support {
|
||||
@apply inline-flex flex-row items-center gap-1 rounded-[0.5rem] relative;
|
||||
@ -1,243 +0,0 @@
|
||||
<template>
|
||||
<h2 class="text-[1.75em]">Debugging</h2>
|
||||
|
||||
<div class="w-full grid grid-cols-1 min-[1200px]:grid-cols-2 min-[1920px]:grid-cols-3 max-w-[2300px] gap-8">
|
||||
|
||||
<div class="grow shrink">
|
||||
<h3 class="mb-4">Settings editor</h3>
|
||||
<div class="flex flex-row w-full">
|
||||
<div class="flex flex-row items-center gap-2">
|
||||
<div>Enable save button:</div>
|
||||
<input v-model="allowSettingsEditing" type="checkbox">
|
||||
</div>
|
||||
<div class="grow">
|
||||
</div>
|
||||
<div>
|
||||
<div v-if="editorSaveFinished">Settings saved ...</div>
|
||||
<button v-else
|
||||
class="danger"
|
||||
:class="{'opacity-50 select-none hover:border-stone-500 hover:text-stone-300': !allowSettingsEditing}"
|
||||
:disabled="!allowSettingsEditing"
|
||||
@click="() => saveSettingsChanges()"
|
||||
>
|
||||
Save
|
||||
</button>
|
||||
</div>
|
||||
<button @click="resetSettingsEditor">
|
||||
Cancel
|
||||
</button>
|
||||
|
||||
</div>
|
||||
<div>
|
||||
<JsonEditor
|
||||
v-model="settingsJson"
|
||||
>
|
||||
</JsonEditor>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grow shrink">
|
||||
<h3 class="mb-4">Snapshots</h3>
|
||||
|
||||
<div class="flex flex-col gap-2">
|
||||
<div
|
||||
v-for="(snapshot, index) of settingsSnapshots" :key="snapshot.createdAt"
|
||||
class="border border-stone-800 p-2"
|
||||
>
|
||||
<small>Created at: {{new Date(snapshot.createdAt).toISOString()}}</small>
|
||||
<div class="flex flex-row">
|
||||
<div class="grow font-bold">
|
||||
{{snapshot.label ?? '<no label>'}}
|
||||
</div>
|
||||
<div class="mr-8">v. {{snapshot.settings.version ?? '<unknown ver.>'}}</div>
|
||||
<div v-if="settings.isAutomatic">(auto)</div>
|
||||
<div v-if="settings.isAutomatic && settings.isProtected">(protected)</div>
|
||||
<div v-if="settings.default">(default)</div>
|
||||
</div>
|
||||
<div class="flex flex-row w-full justify-end mt-2">
|
||||
<button class="flex flex-col" @click="() => testMigration(index)">Test migration</button>
|
||||
<button class="flex flex-col" @click="() => loadFromSnapshot(index)">Load snapshot and migrate<br/><small>normal migration</small></button>
|
||||
<button class="flex flex-col" @click="() => loadFromSnapshot(index, true)">Load & migrate<br/><small>without creating snapshot</small></button>
|
||||
<button class="flex flex-col" @click="() => markDefaultSnapshot(index)"><template v-if="settings.isDefault">Revoke default</template><template v-else>Make default</template></button>
|
||||
<button class="flex flex-col" v-if="settings.isAutomatic" @click="() => toggleSnapshotProtection(index)">Toggle protection</button>
|
||||
<button class="flex flex-col" @click="() => deleteSnapshot(index)">Delete snapshot</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grow shrink">
|
||||
<h3 class="mb-4">Logger configuration</h3>
|
||||
|
||||
<JsonEditor
|
||||
v-model="lastSettings"
|
||||
></JsonEditor>
|
||||
|
||||
<div class="flex flex-row justify-end mt-4 w-full">
|
||||
<button class="bg-black button" @click="getLoggerSettings()">
|
||||
Revert
|
||||
</button>
|
||||
<button class="button button-primary" @click="saveLoggerSettings()">
|
||||
Save
|
||||
</button>
|
||||
<button class="button button-primary" @click="startLogging()">
|
||||
Save and start logging
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { LogAggregator, BLANK_LOGGER_CONFIG } from '@src/ext/lib/logging/LogAggregator';
|
||||
import JsonEditor from '@components/common/JsonEditor.vue';
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
JsonEditor
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loggerPanelRotation: [{
|
||||
title: 'DEFORESTATOR 5000',
|
||||
subtitle: 'Iron Legion\'s finest logging tool'
|
||||
},{
|
||||
title: 'Astinus',
|
||||
subtitle: 'Ultrawidify logging tool'
|
||||
}, {
|
||||
title: 'Tracer',
|
||||
subtitle: "Maybe I'll be Tracer — I'm already printing stack traces."
|
||||
}, {
|
||||
title: 'Grûmsh',
|
||||
subtitle: "He who watches (all the things printed to the console)."
|
||||
}, {
|
||||
title: 'Situation Room/The Council',
|
||||
subtitle: 'We will always be watching.'
|
||||
}, {
|
||||
title: 'Isengard Land Management Services',
|
||||
subtitle: "#log4saruman"
|
||||
}, {
|
||||
title: 'Saw Hero',
|
||||
subtitle: 'Ultrawidify logging tool'
|
||||
}],
|
||||
|
||||
loggerPanel: {
|
||||
title: 'whoopsie daisy',
|
||||
subtitle: 'you broke the header choosing script',
|
||||
pasteConfMode: false,
|
||||
},
|
||||
lastSettings: undefined,
|
||||
parsedSettings: undefined,
|
||||
currentSettings: undefined,
|
||||
|
||||
allowSettingsEditing: false,
|
||||
editorSaveFinished: false,
|
||||
settingsJson: {},
|
||||
settingsSnapshots: []
|
||||
};
|
||||
},
|
||||
props: [
|
||||
'settings',
|
||||
'eventBus',
|
||||
],
|
||||
created() {
|
||||
this.loggerPanel = {
|
||||
...this.loggerPanelRotation[Math.floor(Math.random() * this.loggerPanelRotation.length)],
|
||||
pasteConfMode: false,
|
||||
};
|
||||
this.getLoggerSettings();
|
||||
},
|
||||
mounted() {
|
||||
this.loadSettingsSnapshots();
|
||||
this.resetSettingsEditor();
|
||||
this.loadSettingsSnapshots();
|
||||
},
|
||||
methods: {
|
||||
loadDefaultConfig() {
|
||||
this.lastSettings = JSON.parse(JSON.stringify(BLANK_LOGGER_CONFIG));
|
||||
},
|
||||
async getLoggerSettings() {
|
||||
this.lastSettings = await LogAggregator.getConfig() || BLANK_LOGGER_CONFIG;
|
||||
},
|
||||
async saveLoggerSettings() {
|
||||
console.log('Saving logger settings', this.lastSettings);
|
||||
await LogAggregator.saveConfig({...this.lastSettings});
|
||||
console.log('[ok] logger settings saved');
|
||||
},
|
||||
async startLogging(){
|
||||
this.logStringified = undefined;
|
||||
await LogAggregator.saveConfig({...this.lastSettings});
|
||||
window.location.reload();
|
||||
},
|
||||
|
||||
/**
|
||||
* Resets settings to default
|
||||
*/
|
||||
resetSettings() {
|
||||
this.settings.active = JSON.parse(JSON.stringify(this.settings.default));
|
||||
this.settings.saveWithoutReload();
|
||||
this.resetSettingsEditor();
|
||||
},
|
||||
|
||||
async saveSettingsChanges() {
|
||||
if (this.allowSettingsEditing) {
|
||||
const currentVersion = this.settings.active?.version;
|
||||
this.settings.active = this.settingsJson;
|
||||
|
||||
if (currentVersion !== this.settingsJson.version) {
|
||||
await this.settings.save({forcePreserveVersion: true});
|
||||
return;
|
||||
} else {
|
||||
await this.settings.saveWithoutReload();
|
||||
}
|
||||
|
||||
this.resetSettingsEditor();
|
||||
this.editorSaveFinished = true;
|
||||
|
||||
setTimeout(() => {
|
||||
this.editorSaveFinished = false;
|
||||
}, 3000);
|
||||
}
|
||||
},
|
||||
|
||||
resetSettingsEditor() {
|
||||
this.settingsJson = JSON.parse(JSON.stringify(this.settings?.active ?? {}));
|
||||
},
|
||||
//#endregion
|
||||
|
||||
//#region settings snapshot management
|
||||
async loadSettingsSnapshots() {
|
||||
this.settingsSnapshots = await this.settings.snapshotManager.listSnapshots();
|
||||
},
|
||||
|
||||
async markDefaultSnapshot(index) {
|
||||
await this.settings.snapshotManager.setDefaultSnapshot(index, !this.settingsSnapshots[index].isDefault);
|
||||
await this.loadSettingsSnapshots();
|
||||
this.settings.active.dev.loadFromSnapshot = this.settingsSnapshots[index].isDefault;
|
||||
this.saveSettingsChanges();
|
||||
},
|
||||
|
||||
async toggleSnapshotProtection(index) {
|
||||
await this.settings.snapshotManager.setSnapshotAsProtected(index, !this.settingsSnapshots[index].isProtected);
|
||||
await this.loadSettingsSnapshots();
|
||||
},
|
||||
|
||||
async deleteSnapshot(index) {
|
||||
await this.settings.snapshotManager.deleteSnapshot(index);
|
||||
await this.loadSettingsSnapshots();
|
||||
},
|
||||
|
||||
async loadFromSnapshot(snapshotIndex, skipSnapshot?: boolean) {
|
||||
this.settings.init({snapshot: this.settingsSnapshots[snapshotIndex], skipSnapshot});
|
||||
},
|
||||
|
||||
async testMigration(snapshotIndex) {
|
||||
this.settings.testMigration(this.settingsSnapshots[snapshotIndex]);
|
||||
},
|
||||
}
|
||||
//#endregion
|
||||
});
|
||||
</script>
|
||||
@ -1,190 +0,0 @@
|
||||
<template>
|
||||
<div class="flex flex-col w-full max-w-[960px]">
|
||||
<h2 text="text-[1.75rem]">Import & export settings</h2>
|
||||
|
||||
<!-- Reset options -->
|
||||
<h3>Import & export</h3>
|
||||
<p>
|
||||
Note that settings may contain the sites you visited and used this extension on. If you are being asked to share settings for debugging a bug report
|
||||
and are concerned with your privacy <small>(which you should)</small>, select partial export and only select the websites relevant to your issue.
|
||||
</p>
|
||||
<div class="flex flex-row w-full gap-2">
|
||||
<UploadJsonFileButton
|
||||
@importedJson="handleImportedSettings"
|
||||
@error="handleSettingsImportError"
|
||||
>
|
||||
Import settings
|
||||
</UploadJsonFileButton>
|
||||
<button @click="exportSettings()">Export settings</button>
|
||||
<button @click="startPartialExport()">Partial export </button>
|
||||
</div>
|
||||
|
||||
<h3>Reset settings</h3>
|
||||
<p>Reset settings to this version's default settings. Your custom settings will be lost.</p>
|
||||
|
||||
<ConfirmButton
|
||||
dialogType="danger"
|
||||
@onConfirmed="resetSettings"
|
||||
>
|
||||
Reset settings
|
||||
</ConfirmButton>
|
||||
<!--
|
||||
<div v-if="enableSettingsEditor" class="field">
|
||||
<div class="label">Show developer options</div>
|
||||
<input
|
||||
type="checkbox"
|
||||
v-model="settings.active.ui.devMode"
|
||||
@change="settings.saveWithoutReload"
|
||||
>
|
||||
</div> -->
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<Popup
|
||||
v-if="importSettingDialogConfig.visible"
|
||||
title="Overwrite existing settings?"
|
||||
message="Importing settings from a file will overwrite existing settings. Continue?"
|
||||
confirmButtonText="Import settings"
|
||||
cancelButtonText="Cancel"
|
||||
@onConfirm="importSettingDialogConfig.confirm"
|
||||
@onCancel="importSettingDialogConfig.reject"
|
||||
>
|
||||
</Popup>
|
||||
<Popup
|
||||
v-if="partialExportDialogConfig.visible"
|
||||
title="Custom settings export"
|
||||
confirmButtonText="Export"
|
||||
cancelButtonText="Cancel"
|
||||
@onConfirm="partialExportDialogConfig.confirm"
|
||||
@onCancel="partialExportDialogConfig.reject"
|
||||
>
|
||||
<p>Export settings for the following websites:</p>
|
||||
|
||||
<div class="flex flex-col my-4">
|
||||
<div v-for="site in userSites" :key="site"
|
||||
class="border border-stone-700 px-4 py-2 flex row gap-4"
|
||||
>
|
||||
<input type="checkbox" v-model="site.selectedForExport" :disabled="site.key === '@global'"> {{site.key}} <SupportLevelIndicator :siteSupportLevel="site.type ?? site.defaultType ?? 'problemo'"></SupportLevelIndicator>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</Popup>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Popup from '@components/common/Popup.vue';
|
||||
import ConfirmButton from '@components/common/ConfirmButton.vue';
|
||||
import UploadJsonFileButton from '@components/common/UploadJsonFileButton.vue';
|
||||
import { SiteSettingsInterface } from '@src/common/interfaces/SettingsInterface';
|
||||
import SupportLevelIndicator from '@components/common/SupportLevelIndicator.vue';
|
||||
import { SiteSupportLevel } from '../../../../common/enums/SiteSupportLevel.enum';
|
||||
|
||||
interface ExportSiteData extends SiteSettingsInterface {
|
||||
key: string,
|
||||
selectedForExport: boolean;
|
||||
};
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Popup,
|
||||
ConfirmButton,
|
||||
UploadJsonFileButton,
|
||||
SupportLevelIndicator,
|
||||
},
|
||||
mixins: [],
|
||||
props: [
|
||||
'settings',
|
||||
],
|
||||
data() {
|
||||
return {
|
||||
tab: 'siteSettings',
|
||||
importSettingDialogConfig: {visible: false},
|
||||
partialExportDialogConfig: {visible: false},
|
||||
allowSettingsEditing: false,
|
||||
editorSaveFinished: false,
|
||||
settingsJson: {},
|
||||
settingsSnapshots: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
userSites() {
|
||||
return this.partialExportDialogConfig.filter(
|
||||
(x: ExportSiteData) => (x.type ?? x.defaultType) === SiteSupportLevel.UserDefined || (x.type ?? x.defaultType) === SiteSupportLevel.UserModified);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
setTab(tab) {
|
||||
this.tab = tab;
|
||||
},
|
||||
|
||||
//#region settings management
|
||||
/**
|
||||
* Exports extension settings into a json file.
|
||||
*/
|
||||
exportSettings() {
|
||||
const settingBlob = new Blob(
|
||||
[ JSON.stringify(this.settings.active, null, 2) ],
|
||||
{ type: "application/json"}
|
||||
);
|
||||
const url = window.URL.createObjectURL(settingBlob);
|
||||
|
||||
const a = document.createElement("a");
|
||||
a.href = url;
|
||||
a.download = "ultrawidify-settings.json";
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
URL.revokeObjectURL(url);
|
||||
},
|
||||
|
||||
startPartialExport() {
|
||||
console.log('starting partial export ...');
|
||||
const sites: ExportSiteData[] = [];
|
||||
|
||||
for (const site in this.settings.active.sites) {
|
||||
sites.push({
|
||||
...JSON.parse(JSON.stringify(this.settings.active.sites[site])),
|
||||
key: site,
|
||||
selectedForExport: true
|
||||
});
|
||||
}
|
||||
|
||||
this.partialExportDialogConfig = {
|
||||
visible: true,
|
||||
sites,
|
||||
confirm: () => {
|
||||
console.log('selected sites:', this.partialExportDialogConfig.sites.filter(x => x.selectedForExport));
|
||||
},
|
||||
reject: () => {
|
||||
this.partialExportDialogConfig = {visible: false};
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
handleImportedSettings(newSettings) {
|
||||
this.importSettingDialogConfig = {
|
||||
visible: true,
|
||||
confirm: () => {
|
||||
this.settings.active = newSettings;
|
||||
this.settings.saveWithoutReload();
|
||||
this.importSettingDialogConfig = {visible: false};
|
||||
},
|
||||
reject: () => {
|
||||
this.importSettingDialogConfig = {visible: false};
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
handleSettingsImportError(error) {
|
||||
console.error('Error importing settings:', error);
|
||||
},
|
||||
|
||||
resetSettings() {
|
||||
this.settings.active = JSON.parse(JSON.stringify(this.settings.default));
|
||||
this.settings.saveWithoutReload();
|
||||
},
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -61,7 +61,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import BrowserDetect from '@src/ext/conf/BrowserDetect';
|
||||
import BrowserDetect from '../../../ext/conf/BrowserDetect';
|
||||
import { LogAggregator } from '@src/ext/lib/logging/LogAggregator';
|
||||
import { ComponentLogger } from '@src/ext/lib/logging/ComponentLogger';
|
||||
|
||||
|
||||
@ -6,10 +6,7 @@
|
||||
">
|
||||
|
||||
<!-- page content -->
|
||||
<div
|
||||
class="w-full h-[100dvh] overflow-hidden flex flex-col"
|
||||
:class="{'max-w-[1920px]': !isDebugging}"
|
||||
>
|
||||
<div class="w-full max-w-[1920px] h-[100dvh] overflow-hidden flex flex-col">
|
||||
<PopupHead
|
||||
v-if="role === 'popup' && settings && siteSettings && eventBus"
|
||||
:settings="settings"
|
||||
@ -35,7 +32,6 @@
|
||||
:logger="logger"
|
||||
:inPlayer="false"
|
||||
:site="site"
|
||||
@debugStatusChanged="setDebugStatus"
|
||||
>
|
||||
</SettingsWindowContent>
|
||||
</div>
|
||||
@ -55,7 +51,7 @@ import EventBus from '@src/ext/lib/EventBus';
|
||||
import CommsClient, { CommsOrigin } from '@src/ext/lib/comms/CommsClient';
|
||||
import {ChromeShittinessMitigations as CSM} from '@src/common/js/ChromeShittinessMitigations';
|
||||
|
||||
import PopupHead from '@components/PopupHead.vue';
|
||||
import PopupHead from '@components/PopupHead/PopupHead.vue';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
@ -74,7 +70,6 @@ export default defineComponent({
|
||||
settingsInitialized: false,
|
||||
role: 'settings',
|
||||
initialPath: undefined as string[] | undefined,
|
||||
isDebugging: false,
|
||||
}
|
||||
},
|
||||
async created() {
|
||||
@ -92,18 +87,10 @@ export default defineComponent({
|
||||
await this.setupSettingsPage();
|
||||
}
|
||||
|
||||
if (segment !== '#popup') {
|
||||
// undo that workaround that makes popup work correctly if we aren't in a popup
|
||||
document.getElementsByTagName('html')[0].setAttribute('style', '');
|
||||
}
|
||||
|
||||
await this.settings.init();
|
||||
this.settingsInitialized = true;
|
||||
},
|
||||
methods: {
|
||||
setDebugStatus(isDebugging: boolean) {
|
||||
this.isDebugging = isDebugging;
|
||||
},
|
||||
updateConfig() {
|
||||
this.settings.init();
|
||||
this.$nextTick( () => this.$forceUpdate());
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
@font-face {
|
||||
font-family: "Heebo";
|
||||
src: url("@res/fonts/Heebo.ttf") format("truetype-variations");
|
||||
src: url("../fonts/Heebo.ttf") format("truetype-variations");
|
||||
font-weight: 100 900;
|
||||
font-stretch: 75% 125%;
|
||||
font-style: normal;
|
||||
@ -9,7 +9,7 @@
|
||||
|
||||
@font-face {
|
||||
font-family: "Source Code Pro";
|
||||
src: url("@res/fonts/SourceCodePro.ttf") format("truetype-variations");
|
||||
src: url("../fonts/SourceCodePro.ttf") format("truetype-variations");
|
||||
font-weight: 200 900;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
@ -17,7 +17,7 @@
|
||||
|
||||
@font-face {
|
||||
font-family: "Source Code Pro";
|
||||
src: url("@res/fonts/SourceCodePro-Italic.ttf") format("truetype-variations");
|
||||
src: url("../fonts/SourceCodePro-Italic.ttf") format("truetype-variations");
|
||||
font-weight: 200 900;
|
||||
font-style: italic;
|
||||
font-display: swap;
|
||||
|
||||
@ -1,20 +0,0 @@
|
||||
@import "tailwindcss";
|
||||
@import "tailwindcss/utilities";
|
||||
|
||||
@theme {
|
||||
--breakpoint-popup: 640px;
|
||||
--breakpoint-window: 960px;
|
||||
|
||||
--color-primary: #ff872c;
|
||||
--color-primary-50: #ffddbe;
|
||||
--color-primary-100: #ffcda0;
|
||||
--color-primary-200: #ffbd83;
|
||||
--color-primary-300: #ffac66;
|
||||
--color-primary-400: #ff9a4a;
|
||||
--color-primary-500: #ff872c;
|
||||
--color-primary-600: #de7622;
|
||||
--color-primary-700: #be6518;
|
||||
--color-primary-800: #9f540e;
|
||||
--color-primary-900: #824406;
|
||||
--color-primary-950: #663400;
|
||||
}
|
||||
@ -1,281 +0,0 @@
|
||||
import { CommandInterface } from '@src/common/interfaces/SettingsInterface';
|
||||
import Settings from '@src/ext/lib/settings/Settings';
|
||||
|
||||
const SVG_NS = "http://www.w3.org/2000/svg";
|
||||
|
||||
|
||||
class MenuItemConfig {
|
||||
textSize: number;
|
||||
width: number
|
||||
height: number;
|
||||
|
||||
xPad: number;
|
||||
yPad: number;
|
||||
|
||||
constructor(options: {textSize: number, width: number, xPad: number, yPad: number}) {
|
||||
this.textSize = options.textSize;
|
||||
this.xPad = options.xPad;
|
||||
this.yPad = options.yPad;
|
||||
this.height = options.textSize + 2 * options.yPad;
|
||||
this.width = options.width;
|
||||
}
|
||||
}
|
||||
|
||||
class MenuItem {
|
||||
label: string;
|
||||
hasHover: boolean;
|
||||
clickAction: () => void;
|
||||
parent?: MenuItem;
|
||||
children?: MenuItem[];
|
||||
|
||||
|
||||
svg: any;
|
||||
|
||||
static config: MenuItemConfig;
|
||||
|
||||
static fromCommand(command: CommandInterface, executor: (command: string, args?: any) => void, parent?: MenuItem) {
|
||||
return new MenuItem({
|
||||
label: command.label,
|
||||
clickAction: () => {executor(command.action, command.arguments)},
|
||||
parent: parent
|
||||
});
|
||||
}
|
||||
|
||||
constructor(data: any) {
|
||||
this.label = data.label;
|
||||
this.clickAction = data.clickAction;
|
||||
this.hasHover = false;
|
||||
this.children = [] as MenuItem[];
|
||||
};
|
||||
|
||||
private createSvg() {
|
||||
const group = document.createElementNS(SVG_NS, "g");
|
||||
|
||||
const textElem = document.createElementNS(SVG_NS, "text");
|
||||
textElem.textContent = this.label;
|
||||
textElem.setAttribute('x', `${MenuItem.config.xPad}`);
|
||||
textElem.setAttribute('y', `${MenuItem.config.yPad}`);
|
||||
group.appendChild(textElem);
|
||||
|
||||
// Measure text width safely
|
||||
// const width = textElem.getComputedTextLength() + 2 * hPadding;
|
||||
// const height = fontSize + 2 * vPadding;
|
||||
|
||||
// Background rectangle
|
||||
const rect = document.createElementNS(SVG_NS, "rect");
|
||||
rect.setAttribute('x', '0');
|
||||
rect.setAttribute('y', `0`);
|
||||
rect.setAttribute('width', `${MenuItem.config.width}`);
|
||||
rect.setAttribute('height', `${MenuItem.config.height}`);
|
||||
group.insertBefore(rect, textElem);
|
||||
|
||||
this.svg = group;
|
||||
}
|
||||
|
||||
addSubitem(subitem: MenuItem) {
|
||||
this.children.push(subitem);
|
||||
if (!subitem.parent) {
|
||||
subitem.parent = this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
function buildMenu(settings: Settings, executor: (command: string, args?: any) => void) {
|
||||
const menu = new MenuItem(
|
||||
{label: 'Ultrawidify'}
|
||||
);
|
||||
|
||||
|
||||
const topLevelItems: { label: string; submenu?: CommandInterface[]; isZoom?: boolean }[] = [
|
||||
{ label: "Ultrawidify" },
|
||||
...(settings.active.commands.crop ? [{ label: "Crop", submenu: settings.active.commands.crop }] : []),
|
||||
...(settings.active.commands.stretch ? [{ label: "Stretch", submenu: settings.active.commands.stretch }] : []),
|
||||
...(settings.active.commands.zoom ? [{ label: "Zoom", submenu: settings.active.commands.zoom, isZoom: true }] : []),
|
||||
{ label: "Alignment", submenu: [] },
|
||||
{ label: "Extension settings" },
|
||||
{ label: "Incorrect cropping?" },
|
||||
{ label: "Report problem" }
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
|
||||
function createMenuItem(label) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
export function createSvgMenu(playerEl: HTMLElement, settings: Settings) {
|
||||
if (!settings) {
|
||||
console.warn('trying to create menu, but settings are not defined:', settings, 'player el:', playerEl);
|
||||
return;
|
||||
}
|
||||
|
||||
const style = document.createElement('style');
|
||||
style.textContent = `
|
||||
@font-face {
|
||||
font-family: 'Heebo';
|
||||
src: url(${chrome.runtime.getURL('/ui/res/fonts/Heebo.tff')}) format('truetype');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'SourceCodePro';
|
||||
src: url(${chrome.runtime.getURL('/ui/res/fonts/SourceCodePro.tff')}) format('truetype');
|
||||
}
|
||||
#_uw_player_menu { width:100%; height:100%; position:absolute; top:0; left:0; pointer-events:none; }
|
||||
#_uw_player_menu {
|
||||
.menu { pointer-events:auto; }
|
||||
.menu-item text { font-family: 'Heebo'; font-size:14px; fill:#fff; }
|
||||
.submenu { display:none; }
|
||||
.menu-item:hover > .submenu { display:block; }
|
||||
.hover-zone { fill:transparent; pointer-events:auto; }
|
||||
.menu-item rect { fill:#222; rx:4; }
|
||||
.menu-item:hover > rect { fill:#444; }
|
||||
}
|
||||
`;
|
||||
|
||||
const svg = document.createElementNS(SVG_NS, "svg");
|
||||
svg.setAttribute('id', '_uw_player_menu');
|
||||
svg.append(style);
|
||||
playerEl.appendChild(svg);
|
||||
// shadow.appendChild(svg);
|
||||
|
||||
|
||||
// menuGroup.setAttribute('class', 'menu');
|
||||
svg.appendChild(menuGroup);
|
||||
|
||||
const fontSize = 14;
|
||||
const vPadding = fontSize * 0.4;
|
||||
const hPadding = fontSize * 0.6;
|
||||
|
||||
let currentY = 0;
|
||||
|
||||
// --- Top level items ---
|
||||
const topLevelItems: { label: string; submenu?: CommandInterface[]; isZoom?: boolean }[] = [
|
||||
{ label: "Ultrawidify" },
|
||||
...(settings.active.commands.crop ? [{ label: "Crop", submenu: settings.active.commands.crop }] : []),
|
||||
...(settings.active.commands.stretch ? [{ label: "Stretch", submenu: settings.active.commands.stretch }] : []),
|
||||
...(settings.active.commands.zoom ? [{ label: "Zoom", submenu: settings.active.commands.zoom, isZoom: true }] : []),
|
||||
{ label: "Alignment", submenu: [] },
|
||||
{ label: "Extension settings" },
|
||||
{ label: "Incorrect cropping?" },
|
||||
{ label: "Report problem" }
|
||||
];
|
||||
|
||||
topLevelItems.forEach(item => {
|
||||
const itemGroup = document.createElementNS(SVG_NS, "g");
|
||||
itemGroup.setAttribute('class','menu-item');
|
||||
menuGroup.appendChild(itemGroup);
|
||||
|
||||
// Text element
|
||||
const textElem = document.createElementNS(SVG_NS, "text");
|
||||
textElem.textContent = item.label;
|
||||
textElem.setAttribute('x', `${hPadding}`);
|
||||
textElem.setAttribute('y', `${currentY + fontSize}`);
|
||||
itemGroup.appendChild(textElem);
|
||||
|
||||
// Measure text width safely
|
||||
const width = textElem.getComputedTextLength() + 2 * hPadding;
|
||||
const height = fontSize + 2 * vPadding;
|
||||
|
||||
// Background rectangle
|
||||
const rect = document.createElementNS(SVG_NS, "rect");
|
||||
rect.setAttribute('x', '0');
|
||||
rect.setAttribute('y', `${currentY}`);
|
||||
rect.setAttribute('width', `${width}`);
|
||||
rect.setAttribute('height', `${height}`);
|
||||
itemGroup.insertBefore(rect, textElem);
|
||||
|
||||
// --- Submenu ---
|
||||
if(item.submenu && item.submenu.length > 0) {
|
||||
const submenuGroup = document.createElementNS(SVG_NS, "g");
|
||||
submenuGroup.setAttribute('class','submenu');
|
||||
itemGroup.appendChild(submenuGroup);
|
||||
|
||||
let subY = currentY;
|
||||
item.submenu.forEach(cmd => {
|
||||
const subGroup = document.createElementNS(SVG_NS, "g");
|
||||
subGroup.setAttribute('class','menu-item');
|
||||
submenuGroup.appendChild(subGroup);
|
||||
|
||||
// Submenu text
|
||||
const subText = document.createElementNS(SVG_NS, "text");
|
||||
subText.textContent = cmd.label + (cmd.shortcut ? ` (${cmd.shortcut.key})` : '');
|
||||
subText.setAttribute('x', `${width + hPadding}`);
|
||||
subText.setAttribute('y', `${subY + fontSize}`);
|
||||
subGroup.appendChild(subText);
|
||||
|
||||
const subWidth = subText.getComputedTextLength() + 2*hPadding;
|
||||
const subHeight = fontSize + 2*vPadding;
|
||||
|
||||
const subRect = document.createElementNS(SVG_NS, "rect");
|
||||
subRect.setAttribute('x', `${width}`);
|
||||
subRect.setAttribute('y', `${subY}`);
|
||||
subRect.setAttribute('width', `${subWidth}`);
|
||||
subRect.setAttribute('height', `${subHeight}`);
|
||||
subGroup.insertBefore(subRect, subText);
|
||||
|
||||
subY += subHeight;
|
||||
});
|
||||
|
||||
// Zoom slider
|
||||
if(item.isZoom) {
|
||||
const sliderGroup = document.createElementNS(SVG_NS, "foreignObject");
|
||||
sliderGroup.setAttribute('x', `${width}`);
|
||||
sliderGroup.setAttribute('y', `${subY}`);
|
||||
sliderGroup.setAttribute('width', '150');
|
||||
sliderGroup.setAttribute('height', '40');
|
||||
sliderGroup.innerHTML = `<div style="width:100%;height:100%;background:#333;color:#fff;font-family:Heebo;padding:5px;">Zoom slider placeholder</div>`;
|
||||
submenuGroup.appendChild(sliderGroup);
|
||||
}
|
||||
|
||||
// Hover retention zone
|
||||
const hoverZone = document.createElementNS(SVG_NS, "rect");
|
||||
hoverZone.setAttribute('class','hover-zone');
|
||||
hoverZone.setAttribute('x', `${width}`);
|
||||
hoverZone.setAttribute('y', `${currentY}`);
|
||||
hoverZone.setAttribute('width', '150');
|
||||
hoverZone.setAttribute('height', `${subY - currentY}`);
|
||||
itemGroup.appendChild(hoverZone);
|
||||
}
|
||||
|
||||
currentY += height;
|
||||
});
|
||||
|
||||
// --- Trigger logic ---
|
||||
const activation = settings.active.ui.inPlayer.activation;
|
||||
const triggerZone = settings.active.ui.inPlayer.triggerZoneDimensions;
|
||||
const distanceOptions = settings.active.ui.inPlayer.distanceOptions;
|
||||
|
||||
function updateMenuVisibility(x: number, y: number) {
|
||||
let show = false;
|
||||
const rect = playerEl.getBoundingClientRect();
|
||||
|
||||
if(activation === 'player') {
|
||||
if(x >= 0 && x <= rect.width && y >= 0 && y <= rect.height) show = true;
|
||||
} else if(activation === 'trigger-zone' && triggerZone) {
|
||||
const tx = rect.width * (triggerZone.offsetX / 100);
|
||||
const ty = rect.height * (triggerZone.offsetY / 100);
|
||||
if(x >= tx && x <= tx + triggerZone.width && y >= ty && y <= ty + triggerZone.height) show = true;
|
||||
} else if(activation === 'distance' && distanceOptions) {
|
||||
const dist = distanceOptions.distance / 100 * (distanceOptions.relativeTo === 'width' ? rect.width : rect.height);
|
||||
const cx = rect.width/2;
|
||||
const cy = rect.height/2;
|
||||
if(Math.sqrt((x-cx)**2 + (y-cy)**2) <= dist) show = true;
|
||||
}
|
||||
|
||||
menuGroup.style.display = show ? 'block' : 'none';
|
||||
}
|
||||
|
||||
svg.addEventListener('mousemove', e => {
|
||||
const rect = svg.getBoundingClientRect();
|
||||
const x = e.clientX - rect.left;
|
||||
const y = e.clientY - rect.top;
|
||||
updateMenuVisibility(x,y);
|
||||
});
|
||||
|
||||
menuGroup.style.display = 'none';
|
||||
return { svg, menuGroup };
|
||||
}
|
||||
@ -5,7 +5,6 @@ const WebpackShellPluginNext = require('webpack-shell-plugin-next');
|
||||
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
||||
const { VueLoaderPlugin } = require('vue-loader');
|
||||
const path = require('path');
|
||||
const aliases = require('./paths.config');
|
||||
|
||||
const config = {
|
||||
watchOptions: {
|
||||
@ -33,7 +32,13 @@ const config = {
|
||||
devtool: "source-map",
|
||||
|
||||
resolve: {
|
||||
alias: aliases, // SEE: paths.conf.js
|
||||
alias: {
|
||||
'@src': path.resolve(__dirname, 'src'),
|
||||
'@csui': path.resolve(__dirname, 'src/csui'),
|
||||
'@ui': path.resolve(__dirname, 'src/ui'),
|
||||
'@components': path.resolve(__dirname, 'src/ui/components'),
|
||||
'@': path.resolve(__dirname, 'src'),
|
||||
},
|
||||
// maybe we'll move vue stuff to TS some day, but today is not the day
|
||||
extensions: [
|
||||
'.ts', '.tsx',
|
||||
|
||||
Loading…
Reference in New Issue
Block a user