diff --git a/.eslintrc.yml b/.eslintrc.yml index 9828dd94..9e3a5da1 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -10,6 +10,7 @@ ecmaFeatures: globals: loot: false + should: false extends: - "eslint:recommended" diff --git a/src/gui/handler.cpp b/src/gui/handler.cpp index 8e592da0..c1bbf9b8 100644 --- a/src/gui/handler.cpp +++ b/src/gui/handler.cpp @@ -488,12 +488,12 @@ namespace loot { // First sort out the priority value. This is only given if it was changed. BOOST_LOG_TRIVIAL(trace) << "Calculating userlist metadata priority value from Javascript variables."; - if (pluginMetadata["modPriority"] && pluginMetadata["isGlobalPriority"]) { + if (pluginMetadata["priority"] && pluginMetadata["isPriorityGlobal"]) { BOOST_LOG_TRIVIAL(trace) << "Priority value was changed, recalculating..."; // Priority value was changed, so add it to the userlist data. - newUserlistEntry.Priority(pluginMetadata["modPriority"].as()); + newUserlistEntry.Priority(pluginMetadata["priority"].as()); newUserlistEntry.SetPriorityExplicit(true); - newUserlistEntry.SetPriorityGlobal(pluginMetadata["isGlobalPriority"].as()); + newUserlistEntry.SetPriorityGlobal(pluginMetadata["isPriorityGlobal"].as()); } else { // Priority value wasn't changed, use the existing userlist value. @@ -1056,8 +1056,8 @@ namespace loot { // Now add to pluginNode. YAML::Node pluginNode; pluginNode["name"] = tempPlugin.Name(); - pluginNode["modPriority"] = tempPlugin.Priority(); - pluginNode["isGlobalPriority"] = tempPlugin.IsPriorityGlobal(); + pluginNode["priority"] = tempPlugin.Priority(); + pluginNode["isPriorityGlobal"] = tempPlugin.IsPriorityGlobal(); pluginNode["messages"] = tempPlugin.Messages(); pluginNode["tags"] = tempPlugin.Tags(); pluginNode["isDirty"] = isDirty; diff --git a/src/gui/html/elements/loot-plugin-card.html b/src/gui/html/elements/loot-plugin-card.html index c2959880..c8ddd05a 100644 --- a/src/gui/html/elements/loot-plugin-card.html +++ b/src/gui/html/elements/loot-plugin-card.html @@ -257,6 +257,10 @@ loot-clear-metadata this.classList.toggle('flip'); } + /* Update version and CRC text */ + this.getElementsByClassName('version')[0].textContent = this.data.getCardContent(loot.filters).version; + this.getElementsByClassName('crc')[0].textContent = this.data.getCardContent(loot.filters).crc; + /* Also initialise the non-simple-string data. */ this.onTagsChange(); this.onMessagesChange(); @@ -278,8 +282,13 @@ loot-clear-metadata onTagsChange: function(oldValue, newValue) { if (this.data) { - this.getElementsByClassName('tag add')[0].classList.toggle('hidden', this.data.tagStrings.added.length == 0); - this.getElementsByClassName('tag remove')[0].classList.toggle('hidden', this.data.tagStrings.removed.length == 0); + var cardContent = this.data.getCardContent(loot.filters); + var tagsAdded = this.getElementsByClassName('tag add')[0]; + tagsAdded.textContent = cardContent.tags.added; + tagsAdded.classList.toggle('hidden', cardContent.tags.added.length == 0); + var tagsRemoved = this.getElementsByClassName('tag remove')[0]; + tagsRemoved.textContent = cardContent.tags.removed; + tagsRemoved.classList.toggle('hidden', cardContent.tags.removed.length == 0); } }, @@ -291,16 +300,15 @@ loot-clear-metadata messageUL.removeChild(messageUL.firstElementChild); } /* Now add new messages. */ - var visibleMessages = filters.applyMessageFilters(this.data.messages); - visibleMessages.forEach(function(message) { + var cardContent = this.data.getCardContent(loot.filters); + cardContent.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); + messageLi.innerHTML = marked(message.content); messageUL.appendChild(messageLi); - }); - messageUL.classList.toggle('hidden', visibleMessages.length == 0); + messageUL.classList.toggle('hidden', cardContent.messages.length == 0); } }, diff --git a/src/gui/html/elements/loot-plugin-editor.html b/src/gui/html/elements/loot-plugin-editor.html index cbefbbb0..0ff7eb92 100644 --- a/src/gui/html/elements/loot-plugin-editor.html +++ b/src/gui/html/elements/loot-plugin-editor.html @@ -125,8 +125,8 @@ loot-editor-close

{{data.name}}

- {{data.version}} - {{data.crcString}} + +
@@ -250,8 +250,8 @@ loot-editor-close data: undefined, observe: { - 'data.isGlobalPriority': 'onPriorityChange', - 'data.modPriority': 'onPriorityChange', + 'data.isPriorityGlobal': 'onPriorityChange', + 'data.priority': 'onPriorityChange', 'data.userlist': 'onDataCacheChange', }, @@ -318,10 +318,10 @@ loot-editor-close /* If either of the priority values have been changed, the base priority value they're derived from will have changed, so record both. */ - if (this.shadowRoot.getElementById('globalPriority').checked != oldData.isGlobalPriority - || this.shadowRoot.getElementById('priorityValue').value != oldData.modPriority) { - plugin.isGlobalPriority = this.shadowRoot.getElementById('globalPriority').checked; - plugin.modPriority = this.shadowRoot.getElementById('priorityValue').value; + if (this.shadowRoot.getElementById('globalPriority').checked != oldData.isPriorityGlobal + || this.shadowRoot.getElementById('priorityValue').value != oldData.priority) { + plugin.isPriorityGlobal = this.shadowRoot.getElementById('globalPriority').checked; + plugin.priority = this.shadowRoot.getElementById('priorityValue').value; /* Also mark the priority as being explicitly set in the userlist. */ plugin.userlist.hasExplicitPriority = true; } @@ -349,7 +349,7 @@ loot-editor-close plugin.userlist.msg = rowsData; } else if (tables[j].parentElement.id == 'tags') { rowsData.forEach(function(value, index, arr){ - arr[index] = Plugin.tagFromRowData(value); + arr[index] = loot.Plugin.tagFromRowData(value); }); plugin.userlist.tag = rowsData; } else if (tables[j].parentElement.id == 'dirty') { @@ -391,29 +391,33 @@ loot-editor-close that for userlist and priority data if so. */ var tempData = {}; if (newData.editor) { - if (newData.editor.isGlobalPriority) { - tempData.isGlobalPriority = newData.editor.isGlobalPriority; + if (newData.editor.isPriorityGlobal) { + tempData.isPriorityGlobal = newData.editor.isPriorityGlobal; } - if (newData.editor.modPriority) { - tempData.modPriority = newData.editor.modPriority; + if (newData.editor.priority) { + tempData.priority = newData.editor.priority; } tempData.userlist = newData.editor.userlist; } else { tempData = { - isGlobalPriority: newData.isGlobalPriority, - modPriority: newData.modPriority, + isPriorityGlobal: newData.isPriorityGlobal, + priority: newData.priority, userlist: newData.userlist } } + /* Fill in the version and CRC values. */ + this.shadowRoot.getElementById('version').textContent = newData.getCardContent(loot.filters).version; + this.shadowRoot.getElementById('crc').textContent = newData.getCardContent(loot.filters).crc; + /* Fill in the editor input values. */ if (tempData.userlist && !tempData.userlist.enabled) { this.shadowRoot.getElementById('enableEdits').checked = false; } else { this.shadowRoot.getElementById('enableEdits').checked = true; } - this.shadowRoot.getElementById('globalPriority').checked = tempData.isGlobalPriority; - this.shadowRoot.getElementById('priorityValue').value = tempData.modPriority; + this.shadowRoot.getElementById('globalPriority').checked = tempData.isPriorityGlobal; + this.shadowRoot.getElementById('priorityValue').value = tempData.priority; /* Clear then fill in editor table data. Masterlist-originated rows should have their contents made read-only. */ @@ -493,14 +497,14 @@ loot-editor-close if (newData.masterlist && newData.masterlist.tag) { newData.masterlist.tag.forEach(function(tag) { - var tagData = Plugin.tagToRowData(tag); + var tagData = loot.Plugin.tagToRowData(tag); var row = tables[j].addRow(tagData); tables[j].setReadOnly(row); }, newData); } if (tempData.userlist && tempData.userlist.tag) { tempData.userlist.tag.forEach(function(tag) { - var tagData = Plugin.tagToRowData(tag); + var tagData = loot.Plugin.tagToRowData(tag); tables[j].addRow(tagData); }, tempData); } diff --git a/src/gui/html/elements/loot-plugin-item.html b/src/gui/html/elements/loot-plugin-item.html index f2c289de..2cfb7675 100644 --- a/src/gui/html/elements/loot-plugin-item.html +++ b/src/gui/html/elements/loot-plugin-item.html @@ -140,8 +140,8 @@ observe: { 'data.userlist': 'onUserlistChange', - 'data.modPriority': 'onPriorityChange', - 'data.isGlobalPriority': 'onPriorityIsGlobalChange', + 'data.priority': 'onPriorityChange', + 'data.isPriorityGlobal': 'onPriorityIsGlobalChange', 'data.isEditorOpen': 'onEditorStateChange', }, @@ -163,8 +163,8 @@ }, onPriorityChange: function(oldValue, newValue) { - if (this.data && this.data.modPriority) { - this.shadowRoot.getElementById('priority').textContent = this.data.modPriority; + if (this.data && this.data.priority) { + this.shadowRoot.getElementById('priority').textContent = this.data.priority; this.shadowRoot.getElementById('secondary').classList.remove('hidden'); } else { this.shadowRoot.getElementById('priority').textContent = ''; @@ -173,7 +173,7 @@ }, onPriorityIsGlobalChange: function(oldValue, newValue) { - if (this.data && this.data.isGlobalPriority) { + if (this.data && this.data.isPriorityGlobal) { this.shadowRoot.getElementById('secondary').firstElementChild.classList.remove('hidden'); } else { this.shadowRoot.getElementById('secondary').firstElementChild.classList.add('hidden'); diff --git a/src/gui/html/elements/loot-search.html b/src/gui/html/elements/loot-search.html index fc4fa2a2..1fc91aee 100644 --- a/src/gui/html/elements/loot-search.html +++ b/src/gui/html/elements/loot-search.html @@ -135,33 +135,10 @@ searchTarget is the ID of the core-list element to search the elements of. var crcHidden = document.getElementById('hideCRCs').checked; var bashTagHidden = document.getElementById('hideBashTags').checked; document.getElementById(host.searchTarget).data.forEach(function(plugin, index){ - if (plugin.name.toLowerCase().indexOf(needle) != -1 - || (!versionHidden && plugin.version.toLowerCase().indexOf(needle) != -1) - || (!crcHidden && plugin.crcString.toLowerCase().indexOf(needle) != -1)) { - - host.results.push(index); - plugin.isSearchResult = true; - return; - } - - if (!bashTagHidden) { - var tags = plugin.tagStrings; - if (tags.added.toLowerCase().indexOf(needle) != -1 - || tags.removed.toLowerCase().indexOf(needle) != -1) { - - host.results.push(index); - plugin.isSearchResult = true; - return; - } - } - - var visibleMessages = filters.applyMessageFilters(this.data.messages); - for (var i = 0; i < visibleMessages.length; ++i) { - if (visibleMessages[i].content[0].str.toLowerCase().indexOf(needle) != -1) { - host.results.push(index); - plugin.isSearchResult = true; - return; - } + if (plugin.getCardContent(loot.filters).containsText(needle)) { + host.results.push(index); + plugin.isSearchResult = true; + return; } }); diff --git a/src/gui/html/index.html b/src/gui/html/index.html index a3a9873b..277e7c9f 100644 --- a/src/gui/html/index.html +++ b/src/gui/html/index.html @@ -213,10 +213,10 @@ @@ -315,12 +315,12 @@ + + + - - - - + diff --git a/src/gui/html/js/events.js b/src/gui/html/js/events.js index e9bf8bf8..c07d73e8 100644 --- a/src/gui/html/js/events.js +++ b/src/gui/html/js/events.js @@ -111,10 +111,10 @@ function updateMasterlistNoProgress() { for (var i = 0; i < loot.game.plugins.length; ++i) { if (loot.game.plugins[i].name == plugin.name) { loot.game.plugins[i].isDirty = plugin.isDirty; - loot.game.plugins[i].isGlobalPriority = plugin.isGlobalPriority; + loot.game.plugins[i].isPriorityGlobal = plugin.isPriorityGlobal; loot.game.plugins[i].masterlist = plugin.masterlist; loot.game.plugins[i].messages = plugin.messages; - loot.game.plugins[i].modPriority = plugin.modPriority; + loot.game.plugins[i].priority = plugin.priority; loot.game.plugins[i].tags = plugin.tags; break; } @@ -276,8 +276,8 @@ function onClearAllMetadata(evt) { loot.game.plugins[i].userlist = undefined; loot.game.plugins[i].editor = undefined; - loot.game.plugins[i].modPriority = plugin.modPriority; - loot.game.plugins[i].isGlobalPriority = plugin.isGlobalPriority; + loot.game.plugins[i].priority = plugin.priority; + loot.game.plugins[i].isPriorityGlobal = plugin.isPriorityGlobal; loot.game.plugins[i].messages = plugin.messages; loot.game.plugins[i].tags = plugin.tags; loot.game.plugins[i].isDirty = plugin.isDirty; @@ -317,8 +317,8 @@ function onCopyContent(evt) { isEmpty: plugin.isEmpty, loadsArchive: plugin.loadsArchive, - modPriority: plugin.modPriority, - isGlobalPriority: plugin.isGlobalPriority, + priority: plugin.priority, + isPriorityGlobal: plugin.isPriorityGlobal, messages: plugin.messages, tags: plugin.tags, isDirty: plugin.isDirty @@ -491,8 +491,8 @@ function onEditorClose(evt) { }); promise = loot.query(request).then(JSON.parse).then(function(result){ if (result) { - evt.target.data.modPriority = result.modPriority; - evt.target.data.isGlobalPriority = result.isGlobalPriority; + evt.target.data.priority = result.priority; + evt.target.data.isPriorityGlobal = result.isPriorityGlobal; evt.target.data.messages = result.messages; evt.target.data.tags = result.tags; evt.target.data.isDirty = result.isDirty; @@ -598,8 +598,8 @@ function onClearMetadata(evt) { loot.game.plugins[i].userlist = undefined; loot.game.plugins[i].editor = undefined; - loot.game.plugins[i].modPriority = result.modPriority; - loot.game.plugins[i].isGlobalPriority = result.isGlobalPriority; + loot.game.plugins[i].priority = result.priority; + loot.game.plugins[i].isPriorityGlobal = result.isPriorityGlobal; loot.game.plugins[i].messages = result.messages; loot.game.plugins[i].tags = result.tags; loot.game.plugins[i].isDirty = result.isDirty; @@ -670,8 +670,8 @@ function onContentRefresh(evt) { loot.game.plugins[i].crc = plugin.crc; loot.game.plugins[i].version = plugin.version; - loot.game.plugins[i].modPriority = plugin.modPriority; - loot.game.plugins[i].isGlobalPriority = plugin.isGlobalPriority; + loot.game.plugins[i].priority = plugin.priority; + loot.game.plugins[i].isPriorityGlobal = plugin.isPriorityGlobal; loot.game.plugins[i].messages = plugin.messages; loot.game.plugins[i].tags = plugin.tags; loot.game.plugins[i].isDirty = plugin.isDirty; @@ -715,6 +715,15 @@ function onSearchOpen(evt) { function onSearchClose(evt) { document.getElementById('mainToolbar').classList.remove('search'); } +function onSidebarFilterToggle(evt) { + if (evt.target.id !== 'contentFilter') { + loot.filters[evt.target.id] = evt.target.checked; + } else { + loot.filters.contentSearchString = evt.target.value; + } + saveFilterState(evt); + setFilteredUIData(); +} function setupEventHandlers() { /*Set up handlers for filters.*/ document.getElementById('hideVersionNumbers').addEventListener('change', onToggleDisplayCSS, false); @@ -723,20 +732,15 @@ function setupEventHandlers() { document.getElementById('hideCRCs').addEventListener('change', saveFilterState, false); document.getElementById('hideBashTags').addEventListener('change', onToggleBashTags, false); document.getElementById('hideBashTags').addEventListener('change', saveFilterState, false); - document.getElementById('hideNotes').addEventListener('change', setFilteredUIData, false); - document.getElementById('hideNotes').addEventListener('change', saveFilterState, false); - document.getElementById('hideDoNotCleanMessages').addEventListener('change', setFilteredUIData, false); - document.getElementById('hideDoNotCleanMessages').addEventListener('change', saveFilterState, false); - document.getElementById('hideInactivePlugins').addEventListener('change', setFilteredUIData, false); - document.getElementById('hideInactivePlugins').addEventListener('change', saveFilterState, false); - document.getElementById('hideAllPluginMessages').addEventListener('change', setFilteredUIData, false); - document.getElementById('hideAllPluginMessages').addEventListener('change', saveFilterState, false); - document.getElementById('hideMessagelessPlugins').addEventListener('change', setFilteredUIData, false); - document.getElementById('hideMessagelessPlugins').addEventListener('change', saveFilterState, false); + document.getElementById('hideNotes').addEventListener('change', onSidebarFilterToggle, false); + document.getElementById('hideDoNotCleanMessages').addEventListener('change', onSidebarFilterToggle, false); + document.getElementById('hideInactivePlugins').addEventListener('change', onSidebarFilterToggle, false); + document.getElementById('hideAllPluginMessages').addEventListener('change', onSidebarFilterToggle, false); + document.getElementById('hideMessagelessPlugins').addEventListener('change', onSidebarFilterToggle, false); document.body.addEventListener('loot-filter-conflicts', onConflictsFilter, false); /* Set up event handlers for content filter. */ - document.getElementById('contentFilter').addEventListener('change', setFilteredUIData, false); + document.getElementById('contentFilter').addEventListener('change', onSidebarFilterToggle, false); /* Set up handlers for buttons. */ document.getElementById('redatePluginsButton').addEventListener('click', onRedatePlugins, false); diff --git a/src/gui/html/js/filters.js b/src/gui/html/js/filters.js index dcebfc87..7f229173 100644 --- a/src/gui/html/js/filters.js +++ b/src/gui/html/js/filters.js @@ -1,252 +1,67 @@ -var filters = { - /* Filter functions return true if the given plugin passes the filter and - should be displayed, otherwise false. */ +'use strict'; +(function exportModule(root, factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define([], factory); + } else { + // Browser globals + root.loot = root.loot || {}; + root.loot.Filters = factory(); + } +}(this, () => { + return class Filters { + constructor(l10n) { + /* Plugin filters */ + this.hideMessagelessPlugins = false; + this.hideInactivePlugins = false; + this.conflictingPluginNames = []; + this.contentSearchString = ''; - hiddenPluginNo: 0, - hiddenMessageNo: 0, - conflicts: [], + /* Plugin content filters */ + this.hideVersionNumbers = false; + this.hideCRCs = false; + this.hideBashTags = false; + this.hideAllPluginMessages = false; + this.hideNotes = false; + this.hideDoNotCleanMessages = false; - searchFilter: function(plugin, needle) { - if (needle.length == 0) { - return true; + this._doNotCleanString = l10n.translate('Do not clean').toLowerCase(); + } + + pluginFilter(plugin) { + if (this.hideInactivePlugins && !plugin.isActive) { + return false; } - if (plugin.name.toLowerCase().indexOf(needle) != -1 - || plugin.crcString.toLowerCase().indexOf(needle) != -1 - || plugin.version.toLowerCase().indexOf(needle) != -1) { - - return true; + if (this.conflictingPluginNames.length !== 0 && this.conflictingPluginNames.indexOf(plugin.name) === -1) { + return false; } - var tags = plugin.tagStrings; - if (tags.added.toLowerCase().indexOf(needle) != -1 - || tags.removed.toLowerCase().indexOf(needle) != -1) { - - return true; + if (this.hideMessagelessPlugins && plugin.getCardContent(this).messages.length === 0) { + return false; } - for (var i = 0; i < plugin.messages.length; ++i) { - if (plugin.messages[i].content[0].str.toLowerCase().indexOf(needle) != -1) { - return true; - } - } - }, - - messagelessFilter: function(plugin) { - /* This function could be further optimised to perform fewer checks, - but it's also responsible for setting the hidden message count, so - has to go through everything. */ - - var hasMessages = false; - /* If any messages exist, check if they are hidden or not. Note - that the messages may not be present as elements, so the check - is actually if they would be hidden according to the message - filters. */ - if (this.allMessageFilter()) { - plugin.messages.forEach(function(message){ - if (this.noteFilter(message) - && this.doNotCleanFilter(message)) { - - hasMessages = true; - return; - } - ++hiddenMessageNo; - }, this); - } else { - hiddenMessageNo += plugin.messages.length; + if (this.contentSearchString.length !== 0 && !plugin.getCardContent(this).containsText(this.contentSearchString)) { + return false; } - if (document.getElementById('hideMessagelessPlugins').checked) { - return hasMessages; - } else { - return true; - } - }, + return true; + } - inactiveFilter: function(plugin) { - if (document.getElementById('hideInactivePlugins').checked) { - return plugin.isActive; - } else { - return true; - } - }, - - conflictsFilter: function(plugin) { - if (this.conflicts.length > 0) { - return this.conflicts.indexOf(plugin.name) != -1; - } else { - return true; - } - }, - - applyPluginFilters: function(plugins) { - var search = document.getElementById('contentFilter').value.toLowerCase(); - hiddenPluginNo = 0; - hiddenMessageNo = 0; - var filteredPlugins = []; - - plugins.forEach(function(plugin){ - /* Messageless filter needs to run first. */ - if (this.messagelessFilter(plugin) - && this.inactiveFilter(plugin) - && this.conflictsFilter(plugin) - && this.searchFilter(plugin, search)) { - - filteredPlugins.push(plugin); - return; - } - ++hiddenPluginNo; - }, this); - - document.getElementById('hiddenPluginNo').textContent = hiddenPluginNo; - document.getElementById('hiddenMessageNo').textContent = hiddenMessageNo; - - return filteredPlugins; - }, - - /* Message filter functions are run from within plugin cards, when the card's - messages are to be added as elements. Each filter should return true if the - message is to be displayed. */ - - noteFilter: function(message) { - if (document.getElementById('hideNotes').checked) { - return message.type != 'say'; - } else { - return true; - } - }, - - doNotCleanFilter: function(message) { - if (document.getElementById('hideDoNotCleanMessages').checked) { - return message.content[0].str.indexOf(loot.l10n.translate("Do not clean")) == -1; - } else { - return true; - } - }, - - allMessageFilter: function() { - return !document.getElementById('hideAllPluginMessages').checked; - }, - - applyMessageFilters: function(messages) { - var filteredMessages = []; - - if (this.allMessageFilter()) { - messages.forEach(function(message){ - if (this.noteFilter(message) - && this.doNotCleanFilter(message)) { - - filteredMessages.push(message); - return; - } - }, this); + messageFilter(message) { + if (this.hideAllPluginMessages) { + return false; } - return filteredMessages; - }, -}; - -function getConflictingPluginsFromFilter() { - var conflictsPlugin = document.body.getAttribute('data-conflicts'); - if (conflictsPlugin) { - /* Now get conflicts for the plugin. */ - var request = JSON.stringify({ - name: 'getConflictingPlugins', - args: [ - conflictsPlugin - ] - }); - - showProgress(loot.l10n.translate('Checking if plugins have been loaded...')); - - return loot.query(request).then(JSON.parse).then(function(result){ - if (result) { - /* Filter everything but the plugin itself if there are no - conflicts. */ - var conflicts = [ conflictsPlugin ]; - for (var key in result) { - if (result[key].conflicts) { - conflicts.push(key); - } - for (var i = 0; i < loot.game.plugins.length; ++i) { - if (loot.game.plugins[i].name == key) { - loot.game.plugins[i].crc = result[key].crc; - loot.game.plugins[i].isEmpty = result[key].isEmpty; - - loot.game.plugins[i].messages = result[key].messages; - loot.game.plugins[i].tags = result[key].tags; - loot.game.plugins[i].isDirty = result[key].isDirty; - break; - } - } - } - closeProgressDialog(); - return conflicts; - } - closeProgressDialog(); - return [ conflictsPlugin ]; - }).catch(processCefError); - } - - return Promise.resolve([]); -} - -function setFilteredUIData() { - /* The conflict filter, if enabled, executes C++ code, so needs to be - handled using a promise, so the rest of the function should wait until - it is completed. - */ - getConflictingPluginsFromFilter().then(function(conflicts) { - filters.conflicts = conflicts; - var filtered = filters.applyPluginFilters(loot.game.plugins); - document.getElementById('cardsNav').data = filtered; - document.getElementById('main').lastElementChild.data = filtered; - - filtered.forEach(function(plugin){ - var element = document.getElementById(plugin.id); - if (element) { - element.onMessagesChange(); - } - }); - - /* Now perform search again. If there is no current search, this won't - do anything. */ - document.getElementById('searchBar').search(); - }); -} -function restoreFilterStates() { - if (loot.settings.filters) { - document.getElementById('hideMessagelessPlugins').checked = loot.settings.filters.hideMessagelessPlugins; - document.getElementById('hideInactivePlugins').checked = loot.settings.filters.hideInactivePlugins; - document.getElementById('hideNotes').checked = loot.settings.filters.hideNotes; - document.getElementById('hideDoNotCleanMessages').checked = loot.settings.filters.hideDoNotCleanMessages; - document.getElementById('hideAllPluginMessages').checked = loot.settings.filters.hideAllPluginMessages; - document.getElementById('hideVersionNumbers').checked = loot.settings.filters.hideVersionNumbers; - document.getElementById('hideCRCs').checked = loot.settings.filters.hideCRCs; - document.getElementById('hideBashTags').checked = loot.settings.filters.hideBashTags; - } -} - -function applyEnabledFilters() { - if (loot.settings.filters) { - if (loot.settings.filters.hideMessagelessPlugins - || loot.settings.filters.hideInactivePlugins - || loot.settings.filters.hideNotes - || loot.settings.filters.hideDoNotCleanMessages - || loot.settings.filters.hideAllPluginMessages) { - setFilteredUIData(); + if (this.hideNotes && message.type === 'say') { + return false; } - if (loot.settings.filters.hideVersionNumbers) { - document.getElementById('hideVersionNumbers').dispatchEvent(new Event('change')); + if (this.hideDoNotCleanMessages && message.content.toLowerCase().indexOf(this._doNotCleanString) !== -1) { + return false; } - if (loot.settings.filters.hideCRCs) { - document.getElementById('hideCRCs').dispatchEvent(new Event('change')); - } - - if (loot.settings.filters.hideBashTags) { - document.getElementById('hideBashTags').dispatchEvent(new Event('change')); - } - } -} + return true; + } + }; +})); diff --git a/src/gui/html/js/helpers.js b/src/gui/html/js/helpers.js index 086f3f5d..9f506cb1 100644 --- a/src/gui/html/js/helpers.js +++ b/src/gui/html/js/helpers.js @@ -70,3 +70,74 @@ function handleUnappliedChangesClose(change) { } }); } +function getConflictingPlugins(pluginName) { + if (!pluginName) { + return Promise.resolve([]); + } + + /* Now get conflicts for the plugin. */ + const request = JSON.stringify({ + name: 'getConflictingPlugins', + args: [ + pluginName, + ], + }); + + showProgress(loot.l10n.translate('Checking if plugins have been loaded...')); + + return loot.query(request).then(JSON.parse).then((result) => { + if (result) { + /* Filter everything but the plugin itself if there are no + conflicts. */ + const conflicts = [pluginName]; + for (const key in result) { + if (result[key].conflicts) { + conflicts.push(key); + } + for (let i = 0; i < loot.game.plugins.length; ++i) { + if (loot.game.plugins[i].name === key) { + loot.game.plugins[i].crc = result[key].crc; + loot.game.plugins[i].isEmpty = result[key].isEmpty; + + loot.game.plugins[i].messages = result[key].messages; + loot.game.plugins[i].tags = result[key].tags; + loot.game.plugins[i].isDirty = result[key].isDirty; + break; + } + } + } + closeProgressDialog(); + return conflicts; + } + closeProgressDialog(); + return [pluginName]; + }).catch(processCefError); +} +function setFilteredUIData(filtersState) { + getConflictingPlugins(loot.filters.conflictTargetPluginName).then((conflictingPluginNames) => { + loot.filters.conflictingPluginNames = conflictingPluginNames; + return loot.game.plugins.filter(loot.filters.pluginFilter, loot.filters); + }).then((filteredPlugins) => { + document.getElementById('cardsNav').data = filteredPlugins; + document.getElementById('pluginCardList').data = filteredPlugins; + + filteredPlugins.forEach((plugin) => { + const element = document.getElementById(plugin.id); + if (element) { + element.onMessagesChange(); + } + }); + + /* Now perform search again. If there is no current search, this won't + do anything. */ + document.getElementById('searchBar').search(); + + /* Re-count all hidden plugins and messages. */ + document.getElementById('hiddenPluginNo').textContent = loot.game.plugins.length - filteredPlugins.length; + let hiddenMessageNo = 0; + loot.game.plugins.forEach((plugin) => { + hiddenMessageNo += plugin.messages.length - plugin.getCardContent(loot.filters).messages.length; + }); + document.getElementById('hiddenMessageNo').textContent = hiddenMessageNo; + }); +} diff --git a/src/gui/html/js/init.js b/src/gui/html/js/init.js index 0b8d618e..e5263c9e 100644 --- a/src/gui/html/js/init.js +++ b/src/gui/html/js/init.js @@ -25,6 +25,53 @@ var marked; var l10n; +function restoreFilterStates() { + if (loot.settings.filters && loot.filters) { + loot.filters.hideMessagelessPlugins = loot.settings.filters.hideMessagelessPlugins; + loot.filters.hideInactivePlugins = loot.settings.filters.hideInactivePlugins; + loot.filters.hideNotes = loot.settings.filters.hideNotes; + loot.filters.hideDoNotCleanMessages = loot.settings.filters.hideDoNotCleanMessages; + loot.filters.hideAllPluginMessages = loot.settings.filters.hideAllPluginMessages; + loot.filters.hideVersionNumbers = loot.settings.filters.hideVersionNumbers; + loot.filters.hideCRCs = loot.settings.filters.hideCRCs; + loot.filters.hideBashTags = loot.settings.filters.hideBashTags; + + document.getElementById('hideMessagelessPlugins').checked = loot.settings.filters.hideMessagelessPlugins; + document.getElementById('hideInactivePlugins').checked = loot.settings.filters.hideInactivePlugins; + document.getElementById('hideNotes').checked = loot.settings.filters.hideNotes; + document.getElementById('hideDoNotCleanMessages').checked = loot.settings.filters.hideDoNotCleanMessages; + document.getElementById('hideAllPluginMessages').checked = loot.settings.filters.hideAllPluginMessages; + document.getElementById('hideVersionNumbers').checked = loot.settings.filters.hideVersionNumbers; + document.getElementById('hideCRCs').checked = loot.settings.filters.hideCRCs; + document.getElementById('hideBashTags').checked = loot.settings.filters.hideBashTags; + } +} + +function applyEnabledFilters() { + if (!loot.filters) { + return; + } + + if (loot.filters.hideMessagelessPlugins + || loot.filters.hideInactivePlugins + || loot.filters.hideNotes + || loot.filters.hideDoNotCleanMessages + || loot.filters.hideAllPluginMessages) { + setFilteredUIData(); + } + + if (loot.filters.hideVersionNumbers) { + document.getElementById('hideVersionNumbers').dispatchEvent(new Event('change')); + } + + if (loot.filters.hideCRCs) { + document.getElementById('hideCRCs').dispatchEvent(new Event('change')); + } + + if (loot.filters.hideBashTags) { + document.getElementById('hideBashTags').dispatchEvent(new Event('change')); + } +} function initVars() { loot.query('getVersion').then(function(result){ try { diff --git a/src/gui/html/js/plugin.js b/src/gui/html/js/plugin.js index 94733205..875a85c0 100644 --- a/src/gui/html/js/plugin.js +++ b/src/gui/html/js/plugin.js @@ -32,23 +32,155 @@ root.loot.Plugin = factory(); } }(this, () => { + /* Messages, tags, CRCs and version strings can all be hidden by filters. + Use getters with no setters for member variables as data should not be + written to objects of this class. */ + class PluginCardContent { + constructor(plugin, filters) { + this._name = plugin.name; + this._isActive = plugin.isActive || false; + this._isEmpty = plugin.isEmpty; + this._isMaster = plugin.isMaster; + this._loadsArchive = plugin.loadsArchive; + + if (!filters.hideVersionNumbers) { + this._version = plugin.version; + } else { + this._version = ''; + } + + if (!filters.hideCRCs) { + this._crc = plugin.crc; + } else { + this._crc = 0; + } + + if (!filters.hideBashTags) { + this._tags = plugin.tags; + } else { + this._tags = []; + } + + this._messages = plugin.messages.map((message) => { + return { + type: message.type, + content: message.content[0].str, + }; + }).filter(filters.messageFilter, filters); + } + + get name() { + return this._name; + } + + get isActive() { + return this._isActive; + } + + get isEmpty() { + return this._isEmpty; + } + + get isMaster() { + return this._isMaster; + } + + get loadsArchive() { + return this._loadsArchive; + } + + get version() { + return this._version; + } + + get crc() { + if (this._crc === 0) { + return ''; + } + + /* Pad CRC string to 8 characters. */ + return ('00000000' + this._crc.toString(16).toUpperCase()).slice(-8); + } + + get tags() { + const tagsAdded = []; + const tagsRemoved = []; + + if (this._tags) { + for (let 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._tags[i].name); + } + } + } + /* Now make sure that the same tag doesn't appear in both arrays. + Prefer the removed list. */ + for (let i = 0; i < tagsAdded.length; ++i) { + for (let j = 0; j < tagsRemoved.length; ++j) { + if (tagsRemoved[j].toLowerCase() === tagsAdded[i].toLowerCase()) { + /* Remove tag from the tagsAdded array. */ + tagsAdded.splice(i, 1); + --i; + } + } + } + + return { + added: tagsAdded.join(', '), + removed: tagsRemoved.join(', '), + }; + } + + get messages() { + return this._messages; + } + + containsText(text) { + if (text === undefined || text.length === 0) { + return true; + } + const needle = text.toLowerCase(); + + if (this.name.toLowerCase().indexOf(needle) !== -1 + || this.crc.toLowerCase().indexOf(needle) !== -1 + || this.version.toLowerCase().indexOf(needle) !== -1) { + return true; + } + + if (this.tags.added.toLowerCase().indexOf(needle) !== -1 + || this.tags.removed.toLowerCase().indexOf(needle) !== -1) { + return true; + } + + for (let i = 0; i < this.messages.length; ++i) { + if (this.messages[i].content.toLowerCase().indexOf(needle) !== -1) { + return true; + } + } + + return false; + } + } + return class Plugin { constructor(obj) { /* Plugin data */ this.name = obj.name; - this.crc = obj.crc; - this.version = obj.version; - this.isActive = obj.isActive; - this.isEmpty = obj.isEmpty; - this.isMaster = obj.isMaster; - this.loadsArchive = obj.loadsArchive; + this.crc = obj.crc || 0; + this.version = obj.version || ''; + this.isActive = obj.isActive || false; + this.isEmpty = obj.isEmpty || false; + this.isMaster = obj.isMaster || false; + this.loadsArchive = obj.loadsArchive || false; this.masterlist = obj.masterlist; this.userlist = obj.userlist; - this.modPriority = obj.modPriority; - this.isGlobalPriority = obj.isGlobalPriority; - this._messages = obj.messages; + this.priority = obj.priority || 0; + this.isPriorityGlobal = obj.isPriorityGlobal || false; + this._messages = obj.messages || []; this.tags = obj.tags; this._isDirty = obj.isDirty || false; @@ -100,52 +232,12 @@ return rowData; } - get tagStrings() { - const tagsAdded = []; - const tagsRemoved = []; - - if (this.tags) { - for (let 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.tags[i].name); - } - } - } - /* Now make sure that the same tag doesn't appear in both arrays. - Prefer the removed list. */ - for (let i = 0; i < tagsAdded.length; ++i) { - for (let j = 0; j < tagsRemoved.length; ++j) { - if (tagsRemoved[j].toLowerCase() === tagsAdded[i].toLowerCase()) { - /* Remove tag from the tagsAdded array. */ - tagsAdded.splice(i, 1); - --i; - } - } - } - - return { - added: tagsAdded.join(', '), - removed: tagsRemoved.join(', '), - }; - } - get priorityString() { - if (this.modPriority === undefined || this.modPriority === 0) { + if (this.priority === 0) { return ''; } - return this.modPriority.toString(); - } - - get crcString() { - if (this.crc === undefined || this.crc === 0) { - return ''; - } - - /* Pad CRC string to 8 characters. */ - return ('00000000' + this.crc.toString(16).toUpperCase()).slice(-8); + return this.priority.toString(); } get messages() { @@ -161,29 +253,25 @@ let oldErrs = 0; let newErrs = 0; - if (this._messages) { - oldTotal = this._messages.length; + oldTotal = this._messages.length; - this._messages.forEach((message) => { - if (message.type === 'warn') { - ++oldWarns; - } else if (message.type === 'error') { - ++oldErrs; - } - }); - } + this._messages.forEach((message) => { + if (message.type === 'warn') { + ++oldWarns; + } else if (message.type === 'error') { + ++oldErrs; + } + }); - if (messages) { - newTotal = messages.length; + newTotal = messages.length; - messages.forEach((message) => { - if (message.type === 'warn') { - ++newWarns; - } else if (message.type === 'error') { - ++newErrs; - } - }); - } + messages.forEach((message) => { + if (message.type === 'warn') { + ++newWarns; + } else if (message.type === 'error') { + ++newErrs; + } + }); if (newTotal !== oldTotal || newWarns !== oldWarns || newErrs !== oldErrs) { document.dispatchEvent(new CustomEvent('loot-plugin-message-change', { @@ -214,5 +302,9 @@ this._isDirty = dirty; } + + getCardContent(filters) { + return new PluginCardContent(this, filters); + } }; })); diff --git a/src/tests/gui/html/js/test.html b/src/tests/gui/html/js/test.html index 1bc13433..dcf62cdb 100644 --- a/src/tests/gui/html/js/test.html +++ b/src/tests/gui/html/js/test.html @@ -11,8 +11,10 @@ + +