Complete Update checking/downloading.

This commit is contained in:
J-D-K 2025-09-30 15:51:54 -04:00
parent 9cb6d52268
commit 9b80fa5dc8
14 changed files with 76 additions and 25 deletions

View File

@ -39,7 +39,7 @@ INCLUDES := include ./Libraries/FsLib/Switch/FsLib/include ./Libraries/SDLLib/SD
EXEFS_SRC := exefs_src
APP_TITLE := JKSV
APP_AUTHOR := JK
APP_VERSION := 09.29.2025
APP_VERSION := 09.30.2025
ROMFS := romfs
ICON := icon.jpg

View File

@ -2,6 +2,7 @@
#include "appstates/BaseState.hpp"
#include "sdl.hpp"
#include <atomic>
#include <memory>
#include <vector>
@ -25,9 +26,12 @@ class JKSV
/// @brief Runs JKSV's render routine.
void render();
/// @brief Function to allow tasks to tell JKSV to exit.
static void request_quit() noexcept;
private:
/// @brief Whether or not initialization was successful and JKSV is still running.
bool m_isRunning{};
static inline std::atomic_bool sm_isRunning{};
/// @brief Whether or not to print the translation credits.
bool m_showTranslationInfo{};

View File

@ -3,6 +3,6 @@
namespace builddate
{
inline constexpr int MONTH = 9;
inline constexpr int DAY = 29;
inline constexpr int DAY = 30;
inline constexpr int YEAR = 2025;
}

10
include/cmdargs.hpp Normal file
View File

@ -0,0 +1,10 @@
#pragma once
namespace cmdargs
{
/// @brief Stores the pointers passed to main for later usage without making JKSV a mess.
void store(int argc, const char *argv[]);
/// @brief Gets the argument at index.
const char *get(int index);
}

View File

@ -85,7 +85,7 @@ JKSV::JKSV()
data::launch_initialization(false, finish_initialization);
m_isRunning = true;
sm_isRunning = true;
}
JKSV::~JKSV()
@ -101,7 +101,7 @@ JKSV::~JKSV()
appletUnlockExit();
}
bool JKSV::is_running() const noexcept { return m_isRunning && appletMainLoop(); }
bool JKSV::is_running() const noexcept { return sm_isRunning && appletMainLoop(); }
void JKSV::update()
{
@ -109,7 +109,7 @@ void JKSV::update()
const bool plusPressed = input::button_pressed(HidNpadButton_Plus);
const bool isClosable = StateManager::back_is_closable();
if (plusPressed && isClosable) { m_isRunning = false; }
if (plusPressed && isClosable) { sm_isRunning = false; }
StateManager::update();
ui::PopMessageManager::update();
@ -141,6 +141,8 @@ void JKSV::render()
sdl::frame_end();
}
void JKSV::request_quit() noexcept { sm_isRunning = false; }
bool JKSV::initialize_filesystem()
{
// This needs to be in this specific order

View File

@ -25,7 +25,7 @@ void BlacklistEditState::update()
sm_slidePanel->update(hasFocus);
if (aPressed) { BlacklistEditState::remove_from_blacklist(); }
else if (bPressed || m_blacklist.empty()) { sm_slidePanel->close(); }
else if (bPressed || config::blacklist_is_empty()) { sm_slidePanel->close(); }
else if (sm_slidePanel->is_closed()) { BlacklistEditState::deactivate_state(); }
}

View File

