d10791bbad
Fixes #191
193 lines
No EOL
5 KiB
JavaScript
193 lines
No EOL
5 KiB
JavaScript
define([
|
|
"storage/syncFS",
|
|
"storage/syncfile",
|
|
"command",
|
|
"util/manos"
|
|
], function(sync, SyncFile, command, M) {
|
|
|
|
var defaults = {};
|
|
var local = {};
|
|
var project = {};
|
|
|
|
var clone = function(item) {
|
|
var copy = function(value) {
|
|
if (value instanceof Array) {
|
|
return cloneArray(value);
|
|
} else if (typeof value == "object") {
|
|
return cloneObject(value);
|
|
} else {
|
|
return value;
|
|
}
|
|
};
|
|
var cloneArray = function(a) {
|
|
var n = [];
|
|
for (var i = 0; i < a.length; i++) {
|
|
n[i] = copy(a[i]);
|
|
}
|
|
return n;
|
|
};
|
|
var cloneObject = function(o) {
|
|
var n = {};
|
|
for (var key in o) {
|
|
n[key] = copy(o[key]);
|
|
}
|
|
return n;
|
|
};
|
|
if (item instanceof Array) {
|
|
return cloneArray(item);
|
|
}
|
|
return cloneObject(item);
|
|
};
|
|
|
|
//track transfers to prevent multiple requests
|
|
var pending = {};
|
|
|
|
var Settings = {
|
|
get: function(name) {
|
|
name = name + ".json";
|
|
var comments = /\/\*[\s\S]*?\*\/|\/\/.*$/gm;
|
|
var original = clone(JSON.parse(defaults[name].replace(comments, "")));
|
|
var custom;
|
|
try {
|
|
custom = JSON.parse(local[name].replace(comments, ""));
|
|
} catch (e) {
|
|
//parse failed
|
|
return original;
|
|
}
|
|
//flat arrays (like menus.json) just get returned, not merged
|
|
if (custom && custom instanceof Array) {
|
|
return custom;
|
|
}
|
|
for (var key in custom) {
|
|
original[key] = custom[key];
|
|
}
|
|
//override settings with project settings
|
|
for (var key in project) {
|
|
original[key] = project[key];
|
|
}
|
|
return original;
|
|
},
|
|
getAsString: function(name, original) {
|
|
name = name + ".json";
|
|
if (original) {
|
|
return defaults[name];
|
|
}
|
|
return local[name] || defaults[name];
|
|
},
|
|
getAsFile: function(name) {
|
|
return new SyncFile(name + ".json");
|
|
},
|
|
load: function(name, c) {
|
|
name = name + ".json";
|
|
if (local[name]) {
|
|
return c();
|
|
}
|
|
|
|
//if a request is out, tag along with it
|
|
if (pending[name]) {
|
|
pending[name].push(c);
|
|
return;
|
|
}
|
|
|
|
var merge = function() {
|
|
sync.get(name).then(function(data) {
|
|
if (data) {
|
|
local[name] = data;
|
|
} else {
|
|
local[name] = defaults[name];
|
|
}
|
|
for (var i = 0; i < pending[name].length; i++) {
|
|
pending[name][i]();
|
|
}
|
|
delete pending[name]
|
|
});
|
|
};
|
|
|
|
pending[name] = [c]
|
|
|
|
if (defaults[name]) {
|
|
return merge();
|
|
}
|
|
|
|
require(["util/text!config/" + name], function(raw) {
|
|
defaults[name] = raw;
|
|
merge();
|
|
});
|
|
},
|
|
setProject: function(settings) {
|
|
project = settings;
|
|
command.fire("settings:change-local");
|
|
},
|
|
clearProject: function() {
|
|
project = {};
|
|
command.fire("settings:change-local");
|
|
},
|
|
//load/get all requested settings via a promise
|
|
pull: function() {
|
|
var deferred = M.deferred();
|
|
var names = [].slice.call(arguments);
|
|
var pending = names.map(function(name) {
|
|
return new Promise(function(ok) {
|
|
Settings.load(name, ok);
|
|
});
|
|
});
|
|
Promise.all(pending).then(function() {
|
|
var collected = {};
|
|
names.forEach(function(name) {
|
|
collected[name] = Settings.get(name);
|
|
});
|
|
deferred.done(collected);
|
|
});
|
|
return deferred.promise();
|
|
}
|
|
};
|
|
|
|
command.on("settings:delete-local", function(key) {
|
|
key += ".json";
|
|
local[key] = defaults[key];
|
|
sync.remove(key);
|
|
command.fire("init:restart");
|
|
});
|
|
|
|
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 = {};
|
|
var completed = 0;
|
|
keys.forEach(function(key) {
|
|
Settings.load(key, function() {
|
|
completed++;
|
|
if (completed == keys.length) {
|
|
command.fire("init:restart");
|
|
}
|
|
});
|
|
});
|
|
});
|
|
|
|
command.on("settings:emergency-reset", function() {
|
|
//unlike the menu item, let's confirm it here in case someone fat-fingers the menu/palette
|
|
chrome.notifications.clear("settings:emergency-reset-confirm", function() {
|
|
chrome.notifications.create("settings:emergency-reset-confirm", {
|
|
type: "basic",
|
|
iconUrl: "icon-128.png",
|
|
title: "Confirm Emergency Reset",
|
|
message: "This will wipe out all your settings and return Caret to its initial condition. Are you sure you want to do this?",
|
|
buttons: [
|
|
{ title: "Yes, reset all data" },
|
|
{ title: "Cancel emergency reset" }
|
|
]
|
|
}, function() {});
|
|
});
|
|
});
|
|
|
|
chrome.notifications.onButtonClicked.addListener(function(id, index) {
|
|
if (id != "settings:emergency-reset-confirm") return;
|
|
if (index !== 0) return;
|
|
chrome.runtime.getBackgroundPage(function(page) {
|
|
page.emergencyReset();
|
|
});
|
|
});
|
|
|
|
return Settings;
|
|
|
|
}); |