diff --git a/resources/report/js/script.js b/resources/report/js/script.js index b2b2afcd..7a15f49d 100644 --- a/resources/report/js/script.js +++ b/resources/report/js/script.js @@ -207,7 +207,7 @@ function updateSelectedGame() { index = i; } } - if (loot.settings.games.type == 'Skyrim') { + if (loot.settings.games[index].type == 'Skyrim') { document.getElementById('redatePluginsButton').classList.toggle('disabled', false); } else { document.getElementById('redatePluginsButton').classList.toggle('disabled', true); @@ -245,7 +245,7 @@ function changeGame(evt) { var request = { name: 'changeGame', args: [ - evt.target.getAttribute('data-target') + evt.currentTarget.getAttribute('data-target') ] }; @@ -382,7 +382,7 @@ function toggleMenu(evt) { hideElement(target); /* Also remove event listeners to any dynamically-generated items. */ - var elements = target.querySelectorAll('[data-action]'); + var elements = target.querySelectorAll('[data-action]:not(.disabled)'); for (var i = 0; i < elements.length; ++i) { var action = elements[i].getAttribute('data-action'); if (action == 'show-editor') { @@ -403,7 +403,7 @@ function toggleMenu(evt) { showElement(target); /* Also attach event listeners to any dynamically-generated items. */ - var elements = target.querySelectorAll('[data-action]'); + var elements = target.querySelectorAll('[data-action]:not(.disabled)'); for (var i = 0; i < elements.length; ++i) { var action = elements[i].getAttribute('data-action'); if (action == 'show-editor') { @@ -605,7 +605,7 @@ function setupEventHandlers() { function processCefError(errorCode, errorMessage) { showMessageBox('error', "Error", "Error code: " + error_code + "; " + error_message); } -function initGlobalVars() { +function initVars() { // Create and send a new query. var request_id = window.cefQuery({ request: 'getVersion', @@ -646,78 +646,125 @@ function initGlobalVars() { }, onFailure: processCefError }); - var request_id = window.cefQuery({ + + var parallelPromises = []; + + parallelPromises.push(new Promise(function(resolve, reject) { + var request_id = window.cefQuery({ request: 'getGameTypes', persistent: false, - onSuccess: function(response) { - try { - loot.gameTypes = JSON.parse(response); + onSuccess: resolve, + onFailure: function(errorCode, errorMessage) { + reject(Error('Error code: ' + error_code + '; ' + error_message)) + } + }); + })); - /* Fill in game row template's game type options. */ - var select = document.getElementById('gameRow').content.querySelector('select'); - for (var j = 0; j < loot.gameTypes.length; ++j) { - var option = document.createElement('option'); - option.value = loot.gameTypes[j]; - option.textContent = loot.gameTypes[j]; - select.appendChild(option); - } - } catch (e) { - console.log(e); - console.log('Response: ' + response); + parallelPromises.push(new Promise(function(resolve, reject) { + var request_id = window.cefQuery({ + request: 'getInstalledGames', + persistent: false, + onSuccess: resolve, + onFailure: function(errorCode, errorMessage) { + reject(Error('Error code: ' + error_code + '; ' + error_message)) + } + }); + })); + + parallelPromises.push(new Promise(function(resolve, reject) { + var request_id = window.cefQuery({ + request: 'getGameData', + persistent: false, + onSuccess: resolve, + onFailure: function(errorCode, errorMessage) { + reject(Error('Error code: ' + error_code + '; ' + error_message)) + } + }); + })); + + parallelPromises.push(new Promise(function(resolve, reject) { + var request_id = window.cefQuery({ + request: 'getSettings', + persistent: false, + onSuccess: resolve, + onFailure: function(errorCode, errorMessage) { + reject(Error('Error code: ' + error_code + '; ' + error_message)) + } + }); + })); + + 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.getElementById('gameRow').content.querySelector('select'); + for (var j = 0; j < loot.gameTypes.length; ++j) { + var option = document.createElement('option'); + option.value = loot.gameTypes[j]; + option.textContent = loot.gameTypes[j]; + select.appendChild(option); + } + + try { + loot.installedGames = JSON.parse(results[1]); + } catch (e) { + console.log(e); + console.log('getInstalledGames response: ' + results[1]); + } + + updateInterfaceWithGameInfo(results[2]); + + try { + loot.settings = JSON.parse(results[3]); + } catch (e) { + console.log(e); + console.log('getSettings response: ' + results[3]); + } + + /* Now fill game lists/table. */ + var gameSelect = document.getElementById('defaultGameSelect'); + var gameMenu = document.getElementById('gameMenu').firstElementChild; + var gameTable = document.getElementById('gameTable'); + for (var i = 0; i < loot.settings.games.length; ++i) { + var option = document.createElement('option'); + option.value = loot.settings.games[i].folder; + option.textContent = loot.settings.games[i].name; + gameSelect.appendChild(option); + + var li = document.createElement('li'); + li.setAttribute('data-action', 'change-game'); + li.setAttribute('data-target', loot.settings.games[i].folder); + + if (loot.installedGames.indexOf(loot.settings.games[i].folder) == -1) { + li.classList.toggle('disabled', true); } - // Settings depend on having the game types filled, so now send the CEF query for the settings. - var request_id = window.cefQuery({ - request: 'getSettings', - persistent: false, - onSuccess: function(response) { - try { - loot.settings = JSON.parse(response); + var icon = document.createElement('span'); + icon.className = 'fa fa-fw'; + li.appendChild(icon); + var text = document.createElement('span'); + text.textContent = loot.settings.games[i].name; + li.appendChild(text); - /* Now fill game lists/table. */ - var gameSelect = document.getElementById('defaultGameSelect'); - var gameMenu = document.getElementById('gameMenu').firstElementChild; - var gameTable = document.getElementById('gameTable'); - for (var i = 0; i < loot.settings.games.length; ++i) { - var option = document.createElement('option'); - option.value = loot.settings.games[i].folder; - option.textContent = loot.settings.games[i].name; - gameSelect.appendChild(option); + gameMenu.appendChild(li); - var li = document.createElement('li'); - li.setAttribute('data-action', 'change-game'); - li.setAttribute('data-target', loot.settings.games[i].folder); + gameTable.addRow(loot.settings.games[i]); + } - var icon = document.createElement('span'); - icon.className = 'fa fa-fw'; - li.appendChild(icon); + /* Highlight game in menu. */ + updateSelectedGame(); - var text = document.createElement('span'); - text.textContent = loot.settings.games[i].name; - li.appendChild(text); - - gameMenu.appendChild(li); - - gameTable.addRow(loot.settings.games[i]); - } - - /* Highlight game in menu. */ - updateSelectedGame(); - - gameSelect.value = loot.settings.game; - document.getElementById('languageSelect').value = loot.settings.language; - document.getElementById('debugVerbositySelect').value = loot.settings.debugVerbosity; - } catch (e) { - console.log(e); - console.log('Response: ' + response); - } - - }, - onFailure: processCefError - }); - }, - onFailure: processCefError + gameSelect.value = loot.settings.game; + document.getElementById('languageSelect').value = loot.settings.language; + document.getElementById('debugVerbositySelect').value = loot.settings.debugVerbosity; + }).catch(function(err) { + console.log(err); }); } function getPriorityString(plugin) { @@ -732,7 +779,7 @@ function updateInterfaceWithGameInfo(response) { loot.game = JSON.parse(response, jsonToPlugin); } catch (e) { console.log(e); - console.log('Response: ' + response); + console.log('getGameData response: ' + response); } var totalMessageNo = 0; @@ -796,17 +843,6 @@ function updateInterfaceWithGameInfo(response) { // Now set up event handlers, as they depend on the plugin cards having been created. setupEventHandlers(); } -function getGameData() { - // Create and send a new query. - var request_id = window.cefQuery({ - request: 'getGameData', - persistent: false, - onSuccess: updateInterfaceWithGameInfo, - onFailure: function(error_code, error_message) { - showMessageBox('error', "Error", "Error code: " + error_code + "; " + error_message); - } - }); -} require.config({ baseUrl: "js", @@ -819,8 +855,7 @@ require(['marked', 'order!custom', 'order!plugin'], function(response) { tables: true, sanitize: true }); - initGlobalVars(); - getGameData(); + initVars(); if (isStorageSupported()) { loadSettings(); } diff --git a/src/gui/app.cpp b/src/gui/app.cpp index 3383ceee..16bb66a1 100644 --- a/src/gui/app.cpp +++ b/src/gui/app.cpp @@ -247,6 +247,9 @@ namespace loot { Game& LootState::CurrentGame() { return _games[_currentGame]; } + std::vector& LootState::InstalledGames() { + return _games; + } const YAML::Node& LootState::GetSettings() const { return _settings; diff --git a/src/gui/app.h b/src/gui/app.h index 1737d5a3..110dd626 100644 --- a/src/gui/app.h +++ b/src/gui/app.h @@ -70,12 +70,13 @@ namespace loot { void ChangeGame(const std::string& newGameFolder); Game& CurrentGame(); + std::vector& InstalledGames(); const YAML::Node& GetSettings() const; private: YAML::Node _settings; - std::vector _games; + std::vector _games; size_t _currentGame; }; diff --git a/src/gui/handler.cpp b/src/gui/handler.cpp index 7f8347f4..b68e7781 100644 --- a/src/gui/handler.cpp +++ b/src/gui/handler.cpp @@ -110,6 +110,10 @@ namespace loot { callback->Success(GetGameTypes()); return true; } + else if (request == "getInstalledGames") { + callback->Success(GetInstalledGames()); + return true; + } else if (request == "getGameData") { BOOST_LOG_TRIVIAL(info) << "Setting LOOT window title bar text to include game name: " << g_app_state.CurrentGame().Name(); #if defined(OS_WIN) @@ -136,11 +140,11 @@ namespace loot { return false; } - const std::string requestName = req["name"].as(); + const string requestName = req["name"].as(); if (requestName == "find") { // Has one arg, which is the search string. - const std::string search = req["args"][0].as(); + const string search = req["args"][0].as(); // In case there is a search already running, cancel it. browser->GetHost()->StopFinding(true); @@ -156,7 +160,7 @@ namespace loot { } else if (requestName == "changeGame") { // Has one arg, which is the folder name of the new game. - const std::string folder = req["args"][0].as(); + const string folder = req["args"][0].as(); BOOST_LOG_TRIVIAL(info) << "Changing game to that with folder: " << folder; g_app_state.ChangeGame(folder); @@ -228,6 +232,16 @@ namespace loot { return JSON::stringify(temp); } + std::string Handler::GetInstalledGames() { + BOOST_LOG_TRIVIAL(info) << "Getting LOOT's detected games."; + YAML::Node temp; + for (const auto &game : g_app_state.InstalledGames()) { + if (game.IsInstalled()) + temp.push_back(game.FolderName()); + } + return JSON::stringify(temp); + } + std::string Handler::GetGameData() { BOOST_LOG_TRIVIAL(info) << "Getting data specific to LOOT's active game."; // Get masterlist revision info and parse if it exists. Also get plugin headers info and parse userlist if it exists. diff --git a/src/gui/handler.h b/src/gui/handler.h index a26873a4..6e5a0737 100644 --- a/src/gui/handler.h +++ b/src/gui/handler.h @@ -53,6 +53,7 @@ namespace loot { std::string GetSettings(); std::string GetLanguages(); std::string GetGameTypes(); + std::string GetInstalledGames(); std::string GetGameData(); };