Sync localStorage prefs

This commit is contained in:
tophf 2015-10-04 15:26:50 +03:00
parent 5f9a4d6172
commit 965ea073c9
2 changed files with 80 additions and 40 deletions

View File

@ -13,6 +13,7 @@
"tabs", "tabs",
"webNavigation", "webNavigation",
"contextMenus", "contextMenus",
"storage",
"http://userstyles.org/", "http://userstyles.org/",
"https://userstyles.org/" "https://userstyles.org/"
], ],

View File

@ -157,9 +157,7 @@ function loadPrefs(prefs) {
} }
var prefs = { var prefs = {
// NB: localStorage["not_key"] is undefined, localStorage.getItem("not_key") is null defaults: {
// defaults
"openEditInWindow": false, // new editor opens in a own browser window "openEditInWindow": false, // new editor opens in a own browser window
"windowPosition": {}, // detached window position "windowPosition": {}, // detached window position
"show-badge": true, // display text on popup menu icon "show-badge": true, // display text on popup menu icon
@ -176,7 +174,7 @@ var prefs = {
"editor.options": {}, // CodeMirror.defaults.* "editor.options": {}, // CodeMirror.defaults.*
"editor.lineWrapping": true, // word wrap "editor.lineWrapping": true, // word wrap
"editor.smartIndent": true, // "smart" indent "editor.smartIndent": true, // "smart" indent
"editor.indentWithTabs": false,// smart indent with tabs "editor.indentWithTabs": false, // smart indent with tabs
"editor.tabSize": 4, // tab width, in spaces "editor.tabSize": 4, // tab width, in spaces
"editor.keyMap": navigator.appVersion.indexOf("Windows") > 0 ? "sublime" : "default", "editor.keyMap": navigator.appVersion.indexOf("Windows") > 0 ? "sublime" : "default",
"editor.theme": "default", // CSS theme "editor.theme": "default", // CSS theme
@ -191,18 +189,20 @@ var prefs = {
}, },
"editor.lintDelay": 500, // lint gutter marker update delay, ms "editor.lintDelay": 500, // lint gutter marker update delay, ms
"editor.lintReportDelay": 4500, // lint report update delay, ms "editor.lintReportDelay": 4500, // lint report update delay, ms
},
NO_DEFAULT_PREFERENCE: "No default preference for '%s'", NO_DEFAULT_PREFERENCE: "No default preference for '%s'",
UNHANDLED_DATA_TYPE: "Default '%s' is of type '%s' - what should be done with it?", UNHANDLED_DATA_TYPE: "Default '%s' is of type '%s' - what should be done with it?",
getPref: function(key, defaultValue) { getPref: function(key, defaultValue) {
// Returns localStorage[key], defaultValue, this[key], or undefined // Returns localStorage[key], defaultValue, this.defaults[key], or undefined
// as type of defaultValue, this[key], or localStorage[key] // as type of defaultValue, this.defaults[key], or localStorage[key]
var value = localStorage[key]; var value = localStorage[key];
// NB: localStorage["not_key"] is undefined, localStorage.getItem("not_key") is null
if (value === undefined) { if (value === undefined) {
return defaultValue === undefined ? shallowCopy(this[key]) : defaultValue; return defaultValue === undefined ? shallowCopy(this.defaults[key]) : defaultValue;
} }
switch (typeof (defaultValue === undefined ? this[key] : defaultValue)) { switch (typeof (defaultValue === undefined ? this.defaults[key] : defaultValue)) {
case "boolean": return value.toLowerCase() === "true"; case "boolean": return value.toLowerCase() === "true";
case "number": return Number(value); case "number": return Number(value);
case "object": return JSON.parse(value); case "object": return JSON.parse(value);
@ -212,22 +212,61 @@ var prefs = {
} }
return value; return value;
}, },
setPref: function(key, value) { getAllPrefs: function() {
var all = {}, me = this;
Object.keys(this.defaults).forEach(function(key) { all[key] = me.getPref(key) });
return all;
},
setPref: function(key, value, options) {
var oldValue = localStorage[key]; var oldValue = localStorage[key];
if (value === undefined || equal(value, this[key])) { if (value === undefined || equal(value, this.defaults[key])) {
delete localStorage[key]; delete localStorage[key];
} else { } else {
localStorage[key] = typeof value == "string" ? value : JSON.stringify(value); localStorage[key] = typeof value == "string" ? value : JSON.stringify(value);
} }
if (!equal(value, oldValue === undefined ? this[key] : oldValue)) { if (!equal(value, oldValue === undefined ? this.defaults[key] : oldValue)) {
this.broadcast(key, value, options);
}
},
broadcast: function(key, value, options) {
var message = {method: "prefChanged", prefName: key, value: value}; var message = {method: "prefChanged", prefName: key, value: value};
notifyAllTabs(message); notifyAllTabs(message);
chrome.extension.sendMessage(message); chrome.extension.sendMessage(message);
if (!options || !options.noSync) {
clearTimeout(this.syncTimeout);
this.syncTimeout = setTimeout((function() {
chrome.storage.sync.set({"settings": this.getAllPrefs()});
}).bind(this), 0);
} }
}, },
removePref: function(key) { setPref(key, undefined) } removePref: function(key) { setPref(key, undefined) }
}; };
chrome.storage.sync.get({settings: prefs.getAllPrefs()}, function(result) {
Object.keys(prefs.defaults).forEach(function(key) {
if (key in result.settings) {
prefs.setPref(key, result.settings[key], {noSync: true});
}
});
});
chrome.storage.onChanged.addListener(function(changes, area) {
if (area == "sync" && "settings" in changes) {
var newSettings = changes.settings.newValue;
for (key in prefs.defaults) {
if (key in newSettings) {
prefs.setPref(key, newSettings[key], {noSync: true});
}
}
}
});
window.addEventListener("storage", function(event) {
if (event.storageArea == localStorage && event.key in prefs.defaults) {
prefs.broadcast(event.key, prefs.getPref(event.key));
}
});
function getCodeMirrorThemes(callback) { function getCodeMirrorThemes(callback) {
chrome.runtime.getPackageDirectoryEntry(function(rootDir) { chrome.runtime.getPackageDirectoryEntry(function(rootDir) {
rootDir.getDirectory("codemirror/theme", {create: false}, function(themeDir) { rootDir.getDirectory("codemirror/theme", {create: false}, function(themeDir) {