diff --git a/sphaira/include/app.hpp b/sphaira/include/app.hpp index 1ffb11b..d316983 100644 --- a/sphaira/include/app.hpp +++ b/sphaira/include/app.hpp @@ -304,6 +304,7 @@ public: option::OptionBool m_theme_music{INI_SECTION, "theme_music", true}; option::OptionBool m_show_ip_addr{INI_SECTION, "show_ip_addr", true}; option::OptionLong m_language{INI_SECTION, "language", 0}; // auto + option::OptionString m_center_menu{INI_SECTION, "center_side_menu", "Homebrew"}; option::OptionString m_left_menu{INI_SECTION, "left_side_menu", "FileBrowser"}; option::OptionString m_right_menu{INI_SECTION, "right_side_menu", "Appstore"}; option::OptionBool m_progress_boost_mode{INI_SECTION, "progress_boost_mode", true}; diff --git a/sphaira/include/ui/menus/filebrowser.hpp b/sphaira/include/ui/menus/filebrowser.hpp index e35158f..a98f47e 100644 --- a/sphaira/include/ui/menus/filebrowser.hpp +++ b/sphaira/include/ui/menus/filebrowser.hpp @@ -7,6 +7,7 @@ #include "fs.hpp" #include "option.hpp" #include "hasher.hpp" +#include "nro.hpp" #include namespace sphaira::ui::menu::filebrowser { @@ -479,6 +480,15 @@ protected: std::vector m_filter{}; + // local copy of nro entries that is loaded in LoadAssocEntriesPath() + // if homebrew::GetNroEntries() returns nothing, usually due to + // the menu not being loaded. + // this is a bit of a hack to support replacing the homebrew menu tab, + // sphaira wasn't really designed for this. + // however this will work for now, until i add support for additional + // nro scan mounts, at which point this won't scale. + std::vector m_nro_entries{}; + option::OptionLong m_sort{INI_SECTION, "sort", SortType::SortType_Alphabetical}; option::OptionLong m_order{INI_SECTION, "order", OrderType::OrderType_Descending}; option::OptionBool m_show_hidden{INI_SECTION, "show_hidden", false}; diff --git a/sphaira/include/ui/menus/homebrew.hpp b/sphaira/include/ui/menus/homebrew.hpp index d8e3b97..a45ae80 100644 --- a/sphaira/include/ui/menus/homebrew.hpp +++ b/sphaira/include/ui/menus/homebrew.hpp @@ -34,7 +34,7 @@ auto GetNroEntries() -> std::span; void SignalChange(); struct Menu final : grid::Menu { - Menu(); + Menu(u32 flags); ~Menu(); auto GetShortTitle() const -> const char* override { return "Apps"; }; diff --git a/sphaira/source/app.cpp b/sphaira/source/app.cpp index 7448fec..29402ad 100644 --- a/sphaira/source/app.cpp +++ b/sphaira/source/app.cpp @@ -1506,6 +1506,7 @@ App::App(const char* argv0) { else if (app->m_theme_music.LoadFrom(Key, Value)) {} else if (app->m_show_ip_addr.LoadFrom(Key, Value)) {} else if (app->m_language.LoadFrom(Key, Value)) {} + else if (app->m_center_menu.LoadFrom(Key, Value)) {} else if (app->m_left_menu.LoadFrom(Key, Value)) {} else if (app->m_right_menu.LoadFrom(Key, Value)) {} else if (app->m_install_sysmmc.LoadFrom(Key, Value)) {} @@ -1989,7 +1990,9 @@ void App::DisplayMenuOptions(bool left_side) { ON_SCOPE_EXIT(App::Push(std::move(options))); for (auto& e : ui::menu::main::GetMenuMenuEntries()) { - if (e.name == g_app->m_left_menu.Get()) { + if (e.name == g_app->m_center_menu.Get()) { + continue; + } else if (e.name == g_app->m_left_menu.Get()) { continue; } else if (e.name == g_app->m_right_menu.Get()) { continue; @@ -2078,11 +2081,33 @@ void App::DisplayAdvancedOptions(bool left_side) { App::SetTextScrollSpeed(index_out); }, App::GetTextScrollSpeed(), "Change how fast the scrolling text updates"_i18n); + options->Add("Set center menu"_i18n, menu_items, [menu_names](s64& index_out){ + const auto e = menu_names[index_out]; + if (g_app->m_center_menu.Get() != e) { + // swap menus around. + if (g_app->m_left_menu.Get() == e) { + g_app->m_left_menu.Set(g_app->m_left_menu.Get()); + } else if (g_app->m_right_menu.Get() == e) { + g_app->m_right_menu.Set(g_app->m_left_menu.Get()); + } + g_app->m_center_menu.Set(e); + + App::Push( + "Press OK to restart Sphaira"_i18n, "OK"_i18n, [](auto){ + App::ExitRestart(); + } + ); + } + }, i18n::get(g_app->m_center_menu.Get()), "Set the menu that appears on the center tab."_i18n); + + options->Add("Set left-side menu"_i18n, menu_items, [menu_names](s64& index_out){ const auto e = menu_names[index_out]; if (g_app->m_left_menu.Get() != e) { // swap menus around. - if (g_app->m_right_menu.Get() == e) { + if (g_app->m_center_menu.Get() == e) { + g_app->m_center_menu.Set(g_app->m_left_menu.Get()); + } else if (g_app->m_right_menu.Get() == e) { g_app->m_right_menu.Set(g_app->m_left_menu.Get()); } g_app->m_left_menu.Set(e); @@ -2099,7 +2124,9 @@ void App::DisplayAdvancedOptions(bool left_side) { const auto e = menu_names[index_out]; if (g_app->m_right_menu.Get() != e) { // swap menus around. - if (g_app->m_left_menu.Get() == e) { + if (g_app->m_center_menu.Get() == e) { + g_app->m_center_menu.Set(g_app->m_right_menu.Get()); + } else if (g_app->m_left_menu.Get() == e) { g_app->m_left_menu.Set(g_app->m_right_menu.Get()); } g_app->m_right_menu.Set(e); diff --git a/sphaira/source/ui/menus/filebrowser.cpp b/sphaira/source/ui/menus/filebrowser.cpp index 65eb6ee..710934c 100644 --- a/sphaira/source/ui/menus/filebrowser.cpp +++ b/sphaira/source/ui/menus/filebrowser.cpp @@ -2110,8 +2110,16 @@ void Base::LoadAssocEntriesPath(const fs::FsPath& path) { if (!assoc.path.empty()) { file_exists = view->m_fs->FileExists(assoc.path); } else { + auto nros = homebrew::GetNroEntries(); + if (nros.empty()) { + if (m_nro_entries.empty()) { + nro_scan("/switch", m_nro_entries); + nros = m_nro_entries; + } + } + const auto nro_name = assoc.name + ".nro"; - for (const auto& nro : homebrew::GetNroEntries()) { + for (const auto& nro : nros) { const auto len = std::strlen(nro.path); if (len < nro_name.length()) { continue; diff --git a/sphaira/source/ui/menus/homebrew.cpp b/sphaira/source/ui/menus/homebrew.cpp index 5493f36..eef48c3 100644 --- a/sphaira/source/ui/menus/homebrew.cpp +++ b/sphaira/source/ui/menus/homebrew.cpp @@ -55,7 +55,7 @@ auto GetNroEntries() -> std::span { return g_menu->GetHomebrewList(); } -Menu::Menu() : grid::Menu{"Homebrew"_i18n, MenuFlag_Tab} { +Menu::Menu(u32 flags) : grid::Menu{"Homebrew"_i18n, flags} { g_menu = this; this->SetActions( diff --git a/sphaira/source/ui/menus/main_menu.cpp b/sphaira/source/ui/menus/main_menu.cpp index 7e69b46..1911298 100644 --- a/sphaira/source/ui/menus/main_menu.cpp +++ b/sphaira/source/ui/menus/main_menu.cpp @@ -49,6 +49,10 @@ auto MiscMenuFuncGenerator(u32 flags) { } const MiscMenuEntry MISC_MENU_ENTRIES[] = { + { .name = "Homebrew", .title = "Homebrew", .func = MiscMenuFuncGenerator, .flag = MiscMenuFlag_Shortcut, .info = + "The homebrew menu.\n\n" + "Allows you to launch, delete and mount homebrew!"}, + { .name = "Appstore", .title = "Appstore", .func = MiscMenuFuncGenerator, .flag = MiscMenuFlag_Shortcut, .info = "Download and update apps.\n\n" "Internet connection required." }, @@ -163,9 +167,34 @@ auto InstallUpdate(ProgressBox* pbox, const std::string url, const std::string v R_SUCCEED(); } -auto CreateLeftSideMenu(std::string& name_out) -> std::unique_ptr { +auto CreateCenterMenu(std::string& name_out) -> std::unique_ptr { + const auto name = App::GetApp()->m_center_menu.Get(); + + for (auto& e : GetMenuMenuEntries()) { + if (e.name == name) { + name_out = name; + return e.func(MenuFlag_Tab); + } + } + + name_out = "Homebrew"; + return std::make_unique(MenuFlag_Tab); +} + +auto CreateLeftSideMenu(std::string_view center_name, std::string& name_out) -> std::unique_ptr { const auto name = App::GetApp()->m_left_menu.Get(); + // handle if the user tries to mount the same menu twice. + if (name == center_name) { + // check if we can mount the default. + if (center_name != "FileBrowser") { + return std::make_unique(MenuFlag_Tab); + } else { + // otherwise, fallback to center default. + return std::make_unique(MenuFlag_Tab); + } + } + for (auto& e : GetMenuMenuEntries()) { if (e.name == name) { name_out = name; @@ -177,6 +206,7 @@ auto CreateLeftSideMenu(std::string& name_out) -> std::unique_ptr { return std::make_unique(MenuFlag_Tab); } +// todo: handle center / left menu being the same. auto CreateRightSideMenu(std::string_view left_name) -> std::unique_ptr { const auto name = App::GetApp()->m_right_menu.Get(); @@ -378,11 +408,13 @@ MainMenu::MainMenu() { }} )); - m_centre_menu = std::make_unique(); + std::string center_name; + m_centre_menu = CreateCenterMenu(center_name); m_current_menu = m_centre_menu.get(); std::string left_side_name; - m_left_menu = CreateLeftSideMenu(left_side_name); + m_left_menu = CreateLeftSideMenu(center_name, left_side_name); + m_right_menu = CreateRightSideMenu(left_side_name); AddOnLRPress();