add option to restore hbmenu when disabling "Replace hbmenu on exit".
fixes #66
This commit is contained in:
@@ -42,6 +42,8 @@ public:
|
|||||||
auto Update(Controller* controller, TouchInfo* touch) -> void override;
|
auto Update(Controller* controller, TouchInfo* touch) -> void override;
|
||||||
auto OnLayoutChange() -> void override;
|
auto OnLayoutChange() -> void override;
|
||||||
auto Draw(NVGcontext* vg, Theme* theme) -> void override;
|
auto Draw(NVGcontext* vg, Theme* theme) -> void override;
|
||||||
|
auto OnFocusGained() noexcept -> void override;
|
||||||
|
auto OnFocusLost() noexcept -> void override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
auto Setup(std::size_t index) -> void; // common setup values
|
auto Setup(std::size_t index) -> void; // common setup values
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "ui/menus/main_menu.hpp"
|
#include "ui/menus/main_menu.hpp"
|
||||||
#include "ui/error_box.hpp"
|
#include "ui/error_box.hpp"
|
||||||
|
#include "ui/option_box.hpp"
|
||||||
|
|
||||||
#include "app.hpp"
|
#include "app.hpp"
|
||||||
#include "log.hpp"
|
#include "log.hpp"
|
||||||
@@ -468,7 +469,104 @@ void App::SetLogEnable(bool enable) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void App::SetReplaceHbmenuEnable(bool enable) {
|
void App::SetReplaceHbmenuEnable(bool enable) {
|
||||||
g_app->m_replace_hbmenu.Set(enable);
|
if (App::GetReplaceHbmenuEnable() != enable) {
|
||||||
|
g_app->m_replace_hbmenu.Set(enable);
|
||||||
|
if (!enable) {
|
||||||
|
// check we have already replaced hbmenu with sphaira
|
||||||
|
NacpStruct hbmenu_nacp;
|
||||||
|
if (R_FAILED(nro_get_nacp("/hbmenu.nro", hbmenu_nacp))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (std::strcmp(hbmenu_nacp.lang[0].name, "sphaira")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ask user if they want to restore hbmenu
|
||||||
|
App::Push(std::make_shared<ui::OptionBox>(
|
||||||
|
"Restore hbmenu?"_i18n,
|
||||||
|
"Back"_i18n, "Restore"_i18n, 1, [hbmenu_nacp](auto op_index){
|
||||||
|
if (!op_index || *op_index == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NacpStruct actual_hbmenu_nacp;
|
||||||
|
if (R_FAILED(nro_get_nacp("/switch/hbmenu.nro", actual_hbmenu_nacp))) {
|
||||||
|
App::Push(std::make_shared<ui::OptionBox>(
|
||||||
|
"Failed to find /switch/hbmenu.nro\n\
|
||||||
|
Use the Appstore to re-install hbmenu"_i18n,
|
||||||
|
"OK"_i18n
|
||||||
|
));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: do NOT use rename anywhere here as it's possible
|
||||||
|
// to have a race condition with another app that opens hbmenu as a file
|
||||||
|
// in between the delete + rename.
|
||||||
|
// this would require a sys-module to open hbmenu.nro, such as an ftp server.
|
||||||
|
// a copy means that it opens the file handle, if successfull, then
|
||||||
|
// the full read/write will succeed.
|
||||||
|
fs::FsNativeSd fs;
|
||||||
|
NacpStruct sphaira_nacp;
|
||||||
|
fs::FsPath sphaira_path = "/switch/sphaira/sphaira.nro";
|
||||||
|
Result rc;
|
||||||
|
|
||||||
|
// first, try and backup sphaira, its not super important if this fails.
|
||||||
|
rc = nro_get_nacp(sphaira_path, sphaira_nacp);
|
||||||
|
if (R_FAILED(rc) || std::strcmp(sphaira_nacp.lang[0].name, "sphaira")) {
|
||||||
|
sphaira_path = "/switch/sphaira.nro";
|
||||||
|
rc = nro_get_nacp(sphaira_path, sphaira_nacp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc) && !std::strcmp(sphaira_nacp.lang[0].name, "sphaira")) {
|
||||||
|
if (std::strcmp(sphaira_nacp.display_version, hbmenu_nacp.display_version) < 0) {
|
||||||
|
if (R_FAILED(rc = fs.copy_entire_file(sphaira_path, "/hbmenu.nro", true))) {
|
||||||
|
log_write("failed to copy entire file: %s 0x%X module: %u desc: %u\n", sphaira_path, rc, R_MODULE(rc), R_DESCRIPTION(rc));
|
||||||
|
} else {
|
||||||
|
log_write("success with updating hbmenu!\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// sphaira doesn't yet exist, create a new file.
|
||||||
|
sphaira_path = "/switch/sphaira/sphaira.nro";
|
||||||
|
fs.CreateDirectoryRecursively("/switch/sphaira/");
|
||||||
|
fs.copy_entire_file(sphaira_path, "/hbmenu.nro", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// this should never fail, if it does, well then the sd card is fucked.
|
||||||
|
if (R_FAILED(rc = fs.copy_entire_file("/hbmenu.nro", "/switch/hbmenu.nro", true))) {
|
||||||
|
// try and restore sphaira in a last ditch effort.
|
||||||
|
if (R_FAILED(rc = fs.copy_entire_file("/hbmenu.nro", sphaira_path, true))) {
|
||||||
|
App::Push(std::make_shared<ui::ErrorBox>(rc,
|
||||||
|
"Failed to restore hbmenu, please re-download hbmenu"_i18n
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
App::Push(std::make_shared<ui::OptionBox>(
|
||||||
|
"Failed to restore hbmenu, using sphaira instead"_i18n,
|
||||||
|
"OK"_i18n
|
||||||
|
));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't need this any more.
|
||||||
|
fs.DeleteFile("/switch/hbmenu.nro", true);
|
||||||
|
|
||||||
|
// if we were hbmenu, exit now (as romfs is gone).
|
||||||
|
if (IsHbmenu()) {
|
||||||
|
App::Push(std::make_shared<ui::OptionBox>(
|
||||||
|
"Restored hbmenu, closing sphaira"_i18n,
|
||||||
|
"OK"_i18n, [](auto) {
|
||||||
|
App::Exit();
|
||||||
|
}
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
App::Notify("Restored hbmenu"_i18n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void App::SetInstallEnable(bool enable) {
|
void App::SetInstallEnable(bool enable) {
|
||||||
@@ -1156,18 +1254,19 @@ App::~App() {
|
|||||||
|
|
||||||
// backup hbmenu if it is not sphaira
|
// backup hbmenu if it is not sphaira
|
||||||
if (App::GetReplaceHbmenuEnable() && !IsHbmenu()) {
|
if (App::GetReplaceHbmenuEnable() && !IsHbmenu()) {
|
||||||
NacpStruct nacp;
|
NacpStruct hbmenu_nacp;
|
||||||
fs::FsNativeSd fs;
|
fs::FsNativeSd fs;
|
||||||
if (R_SUCCEEDED(nro_get_nacp("/hbmenu.nro", nacp)) && std::strcmp(nacp.lang[0].name, "sphaira")) {
|
Result rc;
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc = nro_get_nacp("/hbmenu.nro", hbmenu_nacp)) && std::strcmp(hbmenu_nacp.lang[0].name, "sphaira")) {
|
||||||
log_write("backing up hbmenu.nro\n");
|
log_write("backing up hbmenu.nro\n");
|
||||||
if (R_FAILED(fs.copy_entire_file("/switch/hbmenu.nro", "/hbmenu.nro", true))) {
|
if (R_FAILED(rc = fs.copy_entire_file("/switch/hbmenu.nro", "/hbmenu.nro", true))) {
|
||||||
log_write("failed to backup hbmenu.nro\n");
|
log_write("failed to backup hbmenu.nro\n");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log_write("not backing up\n");
|
log_write("not backing up\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
Result rc;
|
|
||||||
if (R_FAILED(rc = fs.copy_entire_file("/hbmenu.nro", GetExePath(), true))) {
|
if (R_FAILED(rc = fs.copy_entire_file("/hbmenu.nro", GetExePath(), true))) {
|
||||||
log_write("failed to copy entire file: %s 0x%X module: %u desc: %u\n", GetExePath(), rc, R_MODULE(rc), R_DESCRIPTION(rc));
|
log_write("failed to copy entire file: %s 0x%X module: %u desc: %u\n", GetExePath(), rc, R_MODULE(rc), R_DESCRIPTION(rc));
|
||||||
} else {
|
} else {
|
||||||
@@ -1175,26 +1274,33 @@ App::~App() {
|
|||||||
}
|
}
|
||||||
} else if (IsHbmenu()) {
|
} else if (IsHbmenu()) {
|
||||||
// check we have a version that's newer than current.
|
// check we have a version that's newer than current.
|
||||||
|
NacpStruct hbmenu_nacp;
|
||||||
fs::FsNativeSd fs;
|
fs::FsNativeSd fs;
|
||||||
NacpStruct sphaira_nacp;
|
|
||||||
fs::FsPath sphaira_path = "/switch/sphaira/sphaira.nro";
|
|
||||||
Result rc;
|
Result rc;
|
||||||
|
|
||||||
rc = nro_get_nacp(sphaira_path, sphaira_nacp);
|
// ensure that are still sphaira
|
||||||
if (R_FAILED(rc) || std::strcmp(sphaira_nacp.lang[0].name, "sphaira")) {
|
if (R_SUCCEEDED(rc = nro_get_nacp("/hbmenu.nro", hbmenu_nacp)) && !std::strcmp(hbmenu_nacp.lang[0].name, "sphaira")) {
|
||||||
sphaira_path = "/switch/sphaira.nro";
|
NacpStruct sphaira_nacp;
|
||||||
rc = nro_get_nacp(sphaira_path, sphaira_nacp);
|
fs::FsPath sphaira_path = "/switch/sphaira/sphaira.nro";
|
||||||
}
|
|
||||||
|
|
||||||
// found sphaira, now lets get compare version
|
rc = nro_get_nacp(sphaira_path, sphaira_nacp);
|
||||||
if (R_SUCCEEDED(rc) && !std::strcmp(sphaira_nacp.lang[0].name, "sphaira")) {
|
if (R_FAILED(rc) || std::strcmp(sphaira_nacp.lang[0].name, "sphaira")) {
|
||||||
if (std::strcmp(APP_VERSION, sphaira_nacp.display_version) < 0) {
|
sphaira_path = "/switch/sphaira.nro";
|
||||||
if (R_FAILED(rc = fs.copy_entire_file(GetExePath(), sphaira_path, true))) {
|
rc = nro_get_nacp(sphaira_path, sphaira_nacp);
|
||||||
log_write("failed to copy entire file: %s 0x%X module: %u desc: %u\n", sphaira_path, rc, R_MODULE(rc), R_DESCRIPTION(rc));
|
}
|
||||||
} else {
|
|
||||||
log_write("success with updating hbmenu!\n");
|
// found sphaira, now lets get compare version
|
||||||
|
if (R_SUCCEEDED(rc) && !std::strcmp(sphaira_nacp.lang[0].name, "sphaira")) {
|
||||||
|
if (std::strcmp(hbmenu_nacp.display_version, sphaira_nacp.display_version) < 0) {
|
||||||
|
if (R_FAILED(rc = fs.copy_entire_file(GetExePath(), sphaira_path, true))) {
|
||||||
|
log_write("failed to copy entire file: %s 0x%X module: %u desc: %u\n", sphaira_path, rc, R_MODULE(rc), R_DESCRIPTION(rc));
|
||||||
|
} else {
|
||||||
|
log_write("success with updating hbmenu!\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
log_write("no longer hbmenu!\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -118,6 +118,16 @@ auto OptionBox::Draw(NVGcontext* vg, Theme* theme) -> void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto OptionBox::OnFocusGained() noexcept -> void {
|
||||||
|
Widget::OnFocusGained();
|
||||||
|
SetHidden(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto OptionBox::OnFocusLost() noexcept -> void {
|
||||||
|
Widget::OnFocusLost();
|
||||||
|
SetHidden(true);
|
||||||
|
}
|
||||||
|
|
||||||
auto OptionBox::Setup(std::size_t index) -> void {
|
auto OptionBox::Setup(std::size_t index) -> void {
|
||||||
m_index = std::min(m_entries.size() - 1, index);
|
m_index = std::min(m_entries.size() - 1, index);
|
||||||
m_entries[m_index].Selected(true);
|
m_entries[m_index].Selected(true);
|
||||||
|
|||||||
Reference in New Issue
Block a user