From 654f3a1446eb4f4a3fafa48021fb0690f3b57a41 Mon Sep 17 00:00:00 2001 From: ITotalJustice <47043333+ITotalJustice@users.noreply.github.com> Date: Wed, 21 May 2025 16:50:18 +0100 Subject: [PATCH] replace progress box result from bool to Result. Display error box if progress box fails. --- sphaira/include/app.hpp | 3 + sphaira/include/ui/progress_box.hpp | 10 +- sphaira/source/app.cpp | 28 ++- sphaira/source/owo.cpp | 4 +- sphaira/source/ui/menus/appstore.cpp | 123 +++++------- sphaira/source/ui/menus/filebrowser.cpp | 236 +++++++++--------------- sphaira/source/ui/menus/ftp_menu.cpp | 14 +- sphaira/source/ui/menus/game_menu.cpp | 34 ++-- sphaira/source/ui/menus/gc_menu.cpp | 49 ++--- sphaira/source/ui/menus/ghdl.cpp | 93 ++++------ sphaira/source/ui/menus/main_menu.cpp | 61 +++--- sphaira/source/ui/menus/themezer.cpp | 64 +++---- sphaira/source/ui/menus/usb_menu.cpp | 14 +- sphaira/source/ui/progress_box.cpp | 7 + 14 files changed, 308 insertions(+), 432 deletions(-) diff --git a/sphaira/include/app.hpp b/sphaira/include/app.hpp index 6e0ea75..80cac2b 100644 --- a/sphaira/include/app.hpp +++ b/sphaira/include/app.hpp @@ -61,6 +61,9 @@ public: static void NotifyClear(ui::NotifEntry::Side side = ui::NotifEntry::Side::RIGHT); static void NotifyFlashLed(); + // if R_FAILED(rc), pushes error box. returns rc passed in. + static Result PushErrorBox(Result rc, const std::string& message); + static auto GetThemeMetaList() -> std::span; static void SetTheme(s64 theme_index); static auto GetThemeIndex() -> s64; diff --git a/sphaira/include/ui/progress_box.hpp b/sphaira/include/ui/progress_box.hpp index 15009ea..273f31c 100644 --- a/sphaira/include/ui/progress_box.hpp +++ b/sphaira/include/ui/progress_box.hpp @@ -8,15 +8,15 @@ namespace sphaira::ui { struct ProgressBox; -using ProgressBoxCallback = std::function; -using ProgressBoxDoneCallback = std::function; +using ProgressBoxCallback = std::function; +using ProgressBoxDoneCallback = std::function; struct ProgressBox final : Widget { ProgressBox( int image, const std::string& action, const std::string& title, - ProgressBoxCallback callback, ProgressBoxDoneCallback done = [](bool success){}, + ProgressBoxCallback callback, ProgressBoxDoneCallback done = [](Result rc){}, int cpuid = 1, int prio = 0x2C, int stack_size = 1024*128 ); ~ProgressBox(); @@ -30,8 +30,10 @@ struct ProgressBox final : Widget { // not const in order to avoid copy by using std::swap auto SetImageData(std::vector& data) -> ProgressBox&; auto SetImageDataConst(std::span data) -> ProgressBox&; + void RequestExit(); auto ShouldExit() -> bool; + auto ShouldExitResult() -> Result; // helper functions auto CopyFile(const fs::FsPath& src, const fs::FsPath& dst) -> Result; @@ -64,7 +66,7 @@ public: struct ThreadData { ProgressBox* pbox{}; ProgressBoxCallback callback{}; - bool result{}; + Result result{}; }; private: diff --git a/sphaira/source/app.cpp b/sphaira/source/app.cpp index 545979d..ff16f86 100644 --- a/sphaira/source/app.cpp +++ b/sphaira/source/app.cpp @@ -50,15 +50,17 @@ void download_default_music() { curl::OnProgress{pbox->OnDownloadProgressCallback()} ); - return result.success; - }, [](bool success){ - if (success) { + if (!result.success) { + R_THROW(0x1); + } + + R_SUCCEED(); + }, [](Result rc){ + App::PushErrorBox(rc, "Failed to, TODO: add message here"_i18n); + + if (R_SUCCEEDED(rc)) { App::Notify("Downloaded "_i18n + "default_music.bfstm"); App::SetTheme(App::GetThemeIndex()); - } else { - App::Push(std::make_shared( - "Failed to download default_music.bfstm, please try again"_i18n - )); } })); } @@ -568,6 +570,13 @@ void App::NotifyFlashLed() { } } +Result App::PushErrorBox(Result rc, const std::string& message) { + if (R_FAILED(rc)) { + App::Push(std::make_shared(rc, message)); + } + return rc; +} + auto App::GetThemeMetaList() -> std::span { return g_app->m_theme_meta_entries; } @@ -742,9 +751,10 @@ void App::SetReplaceHbmenuEnable(bool enable) { if (R_FAILED(rc = fs.copy_entire_file("/hbmenu.nro", "/switch/hbmenu.nro"))) { // try and restore sphaira in a last ditch effort. if (R_FAILED(rc = fs.copy_entire_file("/hbmenu.nro", sphaira_path))) { - App::Push(std::make_shared(rc, + App::PushErrorBox(rc, "Failed to, TODO: add message here"_i18n); + App::PushErrorBox(rc, "Failed to restore hbmenu, please re-download hbmenu"_i18n - )); + ); } else { App::Push(std::make_shared( "Failed to restore hbmenu, using sphaira instead"_i18n, diff --git a/sphaira/source/owo.cpp b/sphaira/source/owo.cpp index 1d96cbc..9174b7a 100644 --- a/sphaira/source/owo.cpp +++ b/sphaira/source/owo.cpp @@ -1012,8 +1012,8 @@ auto install_forwarder(ui::ProgressBox* pbox, OwoConfig& config, NcmStorageId st } auto install_forwarder(OwoConfig& config, NcmStorageId storage_id) -> Result { - App::Push(std::make_shared(0, "Installing Forwarder"_i18n, config.name, [config, storage_id](auto pbox) mutable -> bool { - return R_SUCCEEDED(install_forwarder(pbox, config, storage_id)); + App::Push(std::make_shared(0, "Installing Forwarder"_i18n, config.name, [config, storage_id](auto pbox) mutable -> Result { + return install_forwarder(pbox, config, storage_id); })); R_SUCCEED(); } diff --git a/sphaira/source/ui/menus/appstore.cpp b/sphaira/source/ui/menus/appstore.cpp index c55b533..0562573 100644 --- a/sphaira/source/ui/menus/appstore.cpp +++ b/sphaira/source/ui/menus/appstore.cpp @@ -286,14 +286,12 @@ void ReadFromInfoJson(Entry& e) { // this ignores ShouldExit() as leaving somthing in a half // deleted state is a bad idea :) -auto UninstallApp(ProgressBox* pbox, const Entry& entry) -> bool { +auto UninstallApp(ProgressBox* pbox, const Entry& entry) -> Result { const auto manifest = LoadAndParseManifest(entry); fs::FsNativeSd fs; if (manifest.empty()) { - if (entry.binary.empty()) { - return false; - } + R_UNLESS(!entry.binary.empty(), 0x1); fs.DeleteFile(entry.binary); } else { for (auto& e : manifest) { @@ -319,7 +317,8 @@ auto UninstallApp(ProgressBox* pbox, const Entry& entry) -> bool { } else { log_write("deleted: %s\n", dir.s); } - return true; + + R_SUCCEED(); } // this is called by ProgressBox on a seperate thread @@ -328,12 +327,12 @@ auto UninstallApp(ProgressBox* pbox, const Entry& entry) -> bool { // 2. md5 check the zip // 3. parse manifest and unzip everything to placeholder // 4. move everything from placeholder to normal location -auto InstallApp(ProgressBox* pbox, const Entry& entry) -> bool { +auto InstallApp(ProgressBox* pbox, const Entry& entry) -> Result { static const fs::FsPath zip_out{"/switch/sphaira/cache/appstore/temp.zip"}; constexpr auto chunk_size = 1024 * 512; // 512KiB fs::FsNativeSd fs; - R_TRY_RESULT(fs.GetFsOpenResult(), false); + R_TRY(fs.GetFsOpenResult()); // 1. download the zip if (!pbox->ShouldExit()) { @@ -341,14 +340,13 @@ auto InstallApp(ProgressBox* pbox, const Entry& entry) -> bool { log_write("starting download\n"); const auto url = BuildZipUrl(entry); - if (!curl::Api().ToFile( + const auto result = curl::Api().ToFile( curl::Url{url}, curl::Path{zip_out}, curl::OnProgress{pbox->OnDownloadProgressCallback()} - ).success) { - log_write("error with download\n"); - return false; - } + ); + + R_UNLESS(result.success, 0x1); } ON_SCOPE_EXIT(fs.DeleteFile(zip_out)); @@ -359,15 +357,11 @@ auto InstallApp(ProgressBox* pbox, const Entry& entry) -> bool { log_write("starting md5 check\n"); FsFile f; - if (R_FAILED(fs.OpenFile(zip_out, FsOpenMode_Read, &f))) { - return false; - } + R_TRY(fs.OpenFile(zip_out, FsOpenMode_Read, &f)); ON_SCOPE_EXIT(fsFileClose(&f)); s64 size; - if (R_FAILED(fsFileGetSize(&f, &size))) { - return false; - } + R_TRY(fsFileGetSize(&f, &size)); mbedtls_md5_context ctx; mbedtls_md5_init(&ctx); @@ -380,19 +374,14 @@ auto InstallApp(ProgressBox* pbox, const Entry& entry) -> bool { std::vector chunk(chunk_size); s64 offset{}; while (offset < size) { - if (pbox->ShouldExit()) { - return false; - } + R_TRY(pbox->ShouldExitResult()); u64 bytes_read; - if (R_FAILED(fsFileRead(&f, offset, chunk.data(), chunk.size(), 0, &bytes_read))) { - log_write("failed to read file offset: %zd size: %zd\n", offset, size); - return false; - } + R_TRY(fsFileRead(&f, offset, chunk.data(), chunk.size(), 0, &bytes_read)); if (mbedtls_md5_update_ret(&ctx, chunk.data(), bytes_read)) { log_write("failed to update ret\n"); - return false; + R_THROW(0x1); } offset += bytes_read; @@ -401,7 +390,7 @@ auto InstallApp(ProgressBox* pbox, const Entry& entry) -> bool { u8 md5_out[16]; if (mbedtls_md5_finish_ret(&ctx, (u8*)md5_out)) { - return false; + R_THROW(0x1); } // convert md5 to hex string @@ -412,23 +401,20 @@ auto InstallApp(ProgressBox* pbox, const Entry& entry) -> bool { if (strncasecmp(md5_str, entry.md5.data(), entry.md5.length())) { log_write("bad md5: %.*s vs %.*s\n", 32, md5_str, 32, entry.md5.c_str()); - return false; + R_THROW(0x1); } } // 3. extract the zip if (!pbox->ShouldExit()) { auto zfile = unzOpen64(zip_out); - if (!zfile) { - log_write("failed to open zip: %s\n", zip_out.s); - return false; - } + R_UNLESS(zfile, 0x1); ON_SCOPE_EXIT(unzClose(zfile)); // get manifest if (UNZ_END_OF_LIST_OF_FILE == unzLocateFile(zfile, "manifest.install", 0)) { log_write("failed to find manifest.install\n"); - return false; + R_THROW(0x1); } ManifestEntries new_manifest; @@ -436,47 +422,47 @@ auto InstallApp(ProgressBox* pbox, const Entry& entry) -> bool { { if (UNZ_OK != unzOpenCurrentFile(zfile)) { log_write("failed to open current file\n"); - return false; + R_THROW(0x1); } ON_SCOPE_EXIT(unzCloseCurrentFile(zfile)); unz_file_info64 info; if (UNZ_OK != unzGetCurrentFileInfo64(zfile, &info, 0, 0, 0, 0, 0, 0)) { log_write("failed to get current info\n"); - return false; + R_THROW(0x1); } std::vector manifest_data(info.uncompressed_size); if ((int)info.uncompressed_size != unzReadCurrentFile(zfile, manifest_data.data(), manifest_data.size())) { log_write("failed to read manifest file\n"); - return false; + R_THROW(0x1); } new_manifest = ParseManifest(manifest_data); if (new_manifest.empty()) { log_write("manifest is empty!\n"); - return false; + R_THROW(0x1); } } - const auto unzip_to = [pbox, &fs, zfile](const fs::FsPath& inzip, fs::FsPath output) -> bool { + const auto unzip_to = [pbox, &fs, zfile](const fs::FsPath& inzip, fs::FsPath output) -> Result { pbox->NewTransfer(inzip); if (UNZ_END_OF_LIST_OF_FILE == unzLocateFile(zfile, inzip, 0)) { log_write("failed to find %s\n", inzip.s); - return false; + R_THROW(0x1); } if (UNZ_OK != unzOpenCurrentFile(zfile)) { log_write("failed to open current file\n"); - return false; + R_THROW(0x1); } ON_SCOPE_EXIT(unzCloseCurrentFile(zfile)); unz_file_info64 info; if (UNZ_OK != unzGetCurrentFileInfo64(zfile, &info, 0, 0, 0, 0, 0, 0)) { log_write("failed to get current info\n"); - return false; + R_THROW(0x1); } if (output[0] != '/') { @@ -489,58 +475,41 @@ auto InstallApp(ProgressBox* pbox, const Entry& entry) -> bool { Result rc; if (R_FAILED(rc = fs.CreateFile(output, info.uncompressed_size, 0)) && rc != FsError_PathAlreadyExists) { log_write("failed to create file: %s 0x%04X\n", output.s, rc); - return false; + R_THROW(rc); } FsFile f; - if (R_FAILED(rc = fs.OpenFile(output, FsOpenMode_Write, &f))) { - log_write("failed to open file: %s 0x%04X\n", output.s, rc); - return false; - } + R_TRY(fs.OpenFile(output, FsOpenMode_Write, &f)); ON_SCOPE_EXIT(fsFileClose(&f)); - if (R_FAILED(rc = fsFileSetSize(&f, info.uncompressed_size))) { - log_write("failed to set file size: %s 0x%04X\n", output.s, rc); - return false; - } + R_TRY(fsFileSetSize(&f, info.uncompressed_size)); std::vector buf(chunk_size); u64 offset{}; while (offset < info.uncompressed_size) { - if (pbox->ShouldExit()) { - return false; - } + R_TRY(pbox->ShouldExitResult()); const auto bytes_read = unzReadCurrentFile(zfile, buf.data(), buf.size()); if (bytes_read <= 0) { log_write("failed to read zip file: %s\n", inzip.s); - return false; + R_THROW(0x1); } - if (R_FAILED(rc = fsFileWrite(&f, offset, buf.data(), bytes_read, FsWriteOption_None))) { - log_write("failed to write file: %s 0x%04X\n", output.s, rc); - return false; - } + R_TRY(fsFileWrite(&f, offset, buf.data(), bytes_read, FsWriteOption_None)); pbox->UpdateTransfer(offset, info.uncompressed_size); offset += bytes_read; } - return true; + R_SUCCEED(); }; // unzip manifest and info - if (!unzip_to("info.json", BuildInfoCachePath(entry))) { - return false; - } - if (!unzip_to("manifest.install", BuildManifestCachePath(entry))) { - return false; - } + R_TRY(unzip_to("info.json", BuildInfoCachePath(entry))); + R_TRY(unzip_to("manifest.install", BuildManifestCachePath(entry))); for (auto& new_entry : new_manifest) { - if (pbox->ShouldExit()) { - return false; - } + R_TRY(pbox->ShouldExitResult()); switch (new_entry.command) { case 'E': // both are the same? @@ -586,7 +555,7 @@ auto InstallApp(ProgressBox* pbox, const Entry& entry) -> bool { } log_write("finished install :)\n"); - return true; + R_SUCCEED(); } // case-insensitive version of str.find() @@ -775,27 +744,31 @@ void EntryMenu::UpdateOptions() { const auto install = [this](){ App::Push(std::make_shared(m_entry.image.image, "Downloading "_i18n, m_entry.title, [this](auto pbox){ return InstallApp(pbox, m_entry); - }, [this](bool success){ - if (success) { + }, [this](Result rc){ + App::PushErrorBox(rc, "Failed to, TODO: add message here"_i18n); + + if (R_SUCCEEDED(rc)) { App::Notify("Downloaded "_i18n + m_entry.title); m_entry.status = EntryStatus::Installed; m_menu.SetDirty(); UpdateOptions(); } - }, 2)); + })); }; const auto uninstall = [this](){ App::Push(std::make_shared(m_entry.image.image, "Uninstalling "_i18n, m_entry.title, [this](auto pbox){ return UninstallApp(pbox, m_entry); - }, [this](bool success){ - if (success) { + }, [this](Result rc){ + App::PushErrorBox(rc, "Failed to, TODO: add message here"_i18n); + + if (R_SUCCEEDED(rc)) { App::Notify("Removed "_i18n + m_entry.title); m_entry.status = EntryStatus::Get; m_menu.SetDirty(); UpdateOptions(); } - }, 2)); + })); }; const Option install_option{"Install"_i18n, install}; diff --git a/sphaira/source/ui/menus/filebrowser.cpp b/sphaira/source/ui/menus/filebrowser.cpp index e3666bd..9d4d5b4 100644 --- a/sphaira/source/ui/menus/filebrowser.cpp +++ b/sphaira/source/ui/menus/filebrowser.cpp @@ -489,7 +489,7 @@ Menu::Menu(const std::vector& nro_entries) : MenuBase{"FileBrowser"_i1 Scan(m_path); } else { const auto msg = std::string("Failed to rename file: ") + entry.name; - App::Push(std::make_shared(rc, msg.c_str())); + App::PushErrorBox(rc, msg); } } })); @@ -854,15 +854,13 @@ void Menu::InstallForwarder() { if (op_index) { const auto assoc = assoc_list[*op_index]; log_write("pushing it\n"); - App::Push(std::make_shared(0, "Installing Forwarder"_i18n, GetEntry().name, [assoc, this](auto pbox) -> bool { + App::Push(std::make_shared(0, "Installing Forwarder"_i18n, GetEntry().name, [assoc, this](auto pbox) -> Result { log_write("inside callback\n"); NroEntry nro{}; log_write("parsing nro\n"); - if (R_FAILED(nro_parse(assoc.path, nro))) { - log_write("failed nro parse\n"); - return false; - } + R_TRY(nro_parse(assoc.path, nro)); + log_write("got nro data\n"); auto file_name = assoc.use_base_name ? GetEntry().GetName() : GetEntry().GetInternalName(); @@ -883,7 +881,7 @@ void Menu::InstallForwarder() { config.icon = GetRomIcon(m_fs.get(), pbox, file_name, db_indexs, nro); pbox->SetImageDataConst(config.icon); - return R_SUCCEEDED(App::Install(pbox, config)); + return App::Install(pbox, config); })); } else { log_write("pressed B to skip launch...\n"); @@ -899,19 +897,13 @@ void Menu::InstallFiles() { if (op_index && *op_index) { App::PopToMenu(); - App::Push(std::make_shared(0, "Installing "_i18n, "", [this, targets](auto pbox) mutable -> bool { + App::Push(std::make_shared(0, "Installing "_i18n, "", [this, targets](auto pbox) -> Result { for (auto& e : targets) { - const auto rc = yati::InstallFromFile(pbox, &m_fs->m_fs, GetNewPath(e)); - if (rc == yati::Result_Cancelled) { - break; - } else if (R_FAILED(rc)) { - return false; - } else { - App::Notify("Installed " + e.GetName()); - } + R_TRY(yati::InstallFromFile(pbox, &m_fs->m_fs, GetNewPath(e))); + App::Notify("Installed " + e.GetName()); } - return true; + R_SUCCEED(); })); } })); @@ -925,7 +917,7 @@ void Menu::UnzipFiles(fs::FsPath dir_path) { dir_path = m_path; } - App::Push(std::make_shared(0, "Extracting "_i18n, "", [this, dir_path, targets](auto pbox) mutable -> bool { + App::Push(std::make_shared(0, "Extracting "_i18n, "", [this, dir_path, targets](auto pbox) -> Result { constexpr auto chunk_size = 1024 * 512; // 512KiB auto& fs = *m_fs.get(); @@ -934,28 +926,25 @@ void Menu::UnzipFiles(fs::FsPath dir_path) { const auto zip_out = GetNewPath(e); auto zfile = unzOpen64(zip_out); - if (!zfile) { - log_write("failed to open zip: %s\n", zip_out.s); - return false; - } + R_UNLESS(zfile, 0x1); ON_SCOPE_EXIT(unzClose(zfile)); unz_global_info64 pglobal_info; if (UNZ_OK != unzGetGlobalInfo64(zfile, &pglobal_info)) { - return false; + R_THROW(0x1); } for (int i = 0; i < pglobal_info.number_entry; i++) { if (i > 0) { if (UNZ_OK != unzGoToNextFile(zfile)) { log_write("failed to unzGoToNextFile\n"); - return false; + R_THROW(0x1); } } if (UNZ_OK != unzOpenCurrentFile(zfile)) { log_write("failed to open current file\n"); - return false; + R_THROW(0x1); } ON_SCOPE_EXIT(unzCloseCurrentFile(zfile)); @@ -963,7 +952,7 @@ void Menu::UnzipFiles(fs::FsPath dir_path) { char name[512]; if (UNZ_OK != unzGetCurrentFileInfo64(zfile, &info, name, sizeof(name), 0, 0, 0, 0)) { log_write("failed to get current info\n"); - return false; + R_THROW(0x1); } const auto file_path = fs::AppendPath(dir_path, name); @@ -975,38 +964,27 @@ void Menu::UnzipFiles(fs::FsPath dir_path) { Result rc; if (R_FAILED(rc = fs.CreateFile(file_path, info.uncompressed_size, 0)) && rc != FsError_PathAlreadyExists) { log_write("failed to create file: %s 0x%04X\n", file_path.s, rc); - return false; + R_THROW(rc); } FsFile f; - if (R_FAILED(rc = fs.OpenFile(file_path, FsOpenMode_Write, &f))) { - log_write("failed to open file: %s 0x%04X\n", file_path.s, rc); - return false; - } + R_TRY(fs.OpenFile(file_path, FsOpenMode_Write, &f)); ON_SCOPE_EXIT(fsFileClose(&f)); - if (R_FAILED(rc = fsFileSetSize(&f, info.uncompressed_size))) { - log_write("failed to set file size: %s 0x%04X\n", file_path.s, rc); - return false; - } + R_TRY(fsFileSetSize(&f, info.uncompressed_size)); std::vector buf(chunk_size); s64 offset{}; while (offset < info.uncompressed_size) { - if (pbox->ShouldExit()) { - return false; - } + R_TRY(pbox->ShouldExitResult()); const auto bytes_read = unzReadCurrentFile(zfile, buf.data(), buf.size()); if (bytes_read <= 0) { log_write("failed to read zip file: %s\n", name); - return false; + R_THROW(0x1); } - if (R_FAILED(rc = fsFileWrite(&f, offset, buf.data(), bytes_read, FsWriteOption_None))) { - log_write("failed to write file: %s 0x%04X\n", file_path.s, rc); - return false; - } + R_TRY(fsFileWrite(&f, offset, buf.data(), bytes_read, FsWriteOption_None)); pbox->UpdateTransfer(offset, info.uncompressed_size); offset += bytes_read; @@ -1014,13 +992,14 @@ void Menu::UnzipFiles(fs::FsPath dir_path) { } } - return true; - }, [this](bool success){ - if (success) { + R_SUCCEED(); + }, [this](Result rc){ + App::PushErrorBox(rc, "Failed to, TODO: add message here"_i18n); + + if (R_SUCCEEDED(rc)) { App::Notify("Extract success!"); - } else { - App::Notify("Extract failed!"); } + Scan(m_path); log_write("did extract\n"); })); @@ -1062,7 +1041,7 @@ void Menu::ZipFiles(fs::FsPath zip_out) { } } - App::Push(std::make_shared(0, "Compressing "_i18n, "", [this, zip_out, targets](auto pbox) mutable -> bool { + App::Push(std::make_shared(0, "Compressing "_i18n, "", [this, zip_out, targets](auto pbox) -> Result { constexpr auto chunk_size = 1024 * 512; // 512KiB auto& fs = *m_fs.get(); @@ -1079,13 +1058,10 @@ void Menu::ZipFiles(fs::FsPath zip_out) { zip_info.tmz_date.tm_year = tm->tm_year; auto zfile = zipOpen(zip_out, APPEND_STATUS_CREATE); - if (!zfile) { - log_write("failed to open zip: %s\n", zip_out.s); - return false; - } + R_UNLESS(zfile, 0x1); ON_SCOPE_EXIT(zipClose(zfile, "sphaira v" APP_VERSION_HASH)); - const auto zip_add = [&](const fs::FsPath& file_path){ + const auto zip_add = [&](const fs::FsPath& file_path) -> Result { // the file name needs to be relative to the current directory. const char* file_name_in_zip = file_path.s + std::strlen(m_path); @@ -1100,56 +1076,42 @@ void Menu::ZipFiles(fs::FsPath zip_out) { const auto raw = ext && IsExtension(ext + 1, COMPRESSED_EXTENSIONS); if (ZIP_OK != zipOpenNewFileInZip2(zfile, file_name_in_zip, &zip_info, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION, raw)) { - return false; + R_THROW(0x1); } ON_SCOPE_EXIT(zipCloseFileInZip(zfile)); FsFile f; - Result rc; - if (R_FAILED(rc = fs.OpenFile(file_path, FsOpenMode_Read, &f))) { - log_write("failed to open file: %s 0x%04X\n", file_path.s, rc); - return false; - } + R_TRY(fs.OpenFile(file_path, FsOpenMode_Read, &f)); ON_SCOPE_EXIT(fsFileClose(&f)); s64 file_size; - if (R_FAILED(rc = fsFileGetSize(&f, &file_size))) { - log_write("failed to get file size: %s 0x%04X\n", file_path.s, rc); - return false; - } + R_TRY(fsFileGetSize(&f, &file_size)); std::vector buf(chunk_size); s64 offset{}; while (offset < file_size) { - if (pbox->ShouldExit()) { - return false; - } + R_TRY(pbox->ShouldExitResult()); u64 bytes_read; - if (R_FAILED(rc = fsFileRead(&f, offset, buf.data(), buf.size(), FsReadOption_None, &bytes_read))) { - log_write("failed to write file: %s 0x%04X\n", file_path.s, rc); - return false; - } + R_TRY(fsFileRead(&f, offset, buf.data(), buf.size(), FsReadOption_None, &bytes_read)); if (ZIP_OK != zipWriteInFileInZip(zfile, buf.data(), bytes_read)) { log_write("failed to write zip file: %s\n", file_path.s); - return false; + R_THROW(0x1); } pbox->UpdateTransfer(offset, file_size); offset += bytes_read; } - return true; + R_SUCCEED(); }; for (auto& e : targets) { pbox->SetTitle(e.GetName()); if (e.IsFile()) { const auto file_path = GetNewPath(e); - if (!zip_add(file_path)) { - return false; - } + R_TRY(zip_add(file_path)); } else { FsDirCollections collections; get_collections(GetNewPath(e), e.name, collections); @@ -1157,21 +1119,20 @@ void Menu::ZipFiles(fs::FsPath zip_out) { for (const auto& collection : collections) { for (const auto& file : collection.files) { const auto file_path = fs::AppendPath(collection.path, file.name); - if (!zip_add(file_path)) { - return false; - } + R_TRY(zip_add(file_path)); } } } } - return true; - }, [this](bool success){ - if (success) { + R_SUCCEED(); + }, [this](Result rc){ + App::PushErrorBox(rc, "Failed to, TODO: add message here"_i18n); + + if (R_SUCCEEDED(rc)) { App::Notify("Compress success!"); - } else { - App::Notify("Compress failed!"); } + Scan(m_path); log_write("did compress\n"); })); @@ -1198,7 +1159,7 @@ void Menu::UploadFiles() { } const auto loc = network_locations[*op_index]; - App::Push(std::make_shared(0, "Uploading"_i18n, "", [this, loc](auto pbox) -> bool { + App::Push(std::make_shared(0, "Uploading"_i18n, "", [this, loc](auto pbox) -> Result { auto targets = GetSelectedEntries(); const auto file_add = [&](s64 file_size, const fs::FsPath& file_path, const char* name) -> Result { @@ -1250,9 +1211,7 @@ void Menu::UploadFiles() { for (auto& e : targets) { if (e.IsFile()) { const auto file_path = GetNewPath(e); - if (R_FAILED(file_add(e.file_size, file_path, e.GetName().c_str()))) { - return false; - } + R_TRY(file_add(e.file_size, file_path, e.GetName().c_str())); } else { FsDirCollections collections; get_collections(GetNewPath(e), e.name, collections, true); @@ -1260,24 +1219,20 @@ void Menu::UploadFiles() { for (const auto& collection : collections) { for (const auto& file : collection.files) { const auto file_path = fs::AppendPath(collection.path, file.name); - if (R_FAILED(file_add(file.file_size, file_path, file.name))) { - return false; - } + R_TRY(file_add(file.file_size, file_path, file.name)); } } } } - return true; - }, [this](bool success){ + R_SUCCEED(); + }, [this](Result rc){ + App::PushErrorBox(rc, "Failed to, TODO: add message here"_i18n); ResetSelection(); - if (success) { + if (R_SUCCEEDED(rc)) { App::Notify("Upload successfull!"); log_write("Upload successfull!!!\n"); - } else { - App::Notify("Upload failed!"); - log_write("Upload failed!!!\n"); } })); } @@ -1643,80 +1598,70 @@ void Menu::OnDeleteCallback() { Scan(m_path); log_write("did delete\n"); } else { - App::Push(std::make_shared(0, "Deleting"_i18n, "", [this](auto pbox){ + App::Push(std::make_shared(0, "Deleting"_i18n, "", [this](auto pbox) -> Result { FsDirCollections collections; // build list of dirs / files for (const auto&p : m_selected_files) { pbox->Yield(); - if (pbox->ShouldExit()) { - return false; - } + R_TRY(pbox->ShouldExitResult()); const auto full_path = GetNewPath(m_selected_path, p.name); if (p.IsDir()) { pbox->NewTransfer("Scanning "_i18n + full_path); - if (R_FAILED(get_collections(full_path, p.name, collections))) { - log_write("failed to get dir collection: %s\n", full_path.s); - return false; - } + R_TRY(get_collections(full_path, p.name, collections)); } } // delete everything in collections, reversed for (const auto& c : std::views::reverse(collections)) { - const auto delete_func = [&](auto& array) { + const auto delete_func = [&](auto& array) -> Result { for (const auto& p : array) { pbox->Yield(); - if (pbox->ShouldExit()) { - return false; - } + R_TRY(pbox->ShouldExitResult()); const auto full_path = GetNewPath(c.path, p.name); pbox->NewTransfer("Deleting "_i18n + full_path); if (p.type == FsDirEntryType_Dir) { log_write("deleting dir: %s\n", full_path.s); - m_fs->DeleteDirectory(full_path); + R_TRY(m_fs->DeleteDirectory(full_path)); } else { log_write("deleting file: %s\n", full_path.s); - m_fs->DeleteFile(full_path); + R_TRY(m_fs->DeleteFile(full_path)); } } - return true; + + R_SUCCEED(); }; - if (!delete_func(c.files)) { - return false; - } - if (!delete_func(c.dirs)) { - return false; - } + R_TRY(delete_func(c.files)); + R_TRY(delete_func(c.dirs)); } for (const auto& p : m_selected_files) { pbox->Yield(); - if (pbox->ShouldExit()) { - return false; - } + R_TRY(pbox->ShouldExitResult()); const auto full_path = GetNewPath(m_selected_path, p.name); pbox->NewTransfer("Deleting "_i18n + full_path); if (p.IsDir()) { log_write("deleting dir: %s\n", full_path.s); - m_fs->DeleteDirectory(full_path); + R_TRY(m_fs->DeleteDirectory(full_path)); } else { log_write("deleting file: %s\n", full_path.s); - m_fs->DeleteFile(full_path); + R_TRY(m_fs->DeleteFile(full_path)); } } - return true; - }, [this](bool success){ + R_SUCCEED(); + }, [this](Result rc){ + App::PushErrorBox(rc, "Failed to, TODO: add message here"_i18n); + ResetSelection(); Scan(m_path); log_write("did delete\n"); - }, 2)); + })); } } @@ -1736,14 +1681,12 @@ void Menu::OnPasteCallback() { Scan(m_path); log_write("did paste\n"); } else { - App::Push(std::make_shared(0, "Pasting"_i18n, "", [this](auto pbox){ + App::Push(std::make_shared(0, "Pasting"_i18n, "", [this](auto pbox) -> Result { if (m_selected_type == SelectedType::Cut) { for (const auto& p : m_selected_files) { pbox->Yield(); - if (pbox->ShouldExit()) { - return false; - } + R_TRY(pbox->ShouldExitResult()); const auto src_path = GetNewPath(m_selected_path, p.name); const auto dst_path = GetNewPath(m_path, p.name); @@ -1762,25 +1705,18 @@ void Menu::OnPasteCallback() { // build list of dirs / files for (const auto&p : m_selected_files) { pbox->Yield(); - if (pbox->ShouldExit()) { - return false; - } + R_TRY(pbox->ShouldExitResult()); const auto full_path = GetNewPath(m_selected_path, p.name); if (p.IsDir()) { pbox->NewTransfer("Scanning "_i18n + full_path); - if (R_FAILED(get_collections(full_path, p.name, collections))) { - log_write("failed to get dir collection: %s\n", full_path.s); - return false; - } + R_TRY(get_collections(full_path, p.name, collections)); } } for (const auto& p : m_selected_files) { pbox->Yield(); - if (pbox->ShouldExit()) { - return false; - } + R_TRY(pbox->ShouldExitResult()); const auto src_path = GetNewPath(m_selected_path, p.name); const auto dst_path = GetNewPath(p); @@ -1790,7 +1726,7 @@ void Menu::OnPasteCallback() { m_fs->CreateDirectory(dst_path); } else { pbox->NewTransfer("Copying "_i18n + src_path); - R_TRY_RESULT(pbox->CopyFile(src_path, dst_path), false); + R_TRY(pbox->CopyFile(src_path, dst_path)); } } @@ -1800,9 +1736,7 @@ void Menu::OnPasteCallback() { for (const auto& p : c.dirs) { pbox->Yield(); - if (pbox->ShouldExit()) { - return false; - } + R_TRY(pbox->ShouldExitResult()); const auto src_path = GetNewPath(c.path, p.name); const auto dst_path = GetNewPath(base_dst_path, p.name); @@ -1814,26 +1748,26 @@ void Menu::OnPasteCallback() { for (const auto& p : c.files) { pbox->Yield(); - if (pbox->ShouldExit()) { - return false; - } + R_TRY(pbox->ShouldExitResult()); const auto src_path = GetNewPath(c.path, p.name); const auto dst_path = GetNewPath(base_dst_path, p.name); pbox->NewTransfer("Copying "_i18n + src_path); log_write("copying: %s to %s\n", src_path.s, dst_path.s); - R_TRY_RESULT(pbox->CopyFile(src_path, dst_path), false); + R_TRY(pbox->CopyFile(src_path, dst_path)); } } } - return true; - }, [this](bool success){ + R_SUCCEED(); + }, [this](Result rc){ + App::PushErrorBox(rc, "Failed to, TODO: add message here"_i18n); + ResetSelection(); Scan(m_path); log_write("did paste\n"); - }, 2)); + })); } } diff --git a/sphaira/source/ui/menus/ftp_menu.cpp b/sphaira/source/ui/menus/ftp_menu.cpp index 571946a..724446d 100644 --- a/sphaira/source/ui/menus/ftp_menu.cpp +++ b/sphaira/source/ui/menus/ftp_menu.cpp @@ -202,25 +202,25 @@ void Menu::Update(Controller* controller, TouchInfo* touch) { log_write("set to progress\n"); m_state = State::Progress; log_write("got connection\n"); - App::Push(std::make_shared(0, "Installing "_i18n, "", [this](auto pbox) mutable -> bool { + App::Push(std::make_shared(0, "Installing "_i18n, "", [this](auto pbox) -> Result { log_write("inside progress box\n"); const auto rc = yati::InstallFromSource(pbox, m_source, m_source->m_path); if (R_FAILED(rc)) { m_source->Disable(); - return false; + R_THROW(rc); } - log_write("progress box is done\n"); - return true; - }, [this](bool result){ + R_SUCCEED(); + }, [this](Result rc){ + App::PushErrorBox(rc, "Ftp install failed!"_i18n); + mutexLock(&m_mutex); ON_SCOPE_EXIT(mutexUnlock(&m_mutex)); - if (result) { + if (R_SUCCEEDED(rc)) { App::Notify("Ftp install success!"_i18n); m_state = State::Done; } else { - App::Notify("Ftp install failed!"_i18n); m_state = State::Failed; } })); diff --git a/sphaira/source/ui/menus/game_menu.cpp b/sphaira/source/ui/menus/game_menu.cpp index 7466b46..7f95073 100644 --- a/sphaira/source/ui/menus/game_menu.cpp +++ b/sphaira/source/ui/menus/game_menu.cpp @@ -1361,7 +1361,7 @@ void Menu::OnLayoutChange() { } void Menu::DeleteGames() { - App::Push(std::make_shared(0, "Deleting"_i18n, "", [this](auto pbox) -> bool { + App::Push(std::make_shared(0, "Deleting"_i18n, "", [this](auto pbox) -> Result { auto targets = GetSelectedEntries(); for (s64 i = 0; i < std::size(targets); i++) { @@ -1370,18 +1370,18 @@ void Menu::DeleteGames() { LoadControlEntry(e); pbox->SetTitle(e.GetName()); pbox->UpdateTransfer(i + 1, std::size(targets)); - nsDeleteApplicationCompletely(e.app_id); + R_TRY(nsDeleteApplicationCompletely(e.app_id)); } - return true; - }, [this](bool success){ + R_SUCCEED(); + }, [this](Result rc){ + App::PushErrorBox(rc, "Delete failed"_i18n); + ClearSelection(); m_dirty = true; - if (success) { + if (R_SUCCEEDED(rc)) { App::Notify("Delete successfull!"); - } else { - App::Notify("Delete failed!"); } })); } @@ -1405,7 +1405,7 @@ void Menu::DumpGames(u32 flags) { } const auto index = *op_index; - App::Push(std::make_shared(0, "Dumping"_i18n, "", [this, network_locations, index, flags](auto pbox) -> bool { + App::Push(std::make_shared(0, "Dumping"_i18n, "", [this, network_locations, index, flags](auto pbox) -> Result { auto targets = GetSelectedEntries(); std::vector nsp_entries; @@ -1416,25 +1416,23 @@ void Menu::DumpGames(u32 flags) { const auto index2 = index - network_locations.size(); if (!network_locations.empty() && index < network_locations.size()) { - return R_SUCCEEDED(DumpNspToNetwork(pbox, network_locations[index], nsp_entries)); + R_TRY(DumpNspToNetwork(pbox, network_locations[index], nsp_entries)); } else if (index2 == DumpLocationType_SdCard) { - return R_SUCCEEDED(DumpNspToFile(pbox, nsp_entries)); + R_TRY(DumpNspToFile(pbox, nsp_entries)); } else if (index2 == DumpLocationType_UsbS2S) { - return R_SUCCEEDED(DumpNspToUsbS2S(pbox, nsp_entries)); + R_TRY(DumpNspToUsbS2S(pbox, nsp_entries)); } else if (index2 == DumpLocationType_DevNull) { - return R_SUCCEEDED(DumpNspToDevNull(pbox, nsp_entries)); + R_TRY(DumpNspToDevNull(pbox, nsp_entries)); } - return false; - }, [this](bool success){ + R_SUCCEED(); + }, [this](Result rc){ + App::PushErrorBox(rc, "Dump failed!"_i18n); ClearSelection(); - if (success) { + if (R_SUCCEEDED(rc)) { App::Notify("Dump successfull!"); log_write("dump successfull!!!\n"); - } else { - App::Notify("Dump failed!"); - log_write("dump failed!!!\n"); } })); } diff --git a/sphaira/source/ui/menus/gc_menu.cpp b/sphaira/source/ui/menus/gc_menu.cpp index f54cb2f..7f24852 100644 --- a/sphaira/source/ui/menus/gc_menu.cpp +++ b/sphaira/source/ui/menus/gc_menu.cpp @@ -875,14 +875,14 @@ Result Menu::GcMount() { } if (m_option_index == 0) { - App::Push(std::make_shared(m_icon, "Installing "_i18n, m_entries[m_entry_index].lang_entry.name, [this](auto pbox) mutable -> bool { + App::Push(std::make_shared(m_icon, "Installing "_i18n, m_entries[m_entry_index].lang_entry.name, [this](auto pbox) -> Result { auto source = std::make_shared(m_entries[m_entry_index], m_fs.get()); - return R_SUCCEEDED(yati::InstallFromCollections(pbox, source, source->m_collections, source->m_config)); - }, [this](bool result){ - if (result) { + return yati::InstallFromCollections(pbox, source, source->m_collections, source->m_config); + }, [this](Result rc){ + App::PushErrorBox(rc, "Gc install failed"_i18n); + + if (R_SUCCEEDED(rc)) { App::Notify("Gc install success!"_i18n); - } else { - App::Notify("Gc install failed!"_i18n); } })); } else { @@ -1197,15 +1197,12 @@ void Menu::DumpGames(u32 flags) { } const auto index = *op_index; - App::Push(std::make_shared(0, "Dumping"_i18n, "", [this, network_locations, index, flags](auto pbox) -> bool { + App::Push(std::make_shared(0, "Dumping"_i18n, "", [this, network_locations, index, flags](auto pbox) -> Result { XciEntry entry{}; entry.menu = this; entry.application_name = m_entries[m_entry_index].lang_entry.name; - if (R_FAILED(GcMountStorage())) { - log_write("failed to mount storage\n"); - return false; - } + R_TRY(GcMountStorage()); std::vector paths; if (flags & DumpFileFlag_XCI) { @@ -1221,9 +1218,7 @@ void Menu::DumpGames(u32 flags) { if (flags & DumpFileFlag_Set) { entry.id_set.resize(0xC); - if (R_FAILED(fsDeviceOperatorGetGameCardIdSet(&m_dev_op, entry.id_set.data(), entry.id_set.size(), entry.id_set.size()))) { - return false; - } + R_TRY(fsDeviceOperatorGetGameCardIdSet(&m_dev_op, entry.id_set.data(), entry.id_set.size(), entry.id_set.size())); paths.emplace_back(BuildFullDumpPath(DumpFileType_Set, m_entries)); } @@ -1235,12 +1230,7 @@ void Menu::DumpGames(u32 flags) { if (flags & DumpFileFlag_Cert) { s64 size; entry.cert.resize(0x200); - if (R_FAILED(fsDeviceOperatorGetGameCardDeviceCertificate(&m_dev_op, &m_handle, entry.cert.data(), entry.cert.size(), &size, entry.cert.size()))) { - return false; - } - if (size != entry.cert.size()) { - return false; - } + R_TRY(fsDeviceOperatorGetGameCardDeviceCertificate(&m_dev_op, &m_handle, entry.cert.data(), entry.cert.size(), &size, entry.cert.size())); paths.emplace_back(BuildFullDumpPath(DumpFileType_Cert, m_entries)); } @@ -1252,23 +1242,22 @@ void Menu::DumpGames(u32 flags) { const auto index2 = index - network_locations.size(); if (!network_locations.empty() && index < network_locations.size()) { - return R_SUCCEEDED(DumpNspToNetwork(pbox, network_locations[index], paths, entry)); + R_TRY(DumpNspToNetwork(pbox, network_locations[index], paths, entry)); } else if (index2 == DumpLocationType_SdCard) { - return R_SUCCEEDED(DumpNspToFile(pbox, paths, entry)); + R_TRY(DumpNspToFile(pbox, paths, entry)); } else if (index2 == DumpLocationType_UsbS2S) { - return R_SUCCEEDED(DumpNspToUsbS2S(pbox, paths, entry)); + R_TRY(DumpNspToUsbS2S(pbox, paths, entry)); } else if (index2 == DumpLocationType_DevNull) { - return R_SUCCEEDED(DumpNspToDevNull(pbox, paths, entry)); + R_TRY(DumpNspToDevNull(pbox, paths, entry)); } - return false; - }, [this](bool success){ - if (success) { + R_SUCCEED(); + }, [this](Result rc){ + App::PushErrorBox(rc, "Dump failed!"_i18n); + + if (R_SUCCEEDED(rc)) { App::Notify("Dump successfull!"); log_write("dump successfull!!!\n"); - } else { - App::Notify("Dump failed!"); - log_write("dump failed!!!\n"); } GcUmountStorage(); diff --git a/sphaira/source/ui/menus/ghdl.cpp b/sphaira/source/ui/menus/ghdl.cpp index 983b766..134738e 100644 --- a/sphaira/source/ui/menus/ghdl.cpp +++ b/sphaira/source/ui/menus/ghdl.cpp @@ -81,32 +81,28 @@ void from_json(const fs::FsPath& path, GhApiEntry& e) { ); } -auto DownloadApp(ProgressBox* pbox, const GhApiAsset& gh_asset, const AssetEntry* entry) -> bool { +auto DownloadApp(ProgressBox* pbox, const GhApiAsset& gh_asset, const AssetEntry* entry) -> Result { static const fs::FsPath temp_file{"/switch/sphaira/cache/github/ghdl.temp"}; constexpr auto chunk_size = 1024 * 512; // 512KiB fs::FsNativeSd fs; - R_TRY_RESULT(fs.GetFsOpenResult(), false); + R_TRY(fs.GetFsOpenResult()); ON_SCOPE_EXIT(fs.DeleteFile(temp_file)); - if (gh_asset.browser_download_url.empty()) { - log_write("failed to find asset\n"); - return false; - } + R_UNLESS(!gh_asset.browser_download_url.empty(), 0x1); // 2. download the asset if (!pbox->ShouldExit()) { pbox->NewTransfer("Downloading "_i18n + gh_asset.name); log_write("starting download: %s\n", gh_asset.browser_download_url.c_str()); - if (!curl::Api().ToFile( + const auto result = curl::Api().ToFile( curl::Url{gh_asset.browser_download_url}, curl::Path{temp_file}, curl::OnProgress{pbox->OnDownloadProgressCallback()} - ).success){ - log_write("error with download\n"); - return false; - } + ); + + R_UNLESS(result.success, 0x1); } fs::FsPath root_path{"/"}; @@ -118,28 +114,25 @@ auto DownloadApp(ProgressBox* pbox, const GhApiAsset& gh_asset, const AssetEntry if (gh_asset.content_type.find("zip") != gh_asset.content_type.npos) { log_write("found zip\n"); auto zfile = unzOpen64(temp_file); - if (!zfile) { - log_write("failed to open zip: %s\n", temp_file.s); - return false; - } + R_UNLESS(zfile, 0x1); ON_SCOPE_EXIT(unzClose(zfile)); unz_global_info64 pglobal_info; if (UNZ_OK != unzGetGlobalInfo64(zfile, &pglobal_info)) { - return false; + R_THROW(0x1); } for (int i = 0; i < pglobal_info.number_entry; i++) { if (i > 0) { if (UNZ_OK != unzGoToNextFile(zfile)) { log_write("failed to unzGoToNextFile\n"); - return false; + R_THROW(0x1); } } if (UNZ_OK != unzOpenCurrentFile(zfile)) { log_write("failed to open current file\n"); - return false; + R_THROW(0x1); } ON_SCOPE_EXIT(unzCloseCurrentFile(zfile)); @@ -147,7 +140,7 @@ auto DownloadApp(ProgressBox* pbox, const GhApiAsset& gh_asset, const AssetEntry fs::FsPath file_path; if (UNZ_OK != unzGetCurrentFileInfo64(zfile, &info, file_path, sizeof(file_path), 0, 0, 0, 0)) { log_write("failed to get current info\n"); - return false; + R_THROW(0x1); } file_path = fs::AppendPath(root_path, file_path); @@ -156,44 +149,37 @@ auto DownloadApp(ProgressBox* pbox, const GhApiAsset& gh_asset, const AssetEntry if (file_path[strlen(file_path) -1] == '/') { if (R_FAILED(rc = fs.CreateDirectoryRecursively(file_path)) && rc != FsError_PathAlreadyExists) { log_write("failed to create folder: %s 0x%04X\n", file_path.s, rc); - return false; + R_THROW(rc); } } else { if (R_FAILED(rc = fs.CreateDirectoryRecursivelyWithPath(file_path)) && rc != FsError_PathAlreadyExists) { log_write("failed to create folder: %s 0x%04X\n", file_path.s, rc); - return false; + R_THROW(rc); } if (R_FAILED(rc = fs.CreateFile(file_path, info.uncompressed_size, 0)) && rc != FsError_PathAlreadyExists) { log_write("failed to create file: %s 0x%04X\n", file_path.s, rc); - return false; + R_THROW(rc); } FsFile f; - if (R_FAILED(rc = fs.OpenFile(file_path, FsOpenMode_Write, &f))) { - log_write("failed to open file: %s 0x%04X\n", file_path.s, rc); - return false; - } + R_TRY(fs.OpenFile(file_path, FsOpenMode_Write, &f)); ON_SCOPE_EXIT(fsFileClose(&f)); - if (R_FAILED(rc = fsFileSetSize(&f, info.uncompressed_size))) { - log_write("failed to set file size: %s 0x%04X\n", file_path.s, rc); - return false; - } + R_TRY(fsFileSetSize(&f, info.uncompressed_size)); std::vector buf(chunk_size); s64 offset{}; while (offset < info.uncompressed_size) { + R_TRY(pbox->ShouldExitResult()); + const auto bytes_read = unzReadCurrentFile(zfile, buf.data(), buf.size()); if (bytes_read <= 0) { log_write("failed to read zip file: %s\n", file_path.s); - return false; + R_THROW(0x1); } - if (R_FAILED(rc = fsFileWrite(&f, offset, buf.data(), bytes_read, FsWriteOption_None))) { - log_write("failed to write file: %s 0x%04X\n", file_path.s, rc); - return false; - } + R_TRY(fsFileWrite(&f, offset, buf.data(), bytes_read, FsWriteOption_None)); pbox->UpdateTransfer(offset, info.uncompressed_size); offset += bytes_read; @@ -203,16 +189,14 @@ auto DownloadApp(ProgressBox* pbox, const GhApiAsset& gh_asset, const AssetEntry } else { fs.CreateDirectoryRecursivelyWithPath(root_path); fs.DeleteFile(root_path); - if (R_FAILED(fs.RenameFile(temp_file, root_path))) { - log_write("failed to rename file: %s -> %s\n", temp_file.s, root_path.s); - } + R_TRY(fs.RenameFile(temp_file, root_path)); } log_write("success\n"); - return true; + R_SUCCEED(); } -auto DownloadAssetJson(ProgressBox* pbox, const std::string& url, GhApiEntry& out) -> bool { +auto DownloadAssetJson(ProgressBox* pbox, const std::string& url, GhApiEntry& out) -> Result { // 1. download the json if (!pbox->ShouldExit()) { pbox->NewTransfer("Downloading json"_i18n); @@ -230,15 +214,12 @@ auto DownloadAssetJson(ProgressBox* pbox, const std::string& url, GhApiEntry& ou } ); - if (!result.success) { - log_write("json empty\n"); - return false; - } - + R_UNLESS(result.success, 0x1); from_json(result.path, out); } - return !out.assets.empty(); + R_UNLESS(!out.assets.empty(), 0x1); + R_SUCCEED(); } } // namespace @@ -256,10 +237,12 @@ Menu::Menu() : MenuBase{"GitHub"_i18n} { static GhApiEntry gh_entry; gh_entry = {}; - App::Push(std::make_shared(0, "Downloading "_i18n, GetEntry().repo, [this](auto pbox){ + App::Push(std::make_shared(0, "Downloading "_i18n, GetEntry().repo, [this](auto pbox) -> Result { return DownloadAssetJson(pbox, GenerateApiUrl(GetEntry()), gh_entry); - }, [this](bool success){ - if (success) { + }, [this](Result rc){ + App::PushErrorBox(rc, "Failed to download json"_i18n); + + if (R_SUCCEEDED(rc)) { const auto& assets = GetEntry().assets; PopupList::Items asset_items; std::vector asset_ptr; @@ -304,10 +287,12 @@ Menu::Menu() : MenuBase{"GitHub"_i18n} { } const auto func = [this, &asset_entry, ptr](){ - App::Push(std::make_shared(0, "Downloading "_i18n, GetEntry().repo, [this, &asset_entry, ptr](auto pbox){ + App::Push(std::make_shared(0, "Downloading "_i18n, GetEntry().repo, [this, &asset_entry, ptr](auto pbox) -> Result { return DownloadApp(pbox, asset_entry, ptr); - }, [this, ptr](bool success){ - if (success) { + }, [this, ptr](Result rc){ + App::PushErrorBox(rc, "Failed to download app!"_i18n); + + if (R_SUCCEEDED(rc)) { App::Notify("Downloaded "_i18n + GetEntry().repo); auto post_install_message = GetEntry().post_install_message; if (ptr && !ptr->post_install_message.empty()) { @@ -318,7 +303,7 @@ Menu::Menu() : MenuBase{"GitHub"_i18n} { App::Push(std::make_shared(post_install_message, "OK"_i18n)); } } - }, 2)); + })); }; if (!pre_install_message.empty()) { @@ -335,7 +320,7 @@ Menu::Menu() : MenuBase{"GitHub"_i18n} { } })); } - }, 2)); + })); }}), std::make_pair(Button::B, Action{"Back"_i18n, [this](){ diff --git a/sphaira/source/ui/menus/main_menu.cpp b/sphaira/source/ui/menus/main_menu.cpp index 5d97d1c..6910155 100644 --- a/sphaira/source/ui/menus/main_menu.cpp +++ b/sphaira/source/ui/menus/main_menu.cpp @@ -47,26 +47,25 @@ const MiscMenuEntry MISC_MENU_ENTRIES[] = { { .name = "IRS", .title = "IRS (Infrared Joycon Camera)", .func = MiscMenuFuncGenerator, .flag = MiscMenuFlag_Shortcut }, }; -auto InstallUpdate(ProgressBox* pbox, const std::string url, const std::string version) -> bool { +auto InstallUpdate(ProgressBox* pbox, const std::string url, const std::string version) -> Result { static fs::FsPath zip_out{"/switch/sphaira/cache/update.zip"}; constexpr auto chunk_size = 1024 * 512; // 512KiB fs::FsNativeSd fs; - R_TRY_RESULT(fs.GetFsOpenResult(), false); + R_TRY(fs.GetFsOpenResult()); // 1. download the zip if (!pbox->ShouldExit()) { pbox->NewTransfer("Downloading "_i18n + version); log_write("starting download: %s\n", url.c_str()); - if (!curl::Api().ToFile( + const auto result = curl::Api().ToFile( curl::Url{url}, curl::Path{zip_out}, curl::OnProgress{pbox->OnDownloadProgressCallback()} - ).success) { - log_write("error with download\n"); - return false; - } + ); + + R_UNLESS(result.success, 0x1); } ON_SCOPE_EXIT(fs.DeleteFile(zip_out)); @@ -74,28 +73,25 @@ auto InstallUpdate(ProgressBox* pbox, const std::string url, const std::string v // 2. extract the zip if (!pbox->ShouldExit()) { auto zfile = unzOpen64(zip_out); - if (!zfile) { - log_write("failed to open zip: %s\n", zip_out.s); - return false; - } + R_UNLESS(zfile, 0x1); ON_SCOPE_EXIT(unzClose(zfile)); unz_global_info64 pglobal_info; if (UNZ_OK != unzGetGlobalInfo64(zfile, &pglobal_info)) { - return false; + R_THROW(0x1); } for (int i = 0; i < pglobal_info.number_entry; i++) { if (i > 0) { if (UNZ_OK != unzGoToNextFile(zfile)) { log_write("failed to unzGoToNextFile\n"); - return false; + R_THROW(0x1); } } if (UNZ_OK != unzOpenCurrentFile(zfile)) { log_write("failed to open current file\n"); - return false; + R_THROW(0x1); } ON_SCOPE_EXIT(unzCloseCurrentFile(zfile)); @@ -103,7 +99,7 @@ auto InstallUpdate(ProgressBox* pbox, const std::string url, const std::string v fs::FsPath file_path; if (UNZ_OK != unzGetCurrentFileInfo64(zfile, &info, file_path, sizeof(file_path), 0, 0, 0, 0)) { log_write("failed to get current info\n"); - return false; + R_THROW(0x1); } if (file_path[0] != '/') { @@ -118,26 +114,20 @@ auto InstallUpdate(ProgressBox* pbox, const std::string url, const std::string v if (file_path[strlen(file_path) -1] == '/') { if (R_FAILED(rc = fs.CreateDirectoryRecursively(file_path)) && rc != FsError_PathAlreadyExists) { log_write("failed to create folder: %s 0x%04X\n", file_path.s, rc); - return false; + R_THROW(0x1); } } else { Result rc; if (R_FAILED(rc = fs.CreateFile(file_path, info.uncompressed_size, 0)) && rc != FsError_PathAlreadyExists) { log_write("failed to create file: %s 0x%04X\n", file_path.s, rc); - return false; + R_THROW(rc); } FsFile f; - if (R_FAILED(rc = fs.OpenFile(file_path, FsOpenMode_Write, &f))) { - log_write("failed to open file: %s 0x%04X\n", file_path.s, rc); - return false; - } + R_TRY(fs.OpenFile(file_path, FsOpenMode_Write, &f)); ON_SCOPE_EXIT(fsFileClose(&f)); - if (R_FAILED(rc = fsFileSetSize(&f, info.uncompressed_size))) { - log_write("failed to set file size: %s 0x%04X\n", file_path.s, rc); - return false; - } + R_TRY(fsFileSetSize(&f, info.uncompressed_size)); std::vector buf(chunk_size); s64 offset{}; @@ -145,13 +135,10 @@ auto InstallUpdate(ProgressBox* pbox, const std::string url, const std::string v const auto bytes_read = unzReadCurrentFile(zfile, buf.data(), buf.size()); if (bytes_read <= 0) { // log_write("failed to read zip file: %s\n", inzip.c_str()); - return false; + R_THROW(0x1); } - if (R_FAILED(rc = fsFileWrite(&f, offset, buf.data(), bytes_read, FsWriteOption_None))) { - log_write("failed to write file: %s 0x%04X\n", file_path.s, rc); - return false; - } + R_TRY(fsFileWrite(&f, offset, buf.data(), bytes_read, FsWriteOption_None)); pbox->UpdateTransfer(offset, info.uncompressed_size); offset += bytes_read; @@ -161,7 +148,7 @@ auto InstallUpdate(ProgressBox* pbox, const std::string url, const std::string v } log_write("finished update :)\n"); - return true; + R_SUCCEED(); } auto CreateRightSideMenu() -> std::shared_ptr { @@ -293,10 +280,12 @@ MainMenu::MainMenu() { if (m_update_state == UpdateState::Update) { options->Add(std::make_shared("Download update: "_i18n + m_update_version, [this](){ - App::Push(std::make_shared(0, "Downloading "_i18n, "Sphaira v" + m_update_version, [this](auto pbox){ + App::Push(std::make_shared(0, "Downloading "_i18n, "Sphaira v" + m_update_version, [this](auto pbox) -> Result { return InstallUpdate(pbox, m_update_url, m_update_version); - }, [this](bool success){ - if (success) { + }, [this](Result rc){ + App::PushErrorBox(rc, "Failed to download update"_i18n); + + if (R_SUCCEEDED(rc)) { m_update_state = UpdateState::None; App::Notify("Updated to "_i18n + m_update_version); App::Push(std::make_shared( @@ -304,10 +293,8 @@ MainMenu::MainMenu() { App::ExitRestart(); } )); - } else { - App::Push(std::make_shared(MAKERESULT(351, 1), "Failed to download update"_i18n)); } - }, 2)); + })); })); } })); diff --git a/sphaira/source/ui/menus/themezer.cpp b/sphaira/source/ui/menus/themezer.cpp index 9fa0ed6..5d3385c 100644 --- a/sphaira/source/ui/menus/themezer.cpp +++ b/sphaira/source/ui/menus/themezer.cpp @@ -220,12 +220,12 @@ void from_json(const fs::FsPath& path, PackList& e) { ); } -auto InstallTheme(ProgressBox* pbox, const PackListEntry& entry) -> bool { +auto InstallTheme(ProgressBox* pbox, const PackListEntry& entry) -> Result { static const fs::FsPath zip_out{"/switch/sphaira/cache/themezer/temp.zip"}; constexpr auto chunk_size = 1024 * 512; // 512KiB fs::FsNativeSd fs; - R_TRY_RESULT(fs.GetFsOpenResult(), false); + R_TRY(fs.GetFsOpenResult()); DownloadPack download_pack; @@ -243,7 +243,7 @@ auto InstallTheme(ProgressBox* pbox, const PackListEntry& entry) -> bool { if (!result.success || result.data.empty()) { log_write("error with download: %s\n", url.c_str()); - return false; + R_THROW(0x1); } from_json(result.data, download_pack); @@ -254,13 +254,13 @@ auto InstallTheme(ProgressBox* pbox, const PackListEntry& entry) -> bool { pbox->NewTransfer("Downloading "_i18n + entry.details.name); log_write("starting download: %s\n", download_pack.url.c_str()); - if (!curl::Api().ToFile( + const auto result = curl::Api().ToFile( curl::Url{download_pack.url}, curl::Path{zip_out}, - curl::OnProgress{pbox->OnDownloadProgressCallback()}).success) { - log_write("error with download\n"); - return false; - } + curl::OnProgress{pbox->OnDownloadProgressCallback()} + ); + + R_UNLESS(result.success, 0x1); } ON_SCOPE_EXIT(fs.DeleteFile(zip_out)); @@ -273,28 +273,25 @@ auto InstallTheme(ProgressBox* pbox, const PackListEntry& entry) -> bool { // 3. extract the zip if (!pbox->ShouldExit()) { auto zfile = unzOpen64(zip_out); - if (!zfile) { - log_write("failed to open zip: %s\n", zip_out.s); - return false; - } + R_UNLESS(zfile, 0x1); ON_SCOPE_EXIT(unzClose(zfile)); unz_global_info64 pglobal_info; if (UNZ_OK != unzGetGlobalInfo64(zfile, &pglobal_info)) { - return false; + R_THROW(0x1); } for (int i = 0; i < pglobal_info.number_entry; i++) { if (i > 0) { if (UNZ_OK != unzGoToNextFile(zfile)) { log_write("failed to unzGoToNextFile\n"); - return false; + R_THROW(0x1); } } if (UNZ_OK != unzOpenCurrentFile(zfile)) { log_write("failed to open current file\n"); - return false; + R_THROW(0x1); } ON_SCOPE_EXIT(unzCloseCurrentFile(zfile)); @@ -302,7 +299,7 @@ auto InstallTheme(ProgressBox* pbox, const PackListEntry& entry) -> bool { char name[512]; if (UNZ_OK != unzGetCurrentFileInfo64(zfile, &info, name, sizeof(name), 0, 0, 0, 0)) { log_write("failed to get current info\n"); - return false; + R_THROW(0x1); } const auto file_path = fs::AppendPath(dir_path, name); @@ -311,38 +308,27 @@ auto InstallTheme(ProgressBox* pbox, const PackListEntry& entry) -> bool { Result rc; if (R_FAILED(rc = fs.CreateFile(file_path, info.uncompressed_size, 0)) && rc != FsError_PathAlreadyExists) { log_write("failed to create file: %s 0x%04X\n", file_path.s, rc); - return false; + R_THROW(rc); } FsFile f; - if (R_FAILED(rc = fs.OpenFile(file_path, FsOpenMode_Write, &f))) { - log_write("failed to open file: %s 0x%04X\n", file_path.s, rc); - return false; - } + R_TRY(fs.OpenFile(file_path, FsOpenMode_Write, &f)); ON_SCOPE_EXIT(fsFileClose(&f)); - if (R_FAILED(rc = fsFileSetSize(&f, info.uncompressed_size))) { - log_write("failed to set file size: %s 0x%04X\n", file_path.s, rc); - return false; - } + R_TRY(fsFileSetSize(&f, info.uncompressed_size)); std::vector buf(chunk_size); s64 offset{}; while (offset < info.uncompressed_size) { - if (pbox->ShouldExit()) { - return false; - } + R_TRY(pbox->ShouldExitResult()); const auto bytes_read = unzReadCurrentFile(zfile, buf.data(), buf.size()); if (bytes_read <= 0) { // log_write("failed to read zip file: %s\n", inzip.c_str()); - return false; + R_THROW(0x1); } - if (R_FAILED(rc = fsFileWrite(&f, offset, buf.data(), bytes_read, FsWriteOption_None))) { - log_write("failed to write file: %s 0x%04X\n", file_path.s, rc); - return false; - } + R_TRY(fsFileWrite(&f, offset, buf.data(), bytes_read, FsWriteOption_None)); pbox->UpdateTransfer(offset, info.uncompressed_size); offset += bytes_read; @@ -351,7 +337,7 @@ auto InstallTheme(ProgressBox* pbox, const PackListEntry& entry) -> bool { } log_write("finished install :)\n"); - return true; + R_SUCCEED(); } } // namespace @@ -386,13 +372,15 @@ Menu::Menu() : MenuBase{"Themezer"_i18n} { const auto& entry = page.m_packList[m_index]; const auto url = apiBuildUrlDownloadPack(entry); - App::Push(std::make_shared(entry.themes[0].preview.lazy_image.image, "Downloading "_i18n, entry.details.name, [this, &entry](auto pbox){ + App::Push(std::make_shared(entry.themes[0].preview.lazy_image.image, "Downloading "_i18n, entry.details.name, [this, &entry](auto pbox) -> Result { return InstallTheme(pbox, entry); - }, [this, &entry](bool success){ - if (success) { + }, [this, &entry](Result rc){ + App::PushErrorBox(rc, "Failed to download theme"_i18n); + + if (R_SUCCEEDED(rc)) { App::Notify("Downloaded "_i18n + entry.details.name); } - }, 2)); + })); } } } diff --git a/sphaira/source/ui/menus/usb_menu.cpp b/sphaira/source/ui/menus/usb_menu.cpp index b55b7a3..11dfd89 100644 --- a/sphaira/source/ui/menus/usb_menu.cpp +++ b/sphaira/source/ui/menus/usb_menu.cpp @@ -109,31 +109,31 @@ void Menu::Update(Controller* controller, TouchInfo* touch) { log_write("set to progress\n"); m_state = State::Progress; log_write("got connection\n"); - App::Push(std::make_shared(0, "Installing "_i18n, "", [this](auto pbox) mutable -> bool { + App::Push(std::make_shared(0, "Installing "_i18n, "", [this](auto pbox) -> Result { ON_SCOPE_EXIT(m_usb_source->Finished(FINISHED_TIMEOUT)); log_write("inside progress box\n"); for (const auto& file_name : m_names) { m_usb_source->SetFileNameForTranfser(file_name); - const auto rc = yati::InstallFromSource(pbox, m_usb_source, file_name); if (R_FAILED(rc)) { m_usb_source->SignalCancel(); log_write("exiting usb install\n"); - return false; + R_THROW(rc); } App::Notify("Installed via usb"_i18n); } - return true; - }, [this](bool result){ - if (result) { + R_SUCCEED(); + }, [this](Result rc){ + App::PushErrorBox(rc, "USB install failed"_i18n); + + if (R_SUCCEEDED(rc)) { App::Notify("Usb install success!"_i18n); m_state = State::Done; SetPop(); } else { - App::Notify("Usb install failed!"_i18n); m_state = State::Failed; } })); diff --git a/sphaira/source/ui/progress_box.cpp b/sphaira/source/ui/progress_box.cpp index 409dd8c..0e875d4 100644 --- a/sphaira/source/ui/progress_box.cpp +++ b/sphaira/source/ui/progress_box.cpp @@ -212,6 +212,13 @@ auto ProgressBox::ShouldExit() -> bool { return m_stop_source.stop_requested(); } +auto ProgressBox::ShouldExitResult() -> Result { + if (ShouldExit()) { + R_THROW(0xFFFF); + } + R_SUCCEED(); +} + auto ProgressBox::CopyFile(const fs::FsPath& src_path, const fs::FsPath& dst_path) -> Result { fs::FsNativeSd fs; R_TRY(fs.GetFsOpenResult());