2013-09-03 15:47:59 +00:00
|
|
|
define(["command"], function(command) {
|
|
|
|
|
|
|
|
var defaults = {};
|
|
|
|
var local = {};
|
|
|
|
|
|
|
|
var SyncFile = function(name, c) {
|
|
|
|
this.entry = {};
|
|
|
|
if (name) {
|
|
|
|
this.open(name, c);
|
|
|
|
}
|
2013-09-13 15:25:39 +00:00
|
|
|
this.virtual = true;
|
2013-09-03 15:47:59 +00:00
|
|
|
};
|
|
|
|
SyncFile.prototype = {
|
|
|
|
name: "",
|
|
|
|
open: function(name, c) {
|
|
|
|
this.name = name;
|
|
|
|
this.entry.name = name;
|
|
|
|
if (c) {
|
|
|
|
c(this);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
read: function(c) {
|
|
|
|
var name = this.name;
|
|
|
|
chrome.storage.sync.get(this.name, function(data) {
|
|
|
|
c(null, data[name]);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
write: function(content, c) {
|
|
|
|
var data = {};
|
|
|
|
data[this.name] = content;
|
|
|
|
var self = this;
|
|
|
|
chrome.storage.sync.set(data, function() {
|
2013-09-04 19:26:09 +00:00
|
|
|
command.fire("settings:change-local");
|
2013-09-03 15:47:59 +00:00
|
|
|
if (c) c(null, self);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
retain: function() { return false; }
|
|
|
|
};
|
2013-09-13 20:26:46 +00:00
|
|
|
|
|
|
|
var clone = function(item) {
|
|
|
|
var cloneArray = function(a) {
|
|
|
|
var n = [];
|
|
|
|
for (var i = 0; i < a.length; i++) {
|
|
|
|
if (a[i] instanceof Array) {
|
|
|
|
n[i] = cloneArray(a[i]);
|
|
|
|
} else if (typeof a[i] == "object") {
|
|
|
|
n[i] = cloneObject(a[i]);
|
|
|
|
} else {
|
|
|
|
n[i] = a[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return n;
|
|
|
|
};
|
|
|
|
var cloneObject = function(o) {
|
|
|
|
var n = {};
|
|
|
|
for (var key in o) {
|
|
|
|
if (o[key] instanceof Array) {
|
|
|
|
n[key] = cloneArray(o[key]);
|
|
|
|
} else if (typeof o[key] == "object") {
|
|
|
|
n[key] = cloneObject(o[key]);
|
|
|
|
} else {
|
|
|
|
n[key] = o[key];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return n;
|
|
|
|
};
|
|
|
|
if (item instanceof Array) {
|
|
|
|
return cloneArray(item);
|
|
|
|
}
|
|
|
|
return cloneObject(item);
|
|
|
|
};
|
2013-09-14 01:29:19 +00:00
|
|
|
|
|
|
|
//track transfers to prevent multiple requests
|
|
|
|
var pending = {};
|
2013-09-03 15:47:59 +00:00
|
|
|
|
|
|
|
var Settings = {
|
|
|
|
get: function(name) {
|
2013-09-10 23:26:36 +00:00
|
|
|
name = name + ".json";
|
2013-09-13 20:26:46 +00:00
|
|
|
var comments = /\/\*[\s\S]*?\*\/|\/\/.*$/gm;
|
|
|
|
var original = clone(JSON.parse(defaults[name].replace(comments, "")));
|
|
|
|
var custom = {};
|
2013-09-10 23:26:36 +00:00
|
|
|
try {
|
2013-09-13 20:26:46 +00:00
|
|
|
custom = JSON.parse(local[name].replace(comments, ""));
|
2013-09-10 23:26:36 +00:00
|
|
|
} catch (e) {
|
2013-09-13 20:26:46 +00:00
|
|
|
//parse failed
|
|
|
|
}
|
2013-09-24 15:35:41 +00:00
|
|
|
//flat arrays (like menus.json) just get returned, not merged
|
|
|
|
if (custom && custom instanceof Array) {
|
|
|
|
return custom;
|
|
|
|
}
|
2013-09-13 20:26:46 +00:00
|
|
|
for (var key in custom) {
|
|
|
|
original[key] = custom[key];
|
2013-09-03 15:47:59 +00:00
|
|
|
}
|
2013-09-13 20:26:46 +00:00
|
|
|
return original;
|
2013-09-10 23:26:36 +00:00
|
|
|
},
|
2013-09-13 20:26:46 +00:00
|
|
|
getAsString: function(name, original) {
|
2013-09-03 15:47:59 +00:00
|
|
|
name = name + ".json";
|
2013-09-13 20:26:46 +00:00
|
|
|
if (original) {
|
|
|
|
return defaults[name];
|
|
|
|
}
|
2013-09-10 23:26:36 +00:00
|
|
|
return local[name] || defaults[name];
|
2013-09-03 15:47:59 +00:00
|
|
|
},
|
|
|
|
getAsFile: function(name) {
|
|
|
|
return new SyncFile(name + ".json");
|
|
|
|
},
|
|
|
|
load: function(name, c) {
|
|
|
|
name = name + ".json";
|
|
|
|
if (local[name] || defaults[name]) {
|
|
|
|
return c();
|
|
|
|
}
|
|
|
|
|
2013-09-14 01:29:19 +00:00
|
|
|
//if a request is out, tag along with it
|
|
|
|
if (pending[name]) {
|
|
|
|
pending[name].push(c);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-09-03 15:47:59 +00:00
|
|
|
var onload = function() {
|
2013-09-10 23:26:36 +00:00
|
|
|
var raw = this.responseText.replace();
|
|
|
|
defaults[name] = raw;
|
2013-09-03 15:47:59 +00:00
|
|
|
chrome.storage.sync.get(name, function(data) {
|
|
|
|
if (data[name]) {
|
2013-09-10 23:26:36 +00:00
|
|
|
local[name] = data[name];
|
2013-09-03 15:47:59 +00:00
|
|
|
} else {
|
|
|
|
local[name] = defaults[name];
|
|
|
|
}
|
2013-09-14 01:29:19 +00:00
|
|
|
for (var i = 0; i < pending[name].length; i++) {
|
|
|
|
pending[name][i]();
|
|
|
|
}
|
|
|
|
delete pending[name]
|
2013-09-03 15:47:59 +00:00
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2013-09-14 01:29:19 +00:00
|
|
|
pending[name] = [c]
|
|
|
|
|
2013-09-03 15:47:59 +00:00
|
|
|
var xhr = new XMLHttpRequest();
|
|
|
|
xhr.open("GET", "config/" + name);
|
|
|
|
xhr.onload = onload;
|
|
|
|
xhr.send();
|
|
|
|
}
|
|
|
|
};
|
2013-09-04 17:28:31 +00:00
|
|
|
|
|
|
|
command.on("settings:delete-local", function(key) {
|
|
|
|
key += ".json";
|
|
|
|
local[key] = defaults[key];
|
|
|
|
chrome.storage.sync.remove(key);
|
2013-09-10 23:26:36 +00:00
|
|
|
command.fire("init:restart");
|
2013-09-04 17:28:31 +00:00
|
|
|
});
|
2013-09-04 19:26:09 +00:00
|
|
|
|
|
|
|
command.on("settings:change-local", function() {
|
|
|
|
//reload anything that's been used
|
|
|
|
var keys = Object.keys(defaults).map(function(n) { return n.replace(".json", "")});
|
|
|
|
local = {};
|
|
|
|
defaults = {};
|
|
|
|
var completed = 0;
|
|
|
|
keys.forEach(function(key) {
|
|
|
|
Settings.load(key, function() {
|
|
|
|
completed++;
|
|
|
|
if (completed == keys.length) {
|
|
|
|
command.fire("init:restart");
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
2013-09-03 15:47:59 +00:00
|
|
|
|
|
|
|
return {
|
|
|
|
load: function(name, parentRequire, onLoad, config) {
|
2013-09-16 18:16:06 +00:00
|
|
|
if (name.length == 0) {
|
|
|
|
return onLoad(Settings);
|
|
|
|
}
|
|
|
|
|
2013-09-03 15:47:59 +00:00
|
|
|
var files = name.split(",");
|
|
|
|
var completed = 0;
|
|
|
|
|
|
|
|
files.forEach(function(file) {
|
|
|
|
Settings.load(file, function() {
|
|
|
|
completed++;
|
|
|
|
if (completed == files.length) {
|
|
|
|
onLoad(Settings);
|
|
|
|
}
|
|
|
|
})
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|