Settings snapshots
This commit is contained in:
parent
ae2bb7afcd
commit
391b0ac7ab
@ -21,7 +21,6 @@ const ExtensionConfPatch = [
|
|||||||
normal: ExtensionMode.Default,
|
normal: ExtensionMode.Default,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const uiEnabled =
|
|
||||||
userOptions.sites['@global'].enableUI = {
|
userOptions.sites['@global'].enableUI = {
|
||||||
fullscreen: userOptions.ui.inPlayer.enabled ? ExtensionMode.Enabled : ExtensionMode.Disabled,
|
fullscreen: userOptions.ui.inPlayer.enabled ? ExtensionMode.Enabled : ExtensionMode.Disabled,
|
||||||
theater: ExtensionMode.Enabled,
|
theater: ExtensionMode.Enabled,
|
||||||
@ -84,6 +83,9 @@ const ExtensionConfPatch = [
|
|||||||
|
|
||||||
delete (userOptions as any).actions;
|
delete (userOptions as any).actions;
|
||||||
|
|
||||||
|
userOptions.dev = {
|
||||||
|
loadFromSnapshot: false
|
||||||
|
};
|
||||||
userOptions.ui.dev = {
|
userOptions.ui.dev = {
|
||||||
aardDebugOverlay: {
|
aardDebugOverlay: {
|
||||||
showOnStartup: false,
|
showOnStartup: false,
|
||||||
|
@ -14,6 +14,10 @@ if(Debug.debug)
|
|||||||
console.log("Loading: ExtensionConf.js");
|
console.log("Loading: ExtensionConf.js");
|
||||||
|
|
||||||
const ExtensionConf: SettingsInterface = {
|
const ExtensionConf: SettingsInterface = {
|
||||||
|
dev: {
|
||||||
|
loadFromSnapshot: false,
|
||||||
|
},
|
||||||
|
|
||||||
arDetect: {
|
arDetect: {
|
||||||
aardType: 'auto',
|
aardType: 'auto',
|
||||||
|
|
||||||
@ -728,6 +732,46 @@ const ExtensionConf: SettingsInterface = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"www.youtube-nocookie.com": {
|
||||||
|
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
|
||||||
|
},
|
||||||
|
|
||||||
|
override: false, // ignore value localStorage in favour of this
|
||||||
|
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: 'official',
|
||||||
|
elements: {
|
||||||
|
player: {
|
||||||
|
manual: true,
|
||||||
|
querySelectors: "#movie_player, #player, #c4-player",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"www.netflix.com" : {
|
"www.netflix.com" : {
|
||||||
enable: {
|
enable: {
|
||||||
fullscreen: ExtensionMode.Enabled,
|
fullscreen: ExtensionMode.Enabled,
|
||||||
|
@ -12,11 +12,15 @@ import Logger from './Logger';
|
|||||||
import SettingsInterface from '../../common/interfaces/SettingsInterface';
|
import SettingsInterface from '../../common/interfaces/SettingsInterface';
|
||||||
import AspectRatioType from '../../common/enums/AspectRatioType.enum';
|
import AspectRatioType from '../../common/enums/AspectRatioType.enum';
|
||||||
import { SiteSettings } from './settings/SiteSettings';
|
import { SiteSettings } from './settings/SiteSettings';
|
||||||
|
import { SettingsSnapshotManager } from './settings/SettingsSnapshotManager';
|
||||||
|
|
||||||
if(process.env.CHANNEL !== 'stable'){
|
if(process.env.CHANNEL !== 'stable'){
|
||||||
console.info("Loading Settings");
|
console.info("Loading Settings");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface SetSettingsOptions {
|
||||||
|
forcePreserveVersion?: boolean,
|
||||||
|
}
|
||||||
|
|
||||||
class Settings {
|
class Settings {
|
||||||
//#region flags
|
//#region flags
|
||||||
@ -41,6 +45,17 @@ class Settings {
|
|||||||
afterSettingsChangedCallbacks: (() => void)[] = [];
|
afterSettingsChangedCallbacks: (() => void)[] = [];
|
||||||
|
|
||||||
private sortedPatches: any[];
|
private sortedPatches: any[];
|
||||||
|
|
||||||
|
|
||||||
|
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) {
|
||||||
@ -50,11 +65,14 @@ class Settings {
|
|||||||
this.afterSettingsSaved = options?.afterSettingsSaved;
|
this.afterSettingsSaved = options?.afterSettingsSaved;
|
||||||
this.active = options?.activeSettings ?? undefined;
|
this.active = options?.activeSettings ?? undefined;
|
||||||
this.default = ExtensionConf;
|
this.default = ExtensionConf;
|
||||||
|
this.snapshotManager = new SettingsSnapshotManager();
|
||||||
|
|
||||||
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);
|
this.sortedPatches = this.sortConfPatches(ExtensionConfPatch);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private storageChangeListener(changes, area) {
|
private storageChangeListener(changes, area) {
|
||||||
@ -186,6 +204,18 @@ class Settings {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// save current settings object
|
||||||
|
const currentSettings = this.active;
|
||||||
|
|
||||||
|
this.snapshotManager.createSnapshot(
|
||||||
|
JSON.parse(JSON.stringify(currentSettings)),
|
||||||
|
{
|
||||||
|
label: 'Pre-migration snapshot',
|
||||||
|
isAutomatic: true
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
// apply all remaining patches
|
// apply all remaining patches
|
||||||
this.logger?.log('info', 'settings', `[Settings::applySettingsPatches] There are ${this.sortedPatches.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 < this.sortedPatches.length) {
|
while (index < this.sortedPatches.length) {
|
||||||
@ -209,7 +239,16 @@ class Settings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async init() {
|
async init() {
|
||||||
const settings = await this.get();
|
let settings = await this.get();
|
||||||
|
|
||||||
|
if (settings?.dev?.loadFromSnapshot) {
|
||||||
|
this.logger?.log('info', 'settings', '[Settings::init] Dev mode is enabled, Loading settings from snapshot:', settings.dev.loadFromSnapshot);
|
||||||
|
const snapshot = await this.snapshotManager.getSnapshot();
|
||||||
|
if (snapshot) {
|
||||||
|
settings = snapshot.settings;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.version = this.getExtensionVersion();
|
this.version = this.getExtensionVersion();
|
||||||
|
|
||||||
// |—> on first setup, settings is undefined & settings.version is haram
|
// |—> on first setup, settings is undefined & settings.version is haram
|
||||||
@ -282,7 +321,7 @@ class Settings {
|
|||||||
return this.active;
|
return this.active;
|
||||||
}
|
}
|
||||||
|
|
||||||
async get() {
|
async get(): Promise<SettingsInterface | undefined> {
|
||||||
let ret;
|
let ret;
|
||||||
|
|
||||||
ret = await chrome.storage.local.get('uwSettings');
|
ret = await chrome.storage.local.get('uwSettings');
|
||||||
@ -290,13 +329,13 @@ class Settings {
|
|||||||
this.logger?.log('info', 'settings', 'Got settings:', ret && ret.uwSettings && JSON.parse(ret.uwSettings));
|
this.logger?.log('info', 'settings', 'Got settings:', ret && ret.uwSettings && JSON.parse(ret.uwSettings));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return JSON.parse(ret.uwSettings);
|
return JSON.parse(ret.uwSettings) as SettingsInterface;
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async set(extensionConf, options?) {
|
async set(extensionConf, options?: SetSettingsOptions) {
|
||||||
if (!options || !options.forcePreserveVersion) {
|
if (!options || !options.forcePreserveVersion) {
|
||||||
extensionConf.version = this.version;
|
extensionConf.version = this.version;
|
||||||
}
|
}
|
||||||
@ -344,7 +383,7 @@ class Settings {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async save(options?) {
|
async save(options?: SetSettingsOptions) {
|
||||||
if (Debug.debug && Debug.storage) {
|
if (Debug.debug && Debug.storage) {
|
||||||
console.log("[Settings::save] Saving active settings:", this.active);
|
console.log("[Settings::save] Saving active settings:", this.active);
|
||||||
}
|
}
|
||||||
@ -354,10 +393,10 @@ class Settings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async saveWithoutReload() {
|
async saveWithoutReload(options?: SetSettingsOptions) {
|
||||||
this.active.preventReload = true;
|
this.active.preventReload = true;
|
||||||
this.active.lastModified = new Date();
|
this.active.lastModified = new Date();
|
||||||
await this.set(this.active);
|
await this.set(this.active, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
async rollback() {
|
async rollback() {
|
||||||
|
106
src/ext/lib/settings/SettingsSnapshotManager.ts
Normal file
106
src/ext/lib/settings/SettingsSnapshotManager.ts
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
import { settings } from 'cluster'
|
||||||
|
import SettingsInterface from '@src/common/interfaces/SettingsInterface';
|
||||||
|
|
||||||
|
|
||||||
|
export interface SettingsSnapshot {
|
||||||
|
isAutomatic?: boolean;
|
||||||
|
isProtected?: boolean;
|
||||||
|
isDefault?: boolean;
|
||||||
|
forVersion: string;
|
||||||
|
label: string;
|
||||||
|
settings: SettingsInterface;
|
||||||
|
createdAt: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SettingsSnapshotOptions {
|
||||||
|
isAutomatic?: boolean,
|
||||||
|
isProtected?: boolean,
|
||||||
|
isDefault?: boolean,
|
||||||
|
label?: string,
|
||||||
|
forVersion?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SettingsSnapshotManager {
|
||||||
|
private MAX_AUTOMATIC_SNAPSHOTS = 5;
|
||||||
|
|
||||||
|
async getSnapshot(index?: number) {
|
||||||
|
const snapshots = await this.listSnapshots();
|
||||||
|
|
||||||
|
if (!index) {
|
||||||
|
return snapshots.find(x => x.isDefault);
|
||||||
|
} else {
|
||||||
|
if (index < 0 || index >= snapshots.length) {
|
||||||
|
throw new Error('Invalid index');
|
||||||
|
}
|
||||||
|
return snapshots[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async createSnapshot(settings: SettingsInterface, options?: SettingsSnapshotOptions) {
|
||||||
|
const snapshot = {
|
||||||
|
...options,
|
||||||
|
label: options.label ?? 'Automatic snapshot',
|
||||||
|
forVersion: options.forVersion || settings.version,
|
||||||
|
settings: JSON.parse(JSON.stringify(settings)),
|
||||||
|
createdAt: new Date(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const snapshots = await this.listSnapshots();
|
||||||
|
const automaticSnapshots = snapshots.filter((s) => s.isAutomatic && !s.isProtected);
|
||||||
|
|
||||||
|
if (options.isAutomatic && automaticSnapshots.length >= this.MAX_AUTOMATIC_SNAPSHOTS) {
|
||||||
|
const firstAutomaticIndex = snapshots.findIndex((s) => s.isAutomatic && !s.isProtected);
|
||||||
|
snapshots.splice(firstAutomaticIndex, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
snapshots.push(snapshot);
|
||||||
|
this.set(snapshots);
|
||||||
|
}
|
||||||
|
|
||||||
|
async setDefaultSnapshot(index: number, isDefault: boolean) {
|
||||||
|
const snapshots = await this.listSnapshots();
|
||||||
|
if (index < 0 || index >= snapshots.length) {
|
||||||
|
throw new Error('Invalid index');
|
||||||
|
}
|
||||||
|
if (isDefault) {
|
||||||
|
for (const snapshot of snapshots) {
|
||||||
|
snapshot.isDefault = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
snapshots[index].isDefault = isDefault;
|
||||||
|
this.set(snapshots);
|
||||||
|
}
|
||||||
|
|
||||||
|
async markSnapshotAsProtected(index: number, isProtected: boolean) {
|
||||||
|
const snapshots = await this.listSnapshots();
|
||||||
|
if (index < 0 || index >= snapshots.length) {
|
||||||
|
throw new Error('Invalid index');
|
||||||
|
}
|
||||||
|
snapshots[index].isProtected = isProtected;
|
||||||
|
this.set(snapshots);
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteSnapshot(index: number) {
|
||||||
|
const snapshots = await this.listSnapshots();
|
||||||
|
if (index < 0 || index >= snapshots.length) {
|
||||||
|
throw new Error('Invalid index');
|
||||||
|
}
|
||||||
|
snapshots.splice(index, 1);
|
||||||
|
this.set(snapshots);
|
||||||
|
}
|
||||||
|
|
||||||
|
async listSnapshots(): Promise<SettingsSnapshot[]> {
|
||||||
|
const ret = await chrome.storage.local.get('uwSettings-snapshots');
|
||||||
|
try {
|
||||||
|
JSON.parse(ret['uwSettings-snapshots']) as SettingsSnapshot[];
|
||||||
|
} catch (e) {
|
||||||
|
return [] as SettingsSnapshot[];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async set(snapshots: SettingsSnapshot[]) {
|
||||||
|
await chrome.storage.local.set({
|
||||||
|
'uwSettings-snapshots': JSON.stringify(snapshots),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user