Add local storage options to config

This commit is contained in:
Ajay
2022-02-06 19:17:20 -05:00
parent ccb0e8bed9
commit 816e9a78be
6 changed files with 80 additions and 38 deletions

View File

@@ -685,7 +685,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
clearConfigListener(): void { clearConfigListener(): void {
if (this.configListener) { if (this.configListener) {
Config.configListeners.splice(Config.configListeners.indexOf(this.configListener), 1); Config.configSyncListeners.splice(Config.configSyncListeners.indexOf(this.configListener), 1);
this.configListener = null; this.configListener = null;
} }
} }

View File

@@ -72,7 +72,7 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
// Add as a config listener // Add as a config listener
if (!this.configUpdateListener) { if (!this.configUpdateListener) {
this.configUpdateListener = () => this.configUpdate(); this.configUpdateListener = () => this.configUpdate();
Config.configListeners.push(this.configUpdate.bind(this)); Config.configSyncListeners.push(this.configUpdate.bind(this));
} }
this.checkToShowFullVideoWarning(); this.checkToShowFullVideoWarning();
@@ -80,7 +80,7 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
componentWillUnmount(): void { componentWillUnmount(): void {
if (this.configUpdateListener) { if (this.configUpdateListener) {
Config.configListeners.splice(Config.configListeners.indexOf(this.configUpdate.bind(this)), 1); Config.configSyncListeners.splice(Config.configSyncListeners.indexOf(this.configUpdate.bind(this)), 1);
} }
} }

View File

