diff --git a/Makefile b/Makefile index 96f150b..6a57ef5 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,7 @@ DATA := data INCLUDES := include lib/zipper/include /lib/borealis/library/include/borealis/extern/nlohmann APP_TITLE := All-in-One Switch Updater APP_AUTHOR := HamletDuFromage -APP_VERSION := 2.7.1 +APP_VERSION := 2.8.0 TARGET := $(notdir $(CURDIR)) ROMFS := resources diff --git a/include/app_page.hpp b/include/app_page.hpp index 1005982..49b647b 100644 --- a/include/app_page.hpp +++ b/include/app_page.hpp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -72,6 +73,8 @@ class AppPage_DownloadedCheats : public AppPage void CreateLabel() override; void DeclareGameListItem(const std::string& name, uint64_t tid, NsApplicationControlData **controlData) override; void GetExistingCheatsTids(); + void ShowCheatFiles(uint64_t tid, const std::string& name); + bool CreateCheatList(const std::filesystem::path& path, brls::TabFrame** appView); public: AppPage_DownloadedCheats(); diff --git a/resources/i18n/en-US/menus.json b/resources/i18n/en-US/menus.json index 5555609..18c1e4c 100644 --- a/resources/i18n/en-US/menus.json +++ b/resources/i18n/en-US/menus.json @@ -40,7 +40,9 @@ "gbatemp_dl": "Download cheat codes curated from GBAtemp. Those cheats will be added to the end of your existing cheat file.\n\uE016 Build ID: {}", "gbatemp_dl_cheatcode": "Download cheat code", "gbatemp_dl_successful_dl": "Successfully downloaded the following cheat code:\n{}", - "applet_mode_not_supported": "Due to memory constraints, in applet mode you may only fetch cheat codes for the game you're currently playing. Please launch aio-switch-updater through title redirection to download cheat codes for any game you own." + "applet_mode_not_supported": "Due to memory constraints, in applet mode you may only fetch cheat codes for the game you're currently playing. Please launch aio-switch-updater through title redirection to download cheat codes for any game you own.", + "cheatfile_label": "Here are the cheat codes listed in file {}", + "not_found": "Not proper cheat codes could be found for this game" }, "common": { "downloading": "Downloading...", diff --git a/source/app_page.cpp b/source/app_page.cpp index bce453e..be97504 100644 --- a/source/app_page.cpp +++ b/source/app_page.cpp @@ -9,6 +9,7 @@ #include #include #include +#include namespace i18n = brls::i18n; using namespace i18n::literals; @@ -276,6 +277,7 @@ void AppPage_DownloadedCheats::CreateLabel() void AppPage_DownloadedCheats::DeclareGameListItem(const std::string& name, u64 tid, NsApplicationControlData **controlData) { if (titles.find(util::formatApplicationId(tid)) != titles.end()) { + listItem->getClickEvent()->subscribe([this, tid, name](brls::View* view) { ShowCheatFiles(tid, name); }); AppPage::DeclareGameListItem(name, tid, controlData); } } @@ -295,8 +297,73 @@ void AppPage_DownloadedCheats::GetExistingCheatsTids() { } for(const auto& entry : std::filesystem::directory_iterator(path)) { std::string cheatsPath = entry.path().string() + "/cheats"; - if(std::filesystem::exists(cheatsPath) && !std::filesystem::is_empty(cheatsPath)){ - titles.insert(util::upperCase(cheatsPath.substr(cheatsPath.length() - 7 - 16, 16))); + if(std::filesystem::exists(cheatsPath) && !std::filesystem::is_empty(cheatsPath)) { + for(const auto& cheatFile : std::filesystem::directory_iterator(cheatsPath)) { + if(extract::isBID(cheatFile.path().filename().stem())) { + titles.insert(util::upperCase(cheatsPath.substr(cheatsPath.length() - 7 - 16, 16))); + break; + } + } } } +} + +void AppPage_DownloadedCheats::ShowCheatFiles(u64 tid, const std::string& name) { + std::string path; + switch(CurrentCfw::running_cfw){ + case CFW::ams: + path = std::string(AMS_PATH) + std::string(CONTENTS_PATH); + break; + case CFW::rnx: + path = std::string(REINX_PATH) + std::string(CONTENTS_PATH); + break; + case CFW::sxos: + path = std::string(SXOS_PATH) + std::string(TITLES_PATH); + break; + } + path += util::formatApplicationId(tid) + "/cheats/"; + + brls::TabFrame* appView = new brls::TabFrame(); + bool is_populated = false; + for(const auto& cheatFile : std::filesystem::directory_iterator(path)){ + is_populated |= CreateCheatList(cheatFile.path(), &appView); + } + if(is_populated) { + brls::PopupFrame::open(name, appView, ""); + } + else { + brls::Dialog* dialog = new brls::Dialog("menus/cheats/not_found"_i18n); + brls::GenericEvent::Callback callback = [dialog](brls::View* view) { + dialog->close(); + }; + dialog->addButton("menus/common/ok"_i18n, callback); + dialog->setCancelable(true); + dialog->open(); + } +} + +bool AppPage_DownloadedCheats::CreateCheatList(const std::filesystem::path& path, brls::TabFrame** appView) { + bool res = false; + brls::List* cheatsList = new brls::List(); + if(extract::isBID(path.filename().stem())) { + cheatsList->addView(new brls::Label(brls::LabelStyle::DESCRIPTION, fmt::format("menus/cheats/cheatfile_label"_i18n, path.filename().string()), true)); + + std::string str; + std::regex cheats_expr(R"(\[.+\])"); + std::ifstream in(path); + if(in) { + while (std::getline(in, str)) { + if(str.size() > 0) { + if(std::regex_search(str, cheats_expr)) { + cheatsList->addView(new brls::ListItem(str)); + res = true; + } + } + } + } + } + if(res) { + (*appView)->addTab(path.filename().stem(), cheatsList); + } + return res; } \ No newline at end of file diff --git a/source/changelog_page.cpp b/source/changelog_page.cpp index 0b37148..4acb5b5 100644 --- a/source/changelog_page.cpp +++ b/source/changelog_page.cpp @@ -166,8 +166,8 @@ ChangelogPage::ChangelogPage() : AppletFrame(true, true) verTitles.push_back("v2.7.0"); changes.push_back("\uE016 Fixed Atmosphère updates failing when updating from a system without stratosphere.romfs present on the SD card.\n\uE016 Disabled the option to download individual cheat codes while in applet mode, except for the one game currently running.\n\uE016 UI tweaks.\n\uE016 Prevents crashes when requesting invalid CheatSlips cheat sheets."); - verTitles.push_back("v2.7.1"); - changes.push_back("\uE016 Restored and improved \"View installed cheats\" menu."); + verTitles.push_back("v2.8.0"); + changes.push_back("\uE016 Restored and improved \"View installed cheats\" menu. You can now browse the content of your cheatsheets from the app."); for(int i = verTitles.size() -1 ; i >= 0; i--){ listItem = new brls::ListItem(verTitles[i]); diff --git a/source/extract.cpp b/source/extract.cpp index 5c0d815..9829f27 100644 --- a/source/extract.cpp +++ b/source/extract.cpp @@ -152,7 +152,6 @@ std::vector excludeTitles(const std::string& path, const std::vecto } } } - file.close(); } std::sort(titles.begin(), titles.end()); diff --git a/source/fs.cpp b/source/fs.cpp index a841ab1..3274934 100644 --- a/source/fs.cpp +++ b/source/fs.cpp @@ -42,7 +42,6 @@ namespace fs { void writeJsonToFile(nlohmann::json &data, const std::string& path) { std::ofstream out(path); out << data.dump(4); - out.close(); } bool copyFile(const std::string& from, const std::string& to){ @@ -88,7 +87,6 @@ namespace fs { } } - in.close(); } } if(error == "") { @@ -110,7 +108,6 @@ namespace fs { if(str.size() > 0) titles.insert(str); } - in.close(); } return titles; } diff --git a/source/tools_tab.cpp b/source/tools_tab.cpp index f5e6919..11fd801 100644 --- a/source/tools_tab.cpp +++ b/source/tools_tab.cpp @@ -232,7 +232,6 @@ ToolsTab::ToolsTab(std::string tag, bool erista) : brls::List() updatedLanguage["language"] = l.second; std::ofstream out(LANGUAGE_JSON); out << updatedLanguage.dump(); - out.close(); brls::Application::quit(); return true; }); @@ -257,12 +256,5 @@ ToolsTab::ToolsTab(std::string tag, bool erista) : brls::List() }); changelog->setHeight(LISTITEM_HEIGHT); this->addView(changelog); - -/* language = new brls::ListItem("menus/Language_Option"_i18n); - language->getClickEvent()->subscribe([&](brls::View* view){ - brls::Application::pushView(new LanguageOptionPage()); - }); - language->setHeight(LISTITEM_HEIGHT); - this->addView(language); */ } diff --git a/source/utils.cpp b/source/utils.cpp index ad9143c..2bc7882 100644 --- a/source/utils.cpp +++ b/source/utils.cpp @@ -23,7 +23,6 @@ bool isArchive(const std::string& path){ if(std::filesystem::exists(path)){ file.open(path, std::fstream::in); file >> fileContent; - file.close(); } return fileContent.find("DOCTYPE") == std::string::npos; }