From fe30b48d59a337e081915ebe19fd32274ac60885 Mon Sep 17 00:00:00 2001 From: J-D-K Date: Mon, 18 Aug 2025 10:23:09 -0400 Subject: [PATCH] Revised ConfigContext, remove texture purging from SDLLib for now. --- Libraries/SDLLib | 2 +- include/JSON.hpp | 7 + include/config/ConfigContext.hpp | 106 +++++----- include/config/config.hpp | 3 - source/config/ConfigContext.cpp | 344 +++++++++++++++++-------------- source/config/config.cpp | 41 +--- source/ui/TitleView.cpp | 8 +- 7 files changed, 267 insertions(+), 244 deletions(-) diff --git a/Libraries/SDLLib b/Libraries/SDLLib index 6a1607e..bf1e6f4 160000 --- a/Libraries/SDLLib +++ b/Libraries/SDLLib @@ -1 +1 @@ -Subproject commit 6a1607e155dbba0707381059af6d5516855a8c31 +Subproject commit bf1e6f40677a48d8b350b93b4aa49d411cb363c3 diff --git a/include/JSON.hpp b/include/JSON.hpp index 00a4a5f..588f036 100644 --- a/include/JSON.hpp +++ b/include/JSON.hpp @@ -37,6 +37,13 @@ namespace json /// @brief Returns the json string. static inline const char *get_string(json::Object &json) { return json_object_get_string(json.get()); } + /// @brief Returns the length of the string. I find json_object_get_string_len is unreliable? + static inline int64_t length(json::Object &json) + { + const char *string = json_object_get_string(json.get()); + return std::char_traits::length(string); + } + /// @brief Returns the beginning for iterating. static inline json_object_iterator iter_begin(json::Object &json) { return json_object_iter_begin(json.get()); } diff --git a/include/config/ConfigContext.hpp b/include/config/ConfigContext.hpp index 9f75e8e..2fe5c5a 100644 --- a/include/config/ConfigContext.hpp +++ b/include/config/ConfigContext.hpp @@ -1,8 +1,10 @@ #pragma once #include "fslib.hpp" +#include #include #include +#include #include namespace config @@ -10,102 +12,110 @@ namespace config class ConfigContext { public: - using AppIDList = std::vector; - ConfigContext() = default; - /// @brief Resets the config to its default state. + /// @brief Ensures the config directory exists. + void create_directory(); + + /// @brief Resets and saves the config back to the default values. void reset(); - /// @brief Saves the config to the file. + /// @brief Loads the config and custom paths files from the SD card if possible. + bool load(); + + /// @brief Saves the config to the SD if possible. void save(); - /// @brief Loads the config from SD. - void load(); + /// @brief Attempts to find and return the value of the key passed. + uint8_t get_by_key(std::string_view key) const; - /// @brief Retrieves the value of the key passed. - uint8_t get_by_key(std::string_view key); - - /// @brief Toggles a basic setting by the key passed. + /// @brief Attempts to toggle the value for the key passed. For simple 1 and 0. void toggle_by_key(std::string_view key); - /// @brief Sets the value of a key. + /// @brief Attempts to set the key passed to the value passd. void set_by_key(std::string_view key, uint8_t value); - /// @brief Returns the current working directory for JKSV. + /// @brief Returns the current working directory. fslib::Path get_working_directory() const; - /// @brief Sets the current working directory for JKSV. - bool set_working_directory(std::string_view workDir); + /// @brief Sets the current work directory if the path passed is valid. + void set_working_directory(const fslib::Path &workDir); - /// @brief Returns the current UI transition scaling. + /// @brief Returns the transition scaling speed. double get_animation_scaling() const; - /// @brief Sets the current UI transistion scaling. + /// @brief Sets the current animation scaling speed. void set_animation_scaling(double scaling); - /// @brief Adds a favorite to the list if it hasn't been already. + /// @brief Adds a favorite to the favorite titles. void add_favorite(uint64_t applicationID); - /// @brief Removes a favorite from the lift it it's there. + /// @brief Removes a title from the favorites. void remove_favorite(uint64_t applicationID); - /// @brief Returns whether or not the application ID passed is a favorite title. - bool is_favorite(uint64_t applicationID); + /// @brief Returns if the application ID passed is a favorite. + bool is_favorite(uint64_t applicationID) const; - /// @brief Adds the application ID to the blacklist if it hasn't been already. + /// @brief Adds the application ID passed to the blacklist. void add_to_blacklist(uint64_t applicationID); /// @brief Removes the application ID passed from the blacklist. void remove_from_blacklist(uint64_t applicationID); - /// @brief Gets an array of the currently blacklisted titles. - void get_blacklisted_titles(std::vector &listOut); + /// @brief Writes all of the currently blacklisted titles to the vector passed. + void get_blacklist(std::vector &listOut); - /// @brief Returns whether or not the application ID passed is blacklisted. - bool is_blacklisted(uint64_t applicationID); + /// @brief Returns if the application ID passed is found in the blacklist. + bool is_blacklisted(uint64_t applicationID) const; /// @brief Returns if the blacklist is empty. - bool blacklist_is_empty() const; + bool blacklist_empty() const; - /// @brief Adds a custom output path. - void add_custom_path(uint64_t applicationID, std::string_view path); + /// @brief Returns if the application ID passed has a custom output path. + bool has_custom_path(uint64_t applicationID) const; - /// @brief Returns whether or not the application ID has a custom output path. - bool has_custom_path(uint64_t applicationID); + /// @brief Adds a new output path. + void add_custom_path(uint64_t applicationID, const fslib::Path &path); - /// @brief Gets the output path of the application ID passed. - void get_custom_path(uint64_t applicationID, char *pathBuffer, size_t bufferSize); + /// @brief Gets the custom output path of the applicationID passed. + void get_custom_path(uint64_t applicationID, char *buffer, size_t bufferSize); private: - /// @brief This is where most values are stored. + /// @brief This is where the majority of the config values are. std::map m_configMap{}; - /// @brief This is the main directory JKSV uses. + /// @brief The main directory JKSV operates from. fslib::Path m_workingDirectory{}; - /// @brief The scaling of transitions. + /// @brief This scales the transitions. double m_animationScaling{}; - /// @brief Vector of favorites - ConfigContext::AppIDList m_favorites{}; + /// @brief This holds the favorite titles. + std::vector m_favorites{}; - /// @brief Vector of blacklisted title ids. - ConfigContext::AppIDList m_blacklist{}; + /// @brief This holds the blacklisted titles. + std::vector m_blacklist{}; - /// @brief Map of custom output paths for titles. - std::map m_pathMap; + /// @brief This holds user defined paths. + std::map m_paths{}; - /// @brief Reads an array from a json_object into the vector passed. + /// @brief Loads the config file from SD. + bool load_config_file(); + + /// @brief Saves the config to the SD. + void save_config_file(); + + /// @brief Reads a json array to the vector passed. void read_array_to_vector(std::vector &vector, json_object *array); - /// @brief Saves the custom paths set by the user. + /// @brief Loads the custom output path file from the SD if possible. + void load_custom_paths(); + + /// @brief Saves the custom output paths to the SD card. void save_custom_paths(); - /// @brief Searches for and returns an iterator to the application ID (if found); - ConfigContext::AppIDList::iterator find_favorite(uint64_t applicationID); - - /// @brief Searches for and returns an iterator to the application ID (if found); - ConfigContext::AppIDList::iterator find_blacklist(uint64_t applicationID); + /// @brief Searches the vector passed for the application ID passed. + std::vector::const_iterator find_application_id(const std::vector &vector, + uint64_t applicationID) const; }; } diff --git a/include/config/config.hpp b/include/config/config.hpp index 19a5303..719d344 100644 --- a/include/config/config.hpp +++ b/include/config/config.hpp @@ -34,9 +34,6 @@ namespace config /// @return Working directory. fslib::Path get_working_directory(); - /// @brief Sets JKSV's current working directory. - bool set_working_directory(std::string_view path); - /// @brief Returns the scaling speed of UI transitions and animations. /// @return Scaling variable. double get_animation_scaling(); diff --git a/source/config/ConfigContext.cpp b/source/config/ConfigContext.cpp index fa12414..150136a 100644 --- a/source/config/ConfigContext.cpp +++ b/source/config/ConfigContext.cpp @@ -2,17 +2,32 @@ #include "JSON.hpp" #include "config/keys.hpp" +#include "error.hpp" #include "logging/error.hpp" #include "stringutil.hpp" +#include #include + namespace { constexpr std::string_view PATH_DEFAULT_WORK_DIR = "sdmc:/JKSV"; - constexpr const char *PATH_PATHS_PATH = "sdmc:/config/JKSV/Paths.json"; - constexpr const char *PATH_CONFIG_FILE = "sdmc:/config/JKSV/JKSV.json"; + constexpr std::string_view PATH_CONFIG_FOLDER = "sdmc:/config/JKSV"; + constexpr std::string_view PATH_CONFIG_FILE = "sdmc:/config/JKSV/JKSV.json"; + constexpr std::string_view PATH_PATHS_FILE = "sdmc:/config/JKSV/Paths.json"; - constexpr const char *STRING_APP_ID_FORMAT = "%016llX"; + constexpr double DEFAULT_SCALING = 2.5f; + + constexpr const char *APP_ID_HEX_FORMAT = "%016llX"; +} + +void config::ConfigContext::create_directory() +{ + const fslib::Path configDir{PATH_CONFIG_FOLDER}; + const bool exists = fslib::directory_exists(configDir); + if (exists) { return; } + + error::fslib(fslib::create_directories_recursively(configDir)); } void config::ConfigContext::reset() @@ -35,112 +50,22 @@ void config::ConfigContext::reset() m_configMap[config::keys::JKSM_TEXT_MODE.data()] = 0; m_configMap[config::keys::FORCE_ENGLISH.data()] = 0; m_configMap[config::keys::ENABLE_TRASH_BIN.data()] = 0; - m_animationScaling = 2.5f; + m_animationScaling = DEFAULT_SCALING; + + ConfigContext::save(); } -void config::ConfigContext::save() +bool config::ConfigContext::load() { - - json::Object configJSON = json::new_object(json_object_new_object); - if (!configJSON) { return; } - - json_object *workDir = json_object_new_string(m_workingDirectory.full_path()); - json::add_object(configJSON, config::keys::WORKING_DIRECTORY.data(), workDir); - - for (const auto &[key, value] : m_configMap) - { - json_object *valueObject = json_object_new_uint64(value); - json::add_object(configJSON, key.c_str(), valueObject); - } - - json_object *scaling = json_object_new_double(m_animationScaling); - json::add_object(configJSON, config::keys::UI_ANIMATION_SCALE.data(), scaling); - - json_object *favoritesArray = json_object_new_array(); - for (const uint64_t &applicationID : m_favorites) - { - const std::string appIDHex = stringutil::get_formatted_string(STRING_APP_ID_FORMAT, applicationID); - json_object *newFavorite = json_object_new_string(appIDHex.c_str()); - - json_object_array_add(favoritesArray, newFavorite); - } - json::add_object(configJSON, config::keys::FAVORITES.data(), favoritesArray); - - json_object *blacklistArray = json_object_new_array(); - for (const uint64_t &applicationID : m_blacklist) - { - const std::string appIDHex = stringutil::get_formatted_string(STRING_APP_ID_FORMAT, applicationID); - json_object *newBlacklist = json_object_new_string(appIDHex.c_str()); - - json_object_array_add(blacklistArray, newBlacklist); - } - json::add_object(configJSON, config::keys::BLACKLIST.data(), blacklistArray); - - const char *configString = json::get_string(configJSON); - const int64_t configLength = std::char_traits::length(configString); - fslib::File configFile{PATH_CONFIG_FILE, FsOpenMode_Create | FsOpenMode_Write, configLength}; - if (configFile.is_open()) { configFile << configString; } + ConfigContext::load_custom_paths(); + return ConfigContext::load_config_file(); } -void config::ConfigContext::load() +void config::ConfigContext::save() { ConfigContext::save_config_file(); } + +uint8_t config::ConfigContext::get_by_key(std::string_view key) const { - json::Object configJSON = json::new_object(json_object_from_file, PATH_CONFIG_FILE); - if (!configJSON) - { - error::fslib(false); // This seems weird, but it should catch the problem. - return; - } - - json_object_iterator configIter = json::iter_begin(configJSON); - json_object_iterator configEnd = json::iter_end(configJSON); - while (!json_object_iter_equal(&configIter, &configEnd)) - { - const char *key = json_object_iter_peek_name(&configIter); - json_object *value = json_object_iter_peek_value(&configIter); - - const bool workingDir = std::strcmp(config::keys::WORKING_DIRECTORY.data(), key) == 0; - const bool scaling = std::strcmp(config::keys::UI_ANIMATION_SCALE.data(), key) == 0; - const bool favorites = std::strcmp(config::keys::FAVORITES.data(), key) == 0; - const bool blacklist = std::strcmp(config::keys::BLACKLIST.data(), key) == 0; - - if (workingDir) { m_workingDirectory = json_object_get_string(value); } - else if (scaling) { m_animationScaling = json_object_get_double(value); } - else if (favorites) { ConfigContext::read_array_to_vector(m_favorites, value); } - else if (blacklist) { ConfigContext::read_array_to_vector(m_blacklist, value); } - else { m_configMap[key] = json_object_get_uint64(value); } - - json_object_iter_next(&configIter); - } - - const fslib::Path pathsPath{PATH_PATHS_PATH}; - const bool pathsExists = fslib::file_exists(pathsPath); - if (!pathsExists) { return; } - - json::Object pathsJSON = json::new_object(json_object_from_file, pathsPath.full_path()); - if (!pathsJSON) - { - error::fslib(false); - return; - } - - json_object_iterator pathsIter = json::iter_begin(configJSON); - json_object_iterator pathsEnd = json::iter_end(configJSON); - while (!json_object_iter_equal(&pathsIter, &pathsEnd)) - { - const char *appIDString = json_object_iter_peek_name(&pathsIter); - json_object *pathObject = json_object_iter_peek_value(&pathsIter); - - const uint64_t applicationID = std::strtoull(appIDString, nullptr, 16); - const char *path = json_object_get_string(pathObject); - m_pathMap[applicationID] = path; - - json_object_iter_next(&pathsIter); - } -} - -uint8_t config::ConfigContext::get_by_key(std::string_view key) -{ - auto findKey = m_configMap.find(key.data()); + const auto findKey = m_configMap.find(key.data()); if (findKey == m_configMap.end()) { return 0; } return findKey->second; } @@ -149,25 +74,25 @@ void config::ConfigContext::toggle_by_key(std::string_view key) { auto findKey = m_configMap.find(key.data()); if (findKey == m_configMap.end()) { return; } - findKey->second = findKey->second ? 0 : 1; + + const uint8_t value = findKey->second; + findKey->second = value ? 0 : 1; } void config::ConfigContext::set_by_key(std::string_view key, uint8_t value) { auto findKey = m_configMap.find(key.data()); if (findKey == m_configMap.end()) { return; } + findKey->second = value; } fslib::Path config::ConfigContext::get_working_directory() const { return m_workingDirectory; } -bool config::ConfigContext::set_working_directory(std::string_view path) +void config::ConfigContext::set_working_directory(const fslib::Path &workDir) { - fslib::Path testPath{path}; - if (!testPath.is_valid()) { return false; } - - m_workingDirectory = std::move(testPath); - return true; + if (!workDir.is_valid()) { return; } + m_workingDirectory = workDir; } double config::ConfigContext::get_animation_scaling() const { return m_animationScaling; } @@ -176,107 +101,206 @@ void config::ConfigContext::set_animation_scaling(double scaling) { m_animationS void config::ConfigContext::add_favorite(uint64_t applicationID) { - auto findID = ConfigContext::find_favorite(applicationID); - if (findID != m_favorites.end()) { return; } + const auto findFav = ConfigContext::find_application_id(m_favorites, applicationID); + if (findFav != m_favorites.end()) { return; } m_favorites.push_back(applicationID); + ConfigContext::save_config_file(); } void config::ConfigContext::remove_favorite(uint64_t applicationID) { - auto findID = ConfigContext::find_favorite(applicationID); - if (findID == m_favorites.end()) { return; } - m_favorites.erase(findID); + const auto findFav = ConfigContext::find_application_id(m_favorites, applicationID); + if (findFav == m_favorites.end()) { return; } + m_favorites.erase(findFav); + ConfigContext::save_config_file(); } -bool config::ConfigContext::is_favorite(uint64_t applicationID) +bool config::ConfigContext::is_favorite(uint64_t applicationID) const { - return ConfigContext::find_favorite(applicationID) != m_favorites.end(); + return ConfigContext::find_application_id(m_favorites, applicationID) != m_favorites.end(); } void config::ConfigContext::add_to_blacklist(uint64_t applicationID) { - auto findID = ConfigContext::find_blacklist(applicationID); - if (findID != m_blacklist.end()) { return; } + const auto findTitle = ConfigContext::find_application_id(m_blacklist, applicationID); + if (findTitle != m_blacklist.end()) { return; } m_blacklist.push_back(applicationID); } void config::ConfigContext::remove_from_blacklist(uint64_t applicationID) { - auto findID = ConfigContext::find_blacklist(applicationID); - if (findID == m_blacklist.end()) { return; } - m_blacklist.erase(findID); + const auto findTitle = ConfigContext::find_application_id(m_blacklist, applicationID); + if (findTitle == m_blacklist.end()) { return; } + m_blacklist.erase(findTitle); } -void config::ConfigContext::get_blacklisted_titles(std::vector &listOut) +void config::ConfigContext::get_blacklist(std::vector &listOut) { - listOut.clear(); listOut.assign(m_blacklist.begin(), m_blacklist.end()); } -bool config::ConfigContext::is_blacklisted(uint64_t applicationID) +bool config::ConfigContext::is_blacklisted(uint64_t applicationID) const { - return ConfigContext::find_blacklist(applicationID) != m_blacklist.end(); + return ConfigContext::find_application_id(m_blacklist, applicationID) != m_blacklist.end(); } -bool config::ConfigContext::blacklist_is_empty() const { return m_blacklist.empty(); } +bool config::ConfigContext::blacklist_empty() const { return m_blacklist.empty(); } -void config::ConfigContext::add_custom_path(uint64_t applicationID, std::string_view path) +bool config::ConfigContext::has_custom_path(uint64_t applicationID) const { - m_pathMap[applicationID] = path.data(); + return m_paths.find(applicationID) != m_paths.end(); +} + +void config::ConfigContext::add_custom_path(uint64_t applicationID, const fslib::Path &path) +{ + if (!path.is_valid()) { return; } + m_paths[applicationID] = path.full_path(); ConfigContext::save_custom_paths(); } -bool config::ConfigContext::has_custom_path(uint64_t applicationID) { return m_pathMap.find(applicationID) != m_pathMap.end(); } - -void config::ConfigContext::get_custom_path(uint64_t applicationID, char *pathBuffer, size_t bufferSize) +void config::ConfigContext::get_custom_path(uint64_t applicationID, char *buffer, size_t bufferSize) { if (!ConfigContext::has_custom_path(applicationID)) { return; } - const std::string &path = m_pathMap[applicationID]; - if (path.length() > bufferSize) { return; } + const std::string &path = m_paths[applicationID]; + if (path.length() >= bufferSize) { return; } - std::memset(pathBuffer, 0x00, bufferSize); - std::memcpy(pathBuffer, path.c_str(), path.length()); + std::memset(buffer, 0x00, bufferSize); + std::memcpy(buffer, path.c_str(), path.length()); +} + +bool config::ConfigContext::load_config_file() +{ + const fslib::Path configPath{PATH_CONFIG_FILE}; + const bool exists = fslib::file_exists(configPath); + if (!exists) { return false; } + + json::Object configJSON = json::new_object(json_object_from_file, configPath.full_path()); + if (!configJSON) { return false; } + + json_object_iterator configIter = json::iter_begin(configJSON); + json_object_iterator configEnd = json::iter_end(configJSON); + while (!json_object_iter_equal(&configIter, &configEnd)) + { + const char *key = json_object_iter_peek_name(&configIter); + json_object *value = json_object_iter_peek_value(&configIter); + + const bool workDir = std::strcmp(key, config::keys::WORKING_DIRECTORY.data()) == 0; + const bool scaling = std::strcmp(key, config::keys::UI_ANIMATION_SCALE.data()) == 0; + const bool favorites = std::strcmp(key, config::keys::FAVORITES.data()) == 0; + const bool blacklist = std::strcmp(key, config::keys::BLACKLIST.data()) == 0; + + if (workDir) { m_workingDirectory = json_object_get_string(value); } + else if (scaling) { m_animationScaling = json_object_get_double(value); } + else if (favorites) { ConfigContext::read_array_to_vector(m_favorites, value); } + else if (blacklist) { ConfigContext::read_array_to_vector(m_blacklist, value); } + else { m_configMap[key] = json_object_get_uint64(value); } + + json_object_iter_next(&configIter); + } + return true; +} + +void config::ConfigContext::save_config_file() +{ + json::Object configJSON = json::new_object(json_object_new_object); + if (!configJSON) { return; } + + json_object *workDir = json_object_new_string(m_workingDirectory.full_path()); + json::add_object(configJSON, config::keys::WORKING_DIRECTORY, workDir); + + for (const auto &[key, value] : m_configMap) + { + json_object *jsonValue = json_object_new_uint64(value); + json::add_object(configJSON, key, jsonValue); + } + + json_object *scaling = json_object_new_double(m_animationScaling); + json::add_object(configJSON, config::keys::UI_ANIMATION_SCALE, scaling); + + json_object *favoritesArray = json_object_new_array(); + for (const uint64_t &applicationID : m_favorites) + { + const std::string appIDHex = stringutil::get_formatted_string(APP_ID_HEX_FORMAT, applicationID); + json_object *jsonFavorite = json_object_new_string(appIDHex.c_str()); + + json_object_array_add(favoritesArray, jsonFavorite); + } + json::add_object(configJSON, config::keys::FAVORITES, favoritesArray); + + json_object *blacklistArray = json_object_new_array(); + for (const uint64_t &applicationID : m_blacklist) + { + const std::string appIDHex = stringutil::get_formatted_string(APP_ID_HEX_FORMAT, applicationID); + json_object *jsonBlacklist = json_object_new_string(appIDHex.c_str()); + + json_object_array_add(blacklistArray, jsonBlacklist); + } + json::add_object(configJSON, config::keys::BLACKLIST, blacklistArray); + + const char *jsonString = json::get_string(configJSON); + const int64_t jsonLength = json::length(configJSON); + fslib::File configFile{PATH_CONFIG_FILE, FsOpenMode_Create | FsOpenMode_Write, jsonLength}; + if (error::fslib(configFile.is_open())) { return; } + configFile << jsonString; } void config::ConfigContext::read_array_to_vector(std::vector &vector, json_object *array) { - const int arrayLength = json_object_array_length(array); - for (int i = 0; i < arrayLength; i++) + const size_t arrayLength = json_object_array_length(array); + for (size_t i = 0; i < arrayLength; i++) { - json_object *arrayElement = json_object_array_get_idx(array, i); - if (!arrayElement) { break; } + json_object *element = json_object_array_get_idx(array, i); + const char *idHex = json_object_get_string(element); + const uint64_t applicationID = std::strtoull(idHex, nullptr, 16); - const char *appIDStr = json_object_get_string(arrayElement); - const uint64_t applicationID = std::strtoull(appIDStr, nullptr, 16); vector.push_back(applicationID); } } +void config::ConfigContext::load_custom_paths() +{ + json::Object pathsJSON = json::new_object(json_object_from_file, PATH_PATHS_FILE.data()); + if (!pathsJSON) { return; } + + json_object_iterator pathsIter = json::iter_begin(pathsJSON); + json_object_iterator pathsEnd = json::iter_end(pathsJSON); + while (!json_object_iter_equal(&pathsIter, &pathsEnd)) + { + const char *appIDString = json_object_iter_peek_name(&pathsIter); + json_object *pathObject = json_object_iter_peek_value(&pathsIter); + + const uint64_t applicationID = std::strtoull(appIDString, nullptr, 16); + const char *path = json_object_get_string(pathObject); + + m_paths[applicationID] = path; + + json_object_iter_next(&pathsIter); + } +} + void config::ConfigContext::save_custom_paths() { - json::Object pathsJSON = json::new_object(json_object_new_object); - for (auto &[applicationID, outputPath] : m_pathMap) - { - const std::string appIDHex = stringutil::get_formatted_string(STRING_APP_ID_FORMAT, applicationID); - const char *path = outputPath.c_str(); + json::Object pathsJSON = json::new_object(json_object_from_file, PATH_PATHS_FILE.data()); + if (!pathsJSON) { return; } - json_object *outputString = json_object_new_string(path); - json::add_object(pathsJSON, appIDHex, outputString); + for (auto &[applicationID, path] : m_paths) + { + const std::string key = stringutil::get_formatted_string(APP_ID_HEX_FORMAT, applicationID); + json_object *pathObject = json_object_new_string(path.c_str()); + + json::add_object(pathsJSON, key, pathObject); } - const char *pathsString = json::get_string(pathsJSON); - const int64_t pathsLength = std::char_traits::length(pathsString); - fslib::File pathsFile{PATH_PATHS_PATH, FsOpenMode_Create | FsOpenMode_Write, pathsLength}; - if (pathsFile.is_open()) { pathsFile << pathsString; }; + const char *jsonString = json::get_string(pathsJSON); + const int64_t jsonLength = json::length(pathsJSON); + fslib::File pathsFile{PATH_PATHS_FILE, FsOpenMode_Create | FsOpenMode_Write, jsonLength}; + if (error::fslib(pathsFile.is_open())) { return; } + pathsFile << jsonString; } -config::ConfigContext::AppIDList::iterator config::ConfigContext::find_favorite(uint64_t applicationID) +std::vector::const_iterator config::ConfigContext::find_application_id(const std::vector &vector, + uint64_t applicationID) const { - return std::find(m_favorites.begin(), m_favorites.end(), applicationID); -} - -config::ConfigContext::AppIDList::iterator config::ConfigContext::find_blacklist(uint64_t applicationID) -{ - return std::find(m_blacklist.begin(), m_blacklist.end(), applicationID); + return std::find(vector.begin(), vector.end(), applicationID); } diff --git a/source/config/config.cpp b/source/config/config.cpp index 828c92b..7d97af8 100644 --- a/source/config/config.cpp +++ b/source/config/config.cpp @@ -1,38 +1,19 @@ #include "config/config.hpp" #include "config/ConfigContext.hpp" -#include "logging/error.hpp" namespace { config::ConfigContext s_context{}; - - constexpr std::string_view PATH_CONFIG_FOLDER = "sdmc:/config/JKSV"; - constexpr const char *PATH_CONFIG_FILE = "sdmc:/config/JKSV/JKSV.json"; -} // namespace +} void config::initialize() { - // This is so we don't constantly construct new Paths - const fslib::Path configDir{PATH_CONFIG_FOLDER}; - const fslib::Path configFile{PATH_CONFIG_FILE}; + s_context.create_directory(); + const bool configLoaded = s_context.load(); + if (configLoaded) { return; } - const bool configDirExists = fslib::directory_exists(configDir); - const bool configDirError = !configDirExists && error::fslib(fslib::create_directories_recursively(configDir)); - if (!configDirExists && configDirError) - { - s_context.reset(); - return; - } - - const bool configExists = fslib::file_exists(configFile); - if (!configExists) - { - s_context.reset(); - return; - } - - s_context.load(); + s_context.reset(); } void config::reset_to_default() { s_context.reset(); } @@ -47,15 +28,14 @@ void config::set_by_key(std::string_view key, uint8_t value) { s_context.set_by_ fslib::Path config::get_working_directory() { return s_context.get_working_directory(); } -bool config::set_working_directory(std::string_view path) { return s_context.set_working_directory(path); } - double config::get_animation_scaling() { return s_context.get_animation_scaling(); } void config::set_animation_scaling(double newScale) { s_context.set_animation_scaling(newScale); } void config::add_remove_favorite(uint64_t applicationID) { - if (s_context.is_favorite(applicationID)) { s_context.remove_favorite(applicationID); } + const bool favorite = s_context.is_favorite(applicationID); + if (favorite) { s_context.remove_favorite(applicationID); } else { s_context.add_favorite(applicationID); } s_context.save(); } @@ -64,16 +44,17 @@ bool config::is_favorite(uint64_t applicationID) { return s_context.is_favorite( void config::add_remove_blacklist(uint64_t applicationID) { - if (s_context.is_blacklisted(applicationID)) { s_context.remove_from_blacklist(applicationID); } + const bool blacklisted = s_context.is_blacklisted(applicationID); + if (blacklisted) { s_context.remove_from_blacklist(applicationID); } else { s_context.add_to_blacklist(applicationID); } s_context.save(); } -void config::get_blacklisted_titles(std::vector &listOut) { s_context.get_blacklisted_titles(listOut); } +void config::get_blacklisted_titles(std::vector &listOut) { s_context.get_blacklist(listOut); } bool config::is_blacklisted(uint64_t applicationID) { return s_context.is_blacklisted(applicationID); } -bool config::blacklist_is_empty() { return s_context.blacklist_is_empty(); } +bool config::blacklist_is_empty() { return s_context.blacklist_empty(); } void config::add_custom_path(uint64_t applicationID, std::string_view customPath) { diff --git a/source/ui/TitleView.cpp b/source/ui/TitleView.cpp index 3ffe786..ebf6912 100644 --- a/source/ui/TitleView.cpp +++ b/source/ui/TitleView.cpp @@ -3,6 +3,7 @@ #include "config/config.hpp" #include "graphics/colors.hpp" #include "input.hpp" +#include "logging/error.hpp" #include "logging/logger.hpp" #include @@ -77,14 +78,17 @@ void ui::TitleView::set_selected(int selected) void ui::TitleView::refresh() { m_titleTiles.clear(); + const int entryCount = m_user->get_total_data_entries(); for (int i = 0; i < entryCount; i++) { const uint64_t applicationID = m_user->get_application_id_at(i); - const bool isFavorite = config::is_favorite(applicationID); data::TitleInfo *titleInfo = data::get_title_info_by_id(applicationID); - sdl::SharedTexture icon = titleInfo->get_icon(); // I don't like this but w/e. + if (error::is_null(titleInfo)) { continue; } + + const bool isFavorite = config::is_favorite(applicationID); + sdl::SharedTexture icon = titleInfo->get_icon(); // I don't like this but w/e. m_titleTiles.emplace_back(isFavorite, i, icon); }