@@ -96,11 +96,16 @@ interface SBConfig {
} }
} }
interface SBStorage {
}
export interface SBObject { export interface SBObject {
configListeners: Array<(changes: StorageChangesObject) => unknown>; configSyncListeners: Array<(changes: StorageChangesObject) => unknown>;
defaults: SBConfig; defaults: SBConfig;
localConfig: SBConfig; cachedSyncConfig: SBConfig;
cachedLocalStorage: SBStorage;
config: SBConfig; config: SBConfig;
local: SBStorage;
forceUpdate(prop: string): void; forceUpdate(prop: string): void;
} }
@@ -108,7 +113,7 @@ const Config: SBObject = {
/** /**
* Callback function when an option is updated * Callback function when an option is updated
*/ */
configListeners: [], configSyncListeners: [],
defaults: { defaults: {
userID: null, userID: null,
isVip: false, isVip: false,
@@ -270,27 +275,35 @@ const Config: SBObject = {
} }
} }
}, },
localConfig: null, cachedSyncConfig: null,
cachedLocalStorage: null,
config: null, config: null,
local: null,
forceUpdate forceUpdate
}; };
// Function setup // Function setup
function configProxy(): SBConfig { function configProxy(): { sync: SBConfig, local: SBStorage } {
chrome.storage.onChanged.addListener((changes: {[key: string]: chrome.storage.StorageChange}) => { chrome.storage.onChanged.addListener((changes: {[key: string]: chrome.storage.StorageChange}, areaName) => {
for (const key in changes) { if (areaName === "sync") {
Config.localConfig[key] = changes[key].newValue; for (const key in changes) {
} Config.cachedSyncConfig[key] = changes[key].newValue;
}
for (const callback of Config.configListeners) {
callback(changes); for (const callback of Config.configSyncListeners) {
callback(changes);
}
} else if (areaName === "local") {
for (const key in changes) {
Config.cachedLocalStorage[key] = changes[key].newValue;
}
} }
}); });
const handler: ProxyHandler<SBConfig> = { const syncHandler: ProxyHandler<SBConfig> = {
set<K extends keyof SBConfig>(obj: SBConfig, prop: K, value: SBConfig[K]) { set<K extends keyof SBConfig>(obj: SBConfig, prop: K, value: SBConfig[K]) {
Config.localConfig[prop] = value; Config.cachedSyncConfig[prop] = value;
chrome.storage.sync.set({ chrome.storage.sync.set({
[prop]: value [prop]: value
@@ -300,7 +313,7 @@ function configProxy(): SBConfig {
}, },
get<K extends keyof SBConfig>(obj: SBConfig, prop: K): SBConfig[K] { get<K extends keyof SBConfig>(obj: SBConfig, prop: K): SBConfig[K] {
const data = Config.localConfig[prop]; const data = Config.cachedSyncConfig[prop];
return obj[prop] || data; return obj[prop] || data;
}, },
@@ -313,25 +326,53 @@ function configProxy(): SBConfig {
}; };
return new Proxy<SBConfig>({handler} as unknown as SBConfig, handler); const localHandler: ProxyHandler<SBStorage> = {
set<K extends keyof SBStorage>(obj: SBStorage, prop: K, value: SBStorage[K]) {
Config.cachedLocalStorage[prop] = value;
chrome.storage.local.set({
[prop]: value
});
return true;
},
get<K extends keyof SBStorage>(obj: SBStorage, prop: K): SBStorage[K] {
const data = Config.cachedLocalStorage[prop];
return obj[prop] || data;
},
deleteProperty(obj: SBConfig, prop: keyof SBStorage) {
chrome.storage.local.remove(<string> prop);
return true;
}
};
return {
sync: new Proxy<SBConfig>({handler: syncHandler} as unknown as SBConfig, syncHandler),
local: new Proxy<SBStorage>({handler: localHandler} as unknown as SBConfig, localHandler)
};
} }
function forceUpdate(prop: string): void { function forceUpdate(prop: string): void {
chrome.storage.sync.set({ chrome.storage.sync.set({
[prop]: Config.localConfig[prop] [prop]: Config.cachedSyncConfig[prop]
}); });
} }
function fetchConfig(): Promise<void> { function fetchConfig(): Promise<void> {
return new Promise((resolve) => { return new Promise((resolve) => {
chrome.storage.sync.get(null, function(items) { chrome.storage.sync.get(null, function(items) {
Config.localConfig = <SBConfig> <unknown> items; // Data is ready Config.cachedSyncConfig = <SBConfig> <unknown> items; // Data is ready
resolve(); resolve();
}); });
}); });
} }
function migrateOldFormats(config: SBConfig) { function migrateOldSyncFormats(config: SBConfig) {
if (config["segmentTimes"]) { if (config["segmentTimes"]) {
for (const item of config["segmentTimes"]) { for (const item of config["segmentTimes"]) {
config.unsubmittedSegments[item[0]] = item[1]; config.unsubmittedSegments[item[0]] = item[1];
@@ -428,20 +469,21 @@ async function setupConfig() {
await fetchConfig(); await fetchConfig();
addDefaults(); addDefaults();
const config = configProxy(); const config = configProxy();
migrateOldFormats(config); migrateOldSyncFormats(config.sync);
Config.config = config; Config.config = config.sync;
Config.local = config.local;
} }
// Add defaults // Add defaults
function addDefaults() { function addDefaults() {
for (const key in Config.defaults) { for (const key in Config.defaults) {
if(!Object.prototype.hasOwnProperty.call(Config.localConfig, key)) { if(!Object.prototype.hasOwnProperty.call(Config.cachedSyncConfig, key)) {
Config.localConfig[key] = Config.defaults[key]; Config.cachedSyncConfig[key] = Config.defaults[key];
} else if (key === "barTypes") { } else if (key === "barTypes") {
for (const key2 in Config.defaults[key]) { for (const key2 in Config.defaults[key]) {
if(!Object.prototype.hasOwnProperty.call(Config.localConfig[key], key2)) { if(!Object.prototype.hasOwnProperty.call(Config.cachedSyncConfig[key], key2)) {
Config.localConfig[key][key2] = Config.defaults[key][key2]; Config.cachedSyncConfig[key][key2] = Config.defaults[key][key2];
} }
} }
} }

View File

@@ -227,8 +227,8 @@ function contentConfigUpdateListener(changes: StorageChangesObject) {
} }
} }
if (!Config.configListeners.includes(contentConfigUpdateListener)) { if (!Config.configSyncListeners.includes(contentConfigUpdateListener)) {
Config.configListeners.push(contentConfigUpdateListener); Config.configSyncListeners.push(contentConfigUpdateListener);
} }
function resetValues() { function resetValues() {

View File

@@ -44,8 +44,8 @@ async function init() {
createStickyHeader(); createStickyHeader();
} }
if (!Config.configListeners.includes(optionsConfigUpdateListener)) { if (!Config.configSyncListeners.includes(optionsConfigUpdateListener)) {
Config.configListeners.push(optionsConfigUpdateListener); Config.configSyncListeners.push(optionsConfigUpdateListener);
} }
await utils.wait(() => Config.config !== null); await utils.wait(() => Config.config !== null);
@@ -499,7 +499,7 @@ function activatePrivateTextChange(element: HTMLElement) {
// See if anything extra must be done // See if anything extra must be done
switch (option) { switch (option) {
case "*": { case "*": {
result = JSON.stringify(Config.localConfig); result = JSON.stringify(Config.cachedSyncConfig);
break; break;
} }
} }
@@ -579,7 +579,7 @@ async function setTextOption(option: string, element: HTMLElement, value: string
function downloadConfig() { function downloadConfig() {
const file = document.createElement("a"); const file = document.createElement("a");
const jsonData = JSON.parse(JSON.stringify(Config.localConfig)); const jsonData = JSON.parse(JSON.stringify(Config.cachedSyncConfig));
file.setAttribute("href", "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(jsonData))); file.setAttribute("href", "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(jsonData)));
file.setAttribute("download", "SponsorBlockConfig.json"); file.setAttribute("download", "SponsorBlockConfig.json");
document.body.append(file); document.body.append(file);
@@ -633,7 +633,7 @@ function copyDebugOutputToClipboard() {
language: navigator.language, language: navigator.language,
extensionVersion: chrome.runtime.getManifest().version extensionVersion: chrome.runtime.getManifest().version
}, },
config: JSON.parse(JSON.stringify(Config.localConfig)) // Deep clone config object config: JSON.parse(JSON.stringify(Config.cachedSyncConfig)) // Deep clone config object
}; };
// Sanitise sensitive user config values // Sanitise sensitive user config values

View File

@@ -360,8 +360,8 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> {
// Perform a second update after the config changes take effect as a workaround for a race condition // Perform a second update after the config changes take effect as a workaround for a race condition
const removeListener = (listener: typeof lateUpdate) => { const removeListener = (listener: typeof lateUpdate) => {
const index = Config.configListeners.indexOf(listener); const index = Config.configSyncListeners.indexOf(listener);
if (index !== -1) Config.configListeners.splice(index, 1); if (index !== -1) Config.configSyncListeners.splice(index, 1);
}; };
const lateUpdate = () => { const lateUpdate = () => {
@@ -369,7 +369,7 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> {
removeListener(lateUpdate); removeListener(lateUpdate);
}; };
Config.configListeners.push(lateUpdate); Config.configSyncListeners.push(lateUpdate);
// Remove the listener after 200ms in case the changes were propagated by the time we got the response // Remove the listener after 200ms in case the changes were propagated by the time we got the response
setTimeout(() => removeListener(lateUpdate), 200); setTimeout(() => removeListener(lateUpdate), 200);