Compare commits

..

No commits in common. "32c11d1f61274a2714edf3affc55d850ba008990" and "518e09e3cbff4809c459996b689dd58eb1cad1b6" have entirely different histories.

9 changed files with 144 additions and 529 deletions

View File

@ -78,7 +78,9 @@
</Popup> </Popup>
<button class="flex-grow" @click="exportSettings()">Export settings</button> <button class="flex-grow" @click="exportSettings()">Export settings</button>
</div> </div>
<div></div> <div>
</div>
<ConfirmButton <ConfirmButton
dialogType="danger" dialogType="danger"
@onConfirmed="resetSettings" @onConfirmed="resetSettings"
@ -128,10 +130,15 @@
</JsonEditor> </JsonEditor>
</div> </div>
<h2>Settings migration report</h2>
<pre>
{{settings.migrationReport}}
</pre>
<h2>Settings snapshots</h2> <h2>Settings snapshots</h2>
<div class="flex flex-col"> <div class="flex flex-col">
<div v-for="(snapshot, index) of settingsSnapshots" :key="snapshot.createdAt"> <div v-for="(snapshot, index) of settingsSnapshots" :key="snapshot.createdAt">
<small>{{new Date(snapshot.createdAt).toISOString()}}</small> <small>{{snapshot.createdAt.toISOString()}}</small>
<div class="flex flex-row"> <div class="flex flex-row">
<div class="grow"> <div class="grow">
{{snapshot.name}} {{snapshot.name}}
@ -201,7 +208,6 @@ export default {
}, },
mounted() { mounted() {
this.resetSettingsEditor(); this.resetSettingsEditor();
this.loadSettingsSnapshots();
}, },
methods: { methods: {
setTab(tab) { setTab(tab) {

View File

@ -134,25 +134,16 @@
</template> </template>
<script> <script>
import ShortcutButton from '@csui/src/components/ShortcutButton.vue'; import ShortcutButton from '../../../components/ShortcutButton.vue';
import EditShortcutButton from '@csui/src/components/EditShortcutButton'; import EditShortcutButton from '../../../components/EditShortcutButton';
import EditModeMixin from '@csui/src/utils/EditModeMixin'; import EditModeMixin from '../../../utils/EditModeMixin';
import KeyboardShortcutParserMixin from '@csui/src/utils/KeyboardShortcutParserMixin'; import KeyboardShortcutParserMixin from '../../../utils/KeyboardShortcutParserMixin';
import CommsMixin from '@csui/src/utils/CommsMixin'; import CommsMixin from '../../../utils/CommsMixin';
import AspectRatioType from '@src/common/enums/AspectRatioType.enum'; import AspectRatioType from '../../../../../common/enums/AspectRatioType.enum';
export default { export default {
components: {
ShortcutButton,
EditShortcutButton,
},
mixins: [
// ComputeActionsMixin,
EditModeMixin,
KeyboardShortcutParserMixin,
CommsMixin
],
data() { data() {
return { return {
AspectRatioType: AspectRatioType, AspectRatioType: AspectRatioType,
@ -165,6 +156,12 @@ export default {
} }
} }
}, },
mixins: [
// ComputeActionsMixin,
EditModeMixin,
KeyboardShortcutParserMixin,
CommsMixin
],
props: [ props: [
'settings', // required for buttons and actions, which are global 'settings', // required for buttons and actions, which are global
'siteSettings', 'siteSettings',
@ -172,6 +169,10 @@ export default {
'isEditing', 'isEditing',
'allowSettingSiteDefault' 'allowSettingSiteDefault'
], ],
components: {
ShortcutButton,
EditShortcutButton,
},
computed: { computed: {
siteDefaultCrop() { siteDefaultCrop() {
if (!this.siteSettings) { if (!this.siteSettings) {

View File

@ -50,10 +50,10 @@
v-model="editModeOptions.stretch.selected.arguments.limit" v-model="editModeOptions.stretch.selected.arguments.limit"
> >
</div> </div>
</div> <div class="hint">
<div class="hint"> If vertical borders would take up less than this much of screen width, the image will be stretched. If the borders are too thick, image will not be stretched.
If vertical borders would take up less than this much of screen width, the image will be stretched. If the borders are too thick, image will not be stretched. Value of 1 means 100%. Value of 0.1 means vertical black bars can take up 10% of the width at most. There's no validation on this, use common sense.
Value of 1 means 100%. Value of 0.1 means vertical black bars can take up 10% of the width at most. There's no validation on this, use common sense. </div>
</div> </div>
</template> </template>
@ -70,12 +70,12 @@
@blur="editModeOptions.stretch.selected.label === 'Stretch to ...' ? editModeOptions.stretch.selected.label = `Stretch to ${editModeOptions.stretch.selected.arguments.ratio}` : null" @blur="editModeOptions.stretch.selected.label === 'Stretch to ...' ? editModeOptions.stretch.selected.label = `Stretch to ${editModeOptions.stretch.selected.arguments.ratio}` : null"
> >
</div> </div>
</div> <div class="hint">
<div class="hint">
You can enter a ratio in width:height format (e.g. "21:9" or "1:2.39"), or just the factor You can enter a ratio in width:height format (e.g. "21:9" or "1:2.39"), or just the factor
(in this case, "1:2.39" would become "2.39" and "21:9" would become "2.33"). You should enter (in this case, "1:2.39" would become "2.39" and "21:9" would become "2.33"). You should enter
your numbers without quote marks. Number will be converted to factor form on save. your numbers without quote marks. Number will be converted to factor form on save.
</div> </div>
</div>
<div class="field"> <div class="field">
<div class="label"> <div class="label">
Label: Label:
@ -83,9 +83,9 @@
<div class="input"> <div class="input">
<input v-model="editModeOptions.stretch.selected.label"> <input v-model="editModeOptions.stretch.selected.label">
</div> </div>
</div> <div class="hint">
<div class="hint"> Label for the button. You can make it say something other than ratio.
Label for the button. You can make it say something other than ratio. </div>
</div> </div>
</template> </template>
@ -99,11 +99,11 @@
> >
</EditShortcutButton> </EditShortcutButton>
</div> </div>
</div> <div class="hint">
<div class="hint"> <b>Note:</b> Your browser and OS already use certain key combinations that involve Ctrl and Meta (Windows) keys and, to a lesser extent, Alt.
<b>Note:</b> Your browser and OS already use certain key combinations that involve Ctrl and Meta (Windows) keys and, to a lesser extent, Alt. The extension doesn't (and cannot) check whether the keyboard shortcut you enter is actually free for you to use. The extension also won't override
The extension doesn't (and cannot) check whether the keyboard shortcut you enter is actually free for you to use. The extension also won't override any keyboard shortcuts defined by the site itself.
any keyboard shortcuts defined by the site itself. </div>
</div> </div>
<div class="flex flex-row flex-end"> <div class="flex flex-row flex-end">

View File

@ -1,232 +1,86 @@
<template> <template>
<div class="flex flex-col"> <div class="flex flex-col">
<!--
<div class="sub-panel-content flex flex-row flex-wrap"> min, max and value need to be implemented in js as this slider
should use logarithmic scale
<ShortcutButton -->
v-for="(command, index) of settings?.active.commands.zoom" <div class="flex flex-row flex-end">
class="flex b3 button" <Button
:class="{active: editMode ? index === editModeOptions?.zoom?.selectedIndex : isActiveZoom(command)}" v-if="zoomAspectRatioLocked"
:key="index" label="Unlock aspect ratio"
:label="command.label" icon="lock-open"
:shortcut="getKeyboardShortcutLabel(command)" :fixedWidth="true"
@click="editMode ? editAction(command, index, 'zoom') : execAction(command)" @click="toggleZoomAr()"
> >
</ShortcutButton> </Button>
<Button
<!-- "Add new" button --> v-else
<ShortcutButton label="Lock aspect ratio"
v-if="editMode" icon="lock"
class="button b3" :fixedWidth="true"
:class="{active: editMode ? editModeOptions?.crop?.selectedIndex === null : isActiveCrop(command)}" @click="toggleZoomAr()"
label="Add new" >
@click="editAction( </Button>
{action: 'set-ar-zoom', label: 'New aspect ratio', arguments: {type: AspectRatioType.Fixed}},
null,
'zoom'
)"
></ShortcutButton>
</div> </div>
<template v-if="zoomAspectRatioLocked">
<template v-if="isEditing"> <input id="_input_zoom_slider"
<div v-if="editMode && editModeOptions?.zoom?.selected" class="sub-panel-content"> class="input-slider"
<div class="edit-action-area-header"> type="range"
<span class="text-primary">Editing options for:</span> <b>{{editModeOptions?.zoom?.selected?.label}}</b>&nbsp; step="any"
<template v-if="editModeOptions?.zoom?.selectedIndex === null && editModeOptions?.zoom?.selected?.label !== 'New aspect ratio'">(New ratio)</template> min="-1"
max="3"
:value="zoom.x"
@input="changeZoom($event.target.value)"
/>
<div style="overflow: auto" class="flex flex-row">
<div class="flex flex-grow medium-small x-pad-1em">
Zoom: {{getZoomForDisplay('x')}}
</div> </div>
<div class="edit-action-area"> <div class="flex flex-nogrow flex-noshrink medium-small">
<!-- Some options are only shown for type 4 (fixed) zooms --> <a class="_zoom_reset x-pad-1em" @click="resetZoom()">reset</a>
<template v-if="editModeOptions?.zoom?.selected?.arguments?.type === AspectRatioType.Fixed">
<div class="field">
<div class="label">
Ratio:
</div>
<div class="input">
<!-- We do an ugly in order to avoid spamming functions down at the bottom -->
<input
v-model="editModeOptions.zoom.selected.arguments.ratio"
@blur="editModeOptions.zoom.selected.label === 'New aspect ratio' ? editModeOptions.zoom.selected.label = editModeOptions.zoom.selected.arguments.ratio : null"
>
</div>
</div>
<div class="hint">
You can enter a ratio in width:height format (e.g. "21:9" or "1:2.39"), or just the factor
(in this case, "1:2.39" would become "2.39" and "21:9" would become "2.33"). You should enter
your numbers without quote marks. Number will be converted to factor form on save.
</div>
<div class="field">
<div class="label">
Label:
</div>
<div class="input">
<input v-model="editModeOptions.zoom.selected.label">
</div>
</div>
<div class="hint">
Label for the button. You can make it say something other than ratio.
</div>
</template>
<!-- editing keyboard shortcuts is always allowed -->
<div class="field">
<div class="label">Shortcut:</div>
<div class="">
<EditShortcutButton
:shortcut="editModeOptions?.zoom?.selected?.shortcut"
@shortcutChanged="updateSelectedShortcut($event, 'zoom')"
>
</EditShortcutButton>
</div>
</div>
<div class="hint">
<b>Note:</b> Your browser and OS already use certain key combinations that involve Ctrl and Meta (Windows) keys and, to a lesser extent, Alt.
The extension doesn't (and cannot) check whether the keyboard shortcut you enter is actually free for you to use. The extension also won't override
any keyboard shortcuts defined by the site itself.
</div>
<div class="flex flex-row flex-end">
<div
v-if="editModeOptions?.zoom?.selected?.arguments?.type === AspectRatioType.Fixed && editModeOptions?.zoom?.selectedIndex !== null"
class="button"
@click="deleteAction('zoom')"
>
<mdicon name="delete"></mdicon> Delete
</div>
<div class="flex-grow"></div>
<div class="button" @click="cancelEdit('zoom')">Cancel</div>
<div class="button" @click="saveShortcut('zoom')">
<mdicon name="floppy"></mdicon>
&nbsp;
<template v-if="editModeOptions?.zoom?.selectedIndex === null">Add</template>
<template v-else>Save</template>
</div>
</div>
</div> </div>
</div> </div>
<!-- <div v-if="siteSettings && allowSettingSiteDefault" class="edit-action-area">
<div class="field">
<div class="label">Default for this site</div>
<div class="select">
<select
:value="siteDefaultZoom"
@change="setDefaultZoom($event, 'site')"
>
<option
v-for="(command, index) of settings?.active.commands.zoom"
:key="index"
:value="JSON.stringify(command.arguments)"
>
{{command.label}}
</option>
</select>
</div>
</div>
</div> -->
</template> </template>
<template v-else> <template v-else>
<!-- <div>Horizontal zoom</div>
min, max and value need to be implemented in js as this slider <input id="_input_zoom_slider"
should use logarithmic scale class="input-slider"
--> type="range"
<div class="flex flex-row flex-end"> step="any"
<Button min="-1"
v-if="zoomAspectRatioLocked" max="4"
label="Unlock aspect ratio" :value="zoom.x"
icon="lock-open" @input="changeZoom($event.target.value, 'x')"
:fixedWidth="true" />
@click="toggleZoomAr()"
> <div>Vertical zoom</div>
</Button> <input id="_input_zoom_slider"
<Button class="input-slider"
v-else type="range"
label="Lock aspect ratio" step="any"
icon="lock" min="-1"
:fixedWidth="true" max="3"
@click="toggleZoomAr()" :value="zoom.y"
> @input="changeZoom($event.target.value, 'y')"
</Button> />
<div style="overflow: auto" class="flex flex-row">
<div class="flex flex-grow medium-small x-pad-1em">
Zoom: {{getZoomForDisplay('x')}} x {{getZoomForDisplay('y')}}
</div>
<div class="flex flex-nogrow flex-noshrink medium-small">
<a class="_zoom_reset x-pad-1em" @click="resetZoom()">reset</a>
</div>
</div> </div>
<template v-if="zoomAspectRatioLocked">
<input id="_input_zoom_slider"
class="input-slider"
type="range"
step="any"
min="-1"
max="3"
:value="zoom.x"
@input="changeZoom($event.target.value)"
/>
<div style="overflow: auto" class="flex flex-row">
<div class="flex flex-grow medium-small x-pad-1em">
Zoom: {{getZoomForDisplay('x')}}
</div>
<div class="flex flex-nogrow flex-noshrink medium-small">
<a class="_zoom_reset x-pad-1em" @click="resetZoom()">reset</a>
</div>
</div>
</template>
<template v-else>
<div>Horizontal zoom</div>
<input id="_input_zoom_slider"
class="input-slider"
type="range"
step="any"
min="-1"
max="4"
:value="zoom.x"
@input="changeZoom($event.target.value, 'x')"
/>
<div>Vertical zoom</div>
<input id="_input_zoom_slider"
class="input-slider"
type="range"
step="any"
min="-1"
max="3"
:value="zoom.y"
@input="changeZoom($event.target.value, 'y')"
/>
<div style="overflow: auto" class="flex flex-row">
<div class="flex flex-grow medium-small x-pad-1em">
Zoom: {{getZoomForDisplay('x')}} x {{getZoomForDisplay('y')}}
</div>
<div class="flex flex-nogrow flex-noshrink medium-small">
<a class="_zoom_reset x-pad-1em" @click="resetZoom()">reset</a>
</div>
</div>
</template>
</template> </template>
</div> </div>
</template> </template>
<script> <script>
import ShortcutButton from '@csui/src/components/ShortcutButton.vue';
import EditShortcutButton from '@csui/src/components/EditShortcutButton';
import EditModeMixin from '@csui/src/utils/EditModeMixin';
import KeyboardShortcutParserMixin from '@csui/src/utils/KeyboardShortcutParserMixin';
import CommsMixin from '@csui/src/utils/CommsMixin';
import AspectRatioType from '@src/common/enums/AspectRatioType.enum';
export default { export default {
components: {
ShortcutButton,
EditShortcutButton,
},
mixins: [
// ComputeActionsMixin,
EditModeMixin,
KeyboardShortcutParserMixin,
CommsMixin
],
data() { data() {
return { return {
AspectRatioType,
zoomAspectRatioLocked: true, zoomAspectRatioLocked: true,
zoom: { zoom: {
x: 0, x: 0,
@ -242,26 +96,15 @@ export default {
} }
} }
}, },
mixins: [
],
props: [ props: [
'settings', // required for buttons and actions, which are global 'settings', // required for buttons and actions, which are global
'siteSettings', 'siteSettings',
'eventBus', 'eventBus',
'isEditing' 'isEditing'
], ],
created() {
if (this.isEditing) {
this.enableEditMode();
}
},
watch: {
isEditing(newValue, oldValue) {
if (newValue) {
this.enableEditMode();
} else {
this.disableEditMode();
}
}
},
methods: { methods: {
getZoomForDisplay(axis) { getZoomForDisplay(axis) {
// zoom is internally handled logarithmically, because we want to have x0.5, x1, x2, x4 ... magnifications // zoom is internally handled logarithmically, because we want to have x0.5, x1, x2, x4 ... magnifications
@ -303,9 +146,6 @@ export default {
this.eventBus?.sendToTunnel('set-zoom', {zoom: newZoom, axis: axis ?? 'x'}); this.eventBus?.sendToTunnel('set-zoom', {zoom: newZoom, axis: axis ?? 'x'});
} }
}, },
isActiveZoom(command) {
return false;
}
} }
} }

View File

@ -135,19 +135,6 @@
:isEditing="true" :isEditing="true"
></StretchOptionsPanel> ></StretchOptionsPanel>
</div> </div>
<!-- ZOOM OPTIONS -->
<div>
<div class="flex flex-row">
<h3 class="mth3">ZOOM OPTIONS</h3>
</div>
<ZoomOptionsPanel
:settings="settings"
:eventBus="eventBus"
:isEditing="true"
></ZoomOptionsPanel>
</div>
</div> </div>
</div> </div>
@ -155,18 +142,16 @@
</template> </template>
<script> <script>
import Button from '@csui/src/components/Button.vue' import Button from '../components/Button.vue'
import BrowserDetect from '@src/ext/conf/BrowserDetect'; import BrowserDetect from '../../../ext/conf/BrowserDetect';
import CropOptionsPanel from '@csui/src/PlayerUiPanels/PanelComponents/VideoSettings/CropOptionsPanel.vue' import CropOptionsPanel from './PanelComponents/VideoSettings/CropOptionsPanel.vue'
import StretchOptionsPanel from '@csui/src/PlayerUiPanels/PanelComponents/VideoSettings/StretchOptionsPanel.vue' import StretchOptionsPanel from './PanelComponents/VideoSettings/StretchOptionsPanel.vue'
import ZoomOptionsPanel from '@csui/src/PlayerUiPanels/PanelComponents/VideoSettings/ZoomOptionsPanel.vue'
export default { export default {
components: { components: {
Button, Button,
CropOptionsPanel, CropOptionsPanel,
StretchOptionsPanel, StretchOptionsPanel
ZoomOptionsPanel,
}, },
data() { data() {
return { return {
@ -282,7 +267,7 @@ export default {
gap: 1rem; gap: 1rem;
> * { > * {
width: calc(33% - 0.5rem); width: calc(50% - 0.5rem);
} }
} }

View File

@ -10,7 +10,7 @@ import CropModePersistence from '../../common/enums/CropModePersistence.enum';
import AspectRatioType from '../../common/enums/AspectRatioType.enum'; import AspectRatioType from '../../common/enums/AspectRatioType.enum';
import { update } from 'lodash'; import { update } from 'lodash';
const ExtensionConfPatch = Object.freeze([ const ExtensionConfPatch = [
{ {
forVersion: '6.2.4', forVersion: '6.2.4',
updateFn: (userOptions: SettingsInterface, defaultOptions) => { updateFn: (userOptions: SettingsInterface, defaultOptions) => {
@ -35,19 +35,6 @@ const ExtensionConfPatch = Object.freeze([
}, { }, {
forVersion: '6.2.6', forVersion: '6.2.6',
updateFn: (userOptions: SettingsInterface, defaultOptions) => { updateFn: (userOptions: SettingsInterface, defaultOptions) => {
console.warn('[ultrawidify] STARTING SETTINGS MIGRATION TO 6.2.6');
if (!userOptions.commands) {
userOptions.commands = {
zoom: [],
crop: [],
stretch: [],
pan: [],
internal: []
};
}
userOptions.commands.zoom = [{ userOptions.commands.zoom = [{
action: 'change-zoom', action: 'change-zoom',
label: 'Zoom +5%', label: 'Zoom +5%',
@ -105,139 +92,9 @@ const ExtensionConfPatch = Object.freeze([
showDetectionDetails: true showDetectionDetails: true
} }
} }
const newZoomActions = [{
action: 'set-zoom',
label: 'Reset zoom',
shortcut: {
key: 'r',
code: 'KeyR',
ctrlKey: false,
metaKey: false,
altKey: false,
shiftKey: true,
onKeyUp: true,
onKeyDown: false,
},
internalOnly: true,
actionId: 'set-zoom-reset'
}, {
action: 'set-ar-zoom',
label: 'Automatic',
comment: 'Automatically detect aspect ratio and zoom accordingly',
arguments: {
type: AspectRatioType.Automatic
},
shortcut: {
key: 'a',
code: 'KeyA',
ctrlKey: false,
metaKey: false,
altKey: false,
shiftKey: true,
onKeyUp: true,
onKeyDown: false,
}
}, {
action: 'set-ar-zoom',
label: 'Cycle',
comment: 'Cycle through zoom options',
arguments: {
type: AspectRatioType.Cycle
},
shortcut: {
key: 'c',
code: 'KeyC',
ctrlKey: false,
metaKey: false,
altKey: false,
shiftKey: true,
onKeyUp: true,
onKeyDown: false,
}
}, {
action: 'set-ar-zoom',
label: '21:9',
comment: 'Zoom for 21:9 aspect ratio (1:2.39)',
arguments: {
type: AspectRatioType.Fixed,
ratio: 2.39
},
shortcut: {
key: 'd',
code: 'KeyD',
ctrlKey: false,
metaKey: false,
altKey: false,
shiftKey: true,
onKeyUp: false,
onKeyDown: true,
}
}, {
action: 'set-ar-zoom',
label: '18:9',
comment: 'Zoom for 18:9 aspect ratio (1:2)',
arguments: {
type: AspectRatioType.Fixed,
ratio: 1.78
},
shortcut: {
key: 's',
code: 'KeyS',
ctrlKey: false,
metaKey: false,
altKey: false,
shiftKey: true,
onKeyUp: false,
onKeyDown: true,
}
}, {
action: 'set-ar-zoom',
label: '32:9',
comment: 'Zoom for 32:9 aspect ratio',
arguments: {
type: AspectRatioType.Fixed,
ratio: 3.56
},
}];
const compareShortcuts = (a: any, b: any) => {
if (!a || !b) {
return false;
}
return a.key === b.key && b.code === b.code && a.ctrlKey == b.ctrlKey && a.shiftKey == b.shiftKey && a.metaKey == a.metaKey && a.altKey == b.altKey;
}
const hasConflict = (shortcut: any) => {
for (const ct in userOptions.commands) {
for (const command of userOptions.commands[ct]) {
if (compareShortcuts(shortcut, command.shortcut)) {
return true;
}
}
}
return false;
}
for (const zoomAction of newZoomActions) {
if (
!userOptions.commands.zoom.find(
x => x.action === zoomAction.action
&& x.arguments?.type === zoomAction.arguments?.type
&& x.arguments?.ratio === zoomAction.arguments?.ratio
)
) {
userOptions.commands.zoom.push({
...zoomAction,
shortcut: hasConflict(zoomAction.shortcut) ? undefined : zoomAction.shortcut
});
}
}
} }
} }
]); ];
export default ExtensionConfPatch; export default ExtensionConfPatch;

View File

@ -401,96 +401,11 @@ const ExtensionConf: SettingsInterface = {
}, { }, {
action: 'set-zoom', action: 'set-zoom',
label: 'Reset zoom', label: 'Reset zoom',
shortcut: { arguments: {
key: 'r', zoom: 1,
code: 'KeyR',
ctrlKey: false,
metaKey: false,
altKey: false,
shiftKey: true,
onKeyUp: true,
onKeyDown: false,
}, },
internalOnly: true, internalOnly: true,
actionId: 'set-zoom-reset' actionId: 'set-zoom-reset'
}, {
action: 'set-ar-zoom',
label: 'Automatic',
comment: 'Automatically detect aspect ratio',
arguments: {
type: AspectRatioType.Automatic
},
shortcut: {
key: 'a',
code: 'KeyA',
ctrlKey: false,
metaKey: false,
altKey: false,
shiftKey: true,
onKeyUp: true,
onKeyDown: false,
}
}, {
action: 'set-ar-zoom',
label: 'Cycle',
comment: 'Cycle through crop options',
arguments: {
type: AspectRatioType.Cycle
},
shortcut: {
key: 'c',
code: 'KeyC',
ctrlKey: false,
metaKey: false,
altKey: false,
shiftKey: true,
onKeyUp: true,
onKeyDown: false,
}
}, {
action: 'set-ar-zoom',
label: '21:9',
comment: 'Crop for 21:9 aspect ratio (1:2.39)',
arguments: {
type: AspectRatioType.Fixed,
ratio: 2.39
},
shortcut: {
key: 'd',
code: 'KeyD',
ctrlKey: false,
metaKey: false,
altKey: false,
shiftKey: true,
onKeyUp: false,
onKeyDown: true,
}
}, {
action: 'set-ar-zoom',
label: '18:9',
comment: 'Crop for 18:9 aspect ratio (1:2)',
arguments: {
type: AspectRatioType.Fixed,
ratio: 1.78
},
shortcut: {
key: 's',
code: 'KeyS',
ctrlKey: false,
metaKey: false,
altKey: false,
shiftKey: true,
onKeyUp: false,
onKeyDown: true,
}
}, {
action: 'set-ar-zoom',
label: '32:9',
comment: 'Crop for 32:9 aspect ratio',
arguments: {
type: AspectRatioType.Fixed,
ratio: 3.56
},
}], }],
pan: [{ pan: [{
action: 'set-alignment', action: 'set-alignment',

View File

@ -44,9 +44,18 @@ class Settings {
onChangedCallbacks: (() => void)[] = []; onChangedCallbacks: (() => void)[] = [];
afterSettingsChangedCallbacks: (() => void)[] = []; afterSettingsChangedCallbacks: (() => void)[] = [];
private sortedPatches: any[];
public snapshotManager: SettingsSnapshotManager; public snapshotManager: SettingsSnapshotManager;
private _migrationReport: string = '';
private set migrationReport(report: string) {
this._migrationReport = report;
}
public get migrationReport(): string {
return this._migrationReport;
}
//#endregion //#endregion
constructor(options) { constructor(options) {
@ -61,6 +70,9 @@ class Settings {
this.default['version'] = this.getExtensionVersion(); this.default['version'] = this.getExtensionVersion();
chrome.storage.onChanged.addListener((changes, area) => {this.storageChangeListener(changes, area)}); chrome.storage.onChanged.addListener((changes, area) => {this.storageChangeListener(changes, area)});
this.sortedPatches = this.sortConfPatches(ExtensionConfPatch);
} }
private storageChangeListener(changes, area) { private storageChangeListener(changes, area) {
@ -182,7 +194,7 @@ class Settings {
} }
private findFirstNecessaryPatch(version) { private findFirstNecessaryPatch(version) {
return ExtensionConfPatch.findIndex(x => this.compareExtensionVersions(x.forVersion, version) > 0); return this.sortedPatches.findIndex(x => this.compareExtensionVersions(x.forVersion, version) > 0);
} }
private applySettingsPatches(oldVersion) { private applySettingsPatches(oldVersion) {
let index = this.findFirstNecessaryPatch(oldVersion); let index = this.findFirstNecessaryPatch(oldVersion);
@ -205,20 +217,20 @@ class Settings {
// apply all remaining patches // apply all remaining patches
this.logger?.log('info', 'settings', `[Settings::applySettingsPatches] There are ${ExtensionConfPatch.length - index} settings patches to apply`); this.logger?.log('info', 'settings', `[Settings::applySettingsPatches] There are ${this.sortedPatches.length - index} settings patches to apply`);
while (index < ExtensionConfPatch.length) { while (index < this.sortedPatches.length) {
const updateFn = ExtensionConfPatch[index].updateFn; const updateFn = this.sortedPatches[index].updateFn;
delete this.sortedPatches[index].forVersion;
delete this.sortedPatches[index].updateFn;
if (Object.keys( this.sortedPatches[index]).length > 0) {
ObjectCopy.overwrite(this.active, this.sortedPatches[index]);
}
if (updateFn) { if (updateFn) {
try { try {
updateFn(this.active, this.getDefaultSettings()); updateFn(this.active, this.getDefaultSettings());
} catch (e) { } catch (e) {
this.logger?.log('error', 'settings', '[Settings::applySettingsPatches] Failed to execute update function. Keeping settings object as-is. Error:', e); this.logger?.log('error', 'settings', '[Settings::applySettingsPatches] Failed to execute update function. Keeping settings object as-is. Error:', e);
console.warn(
'————————————————————————————————————\n',
'Applying patch', index, ' failed :', '\n',
e, '\n',
'————————————————————————————————————\n',
);
} }
} }
@ -242,7 +254,7 @@ class Settings {
// |—> on first setup, settings is undefined & settings.version is haram // |—> on first setup, settings is undefined & settings.version is haram
// | since new installs ship with updates by default, no patching is // | since new installs ship with updates by default, no patching is
// | needed. In this case, we assume we're on the current version // | needed. In this case, we assume we're on the current version
const oldVersion = settings?.version ?? this.version; const oldVersion = (settings && settings.version) || this.version;
if (settings) { if (settings) {
this.logger?.log('info', 'settings', "[Settings::init] Configuration fetched from storage:", settings, this.logger?.log('info', 'settings', "[Settings::init] Configuration fetched from storage:", settings,
@ -264,7 +276,6 @@ class Settings {
this.active = this.getDefaultSettings(); this.active = this.getDefaultSettings();
this.active.version = this.version; this.active.version = this.version;
await this.save(); await this.save();
return this.active; return this.active;
} }
@ -328,6 +339,7 @@ class Settings {
if (!options || !options.forcePreserveVersion) { if (!options || !options.forcePreserveVersion) {
extensionConf.version = this.version; extensionConf.version = this.version;
} }
this.logger?.log('info', 'settings', "[Settings::set] setting new settings:", extensionConf) this.logger?.log('info', 'settings', "[Settings::set] setting new settings:", extensionConf)
return chrome.storage.local.set( {'uwSettings': JSON.stringify(extensionConf)}); return chrome.storage.local.set( {'uwSettings': JSON.stringify(extensionConf)});
@ -373,7 +385,7 @@ class Settings {
async save(options?: SetSettingsOptions) { async save(options?: SetSettingsOptions) {
if (Debug.debug && Debug.storage) { if (Debug.debug && Debug.storage) {
console.log("[Settings::save] Saving active settings — save options", options, "; settings:", this.active); console.log("[Settings::save] Saving active settings:", this.active);
} }
this.active.preventReload = undefined; this.active.preventReload = undefined;
this.active.lastModified = new Date(); this.active.lastModified = new Date();

View File

@ -92,14 +92,13 @@ export class SettingsSnapshotManager {
async listSnapshots(): Promise<SettingsSnapshot[]> { async listSnapshots(): Promise<SettingsSnapshot[]> {
const ret = await chrome.storage.local.get('uwSettings-snapshots'); const ret = await chrome.storage.local.get('uwSettings-snapshots');
try { try {
const json = JSON.parse(ret['uwSettings-snapshots']) as SettingsSnapshot[]; JSON.parse(ret['uwSettings-snapshots']) as SettingsSnapshot[];
return json;
} catch (e) { } catch (e) {
return [] as SettingsSnapshot[]; return [] as SettingsSnapshot[];
} }
} }
private async set(snapshots: SettingsSnapshot[] = []) { private async set(snapshots: SettingsSnapshot[]) {
await chrome.storage.local.set({ await chrome.storage.local.set({
'uwSettings-snapshots': JSON.stringify(snapshots), 'uwSettings-snapshots': JSON.stringify(snapshots),
}); });