mirror of
https://github.com/loot/libloot.git
synced 2026-07-27 14:16:01 -07:00
Added display of plugin Bash Tags and messages.
This commit is contained in:
@@ -290,9 +290,14 @@ li.warn{
|
||||
}
|
||||
.tag.add {
|
||||
color:green;
|
||||
margin-left: 1.75em;
|
||||
}
|
||||
.tag.remove {
|
||||
color:red;
|
||||
margin-left: 1.75em;
|
||||
}
|
||||
plugin-card > ul {
|
||||
margin-left: 1.75em;
|
||||
}
|
||||
|
||||
#settings {
|
||||
|
||||
@@ -28,16 +28,22 @@ var pluginCardProto = Object.create(HTMLElement.prototype, {
|
||||
|
||||
onMenuItemClick: {
|
||||
value: function(evt) {
|
||||
if (evt.target.id == 'editMetadata') {
|
||||
|
||||
} else if (evt.target.id == 'copyMetadata') {
|
||||
|
||||
} else if (evt.target.id == 'clearMetadata') {
|
||||
showMessageDialog('Clear Plugin Metadata', 'Are you sure you want to clear all existing user-added metadata from "' + evt.target.parentElement.parentElement.querySelector('h1').textContent + '"?');
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onMenuClick: {
|
||||
value: function(evt) {
|
||||
var section = evt.currentTarget.parentElement.parentElement;
|
||||
section.querySelector('#editMetadata').addEventListener('click', this.onMenuItemClick, false);
|
||||
section.querySelector('#copyMetadata').addEventListener('click', this.onMenuItemClick, false);
|
||||
section.querySelector('#clearMetadata').addEventListener('click', this.onMenuItemClick, false);
|
||||
section.querySelector('#editMetadata').addEventListener('click', section.parentNode.host.onMenuItemClick, false);
|
||||
section.querySelector('#copyMetadata').addEventListener('click', section.parentNode.host.onMenuItemClick, false);
|
||||
section.querySelector('#clearMetadata').addEventListener('click', section.parentNode.host.onMenuItemClick, false);
|
||||
|
||||
section.querySelector('#menu').classList.toggle('hidden');
|
||||
}
|
||||
@@ -61,6 +67,16 @@ var pluginCardProto = Object.create(HTMLElement.prototype, {
|
||||
version.className = 'version';
|
||||
this.appendChild(version);
|
||||
|
||||
var tagAdd = document.createElement('div');
|
||||
tagAdd.className = 'tag add';
|
||||
this.appendChild(tagAdd);
|
||||
var tagRemove = document.createElement('div');
|
||||
tagRemove.className = 'tag remove';
|
||||
this.appendChild(tagRemove);
|
||||
|
||||
var messages = document.createElement('ul');
|
||||
this.appendChild(messages);
|
||||
|
||||
this.shadowRoot.querySelector('#menuButton').addEventListener('click', this.onMenuClick, false);
|
||||
|
||||
}
|
||||
|
||||
@@ -34,18 +34,24 @@ function Plugin(obj) {
|
||||
this.masterlist = obj.masterlist;
|
||||
this.userlist = obj.userlist;
|
||||
|
||||
this.modPriority = obj.modPriority;
|
||||
this.isGlobalPriority = obj.isGlobalPriority;
|
||||
this.messages = obj.messages;
|
||||
this.tags = obj.tags;
|
||||
this.isDirty = obj.isDirty;
|
||||
|
||||
this.id = this.name.replace(/\s+/g, '');
|
||||
|
||||
Plugin.prototype.getTagsStrings = function () {
|
||||
var tagsAdded = [];
|
||||
var tagsRemoved = [];
|
||||
|
||||
if (this.masterlist && this.masterlist.tag) {
|
||||
for (var i = 0; i < this.masterlist.tag.length; ++i) {
|
||||
if (this.masterlist.tag[i].name[0] == '-') {
|
||||
tagsRemoved.push(this.masterlist.tag[i].name);
|
||||
if (this.tags) {
|
||||
for (var i = 0; i < this.tags.length; ++i) {
|
||||
if (this.tags[i].name[0] == '-') {
|
||||
tagsRemoved.push(this.tags[i].name.substr(1));
|
||||
} else {
|
||||
tagsAdded.push(this.masterlist.tag[i].name);
|
||||
tagsAdded.push(this.tags[i].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -53,28 +59,7 @@ function Plugin(obj) {
|
||||
Prefer the removed list. */
|
||||
for (var i = 0; i < tagsAdded.length; ++i) {
|
||||
for (var j = 0; j < tagsRemoved.length; ++j) {
|
||||
if (tagsRemoved[j].name.toLowerCase() == tagsAdded[i].name.toLowerCase()) {
|
||||
/* Remove tag from the tagsAdded array. */
|
||||
tagsAdded.splice(i, 1);
|
||||
--i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.userlist && this.userlist.tag) {
|
||||
for (var i = 0; i < this.userlist.tag.length; ++i) {
|
||||
if (this.userlist.tag[i][0] == '-') {
|
||||
tagsRemoved.push(this.userlist.tag[i]);
|
||||
} else {
|
||||
tagsAdded.push(this.userlist.tag[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Now again make sure that the same tag doesn't appear in both arrays.
|
||||
Prefer the removed list. */
|
||||
for (var i = 0; i < tagsAdded.length; ++i) {
|
||||
for (var j = 0; j < tagsRemoved.length; ++j) {
|
||||
if (tagsRemoved[j].name.toLowerCase() == tagsAdded[i].name.toLowerCase()) {
|
||||
if (tagsRemoved[j].toLowerCase() == tagsAdded[i].toLowerCase()) {
|
||||
/* Remove tag from the tagsAdded array. */
|
||||
tagsAdded.splice(i, 1);
|
||||
--i;
|
||||
@@ -95,40 +80,67 @@ function Plugin(obj) {
|
||||
this.card = card;
|
||||
|
||||
card.id = this.id;
|
||||
card.querySelector('h1').textContent = this.name;
|
||||
if (this.crc != '0') {
|
||||
card.querySelector('.crc').textContent = this.crc;
|
||||
}
|
||||
card.querySelector('.version').textContent = this.version;
|
||||
|
||||
card.setAttribute('data-active', this.isActive);
|
||||
card.setAttribute('data-dummy', this.isDummy);
|
||||
card.setAttribute('data-bsa', this.loadsBSA);
|
||||
card.setAttribute('data-edits', this.userlist != undefined);
|
||||
|
||||
/* Fill in name, version, CRC. */
|
||||
card.querySelector('h1').textContent = this.name;
|
||||
card.querySelector('.version').textContent = this.version;
|
||||
if (this.crc != '0') {
|
||||
card.querySelector('.crc').textContent = this.crc;
|
||||
}
|
||||
|
||||
/* Fill in Bash Tag suggestions. */
|
||||
var tags = this.getTagsStrings();
|
||||
if (tags.tagsAdded) {
|
||||
card.getElementsByClassName('tag add')[0].textContent = tags.tagsAdded;
|
||||
} else {
|
||||
card.getElementsByClassName('tag add')[0].classList.toggle('hidden');
|
||||
}
|
||||
if (tags.tagsRemoved) {
|
||||
card.getElementsByClassName('tag remove')[0].textContent = tags.tagsRemoved;
|
||||
} else {
|
||||
card.getElementsByClassName('tag remove')[0].classList.toggle('hidden');
|
||||
}
|
||||
|
||||
/* Fill in messages. */
|
||||
if (this.messages && this.messages.length != 0) {
|
||||
this.messages.forEach(function(message) {
|
||||
var messageLi = document.createElement('li');
|
||||
messageLi.className = message.type;
|
||||
// Use the Marked library for Markdown formatting support.
|
||||
messageLi.innerHTML = marked(message.content[0].str);
|
||||
card.getElementsByTagName('ul')[0].appendChild(messageLi);
|
||||
|
||||
});
|
||||
} else {
|
||||
card.getElementsByTagName('ul')[0].classList.toggle('hidden');
|
||||
}
|
||||
|
||||
/* The content elements steal the name, CRC and version, so they
|
||||
don't get distributed into the editor part of the shadow DOM.
|
||||
Update the editor elements manually. */
|
||||
|
||||
card.shadowRoot.querySelector('#editor h1').textContent = this.name;
|
||||
card.shadowRoot.querySelector('#editor .version').textContent = this.version;
|
||||
if (this.crc != '0') {
|
||||
card.shadowRoot.querySelector('#editor .crc').textContent = this.crc;
|
||||
}
|
||||
|
||||
document.getElementById('main').appendChild(card);
|
||||
}
|
||||
|
||||
Plugin.prototype.getPriorityString = function() {
|
||||
if (this.userlist) {
|
||||
var priorityText = 'Priority: ' + this.userlist.modPriority + ', Global: ';
|
||||
if (this.userlist.isGlobalPriority) {
|
||||
priorityText += '✓';
|
||||
} else {
|
||||
priorityText += '✗';
|
||||
}
|
||||
return priorityText;
|
||||
} else if (this.masterlist) {
|
||||
var priorityText = 'Priority: ' + this.masterlist.modPriority + ', Global: ';
|
||||
if (this.masterlist.isGlobalPriority) {
|
||||
priorityText += '✓';
|
||||
} else {
|
||||
priorityText += '✗';
|
||||
}
|
||||
return priorityText;
|
||||
var priorityText = 'Priority: ' + this.modPriority + ', Global: ';
|
||||
if (this.isGlobalPriority) {
|
||||
priorityText += '✓';
|
||||
} else {
|
||||
return 'Priority: 0, Global: ✗';
|
||||
priorityText += '✗';
|
||||
}
|
||||
return priorityText;
|
||||
}
|
||||
|
||||
Plugin.prototype.createListItem = function() {
|
||||
|
||||
@@ -763,42 +763,21 @@ function updateInterfaceWithGameInfo(response) {
|
||||
++activePluginNo;
|
||||
}
|
||||
|
||||
/*if (plugin.isDirty) {
|
||||
if (plugin.isDirty) {
|
||||
++dirtyPluginNo;
|
||||
}*/
|
||||
|
||||
/*
|
||||
var tags = getTagsStrings(plugin);
|
||||
if (tags.tagsAdded) {
|
||||
clone.getElementsByClassName('tag add')[0].textContent = tags.tagsAdded;
|
||||
} else {
|
||||
hideElement(clone.getElementsByClassName('tag add')[0]);
|
||||
}
|
||||
if (tags.tagsRemoved) {
|
||||
clone.getElementsByClassName('tag remove')[0].textContent = tags.tagsRemoved;
|
||||
} else {
|
||||
hideElement(clone.getElementsByClassName('tag remove')[0]);
|
||||
}
|
||||
|
||||
if (plugin.masterlist && plugin.masterlist.msg && plugin.masterlist.msg.length != 0) {
|
||||
plugin.masterlist.msg.forEach(function(message) {
|
||||
var messageLi = document.createElement('li');
|
||||
messageLi.className = message.type;
|
||||
// Use the Marked library for Markdown formatting support.
|
||||
messageLi.innerHTML = marked(message.content[0].str);
|
||||
clone.getElementsByTagName('ul')[0].appendChild(messageLi);
|
||||
if (plugin.messages && plugin.messages.length != 0) {
|
||||
plugin.messages.forEach(function(message) {
|
||||
|
||||
if (messageLi.className == 'warn') {
|
||||
if (message.type == 'warn') {
|
||||
warnMessageNo++;
|
||||
} else if (messageLi.className == 'error') {
|
||||
} else if (message.type == 'error') {
|
||||
errorMessageNo++;
|
||||
}
|
||||
totalMessageNo++;
|
||||
});
|
||||
} else {
|
||||
clone.getElementsByTagName('ul')[0].className += ' hidden';
|
||||
}
|
||||
*/
|
||||
});
|
||||
document.getElementById('filterTotalMessageNo').textContent = totalMessageNo;
|
||||
document.getElementById('totalMessageNo').textContent = totalMessageNo;
|
||||
|
||||
@@ -182,8 +182,8 @@
|
||||
</section>
|
||||
<section id="editor">
|
||||
<h1></h1>
|
||||
<div class="crc"></div>
|
||||
<div class="version"></div>
|
||||
<span class="version"></span>
|
||||
<span class="crc"></span>
|
||||
<input type="checkbox" id="editorEnableEdits">
|
||||
<label for="editorEnableEdits">Enable Edits</label><br>
|
||||
<input type="checkbox" id="editorGlobalPriority">
|
||||
|
||||
+64
-33
@@ -221,9 +221,9 @@ namespace loot {
|
||||
|
||||
// Now store plugin data.
|
||||
for (const auto& plugin : installed) {
|
||||
// Test data has 'hasUserEdits', and 'tagsAdd', 'tagsRemove' keys, but
|
||||
// the first will be handled by userlist lookups, and the other two are probably
|
||||
// going to get moved around, haven't decided how best to handle the split between masterlist, userlist and plugin-sourced metadata.
|
||||
/* Each plugin has members while hold its raw masterlist and userlist data for
|
||||
the editor, and also processed data for the main display.
|
||||
*/
|
||||
YAML::Node pluginNode;
|
||||
pluginNode["__type"] = "Plugin"; // For conversion back into a JS typed object.
|
||||
pluginNode["name"] = plugin.Name();
|
||||
@@ -239,22 +239,7 @@ namespace loot {
|
||||
mlistPlugin.MergeMetadata(g_app_state.CurrentGame().masterlist.FindPlugin(plugin.Name()));
|
||||
|
||||
if (!mlistPlugin.HasNameOnly()) {
|
||||
//Evaluate any conditions
|
||||
BOOST_LOG_TRIVIAL(trace) << "Evaluate conditions for merged plugin data.";
|
||||
try {
|
||||
mlistPlugin.EvalAllConditions(g_app_state.CurrentGame(), language);
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
BOOST_LOG_TRIVIAL(error) << "\"" << mlistPlugin.Name() << "\" contains a condition that could not be evaluated. Details: " << e.what();
|
||||
g_app_state.CurrentGame().masterlist.messages.push_back(Message(Message::error, (format(loc::translate("\"%1%\" contains a condition that could not be evaluated. Details: %2%")) % mlistPlugin.Name() % e.what()).str()));
|
||||
}
|
||||
|
||||
//Also check install validity.
|
||||
BOOST_LOG_TRIVIAL(trace) << "Checking that the current install is valid according to this plugin's data.";
|
||||
mlistPlugin.CheckInstallValidity(g_app_state.CurrentGame());
|
||||
|
||||
// Now add the masterlist metadata to the pluginNode.
|
||||
|
||||
// Now add the masterlist metadata to the pluginNode.]
|
||||
pluginNode["masterlist"]["modPriority"] = modulo(mlistPlugin.Priority(), max_priority);
|
||||
pluginNode["masterlist"]["isGlobalPriority"] = (abs(mlistPlugin.Priority()) >= max_priority);
|
||||
pluginNode["masterlist"]["after"] = mlistPlugin.LoadAfter();
|
||||
@@ -273,20 +258,6 @@ namespace loot {
|
||||
ulistPlugin.MergeMetadata(g_app_state.CurrentGame().userlist.FindPlugin(plugin.Name()));
|
||||
|
||||
if (!ulistPlugin.HasNameOnly()) {
|
||||
//Evaluate any conditions
|
||||
BOOST_LOG_TRIVIAL(trace) << "Evaluate conditions for merged plugin data.";
|
||||
try {
|
||||
ulistPlugin.EvalAllConditions(g_app_state.CurrentGame(), language);
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
BOOST_LOG_TRIVIAL(error) << "\"" << ulistPlugin.Name() << "\" contains a condition that could not be evaluated. Details: " << e.what();
|
||||
g_app_state.CurrentGame().masterlist.messages.push_back(Message(Message::error, (format(loc::translate("\"%1%\" contains a condition that could not be evaluated. Details: %2%")) % ulistPlugin.Name() % e.what()).str()));
|
||||
}
|
||||
|
||||
//Also check install validity.
|
||||
BOOST_LOG_TRIVIAL(trace) << "Checking that the current install is valid according to this plugin's data.";
|
||||
ulistPlugin.CheckInstallValidity(g_app_state.CurrentGame());
|
||||
|
||||
// Now add the masterlist metadata to the pluginNode.
|
||||
|
||||
pluginNode["userlist"]["modPriority"] = modulo(ulistPlugin.Priority(), max_priority);
|
||||
@@ -299,6 +270,66 @@ namespace loot {
|
||||
pluginNode["userlist"]["dirty"] = ulistPlugin.DirtyInfo();
|
||||
}
|
||||
|
||||
// Now merge masterlist and userlist metadata and evaluate,
|
||||
// putting any resulting metadata into the base of the pluginNode.
|
||||
|
||||
mlistPlugin.MergeMetadata(ulistPlugin);
|
||||
|
||||
//Evaluate any conditions
|
||||
BOOST_LOG_TRIVIAL(trace) << "Evaluate conditions for merged plugin data.";
|
||||
try {
|
||||
mlistPlugin.EvalAllConditions(g_app_state.CurrentGame(), language);
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
BOOST_LOG_TRIVIAL(error) << "\"" << mlistPlugin.Name() << "\" contains a condition that could not be evaluated. Details: " << e.what();
|
||||
g_app_state.CurrentGame().masterlist.messages.push_back(Message(Message::error, (format(loc::translate("\"%1%\" contains a condition that could not be evaluated. Details: %2%")) % mlistPlugin.Name() % e.what()).str()));
|
||||
}
|
||||
|
||||
//Also check install validity.
|
||||
BOOST_LOG_TRIVIAL(trace) << "Checking that the current install is valid according to this plugin's data.";
|
||||
mlistPlugin.CheckInstallValidity(g_app_state.CurrentGame());
|
||||
|
||||
// Also evaluate dirty info.
|
||||
std::list<Message> messages = mlistPlugin.Messages();
|
||||
std::set<PluginDirtyInfo> dirtyInfo = mlistPlugin.DirtyInfo();
|
||||
size_t numDirtyInfo(0);
|
||||
for (const auto &element : dirtyInfo) {
|
||||
boost::format f;
|
||||
if (element.ITMs() > 0 && element.UDRs() > 0 && element.DeletedNavmeshes() > 0)
|
||||
f = boost::format(boost::locale::translate("Contains %1% ITM records, %2% UDR records and %3% deleted navmeshes. Clean with %4%.")) % element.ITMs() % element.UDRs() % element.DeletedNavmeshes() % element.CleaningUtility();
|
||||
else if (element.ITMs() == 0 && element.UDRs() == 0 && element.DeletedNavmeshes() == 0)
|
||||
f = boost::format(boost::locale::translate("Clean with %1%.")) % element.CleaningUtility();
|
||||
|
||||
|
||||
else if (element.ITMs() == 0 && element.UDRs() > 0 && element.DeletedNavmeshes() > 0)
|
||||
f = boost::format(boost::locale::translate("Contains %1% UDR records and %2% deleted navmeshes. Clean with %3%.")) % element.UDRs() % element.DeletedNavmeshes() % element.CleaningUtility();
|
||||
else if (element.ITMs() == 0 && element.UDRs() == 0 && element.DeletedNavmeshes() > 0)
|
||||
f = boost::format(boost::locale::translate("Contains %1% deleted navmeshes. Clean with %2%.")) % element.DeletedNavmeshes() % element.CleaningUtility();
|
||||
else if (element.ITMs() == 0 && element.UDRs() > 0 && element.DeletedNavmeshes() == 0)
|
||||
f = boost::format(boost::locale::translate("Contains %1% UDR records. Clean with %2%.")) % element.UDRs() % element.CleaningUtility();
|
||||
|
||||
else if (element.ITMs() > 0 && element.UDRs() == 0 && element.DeletedNavmeshes() > 0)
|
||||
f = boost::format(boost::locale::translate("Contains %1% ITM records and %2% deleted navmeshes. Clean with %3%.")) % element.ITMs() % element.DeletedNavmeshes() % element.CleaningUtility();
|
||||
else if (element.ITMs() > 0 && element.UDRs() == 0 && element.DeletedNavmeshes() == 0)
|
||||
f = boost::format(boost::locale::translate("Contains %1% ITM records. Clean with %2%.")) % element.ITMs() % element.CleaningUtility();
|
||||
|
||||
else if (element.ITMs() > 0 && element.UDRs() > 0 && element.DeletedNavmeshes() == 0)
|
||||
f = boost::format(boost::locale::translate("Contains %1% ITM records and %2% UDR records. Clean with %3%.")) % element.ITMs() % element.UDRs() % element.CleaningUtility();
|
||||
|
||||
messages.push_back(loot::Message(loot::Message::warn, f.str()));
|
||||
++numDirtyInfo;
|
||||
}
|
||||
|
||||
// Now add to pluginNode.
|
||||
pluginNode["modPriority"] = modulo(mlistPlugin.Priority(), max_priority);
|
||||
pluginNode["isGlobalPriority"] = (abs(mlistPlugin.Priority()) >= max_priority);
|
||||
pluginNode["messages"] = messages;
|
||||
pluginNode["tags"] = mlistPlugin.Tags();
|
||||
pluginNode["isDirty"] = (numDirtyInfo > 0);
|
||||
|
||||
BOOST_LOG_TRIVIAL(trace) << "messages length: " << messages.size();
|
||||
BOOST_LOG_TRIVIAL(trace) << "tags length: " << mlistPlugin.Tags().size();
|
||||
|
||||
|
||||
gameNode["plugins"].push_back(pluginNode);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user