From e025901b0bd8f7712028ca3b7dcafcad2a810a27 Mon Sep 17 00:00:00 2001 From: J-D-K Date: Mon, 18 Aug 2025 21:09:11 -0400 Subject: [PATCH] Implement changing working directory. --- Libraries/FsLib | 2 +- include/appstates/BaseTask.hpp | 3 +++ include/config/ConfigContext.hpp | 2 +- include/config/config.hpp | 4 ++++ romfs/Text/ENUS.json | 4 +++- source/appstates/DataLoadingState.cpp | 12 ++++------ source/appstates/ProgressState.cpp | 7 +++--- source/appstates/SettingsState.cpp | 34 ++++++++++++++++++++++++++- source/appstates/TaskState.cpp | 4 ++-- source/config/ConfigContext.cpp | 6 +++-- source/config/config.cpp | 9 +++++++ source/keyboard.cpp | 2 +- 12 files changed, 68 insertions(+), 21 deletions(-) diff --git a/Libraries/FsLib b/Libraries/FsLib index 3dad2c2..a98a7f5 160000 --- a/Libraries/FsLib +++ b/Libraries/FsLib @@ -1 +1 @@ -Subproject commit 3dad2c27fd568d1522b0c28651a47b06ff25ab7f +Subproject commit a98a7f579e5ec78b315ad84832f708abca7ebf39 diff --git a/include/appstates/BaseTask.hpp b/include/appstates/BaseTask.hpp index 49dd9c3..ea76377 100644 --- a/include/appstates/BaseTask.hpp +++ b/include/appstates/BaseTask.hpp @@ -34,6 +34,9 @@ class BaseTask : public BaseState /// @brief Updates the loading glyph animation. void update_loading_glyph(); + /// @brief This is the font size used for displaying text during tasks. + static inline constexpr int FONT_SIZE = 20; + private: /// @brief This is the current frame of the loading glyph animation. int m_currentFrame{}; diff --git a/include/config/ConfigContext.hpp b/include/config/ConfigContext.hpp index 2fe5c5a..78b9906 100644 --- a/include/config/ConfigContext.hpp +++ b/include/config/ConfigContext.hpp @@ -39,7 +39,7 @@ namespace config fslib::Path get_working_directory() const; /// @brief Sets the current work directory if the path passed is valid. - void set_working_directory(const fslib::Path &workDir); + bool set_working_directory(const fslib::Path &workDir); /// @brief Returns the transition scaling speed. double get_animation_scaling() const; diff --git a/include/config/config.hpp b/include/config/config.hpp index 719d344..0d5ac8c 100644 --- a/include/config/config.hpp +++ b/include/config/config.hpp @@ -34,6 +34,10 @@ namespace config /// @return Working directory. fslib::Path get_working_directory(); + /// @brief Attempts to set the working directory to the one passed. + /// @param path Path for JKSV to use. + bool set_working_directory(const fslib::Path &path); + /// @brief Returns the scaling speed of UI transitions and animations. /// @return Scaling variable. double get_animation_scaling(); diff --git a/romfs/Text/ENUS.json b/romfs/Text/ENUS.json index 3c1e992..ef33108 100644 --- a/romfs/Text/ENUS.json +++ b/romfs/Text/ENUS.json @@ -166,7 +166,9 @@ "19: Animation scaling: %.02f" ], "SettingsPops": [ - "0: Blacklist is empty!" + "0: Blacklist is empty!", + "1: JKSV output set to #%s#!", + "2: Failed to set JKSV working directory!" ], "SortTypes": [ "0: Alphabetically", diff --git a/source/appstates/DataLoadingState.cpp b/source/appstates/DataLoadingState.cpp index 6b8cdc2..ec5fad3 100644 --- a/source/appstates/DataLoadingState.cpp +++ b/source/appstates/DataLoadingState.cpp @@ -10,15 +10,8 @@ namespace void DataLoadingState::update() { - static constexpr int SCREEN_CENTER = 640; - - const std::string status = m_task->get_status(); - const int statusWidth = sdl::text::get_width(22, status); - m_statusX = SCREEN_CENTER - (statusWidth / 2); - BaseTask::update_loading_glyph(); if (!m_task->is_running()) { DataLoadingState::deactivate_state(); } - m_context.process_icon_queue(); } @@ -28,9 +21,12 @@ void DataLoadingState::render() static constexpr int ICON_Y_COORD = 226; const std::string status = m_task->get_status(); + const int statusWidth = sdl::text::get_width(BaseTask::FONT_SIZE, status); + m_statusX = SCREEN_CENTER - (statusWidth / 2); + sdl::render_rect_fill(sdl::Texture::Null, 0, 0, 1280, 720, colors::CLEAR_COLOR); sm_jksvIcon->render(sdl::Texture::Null, ICON_X_COORD, ICON_Y_COORD); - sdl::text::render(sdl::Texture::Null, m_statusX, 673, 22, sdl::text::NO_WRAP, colors::WHITE, status); + sdl::text::render(sdl::Texture::Null, m_statusX, 673, BaseTask::FONT_SIZE, sdl::text::NO_WRAP, colors::WHITE, status); BaseTask::render_loading_glyph(); } diff --git a/source/appstates/ProgressState.cpp b/source/appstates/ProgressState.cpp index e1b8b37..84f4712 100644 --- a/source/appstates/ProgressState.cpp +++ b/source/appstates/ProgressState.cpp @@ -19,7 +19,6 @@ namespace constexpr int COORD_DISPLAY_CENTER = 640; constexpr double SIZE_BAR_WIDTH = 656.0f; - constexpr int SIZE_FONT_SIZE = 18; } void ProgressState::update() @@ -33,7 +32,7 @@ void ProgressState::update() m_progressBarWidth = std::round(SIZE_BAR_WIDTH * current); m_progress = std::round(current * 100); m_percentageString = stringutil::get_formatted_string("%u%%", m_progress); - const int percentageWidth = sdl::text::get_width(18, m_percentageString.c_str()); + const int percentageWidth = sdl::text::get_width(BaseTask::FONT_SIZE, m_percentageString.c_str()); m_percentageX = COORD_DISPLAY_CENTER - percentageWidth; } @@ -45,14 +44,14 @@ void ProgressState::render() sdl::render_rect_fill(sdl::Texture::Null, 0, 0, 1280, 720, colors::DIM_BACKGROUND); sm_dialog->render(sdl::Texture::Null, hasFocus); - sdl::text::render(sdl::Texture::Null, 312, 288, 18, 656, colors::WHITE, status); + sdl::text::render(sdl::Texture::Null, 312, 288, BaseTask::FONT_SIZE, 656, colors::WHITE, status); sdl::render_rect_fill(sdl::Texture::Null, COORD_BAR_X, COORD_BAR_Y, barWidth, 32, colors::BLACK); sdl::render_rect_fill(sdl::Texture::Null, COORD_BAR_X, COORD_BAR_Y, m_progressBarWidth, 32, colors::GREEN); sdl::text::render(sdl::Texture::Null, m_percentageX, COORD_TEXT_Y, - SIZE_FONT_SIZE, + BaseTask::FONT_SIZE, sdl::text::NO_WRAP, colors::WHITE, m_percentageString); diff --git a/source/appstates/SettingsState.cpp b/source/appstates/SettingsState.cpp index 6a194bf..325dd60 100644 --- a/source/appstates/SettingsState.cpp +++ b/source/appstates/SettingsState.cpp @@ -9,6 +9,7 @@ #include "graphics/colors.hpp" #include "input.hpp" #include "keyboard.hpp" +#include "logging/error.hpp" #include "logging/logger.hpp" #include "strings/strings.hpp" #include "stringutil.hpp" @@ -144,7 +145,38 @@ void SettingsState::update_menu_options() } } -void SettingsState::change_working_directory() {} +void SettingsState::change_working_directory() +{ + const int popTicks = ui::PopMessageManager::DEFAULT_TICKS; + const char *inputHeader = strings::get_by_name(strings::names::KEYBOARD, 2); + const char *popSuccessFormat = strings::get_by_name(strings::names::SETTINGS_POPS, 1); + const char *popFailed = strings::get_by_name(strings::names::SETTINGS_POPS, 2); + + const fslib::Path oldPath{config::get_working_directory()}; + std::array pathBuffer = {0}; + + const bool input = keyboard::get_input(SwkbdType_Normal, oldPath.full_path(), inputHeader, pathBuffer.data(), FS_MAX_PATH); + if (!input) { return; } + + const fslib::Path newPath{pathBuffer.data()}; + const bool exists = fslib::directory_exists(newPath); + if (exists) + { + ui::PopMessageManager::push_message(popTicks, popFailed); + return; + } + + const bool pathSet = config::set_working_directory(newPath); + const bool renameError = pathSet && error::fslib(fslib::rename_directory(oldPath, newPath)); + if (!pathSet || renameError) + { + ui::PopMessageManager::push_message(popTicks, popFailed); + return; + } + + const std::string popMessage = stringutil::get_formatted_string(popSuccessFormat, newPath.full_path()); + ui::PopMessageManager::push_message(popTicks, popMessage); +} void SettingsState::create_push_blacklist_edit() { diff --git a/source/appstates/TaskState.cpp b/source/appstates/TaskState.cpp index 6d3ec3d..d13edd9 100644 --- a/source/appstates/TaskState.cpp +++ b/source/appstates/TaskState.cpp @@ -16,10 +16,10 @@ void TaskState::update() void TaskState::render() { const std::string status = m_task->get_status(); - const int statusX = 640 - (sdl::text::get_width(24, status.c_str()) / 2); + const int statusX = 640 - (sdl::text::get_width(BaseTask::FONT_SIZE, status.c_str()) / 2); sdl::render_rect_fill(sdl::Texture::Null, 0, 0, 1280, 720, colors::DIM_BACKGROUND); - sdl::text::render(sdl::Texture::Null, statusX, 351, 24, sdl::text::NO_WRAP, colors::WHITE, status); + sdl::text::render(sdl::Texture::Null, statusX, 351, BaseTask::FONT_SIZE, sdl::text::NO_WRAP, colors::WHITE, status); BaseTask::render_loading_glyph(); } diff --git a/source/config/ConfigContext.cpp b/source/config/ConfigContext.cpp index 150136a..e6e76be 100644 --- a/source/config/ConfigContext.cpp +++ b/source/config/ConfigContext.cpp @@ -89,10 +89,12 @@ void config::ConfigContext::set_by_key(std::string_view key, uint8_t value) fslib::Path config::ConfigContext::get_working_directory() const { return m_workingDirectory; } -void config::ConfigContext::set_working_directory(const fslib::Path &workDir) +bool config::ConfigContext::set_working_directory(const fslib::Path &workDir) { - if (!workDir.is_valid()) { return; } + if (!workDir.is_valid()) { return false; } + m_workingDirectory = workDir; + return true; } double config::ConfigContext::get_animation_scaling() const { return m_animationScaling; } diff --git a/source/config/config.cpp b/source/config/config.cpp index 7d97af8..1711019 100644 --- a/source/config/config.cpp +++ b/source/config/config.cpp @@ -28,6 +28,15 @@ 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(const fslib::Path &path) +{ + const bool pathSet = s_context.set_working_directory(path); + if (!pathSet) { return false; } + + s_context.save(); + return true; +} + double config::get_animation_scaling() { return s_context.get_animation_scaling(); } void config::set_animation_scaling(double newScale) { s_context.set_animation_scaling(newScale); } diff --git a/source/keyboard.cpp b/source/keyboard.cpp index 184a367..16ab221 100644 --- a/source/keyboard.cpp +++ b/source/keyboard.cpp @@ -18,7 +18,7 @@ bool keyboard::get_input(SwkbdType keyboardType, swkbdConfigSetGuideText(&keyboard, header.data()); swkbdConfigSetType(&keyboard, keyboardType); swkbdConfigSetStringLenMax(&keyboard, stringLength); - swkbdConfigSetKeySetDisableBitmask(&keyboard, SwkbdKeyDisableBitmask_ForwardSlash | SwkbdKeyDisableBitmask_Backslash); + swkbdConfigSetKeySetDisableBitmask(&keyboard, SwkbdKeyDisableBitmask_Backslash); const bool swkbdError = error::libnx(swkbdShow(&keyboard, stringOut, stringLength)); const bool empty = std::char_traits::length(stringOut) == 0;