mirror of
https://github.com/loot/libloot.git
synced 2026-07-27 14:16:01 -07:00
Merge branch 'js-refactor' into dev
This commit is contained in:
@@ -148,7 +148,7 @@ html /deep/ table[is=editable-table] paper-icon-button[icon=add]:hover {
|
||||
/* Create a <editable-table> element type that extends from <table>. */
|
||||
var EditableTableProto = Object.create(HTMLTableElement.prototype, {
|
||||
|
||||
handleDrop: {
|
||||
onDrop: {
|
||||
value: function(evt) {
|
||||
evt.stopPropagation();
|
||||
|
||||
@@ -163,7 +163,7 @@ html /deep/ table[is=editable-table] paper-icon-button[icon=add]:hover {
|
||||
}
|
||||
},
|
||||
|
||||
handleDragOver: {
|
||||
onDragOver: {
|
||||
value: function(evt) {
|
||||
evt.preventDefault();
|
||||
evt.dataTransfer.dropEffect = 'copy';
|
||||
@@ -234,21 +234,21 @@ html /deep/ table[is=editable-table] paper-icon-button[icon=add]:hover {
|
||||
}
|
||||
},
|
||||
|
||||
removeRow: {
|
||||
onRemoveRow: {
|
||||
value: function(evt) {
|
||||
var tr = evt.target.parentElement.parentElement.parentElement;
|
||||
var tbody = tr.parentElement;
|
||||
var table = tbody.parentElement;
|
||||
|
||||
/* Remove deletion listener. */
|
||||
evt.target.removeEventListener('click', table.removeRow, false);
|
||||
evt.target.removeEventListener('click', table.onRemoveRow, false);
|
||||
|
||||
/* Now remove row. */
|
||||
tbody.removeChild(tr);
|
||||
}
|
||||
},
|
||||
|
||||
addEmptyRow: {
|
||||
onAddEmptyRow: {
|
||||
value: function(evt) {
|
||||
/* Create new row. */
|
||||
var table = evt.currentTarget.parentElement.parentElement.parentElement.parentElement.parentElement;
|
||||
@@ -264,7 +264,7 @@ html /deep/ table[is=editable-table] paper-icon-button[icon=add]:hover {
|
||||
table.tBodies[0].insertBefore(row, table.tBodies[0].lastElementChild);
|
||||
|
||||
/* Add deletion listener. */
|
||||
table.tBodies[0].lastElementChild.previousElementSibling.getElementsByClassName('delete')[0].addEventListener('click', table.removeRow, false);
|
||||
table.tBodies[0].lastElementChild.previousElementSibling.getElementsByClassName('delete')[0].addEventListener('click', table.onRemoveRow, false);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -292,7 +292,7 @@ html /deep/ table[is=editable-table] paper-icon-button[icon=add]:hover {
|
||||
}
|
||||
|
||||
/* Add deletion listener. */
|
||||
row.getElementsByClassName('delete')[0].addEventListener('click', this.removeRow, false);
|
||||
row.getElementsByClassName('delete')[0].addEventListener('click', this.onRemoveRow, false);
|
||||
|
||||
return row;
|
||||
}
|
||||
@@ -312,14 +312,14 @@ html /deep/ table[is=editable-table] paper-icon-button[icon=add]:hover {
|
||||
row = this.tBodies[0].lastElementChild;
|
||||
|
||||
/* Add new row listener. */
|
||||
row.querySelector('paper-icon-button').addEventListener('click', this.addEmptyRow, false);
|
||||
row.querySelector('paper-icon-button').addEventListener('click', this.onAddEmptyRow, false);
|
||||
|
||||
/* Add drag 'n' drop listeners.
|
||||
Drag 'n' drop should only be enabled for file-row tables.
|
||||
*/
|
||||
if (this.getAttribute('data-template') == 'fileRow') {
|
||||
this.addEventListener('drop', this.handleDrop, false);
|
||||
this.addEventListener('dragover', this.handleDragOver, false);
|
||||
this.addEventListener('drop', this.onDrop, false);
|
||||
this.addEventListener('dragover', this.onDragOver, false);
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -329,15 +329,15 @@ html /deep/ table[is=editable-table] paper-icon-button[icon=add]:hover {
|
||||
/* Remove deletion listener. */
|
||||
var icons = this.tBodies[0].getElementsByClassName('delete');
|
||||
for (var i = 0; i < icons.length; ++i) {
|
||||
icons[i].removeEventListener('click', this.removeRow, false);
|
||||
icons[i].removeEventListener('click', this.onRemoveRow, false);
|
||||
}
|
||||
|
||||
/* Remove new row listener. */
|
||||
this.querySelector('tbody tr:last-child paper-icon-button').removeEventListener('click', this.addEmptyRow, false);
|
||||
this.querySelector('tbody tr:last-child paper-icon-button').removeEventListener('click', this.onAddEmptyRow, false);
|
||||
|
||||
/* Remove drag 'n' drop listeners. */
|
||||
this.removeEventListener('drop', this.handleDrop, false);
|
||||
this.removeEventListener('dragover', this.handleDragOver, false);
|
||||
this.removeEventListener('drop', this.onDrop, false);
|
||||
this.removeEventListener('dragover', this.onDragOver, false);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -149,7 +149,7 @@
|
||||
return this.textContent.trim();
|
||||
},
|
||||
|
||||
handleDragStart: function(evt) {
|
||||
onDragStart: function(evt) {
|
||||
evt.dataTransfer.effectAllowed = 'copy';
|
||||
evt.dataTransfer.setData('text/plain', evt.currentTarget.getName());
|
||||
},
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -146,7 +146,52 @@ var filters = {
|
||||
},
|
||||
};
|
||||
|
||||
function setFilteredUIData(evt) {
|
||||
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(l10n.jed.translate('Checking if plugins have been loaded...').fetch());
|
||||
|
||||
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.
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
function processCefError(err) {
|
||||
/* Error.stack seems to be Chromium-specific. It gives a lot more useful
|
||||
info than just the error message. Also, this can be used to catch any
|
||||
promise errors, not just CEF errors. */
|
||||
console.log(err.stack);
|
||||
closeProgressDialog();
|
||||
showMessageBox(l10n.jed.translate('Error').fetch(), err.message);
|
||||
}
|
||||
|
||||
function showElement(element) {
|
||||
if (element != null) {
|
||||
element.classList.toggle('hidden', false);
|
||||
}
|
||||
}
|
||||
function hideElement(element) {
|
||||
if (element != null) {
|
||||
element.classList.toggle('hidden', true);
|
||||
}
|
||||
}
|
||||
function toast(text) {
|
||||
var toast = document.getElementById('toast');
|
||||
toast.text = text;
|
||||
toast.show();
|
||||
}
|
||||
function showMessageDialog(title, text, positiveText, closeCallback) {
|
||||
var dialog = document.createElement('loot-message-dialog');
|
||||
dialog.setButtonText(positiveText, l10n.jed.translate('Cancel').fetch());
|
||||
dialog.showModal(title, text, closeCallback);
|
||||
document.body.appendChild(dialog);
|
||||
}
|
||||
function showMessageBox(title, text) {
|
||||
var dialog = document.createElement('loot-message-dialog');
|
||||
dialog.setButtonText(l10n.jed.translate('OK').fetch());
|
||||
dialog.showModal(title, text);
|
||||
document.body.appendChild(dialog);
|
||||
}
|
||||
|
||||
function showProgress(message) {
|
||||
var progressDialog = document.getElementById('progressDialog');
|
||||
if (message) {
|
||||
progressDialog.getElementsByTagName('p')[0].textContent = message;
|
||||
}
|
||||
if (!progressDialog.opened) {
|
||||
progressDialog.showModal();
|
||||
}
|
||||
}
|
||||
function closeProgressDialog() {
|
||||
var progressDialog = document.getElementById('progressDialog');
|
||||
if (progressDialog.opened) {
|
||||
progressDialog.close();
|
||||
}
|
||||
}
|
||||
function handleUnappliedChangesClose(change) {
|
||||
showMessageDialog('', l10n.jed.translate('You have not yet applied or cancelled your %s. Are you sure you want to quit?').fetch(change), l10n.jed.translate('Quit').fetch(), function(result){
|
||||
if (result) {
|
||||
/* Cancel any sorting and close any editors. Cheat by sending a
|
||||
cancelSort query for as many times as necessary. */
|
||||
var queries = [];
|
||||
var numQueries = 0;
|
||||
if (!document.getElementById('applySortButton').classList.contains('hidden')) {
|
||||
numQueries += 1;
|
||||
}
|
||||
numQueries += document.body.getAttribute('data-editors');
|
||||
for (var i = 0; i < numQueries; ++i) {
|
||||
queries.push(loot.query('cancelSort'));
|
||||
}
|
||||
Promise.all(queries).then(function(){
|
||||
window.close();
|
||||
}).catch(processCefError);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,199 @@
|
||||
/* LOOT
|
||||
|
||||
A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and
|
||||
Fallout: New Vegas.
|
||||
|
||||
Copyright (C) 2013-2015 WrinklyNinja
|
||||
|
||||
This file is part of LOOT.
|
||||
|
||||
LOOT is free software: you can redistribute
|
||||
it and/or modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
LOOT is distributed in the hope that it will
|
||||
be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with LOOT. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
'use strict';
|
||||
var marked;
|
||||
var l10n;
|
||||
|
||||
function initVars() {
|
||||
loot.query('getVersion').then(function(result){
|
||||
try {
|
||||
loot.version = JSON.parse(result);
|
||||
|
||||
/* The fourth part of the version string is the build number. Trim it. */
|
||||
var pos = loot.version.lastIndexOf('.');
|
||||
if (loot.version.length > pos + 1) {
|
||||
document.getElementById('LOOTBuild').textContent = loot.version.substring(pos + 1);
|
||||
} else {
|
||||
document.getElementById('LOOTBuild').textContent = l10n.jed.translate('unknown').fetch();
|
||||
}
|
||||
|
||||
loot.version = loot.version.substring(0, pos);
|
||||
document.getElementById('LOOTVersion').textContent = loot.version;
|
||||
document.getElementById('firstTimeLootVersion').textContent = loot.version;
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
console.log('Response: ' + result);
|
||||
}
|
||||
}).catch(processCefError);
|
||||
|
||||
loot.query('getLanguages').then(function(result){
|
||||
try {
|
||||
loot.languages = JSON.parse(result);
|
||||
|
||||
/* Now fill in language options. */
|
||||
var settingsLangSelect = document.getElementById('languageSelect');
|
||||
var messageLangSelect = document.querySelector('link[rel="import"][href$="editable-table.html"]');
|
||||
if (messageLangSelect) {
|
||||
messageLangSelect = messageLangSelect.import.querySelector('#messageRow').content.querySelector('.language');
|
||||
} else {
|
||||
messageLangSelect = document.querySelector('#messageRow').content.querySelector('.language');
|
||||
}
|
||||
|
||||
for (var i = 0; i < loot.languages.length; ++i) {
|
||||
var settingsItem = document.createElement('paper-item');
|
||||
settingsItem.setAttribute('value', loot.languages[i].locale);
|
||||
settingsItem.setAttribute('noink', '');
|
||||
settingsItem.textContent = loot.languages[i].name;
|
||||
settingsLangSelect.appendChild(settingsItem);
|
||||
messageLangSelect.appendChild(settingsItem.cloneNode(true));
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
console.log('Response: ' + result);
|
||||
}
|
||||
}).catch(processCefError);
|
||||
|
||||
loot.query('getInitErrors').then(JSON.parse).then(function(result){
|
||||
if (result) {
|
||||
var generalMessagesList = document.getElementById('summary').getElementsByTagName('ul')[0];
|
||||
|
||||
result.forEach(function(message){
|
||||
var li = document.createElement('li');
|
||||
li.className = 'error';
|
||||
/* Use the Marked library for Markdown formatting support. */
|
||||
li.innerHTML = marked(message);
|
||||
generalMessagesList.appendChild(li);
|
||||
});
|
||||
|
||||
document.getElementById('filterTotalMessageNo').textContent = result.length;
|
||||
document.getElementById('totalMessageNo').textContent = result.length;
|
||||
document.getElementById('totalErrorNo').textContent = result.length;
|
||||
}
|
||||
|
||||
var parallelPromises = [
|
||||
loot.query('getGameTypes'),
|
||||
loot.query('getInstalledGames'),
|
||||
loot.query('getSettings'),
|
||||
];
|
||||
|
||||
showProgress('Initialising user interface...');
|
||||
Promise.all(parallelPromises).then(function(results) {
|
||||
try {
|
||||
loot.gameTypes = JSON.parse(results[0]);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
console.log('getGameTypes response: ' + results[0]);
|
||||
}
|
||||
|
||||
/* Fill in game row template's game type options. */
|
||||
var select = document.querySelector('link[rel="import"][href$="editable-table.html"]');
|
||||
if (select) {
|
||||
select = select.import.querySelector('#gameRow').content.querySelector('.type')
|
||||
} else {
|
||||
select = document.querySelector('#gameRow').content.querySelector('.type');
|
||||
}
|
||||
for (var j = 0; j < loot.gameTypes.length; ++j) {
|
||||
var item = document.createElement('paper-item');
|
||||
item.setAttribute('value', loot.gameTypes[j]);
|
||||
item.setAttribute('noink', '');
|
||||
item.textContent = loot.gameTypes[j];
|
||||
select.appendChild(item);
|
||||
}
|
||||
|
||||
try {
|
||||
loot.installedGames = JSON.parse(results[1]);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
console.log('getInstalledGames response: ' + results[1]);
|
||||
}
|
||||
|
||||
try {
|
||||
loot.settings = JSON.parse(results[2]);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
console.log('getSettings response: ' + results[2]);
|
||||
}
|
||||
}).then(function(){
|
||||
return l10n.getJedInstance(loot.settings.language).then(function(jed){
|
||||
l10n.translateStaticText(jed);
|
||||
l10n.jed = jed;
|
||||
|
||||
/* Also need to update the settings UI. */
|
||||
loot.updateSettingsUI();
|
||||
}).catch(processCefError);
|
||||
}).then(function(){
|
||||
if (result) {
|
||||
return new Promise(function(resolve, reject){
|
||||
closeProgressDialog();
|
||||
document.getElementById('settingsButton').click();
|
||||
resolve('');
|
||||
});
|
||||
} else {
|
||||
return loot.query('getGameData').then(function(result){
|
||||
var game = JSON.parse(result, jsonToPlugin);
|
||||
loot.game.folder = game.folder;
|
||||
loot.game.masterlist = game.masterlist;
|
||||
loot.game.globalMessages = game.globalMessages;
|
||||
loot.game.plugins = game.plugins;
|
||||
document.getElementById('cardsNav').data = loot.game.plugins;
|
||||
document.getElementById('main').lastElementChild.data = loot.game.plugins;
|
||||
|
||||
setTimeout(function() {
|
||||
document.getElementById('cardsNav').updateSize();
|
||||
closeProgressDialog();
|
||||
}, 100);
|
||||
|
||||
return '';
|
||||
}).catch(processCefError);
|
||||
}
|
||||
}).then(function(){
|
||||
if (!loot.settings.lastVersion || loot.settings.lastVersion != loot.version) {
|
||||
document.getElementById('firstRun').showModal();
|
||||
}
|
||||
}).catch(processCefError);
|
||||
}).catch(processCefError);
|
||||
}
|
||||
|
||||
window.addEventListener('polymer-ready', function(e) {
|
||||
/* Set the plugin list's scroll target to its parent. */
|
||||
document.getElementById('main').lastElementChild.scrollTarget = document.getElementById('main');
|
||||
|
||||
require(['bower_components/marked/lib/marked', 'js/l10n', 'js/plugin', 'js/helpers', 'js/loot', 'js/filters', 'js/events'], function(markedResponse, l10nResponse) {
|
||||
|
||||
/* Register object observers. */
|
||||
Object.observe(loot, loot.observer);
|
||||
Object.observe(loot.game, loot.gameObserver);
|
||||
|
||||
marked = markedResponse;
|
||||
l10n = l10nResponse;
|
||||
/* Make sure settings are what I want. */
|
||||
marked.setOptions({
|
||||
gfm: true,
|
||||
tables: true,
|
||||
sanitize: true
|
||||
});
|
||||
setupEventHandlers();
|
||||
initVars();
|
||||
});
|
||||
}, false);
|
||||
@@ -0,0 +1,309 @@
|
||||
var loot = {
|
||||
installedGames: [],
|
||||
settings: {},
|
||||
game: {
|
||||
folder: '',
|
||||
globalMessages: [],
|
||||
masterlist: {},
|
||||
plugins: [],
|
||||
|
||||
/* Call whenever game is changed or game menu / game table are rewritten. */
|
||||
updateSelectedGame: function() {
|
||||
document.getElementById('gameMenu').value = this.folder;
|
||||
|
||||
/* Also disable deletion of the game's row in the settings dialog. */
|
||||
var table = document.getElementById('gameTable');
|
||||
for (var i = 0; i < table.tBodies[0].rows.length; ++i) {
|
||||
if (table.tBodies[0].rows[i].getElementsByClassName('folder').length > 0) {
|
||||
if (table.tBodies[0].rows[i].getElementsByClassName('folder')[0].value == this.folder) {
|
||||
table.setReadOnly(table.tBodies[0].rows[i], ['delete']);
|
||||
} else {
|
||||
table.setReadOnly(table.tBodies[0].rows[i], ['delete'], false);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/* Call whenever game is changed. */
|
||||
updateRedatePluginsButtonState: function() {
|
||||
/* Also enable/disable the redate plugins option. */
|
||||
var index = undefined;
|
||||
for (var i = 0; i < loot.settings.games.length; ++i) {
|
||||
if (loot.settings.games[i].folder == this.folder) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
var redateButton = document.getElementById('redatePluginsButton');
|
||||
if (index != undefined && loot.settings.games[index].type == 'Skyrim') {
|
||||
redateButton.removeAttribute('disabled');
|
||||
} else {
|
||||
redateButton.setAttribute('disabled', true);
|
||||
}
|
||||
},
|
||||
|
||||
pluginsObserver: function(changes) {
|
||||
changes.forEach(function(change){
|
||||
/* Need to handle plugin addition and removal.
|
||||
Update plugin and message counts. */
|
||||
var totalChange = 0;
|
||||
var warnChange = 0;
|
||||
var errorChange = 0;
|
||||
var activeChange = 0;
|
||||
var dirtyChange = 0;
|
||||
|
||||
if (change.addedCount > 0) {
|
||||
/* Addition */
|
||||
for (var i = change.index; i < change.index + change.addedCount; ++i) {
|
||||
if (change.object[i].isActive) {
|
||||
++activeChange;
|
||||
}
|
||||
if (change.object[i].isDirty) {
|
||||
++dirtyChange;
|
||||
}
|
||||
if (change.object[i].messages) {
|
||||
totalChange += change.object[i].messages.length;
|
||||
change.object[i].messages.forEach(function(message) {
|
||||
if (message.type == 'warn') {
|
||||
++warnChange;
|
||||
} else if (message.type == 'error') {
|
||||
++errorChange;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
if (change.removed.length > 0) {
|
||||
/* Removal */
|
||||
change.removed.forEach(function(plugin){
|
||||
if (plugin.isActive) {
|
||||
--activeChange;
|
||||
}
|
||||
if (plugin.isDirty) {
|
||||
--dirtyChange;
|
||||
}
|
||||
if (plugin.messages) {
|
||||
totalChange -= plugin.messages.length;
|
||||
plugin.messages.forEach(function(message) {
|
||||
if (message.type == 'warn') {
|
||||
--warnChange;
|
||||
} else if (message.type == 'error') {
|
||||
--errorChange;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
document.getElementById('filterTotalMessageNo').textContent = parseInt(document.getElementById('filterTotalMessageNo').textContent, 10) + totalChange;
|
||||
document.getElementById('totalMessageNo').textContent = document.getElementById('filterTotalMessageNo').textContent;
|
||||
document.getElementById('totalWarningNo').textContent = parseInt(document.getElementById('totalWarningNo').textContent, 10) + warnReduction;
|
||||
document.getElementById('totalErrorNo').textContent = parseInt(document.getElementById('totalErrorNo').textContent, 10) + errorReduction;
|
||||
document.getElementById('filterTotalPluginNo').textContent = parseInt(document.getElementById('filterTotalPluginNo').textContent, 10) + change.addedCount - change.removed.length;
|
||||
document.getElementById('totalPluginNo').textContent = document.getElementById('filterTotalPluginNo').textContent;
|
||||
document.getElementById('activePluginNo').textContent = parseInt(document.getElementById('activePluginNo').textContent, 10) + activeReduction;
|
||||
document.getElementById('dirtyPluginNo').textContent = parseInt(document.getElementById('dirtyPluginNo').textContent, 10) + dirtyReduction;
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/* Call whenever installedGames is changed or game menu is rewritten. */
|
||||
updateEnabledGames: function() {
|
||||
/* Update the disabled games in the game menu. */
|
||||
var gameMenuItems = document.getElementById('gameMenu').children;
|
||||
for (var i = 0; i < gameMenuItems.length; ++i) {
|
||||
if (this.installedGames.indexOf(gameMenuItems[i].getAttribute('value')) == -1) {
|
||||
gameMenuItems[i].setAttribute('disabled', true);
|
||||
gameMenuItems[i].removeEventListener('click', onChangeGame, false);
|
||||
} else {
|
||||
gameMenuItems[i].removeAttribute('disabled');
|
||||
gameMenuItems[i].addEventListener('click', onChangeGame, false);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/* Call whenever settings are changed. */
|
||||
updateSettingsUI: function() {
|
||||
var gameSelect = document.getElementById('defaultGameSelect');
|
||||
var gameMenu = document.getElementById('gameMenu');
|
||||
var gameTable = document.getElementById('gameTable');
|
||||
|
||||
/* First make sure game listing elements don't have any existing entries. */
|
||||
while (gameSelect.children.length > 1) {
|
||||
gameSelect.removeChild(gameSelect.lastElementChild);
|
||||
}
|
||||
while (gameMenu.firstElementChild) {
|
||||
gameMenu.firstElementChild.removeEventListener('click', onChangeGame, false);
|
||||
gameMenu.removeChild(gameMenu.firstElementChild);
|
||||
}
|
||||
gameTable.clear();
|
||||
|
||||
/* Now fill with new values. */
|
||||
this.settings.games.forEach(function(game){
|
||||
var menuItem = document.createElement('paper-item');
|
||||
menuItem.setAttribute('value', game.folder);
|
||||
menuItem.setAttribute('noink', '');
|
||||
menuItem.textContent = game.name;
|
||||
gameMenu.appendChild(menuItem);
|
||||
gameSelect.appendChild(menuItem.cloneNode(true));
|
||||
|
||||
var row = gameTable.addRow(game);
|
||||
gameTable.setReadOnly(row, ['name','folder','type']);
|
||||
});
|
||||
|
||||
gameSelect.value = this.settings.game;
|
||||
document.getElementById('languageSelect').value = this.settings.language;
|
||||
document.getElementById('enableDebugLogging').checked = this.settings.enableDebugLogging;
|
||||
document.getElementById('updateMasterlist').checked = this.settings.updateMasterlist;
|
||||
|
||||
this.updateEnabledGames();
|
||||
this.game.updateSelectedGame();
|
||||
},
|
||||
|
||||
/* Observer for loot members. */
|
||||
observer: function(changes) {
|
||||
changes.forEach(function(change){
|
||||
if (change.name == 'installedGames') {
|
||||
change.object.updateEnabledGames();
|
||||
} else if (change.name == 'settings') {
|
||||
change.object.updateSettingsUI();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/* Observer for loot.game members. */
|
||||
gameObserver: function(changes) {
|
||||
changes.forEach(function(change){
|
||||
if (change.name == 'folder') {
|
||||
change.object.updateSelectedGame();
|
||||
change.object.updateRedatePluginsButtonState();
|
||||
} else if (change.name == 'masterlist') {
|
||||
if (change.object[change.name] && change.object[change.name].revision) {
|
||||
document.getElementById('masterlistRevision').textContent = change.object[change.name].revision;
|
||||
} else {
|
||||
document.getElementById('masterlistRevision').textContent = l10n.jed.translate("N/A").fetch();
|
||||
}
|
||||
if (change.object[change.name] && change.object[change.name].date) {
|
||||
document.getElementById('masterlistDate').textContent = change.object[change.name].date;
|
||||
} else {
|
||||
document.getElementById('masterlistDate').textContent = l10n.jed.translate("N/A").fetch();
|
||||
}
|
||||
} else if (change.name == 'globalMessages') {
|
||||
/* For the messages, they don't have a JS 'class' so need to everything
|
||||
here. Count up the global message types that exist, then remove them
|
||||
and add the new ones, counting their types, then update the message
|
||||
counts. I tried using an observer for this, but it wouldn't fire for
|
||||
some reason. */
|
||||
|
||||
var oldTotal = change.oldValue.length;
|
||||
var newTotal = 0;
|
||||
var oldWarn = 0;
|
||||
var newWarn = 0;
|
||||
var oldErr = 0;
|
||||
var newErr = 0;
|
||||
|
||||
/* Count up old warnings and errors. */
|
||||
change.oldValue.forEach(function(message){
|
||||
if (message.type == 'warn') {
|
||||
++oldWarn;
|
||||
} else if (message.type == 'error') {
|
||||
++oldErr;
|
||||
}
|
||||
});
|
||||
|
||||
/* Remove old messages from UI. */
|
||||
var generalMessagesList = document.getElementById('summary').getElementsByTagName('ul')[0];
|
||||
while (generalMessagesList.firstElementChild) {
|
||||
generalMessagesList.removeChild(generalMessagesList.firstElementChild);
|
||||
}
|
||||
|
||||
/* Add new messages. */
|
||||
if (change.object[change.name]) {
|
||||
newTotal = change.object[change.name].length;
|
||||
change.object[change.name].forEach(function(message){
|
||||
var li = document.createElement('li');
|
||||
li.className = message.type;
|
||||
/* Use the Marked library for Markdown formatting support. */
|
||||
li.innerHTML = marked(message.content[0].str);
|
||||
generalMessagesList.appendChild(li);
|
||||
|
||||
if (li.className == 'warn') {
|
||||
++newWarn;
|
||||
} else if (li.className == 'error') {
|
||||
++newErr;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* Update message counts in UI. */
|
||||
document.getElementById('filterTotalMessageNo').textContent = parseInt(document.getElementById('filterTotalMessageNo').textContent, 10) + newTotal - oldTotal;
|
||||
document.getElementById('totalMessageNo').textContent = document.getElementById('filterTotalMessageNo').textContent;
|
||||
document.getElementById('totalWarningNo').textContent = parseInt(document.getElementById('totalWarningNo').textContent, 10) + newWarn - oldWarn;
|
||||
document.getElementById('totalErrorNo').textContent = parseInt(document.getElementById('totalErrorNo').textContent, 10) + newErr - oldErr;
|
||||
} else if (change.name == 'plugins') {
|
||||
/* Update plugin and message counts. Unlike for global messages
|
||||
it's not worth calculating the count differences, just count
|
||||
from zero. */
|
||||
var totalMessageNo = 0;
|
||||
var warnMessageNo = 0;
|
||||
var errorMessageNo = 0;
|
||||
var activePluginNo = 0;
|
||||
var dirtyPluginNo = 0;
|
||||
|
||||
if (change.object.globalMessages) {
|
||||
totalMessageNo = change.object.globalMessages.length;
|
||||
change.object.globalMessages.forEach(function(message){
|
||||
if (message.type == 'warn') {
|
||||
++warnMessageNo;
|
||||
} else if (message.type == 'error') {
|
||||
++errorMessageNo;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
change.object[change.name].forEach(function(plugin) {
|
||||
if (plugin.isActive) {
|
||||
++activePluginNo;
|
||||
}
|
||||
if (plugin.isDirty) {
|
||||
++dirtyPluginNo;
|
||||
}
|
||||
if (plugin.messages) {
|
||||
totalMessageNo += plugin.messages.length;
|
||||
plugin.messages.forEach(function(message) {
|
||||
if (message.type == 'warn') {
|
||||
++warnMessageNo;
|
||||
} else if (message.type == 'error') {
|
||||
++errorMessageNo;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
document.getElementById('filterTotalMessageNo').textContent = totalMessageNo;
|
||||
document.getElementById('totalMessageNo').textContent = totalMessageNo;
|
||||
document.getElementById('totalWarningNo').textContent = warnMessageNo;
|
||||
document.getElementById('totalErrorNo').textContent = errorMessageNo;
|
||||
document.getElementById('filterTotalPluginNo').textContent = change.object[change.name].length;
|
||||
document.getElementById('totalPluginNo').textContent = change.object[change.name].length;
|
||||
document.getElementById('activePluginNo').textContent = activePluginNo;
|
||||
document.getElementById('dirtyPluginNo').textContent = dirtyPluginNo;
|
||||
|
||||
/* Register a new array observer. */
|
||||
Array.observe(change.object[change.name], change.object.pluginsObserver);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/* Returns a cefQuery as a Promise. */
|
||||
query: function(request) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
window.cefQuery({
|
||||
request: request,
|
||||
persistent: false,
|
||||
onSuccess: resolve,
|
||||
onFailure: function(errorCode, errorMessage) {
|
||||
reject(Error('Error code: ' + errorCode + '; ' + errorMessage))
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -298,5 +298,5 @@
|
||||
<p>LOOT is free, but if you want to show your appreciation with some money, donations may be made to WrinklyNinja (LOOT's creator and main developer) using <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=HDR3YBGGYCLBG">PayPal</a>, <a href="https://wrinklyninja.github.io/bitcoin/">Bitcoin</a> or <a href="https://flattr.com/submit/auto?user_id=OliverHamlet&url=https://wrinklyninja.github.io&title=LOOT">Flattr</a>.</p>
|
||||
<paper-button affirmative autofocus>OK</paper-button>
|
||||
</loot-dialog>
|
||||
<script src="js/script.js"></script>
|
||||
<script src="js/init.js"></script>
|
||||
</body>
|
||||
|
||||
+5
-2
@@ -141,9 +141,12 @@ def createAppArchive(archive_path):
|
||||
shutil.copy( os.path.join('..', 'resources', 'report', 'bower_components', 'Jed', 'jed.js'), os.path.join(temp_path, 'resources', 'report', 'bower_components', 'Jed') )
|
||||
shutil.copy( os.path.join('..', 'resources', 'report', 'bower_components', 'jed-gettext-parser', 'jedGettextParser.js'), os.path.join(temp_path, 'resources', 'report', 'bower_components', 'jed-gettext-parser') )
|
||||
shutil.copytree( os.path.join('..', 'resources', 'report', 'fonts'), os.path.join(temp_path, 'resources', 'report', 'fonts') )
|
||||
shutil.copy( os.path.join('..', 'resources', 'report', 'js', 'l10n.js'), os.path.join(temp_path, 'resources', 'report', 'js') )
|
||||
shutil.copy( os.path.join('..', 'resources', 'report', 'js', 'plugin.js'), os.path.join(temp_path, 'resources', 'report', 'js') )
|
||||
shutil.copy( os.path.join('..', 'resources', 'report', 'js', 'events.js'), os.path.join(temp_path, 'resources', 'report', 'js') )
|
||||
shutil.copy( os.path.join('..', 'resources', 'report', 'js', 'filters.js'), os.path.join(temp_path, 'resources', 'report', 'js') )
|
||||
shutil.copy( os.path.join('..', 'resources', 'report', 'js', 'helpers.js'), os.path.join(temp_path, 'resources', 'report', 'js') )
|
||||
shutil.copy( os.path.join('..', 'resources', 'report', 'js', 'l10n.js'), os.path.join(temp_path, 'resources', 'report', 'js') )
|
||||
shutil.copy( os.path.join('..', 'resources', 'report', 'js', 'loot.js'), os.path.join(temp_path, 'resources', 'report', 'js') )
|
||||
shutil.copy( os.path.join('..', 'resources', 'report', 'js', 'plugin.js'), os.path.join(temp_path, 'resources', 'report', 'js') )
|
||||
|
||||
# Docs.
|
||||
shutil.copytree( os.path.join('..', 'docs', 'images'), os.path.join(temp_path, 'docs', 'images') )
|
||||
|
||||
+10
-4
@@ -348,9 +348,12 @@ FunctionEnd
|
||||
SetOutPath "$INSTDIR\resources\report\fonts"
|
||||
File "..\resources\report\fonts\*"
|
||||
SetOutPath "$INSTDIR\resources\report\js"
|
||||
File "..\resources\report\js\l10n.js"
|
||||
File "..\resources\report\js\plugin.js"
|
||||
File "..\resources\report\js\events.js"
|
||||
File "..\resources\report\js\filters.js"
|
||||
File "..\resources\report\js\helpers.js"
|
||||
File "..\resources\report\js\l10n.js"
|
||||
File "..\resources\report\js\loot.js"
|
||||
File "..\resources\report\js\plugin.js"
|
||||
|
||||
;Install documentation images.
|
||||
SetOutPath "$INSTDIR\docs\images"
|
||||
@@ -508,9 +511,12 @@ FunctionEnd
|
||||
Delete "$INSTDIR\resources\report\bower_components\Jed\jed.js"
|
||||
Delete "$INSTDIR\resources\report\bower_components\jed-gettext-parser\jedGettextParser.js"
|
||||
RMDir /r "$INSTDIR\resources\report\fonts"
|
||||
Delete "$INSTDIR\resources\report\js\l10n.js"
|
||||
Delete "$INSTDIR\resources\report\js\plugin.js"
|
||||
Delete "$INSTDIR\resources\report\js\events.js"
|
||||
Delete "$INSTDIR\resources\report\js\filters.js"
|
||||
Delete "$INSTDIR\resources\report\js\helpers.js"
|
||||
Delete "$INSTDIR\resources\report\js\l10n.js"
|
||||
Delete "$INSTDIR\resources\report\js\loot.js"
|
||||
Delete "$INSTDIR\resources\report\js\plugin.js"
|
||||
RMDir /r "$INSTDIR\resources\report"
|
||||
|
||||
;Remove language files.
|
||||
|
||||
Reference in New Issue
Block a user