@ -179,7 +179,9 @@ void SettingsState::change_working_directory()
moved = fs::move_directory_recursively(oldPath, newPath);
error::fslib(fslib::delete_directory_recursively(oldPath));
}
else { moved = fslib::rename_directory(oldPath, newPath); }
else {
moved = fslib::rename_directory(oldPath, newPath);
}
if (!moved)
{
@ -212,6 +214,7 @@ void SettingsState::create_push_blacklist_edit()
void SettingsState::toggle_options()
{
const int selected = m_settingsMenu->get_selected();
switch (selected)
{
case CHANGE_WORK_DIR: SettingsState::change_working_directory(); break;
@ -270,7 +273,9 @@ void SettingsState::toggle_trash_folder()
config::toggle_by_key(config::keys::ENABLE_TRASH_BIN);
if (trashEnabled) { error::fslib(fslib::delete_directory_recursively(trashPath)); }
else { error::fslib(fslib::create_directory(trashPath)); }
else {
error::fslib(fslib::create_directory(trashPath));
}
}
void SettingsState::cycle_anim_scaling()

21
source/cmdargs.cpp Normal file
View File

@ -0,0 +1,21 @@
#include "CmdArgs.hpp"
#include <vector>
namespace
{
std::vector<const char *> s_args{};
}
void cmdargs::store(int argc, const char *argv[])
{
for (int i = 0; i < argc; i++) { s_args.push_back(argv[i]); }
}
const char *cmdargs::get(int index)
{
const int argCount = s_args.size();
if (index < 0 || index >= argCount) { return nullptr; }
return s_args[index];
}

View File

@ -201,7 +201,9 @@ bool config::ConfigContext::load_config_file()
else if (scaling) { m_animationScaling = json_object_get_double(value); }
else if (favorites) { ConfigContext::read_array_to_set(m_favorites, value); }
else if (blacklist) { ConfigContext::read_array_to_set(m_blacklist, value); }
else { m_configMap[key] = json_object_get_uint64(value); }
else {
m_configMap[key] = json_object_get_uint64(value);
}
json_object_iter_next(&configIter);
}

View File

@ -1,6 +1,7 @@
#include "config/config.hpp"
#include "config/ConfigContext.hpp"
#include "logging/logger.hpp"
namespace
{
@ -38,7 +39,9 @@ void config::add_remove_favorite(uint64_t applicationID)
{
const bool favorite = s_context.is_favorite(applicationID);
if (favorite) { s_context.remove_favorite(applicationID); }
else { s_context.add_favorite(applicationID); }
else {
s_context.add_favorite(applicationID);
}
}
bool config::is_favorite(uint64_t applicationID) noexcept { return s_context.is_favorite(applicationID); }
@ -47,7 +50,9 @@ void config::add_remove_blacklist(uint64_t applicationID)
{
const bool blacklisted = s_context.is_blacklisted(applicationID);
if (blacklisted) { s_context.remove_from_blacklist(applicationID); }
else { s_context.add_to_blacklist(applicationID); }
else {
s_context.add_to_blacklist(applicationID);
}
}
void config::get_blacklisted_titles(std::vector<uint64_t> &listOut) { s_context.get_blacklist(listOut); }

View File

@ -1,6 +1,7 @@
#include "data/data.hpp"
#include "appstates/DataLoadingState.hpp"
#include "appstates/FadeState.hpp"
#include "data/DataContext.hpp"
#include "error.hpp"
#include "logging/logger.hpp"

View File

@ -1,9 +1,13 @@
#include "JKSV.hpp"
#include "cmdargs.hpp"
#include <switch.h>
int main(int argc, const char *argv[])
{
// Store the pointers here so JKSV can update itself from where ever the use might have placed it.
cmdargs::store(argc, argv);
JKSV jksv{};
while (jksv.is_running())
{

View File

@ -40,8 +40,6 @@ void tasks::backup::create_new_backup_local(sys::threadpool::JobData taskData)
if (error::is_null(user) || error::is_null(titleInfo)) { TASK_FINISH_RETURN(task); }
const std::string targetString = target.string();
logger::log("targetString: %s", targetString.c_str());
const bool hasZipExt = std::strstr(targetString.c_str(), STRING_ZIP_EXT);
const uint64_t applicationID = titleInfo->get_application_id();
const FsSaveDataInfo *saveInfo = user->get_save_info_by_id(applicationID);
@ -56,8 +54,7 @@ void tasks::backup::create_new_backup_local(sys::threadpool::JobData taskData)
auto scopedMount = create_scoped_mount(saveInfo);
fs::copy_directory_to_zip(fs::DEFAULT_SAVE_ROOT, zip, task);
}
else
{
else {
const bool needsDir = !fslib::directory_exists(target);
const bool createError = needsDir && error::fslib(fslib::create_directory(target));
if (needsDir && createError) { TASK_FINISH_RETURN(task); }
@ -264,8 +261,7 @@ void tasks::backup::restore_backup_local(sys::threadpool::JobData taskData)
auto scopedMount = create_scoped_mount(saveInfo);
fs::copy_directory_commit(target, fs::DEFAULT_SAVE_ROOT, journalSize, task);
}
else
{
else {
auto scopedMount = create_scoped_mount(saveInfo);
fs::copy_file_commit(target, fs::DEFAULT_SAVE_ROOT, journalSize, task);
}
@ -395,8 +391,7 @@ void tasks::backup::delete_backup_local(sys::threadpool::JobData taskData)
dirError = isDir && error::fslib(fslib::rename_directory(path, newPath));
fileError = !isDir && error::fslib(fslib::rename_file(path, newPath));
}
else
{
else {
dirError = isDir && error::fslib(fslib::delete_directory_recursively(path));
fileError = !isDir && error::fslib(fslib::delete_file(path));
}
@ -535,14 +530,12 @@ static void auto_backup(sys::ProgressTask *task, BackupMenuState::TaskData taskD
tasks::backup::create_new_backup_remote(tempData);
}
else
{
else {
// We're going to get the target dir from the path passed.
const size_t lastSlash = target.find_last_of('/');
if (lastSlash == target.NOT_FOUND) { return; }
fslib::Path autoTarget{target.sub_path(lastSlash) / backupName};
logger::log("autoTarget: %s", autoTarget.string().c_str());
tempData->path = std::move(autoTarget);

View File

@ -4,6 +4,7 @@
#include "appstates/ConfirmState.hpp"
#include "appstates/MainMenuState.hpp"
#include "builddate.hpp"
#include "cmdargs.hpp"
#include "curl/curl.hpp"
#include "error.hpp"
#include "json.hpp"
@ -75,8 +76,9 @@ void tasks::update::download_update(sys::threadpool::JobData jobData)
task->reset(static_cast<double>(nroSize));
// To do: Figure out how to get the argument from main here.
error::libnx(romfsExit()); // This is needed so I can overwrite the NRO.
fslib::File jksv{"sdmc:/switch/JKSV.nro", FsOpenMode_Create | FsOpenMode_Write, static_cast<int64_t>(nroSize)};
error::libnx(romfsExit()); // This is needed so I can overwrite the NRO.
const char *location = cmdargs::get(0); // This is the location from the command line args.
fslib::File jksv{location, FsOpenMode_Create | FsOpenMode_Write, static_cast<int64_t>(nroSize)};
if (error::fslib(jksv.is_open())) { TASK_FINISH_RETURN(task); }
auto download = curl::create_download_struct(jksv, task, nroSize);
@ -90,6 +92,8 @@ void tasks::update::download_update(sys::threadpool::JobData jobData)
download->writeComplete.acquire();
task->complete();
JKSV::request_quit();
}
static std::string get_git_json(curl::Handle &handle)