Masterlist update is now non-UI-blocking.

For #246.
This commit is contained in:
WrinklyNinja
2014-08-26 23:40:39 +01:00
parent 86b81dcafd
commit ac6c28364b
3 changed files with 111 additions and 103 deletions
+16 -7
View File
@@ -359,6 +359,7 @@ function processCefError(err) {
/* Error.stack seems to be Chromium-specific. It gives a lot more useful
info than just the error message. */
console.log(err.stack);
closeProgressDialog();
showMessageBox('error', 'Error', err.message);
}
@@ -661,8 +662,11 @@ function openReadme(evt) {
loot.query('openReadme').catch(processCefError);
}
function updateMasterlist(evt) {
updateProgressDialog('Updating masterlist...');
openProgressDialog();
loot.query('updateMasterlist').then(JSON.parse).then(function(result){
if (result == null) {
closeProgressDialog();
return;
}
/* Update JS variables. */
@@ -683,6 +687,7 @@ function updateMasterlist(evt) {
}
}
});
closeProgressDialog();
}).catch(processCefError);
}
function sortUIElements(pluginNames) {
@@ -746,11 +751,9 @@ function sortUIElements(pluginNames) {
lastCard = card;
});
}
function toggleProgressDialog() {
function openProgressDialog() {
var progressDialog = document.getElementById('progressDialog');
if (progressDialog.open) {
progressDialog.close();
} else {
if (!progressDialog.open) {
progressDialog.showModal();
}
}
@@ -758,12 +761,18 @@ function updateProgressDialog(message) {
var progressDialog = document.getElementById('progressDialog');
progressDialog.getElementsByTagName('h1')[0].textContent = message;
}
function closeProgressDialog() {
var progressDialog = document.getElementById('progressDialog');
if (progressDialog.open) {
progressDialog.close();
}
}
function sortPlugins(evt) {
updateProgressDialog('Sorting plugins...');
toggleProgressDialog();
if (loot.settings.updateMasterlist) {
updateMasterlist(evt);
}
updateProgressDialog('Sorting plugins...');
openProgressDialog();
loot.query('sortPlugins').then(JSON.parse).then(function(result){
if (result) {
var loadOrder = [];
@@ -800,7 +809,7 @@ function sortPlugins(evt) {
hideElement(document.getElementById('sortButton'));
showElement(document.getElementById('applySortButton'));
showElement(document.getElementById('cancelSortButton'));
toggleProgressDialog();
closeProgressDialog();
}
}).catch(processCefError);
}
+94 -95
View File
@@ -166,18 +166,7 @@ namespace loot {
return true;
}
else if (request == "updateMasterlist") {
try {
callback->Success(UpdateMasterlist());
}
catch (error &e) {
BOOST_LOG_TRIVIAL(error) << "Failed to update the masterlist. " << e.what();
callback->Failure(e.code(), e.what());
}
catch (exception &e) {
BOOST_LOG_TRIVIAL(error) << "Failed to update the masterlist. " << e.what();
callback->Failure(-1, e.what());
}
return true;
return CefPostTask(TID_FILE, base::Bind(&Handler::UpdateMasterlist, base::Unretained(this), callback));
}
else if (request == "sortPlugins") {
return CefPostTask(TID_FILE, base::Bind(&Handler::SortPlugins, base::Unretained(this), callback));
@@ -728,93 +717,103 @@ namespace loot {
return JSON::stringify(gameNode);
}
std::string Handler::UpdateMasterlist() {
BOOST_LOG_TRIVIAL(debug) << "Updating and parsing masterlist.";
//Set language.
unsigned int language;
if (g_app_state.GetSettings()["language"])
language = Language(g_app_state.GetSettings()["language"].as<string>()).Code();
else
language = Language::any;
BOOST_LOG_TRIVIAL(info) << "Using message language: " << Language(language).Name();
// Update / parse masterlist.
bool wasChanged = true;
void Handler::UpdateMasterlist(CefRefPtr<Callback> callback) {
try {
wasChanged = g_app_state.CurrentGame().masterlist.Load(g_app_state.CurrentGame(), language);
}
catch (loot::error &e) {
if (e.code() == loot::error::ok) {
// There was a parsing error, but roll-back was successful, so the process
// should still complete.
g_app_state.CurrentGame().masterlist.messages.push_back(Message(Message::error, e.what()));
wasChanged = true;
BOOST_LOG_TRIVIAL(debug) << "Updating and parsing masterlist.";
//Set language.
unsigned int language;
if (g_app_state.GetSettings()["language"])
language = Language(g_app_state.GetSettings()["language"].as<string>()).Code();
else
language = Language::any;
BOOST_LOG_TRIVIAL(info) << "Using message language: " << Language(language).Name();
// Update / parse masterlist.
bool wasChanged = true;
try {
wasChanged = g_app_state.CurrentGame().masterlist.Load(g_app_state.CurrentGame(), language);
}
catch (loot::error &e) {
if (e.code() == loot::error::ok) {
// There was a parsing error, but roll-back was successful, so the process
// should still complete.
g_app_state.CurrentGame().masterlist.messages.push_back(Message(Message::error, e.what()));
wasChanged = true;
}
else
throw e;
}
// Now regenerate the JS-side masterlist data if the masterlist was changed.
if (wasChanged) {
// The data structure is to be set as 'loot.game'.
YAML::Node gameNode;
// Store the masterlist revision and date.
gameNode["masterlist"]["revision"] = g_app_state.CurrentGame().masterlist.GetRevision(g_app_state.CurrentGame().MasterlistPath());
gameNode["masterlist"]["date"] = g_app_state.CurrentGame().masterlist.GetDate(g_app_state.CurrentGame().MasterlistPath());
for (const auto& pluginPair : g_app_state.CurrentGame().plugins) {
Plugin mlistPlugin(pluginPair.second);
mlistPlugin.MergeMetadata(g_app_state.CurrentGame().masterlist.FindPlugin(pluginPair.second));
YAML::Node pluginNode;
if (!mlistPlugin.HasNameOnly()) {
// Now add the masterlist metadata to the pluginNode.
pluginNode["masterlist"]["after"] = mlistPlugin.LoadAfter();
pluginNode["masterlist"]["req"] = mlistPlugin.Reqs();
pluginNode["masterlist"]["inc"] = mlistPlugin.Incs();
pluginNode["masterlist"]["msg"] = mlistPlugin.Messages();
pluginNode["masterlist"]["tag"] = mlistPlugin.Tags();
pluginNode["masterlist"]["dirty"] = mlistPlugin.DirtyInfo();
}
// Now merge masterlist and userlist metadata and evaluate,
// putting any resulting metadata into the base of the pluginNode.
YAML::Node derivedNode = GenerateDerivedMetadata(pluginPair.second.Name());
for (auto it = derivedNode.begin(); it != derivedNode.end(); ++it) {
const string key = it->first.as<string>();
pluginNode[key] = it->second;
}
gameNode["plugins"].push_back(pluginNode);
}
//Evaluate any conditions in the global messages.
BOOST_LOG_TRIVIAL(debug) << "Evaluating global message conditions.";
list<Message> messages = g_app_state.CurrentGame().masterlist.messages;
try {
list<Message>::iterator it = messages.begin();
while (it != messages.end()) {
if (!it->EvalCondition(g_app_state.CurrentGame(), language))
it = messages.erase(it);
else
++it;
}
}
catch (std::exception& e) {
BOOST_LOG_TRIVIAL(error) << "A global message contains a condition that could not be evaluated. Details: " << e.what();
messages.push_back(Message(Message::error, (format(loc::translate("A global message contains a condition that could not be evaluated. Details: %1%")) % e.what()).str()));
}
// Now store global messages from masterlist.
gameNode["globalMessages"] = messages;
callback->Success(JSON::stringify(gameNode));
}
else
throw e;
callback->Success("null");
}
// Now regenerate the JS-side masterlist data if the masterlist was changed.
if (wasChanged) {
// The data structure is to be set as 'loot.game'.
YAML::Node gameNode;
// Store the masterlist revision and date.
gameNode["masterlist"]["revision"] = g_app_state.CurrentGame().masterlist.GetRevision(g_app_state.CurrentGame().MasterlistPath());
gameNode["masterlist"]["date"] = g_app_state.CurrentGame().masterlist.GetDate(g_app_state.CurrentGame().MasterlistPath());
for (const auto& pluginPair : g_app_state.CurrentGame().plugins) {
Plugin mlistPlugin(pluginPair.second);
mlistPlugin.MergeMetadata(g_app_state.CurrentGame().masterlist.FindPlugin(pluginPair.second));
YAML::Node pluginNode;
if (!mlistPlugin.HasNameOnly()) {
// Now add the masterlist metadata to the pluginNode.
pluginNode["masterlist"]["after"] = mlistPlugin.LoadAfter();
pluginNode["masterlist"]["req"] = mlistPlugin.Reqs();
pluginNode["masterlist"]["inc"] = mlistPlugin.Incs();
pluginNode["masterlist"]["msg"] = mlistPlugin.Messages();
pluginNode["masterlist"]["tag"] = mlistPlugin.Tags();
pluginNode["masterlist"]["dirty"] = mlistPlugin.DirtyInfo();
}
// Now merge masterlist and userlist metadata and evaluate,
// putting any resulting metadata into the base of the pluginNode.
YAML::Node derivedNode = GenerateDerivedMetadata(pluginPair.second.Name());
for (auto it = derivedNode.begin(); it != derivedNode.end(); ++it) {
const string key = it->first.as<string>();
pluginNode[key] = it->second;
}
gameNode["plugins"].push_back(pluginNode);
}
//Evaluate any conditions in the global messages.
BOOST_LOG_TRIVIAL(debug) << "Evaluating global message conditions.";
list<Message> messages = g_app_state.CurrentGame().masterlist.messages;
try {
list<Message>::iterator it = messages.begin();
while (it != messages.end()) {
if (!it->EvalCondition(g_app_state.CurrentGame(), language))
it = messages.erase(it);
else
++it;
}
}
catch (std::exception& e) {
BOOST_LOG_TRIVIAL(error) << "A global message contains a condition that could not be evaluated. Details: " << e.what();
messages.push_back(Message(Message::error, (format(loc::translate("A global message contains a condition that could not be evaluated. Details: %1%")) % e.what()).str()));
}
// Now store global messages from masterlist.
gameNode["globalMessages"] = messages;
return JSON::stringify(gameNode);
catch (error &e) {
BOOST_LOG_TRIVIAL(error) << "Failed to update the masterlist. " << e.what();
callback->Failure(e.code(), e.what());
}
catch (exception &e) {
BOOST_LOG_TRIVIAL(error) << "Failed to update the masterlist. " << e.what();
callback->Failure(-1, e.what());
}
else
return "null";
}
std::string Handler::ClearAllMetadata() {
@@ -843,7 +842,7 @@ namespace loot {
return "[]";
}
void Handler::SortPlugins(CefRefPtr<CefMessageRouterBrowserSide::Callback> callback) {
void Handler::SortPlugins(CefRefPtr<Callback> callback) {
//Set language.
unsigned int language;
if (g_app_state.GetSettings()["language"])
+1 -1
View File
@@ -57,7 +57,7 @@ namespace loot {
std::string GetGameTypes();
std::string GetInstalledGames();
std::string GetGameData();
std::string UpdateMasterlist();
void UpdateMasterlist(CefRefPtr<Callback> callback);
std::string ClearAllMetadata();
void SortPlugins(CefRefPtr<Callback> callback);