1
0
mirror of https://github.com/kkapsner/CanvasBlocker synced 2024-05-29 09:28:06 +02:00
CanvasBlocker/lib/settings.js

232 lines
6.1 KiB
JavaScript
Raw Normal View History

2017-09-24 00:12:12 +02:00
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
2017-11-07 00:36:44 +01:00
(function(){
2017-09-24 00:12:12 +02:00
"use strict";
var scope;
if ((typeof exports) !== "undefined"){
scope = exports;
}
else {
2017-11-07 00:36:44 +01:00
scope = {};
window.scope.settings = scope;
2017-09-24 00:12:12 +02:00
}
2017-11-07 00:36:44 +01:00
var logging = {};
(function(){
var loggingQueue = [];
require.on("./logging", function(realLogging){
logging = realLogging;
loggingQueue.forEach(function(logEntry){
logging[logEntry.name](...logEntry.args, logEntry.date);
});
loggingQueue = [];
});
["error", "warning", "message", "notice", "verbose"].forEach(function(name){
logging[name] = function(...args){
loggingQueue.push({name, args, date: new Date()});
};
});
}());
const settingDefinitions = require("./settingDefinitions.js");
const eventHandler = {any: []};
eventHandler.all = eventHandler.any;
const settings = {};
2017-09-24 00:12:12 +02:00
settingDefinitions.forEach(function(settingDefinition){
var name = settingDefinition.name;
settings[name] = settingDefinition.defaultValue;
2017-11-07 00:36:44 +01:00
eventHandler[name] = [];
settingDefinition.on = function on(callback){
scope.on(name, callback);
};
2017-11-14 01:07:27 +01:00
settingDefinition.invalid = function invalid(newValue){
if (settingDefinition.fixed){
2017-11-14 01:07:27 +01:00
return "fixed";
2017-09-24 00:12:12 +02:00
}
else if ((typeof newValue) !== (typeof settingDefinition.defaultValue)){
2017-11-14 01:07:27 +01:00
return "wrongType";
2017-11-07 00:36:44 +01:00
}
else if (
settingDefinition.options &&
!settingDefinition.options.includes(newValue)
){
2017-11-14 01:07:27 +01:00
return "noOption";
}
return false;
};
settingDefinition.get = function getValue(){
return settings[name];
};
settingDefinition.set = function setValue(newValue){
logging.verbose("New value for %s:", name, newValue);
var invalid = settingDefinition.invalid(newValue);
if (invalid){
if (invalid === "fixed"){
logging.warning("Trying to set the fixed setting", name, ":", newValue);
}
else if (invalid === "wrongType"){
logging.warning("Wrong type provided for setting", name, ":", newValue);
}
else if (invalid === "noOption"){
logging.warning("Provided value outside specified options for ", name, ":", newValue);
}
else {
logging.warning("Unknown invalid state:", invalid);
}
}
else {
settings[name] = newValue;
if (!settingDefinition.transient){
var storeObject = {};
storeObject[name] = newValue;
browser.storage.local.set(storeObject);
}
}
2017-11-07 00:36:44 +01:00
};
Object.defineProperty(
scope,
name,
{
get: settingDefinition.get,
2017-11-07 19:51:49 +01:00
set: settingDefinition.set,
enumerable: true
2017-11-07 00:36:44 +01:00
}
2017-09-24 00:12:12 +02:00
);
});
2017-11-07 00:36:44 +01:00
scope.getDefinition = function(name){
var foundDefinitions = settingDefinitions.filter(function(settingDefinition){
return name === settingDefinition.name;
});
if (foundDefinitions.length){
return Object.create(foundDefinitions[0]);
}
else {
return undefined;
}
};
2017-09-24 00:12:12 +02:00
scope.forEach = function forEachSetting(...args){
settingDefinitions.map(function(settingDefinition){
return Object.create(settingDefinition);
}).forEach(...args);
2017-11-07 00:36:44 +01:00
};
scope.on = function onSettingsChange(name, callback){
if (Array.isArray(name)){
name.forEach(function(name){
onSettingsChange(name, callback);
});
2017-11-07 00:36:44 +01:00
}
else {
if (eventHandler.hasOwnProperty(name)){
eventHandler[name].push(callback);
}
else {
logging.warning("Unable to register event handler for unknown setting", name);
}
2017-11-07 00:36:44 +01:00
}
};
function changeValue(name, newValue){
var oldValue = settings[name];
settings[name] = newValue;
(eventHandler[name] || []).forEach(function(callback){
callback({name, newValue, oldValue});
});
2017-09-24 00:12:12 +02:00
}
2017-11-07 00:36:44 +01:00
logging.verbose("registering storage onchange listener");
browser.storage.onChanged.addListener(function(changes, area){
if (area === "local"){
logging.notice("settings changed", changes);
Object.entries(changes).forEach(function(entry){
const [name, change] = entry;
changeValue(name, change.newValue);
});
eventHandler.any.forEach(function(callback){
callback();
});
}
});
const settingsMigration = {
validVersions: [undefined, 0.1, 0.2],
transitions: {
"": function(oldStorage){
return {
storageVersion: 0.2
};
},
0.1: function(oldStorage){
var newStorage = {
storageVersion: 0.2
};
if (oldStorage.hasOwnProperty("askOnlyOnce")){
newStorage.askOnlyOnce = oldStorage.askOnlyOnce? "individual": "no";
}
return newStorage;
}
}
};
2017-11-07 00:36:44 +01:00
logging.verbose("loading settings");
let initialized = false;
const initEvents = [];
scope.init = function(storage){
if (initialized){
return false;
}
initialized = true;
2017-11-07 00:36:44 +01:00
logging.message("settings loaded");
if (!storage.storageVersion){
logging.message("No storage version found. Initializing storage.");
browser.storage.local.remove(Object.keys(storage));
storage = settingsMigration.transitions[""]({});
browser.storage.local.set(storage);
}
else if (storage.storageVersion !== settings.storageVersion){
var toChange = {};
while (storage.storageVersion !== settings.storageVersion){
logging.message("Old storage found. Storage version", storage.storageVersion);
if (settingsMigration.transitions[storage.storageVersion]){
var changes = settingsMigration.transitions[storage.storageVersion](storage);
Object.entries(changes).forEach(function(entry){
const [name, value] = entry;
toChange[name] = value;
storage[name] = value;
});
}
else {
logging.warning("Unable to migrate storage.");
break;
}
}
logging.notice("Changed settings:", toChange);
browser.storage.local.set(toChange);
}
2017-11-07 00:36:44 +01:00
Object.entries(storage).forEach(function(entry){
const [name, value] = entry;
changeValue(name, value);
});
changeValue("isStillDefault", false);
initEvents.forEach(function(callback){callback();});
return true;
};
scope.loaded = browser.storage.local.get().then(scope.init);
2017-11-07 00:36:44 +01:00
scope.onloaded = function(callback){
if (scope.isStillDefault){
initEvents.push(callback);
2017-11-07 00:36:44 +01:00
}
else {
callback();
}
};
Object.seal(scope);
2017-09-24 00:12:12 +02:00
}());