add support for changing the left-side menu.

fixes #148
This commit is contained in:
ITotalJustice
2025-05-26 22:55:06 +01:00
parent e2a5454263
commit c11d9edc4e
27 changed files with 164 additions and 63 deletions

View File

@@ -240,7 +240,8 @@ public:
option::OptionBool m_theme_music{INI_SECTION, "theme_music", true}; option::OptionBool m_theme_music{INI_SECTION, "theme_music", true};
option::OptionBool m_12hour_time{INI_SECTION, "12hour_time", false}; option::OptionBool m_12hour_time{INI_SECTION, "12hour_time", false};
option::OptionLong m_language{INI_SECTION, "language", 0}; // auto option::OptionLong m_language{INI_SECTION, "language", 0}; // auto
option::OptionString m_right_side_menu{INI_SECTION, "right_side_menu", "Appstore"}; 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}; option::OptionBool m_progress_boost_mode{INI_SECTION, "progress_boost_mode", true};
// install options // install options

View File

@@ -139,7 +139,7 @@ enum OrderType {
using LayoutType = grid::LayoutType; using LayoutType = grid::LayoutType;
struct Menu final : grid::Menu { struct Menu final : grid::Menu {
Menu(); Menu(u32 flags);
~Menu(); ~Menu();
auto GetShortTitle() const -> const char* override { return "Store"; }; auto GetShortTitle() const -> const char* override { return "Store"; };

View File

@@ -3,7 +3,6 @@
#include "ui/menus/menu_base.hpp" #include "ui/menus/menu_base.hpp"
#include "ui/scrolling_text.hpp" #include "ui/scrolling_text.hpp"
#include "ui/list.hpp" #include "ui/list.hpp"
#include "nro.hpp"
#include "fs.hpp" #include "fs.hpp"
#include "option.hpp" #include "option.hpp"
#include "hasher.hpp" #include "hasher.hpp"
@@ -341,7 +340,7 @@ struct SelectedStash {
struct Menu final : MenuBase { struct Menu final : MenuBase {
friend class FsView; friend class FsView;
Menu(const std::vector<NroEntry>& nro_entries); Menu(u32 flags);
~Menu(); ~Menu();
auto GetShortTitle() const -> const char* override { return "Files"; }; auto GetShortTitle() const -> const char* override { return "Files"; };
@@ -381,10 +380,11 @@ private:
void UpdateSubheading(); void UpdateSubheading();
void PromptIfShouldExit();
private: private:
static constexpr inline const char* INI_SECTION = "filebrowser"; static constexpr inline const char* INI_SECTION = "filebrowser";
const std::vector<NroEntry>& m_nro_entries;
std::shared_ptr<FsView> view{}; std::shared_ptr<FsView> view{};
std::shared_ptr<FsView> view_left{}; std::shared_ptr<FsView> view_left{};
std::shared_ptr<FsView> view_right{}; std::shared_ptr<FsView> view_right{};

View File

@@ -35,7 +35,7 @@ struct StreamFtp final : yati::source::Stream {
}; };
struct Menu final : MenuBase { struct Menu final : MenuBase {
Menu(); Menu(u32 flags);
~Menu(); ~Menu();
auto GetShortTitle() const -> const char* override { return "FTP"; }; auto GetShortTitle() const -> const char* override { return "FTP"; };

View File

@@ -88,7 +88,7 @@ enum OrderType {
using LayoutType = grid::LayoutType; using LayoutType = grid::LayoutType;
struct Menu final : grid::Menu { struct Menu final : grid::Menu {
Menu(); Menu(u32 flags);
~Menu(); ~Menu();
auto GetShortTitle() const -> const char* override { return "Games"; }; auto GetShortTitle() const -> const char* override { return "Games"; };

View File

@@ -166,7 +166,7 @@ struct ApplicationEntry {
}; };
struct Menu final : MenuBase { struct Menu final : MenuBase {
Menu(); Menu(u32 flags);
~Menu(); ~Menu();
auto GetShortTitle() const -> const char* override { return "GC"; }; auto GetShortTitle() const -> const char* override { return "GC"; };

View File

@@ -42,7 +42,7 @@ struct GhApiEntry {
}; };
struct Menu final : MenuBase { struct Menu final : MenuBase {
Menu(); Menu(u32 flags);
~Menu(); ~Menu();
auto GetShortTitle() const -> const char* override { return "GitHub"; }; auto GetShortTitle() const -> const char* override { return "GitHub"; };

View File

@@ -24,6 +24,8 @@ enum OrderType {
using LayoutType = grid::LayoutType; using LayoutType = grid::LayoutType;
auto GetNroEntries() -> std::span<const NroEntry>;
struct Menu final : grid::Menu { struct Menu final : grid::Menu {
Menu(); Menu();
~Menu(); ~Menu();

View File

@@ -27,7 +27,7 @@ struct Entry {
}; };
struct Menu final : MenuBase { struct Menu final : MenuBase {
Menu(); Menu(u32 flags);
~Menu(); ~Menu();
auto GetShortTitle() const -> const char* override { return "IRS"; }; auto GetShortTitle() const -> const char* override { return "IRS"; };

View File

@@ -1,8 +1,8 @@
#pragma once #pragma once
#include "ui/widget.hpp" #include "ui/widget.hpp"
#include "ui/menus/homebrew.hpp" #include "ui/menus/menu_base.hpp"
#include "ui/menus/filebrowser.hpp" #include <span>
namespace sphaira::ui::menu::main { namespace sphaira::ui::menu::main {
@@ -17,7 +17,7 @@ enum class UpdateState {
Error, Error,
}; };
using MiscMenuFunction = std::function<std::shared_ptr<ui::menu::MenuBase>(void)>; using MiscMenuFunction = std::function<std::shared_ptr<ui::menu::MenuBase>(u32 flags)>;
enum MiscMenuFlag : u8 { enum MiscMenuFlag : u8 {
// can be set as the rightside menu. // can be set as the rightside menu.
@@ -62,9 +62,9 @@ private:
void AddOnLRPress(); void AddOnLRPress();
private: private:
std::shared_ptr<homebrew::Menu> m_homebrew_menu{}; std::shared_ptr<MenuBase> m_centre_menu{};
std::shared_ptr<filebrowser::Menu> m_filebrowser_menu{}; std::shared_ptr<MenuBase> m_left_menu{};
std::shared_ptr<MenuBase> m_right_side_menu{}; std::shared_ptr<MenuBase> m_right_menu{};
std::shared_ptr<MenuBase> m_current_menu{}; std::shared_ptr<MenuBase> m_current_menu{};
std::string m_update_url{}; std::string m_update_url{};

View File

@@ -6,6 +6,11 @@
namespace sphaira::ui::menu { namespace sphaira::ui::menu {
enum MenuFlag {
MenuFlag_None = 0,
MenuFlag_Tab = 1 << 1,
};
struct PolledData { struct PolledData {
struct tm tm{}; struct tm tm{};
u32 battery_percetange{}; u32 battery_percetange{};
@@ -17,7 +22,7 @@ struct PolledData {
}; };
struct MenuBase : Widget { struct MenuBase : Widget {
MenuBase(std::string title); MenuBase(const std::string& title, u32 flags);
virtual ~MenuBase(); virtual ~MenuBase();
virtual auto GetShortTitle() const -> const char* = 0; virtual auto GetShortTitle() const -> const char* = 0;
@@ -36,6 +41,10 @@ struct MenuBase : Widget {
return m_title; return m_title;
} }
auto IsTab() const -> bool {
return m_flags & MenuFlag_Tab;
}
static auto GetPolledData(bool force_refresh = false) -> PolledData; static auto GetPolledData(bool force_refresh = false) -> PolledData;
private: private:
@@ -45,6 +54,8 @@ private:
ScrollingText m_scroll_title_sub_heading{}; ScrollingText m_scroll_title_sub_heading{};
ScrollingText m_scroll_sub_heading{}; ScrollingText m_scroll_sub_heading{};
u32 m_flags{};
}; };
} // namespace sphaira::ui::menu } // namespace sphaira::ui::menu

View File

@@ -130,7 +130,7 @@ struct PageEntry {
}; };
struct Menu final : MenuBase { struct Menu final : MenuBase {
Menu(); Menu(u32 flags);
~Menu(); ~Menu();
auto GetShortTitle() const -> const char* override { return "Themezer"; }; auto GetShortTitle() const -> const char* override { return "Themezer"; };

View File

@@ -21,7 +21,7 @@ enum class State {
}; };
struct Menu final : MenuBase { struct Menu final : MenuBase {
Menu(); Menu(u32 flags);
~Menu(); ~Menu();
auto GetShortTitle() const -> const char* override { return "USB"; }; auto GetShortTitle() const -> const char* override { return "USB"; };

View File

@@ -1310,7 +1310,8 @@ App::App(const char* argv0) {
else if (app->m_theme_music.LoadFrom(Key, Value)) {} else if (app->m_theme_music.LoadFrom(Key, Value)) {}
else if (app->m_12hour_time.LoadFrom(Key, Value)) {} else if (app->m_12hour_time.LoadFrom(Key, Value)) {}
else if (app->m_language.LoadFrom(Key, Value)) {} else if (app->m_language.LoadFrom(Key, Value)) {}
else if (app->m_right_side_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)) {} else if (app->m_install_sysmmc.LoadFrom(Key, Value)) {}
else if (app->m_install_emummc.LoadFrom(Key, Value)) {} else if (app->m_install_emummc.LoadFrom(Key, Value)) {}
else if (app->m_install_sd.LoadFrom(Key, Value)) {} else if (app->m_install_sd.LoadFrom(Key, Value)) {}
@@ -1581,7 +1582,7 @@ void App::DisplayMiscOptions(bool left_side) {
ON_SCOPE_EXIT(App::Push(options)); ON_SCOPE_EXIT(App::Push(options));
for (auto& e : ui::menu::main::GetMiscMenuEntries()) { for (auto& e : ui::menu::main::GetMiscMenuEntries()) {
if (e.name == g_app->m_right_side_menu.Get()) { if (e.name == g_app->m_right_menu.Get()) {
continue; continue;
} }
@@ -1590,7 +1591,7 @@ void App::DisplayMiscOptions(bool left_side) {
} }
options->Add(std::make_shared<ui::SidebarEntryCallback>(i18n::get(e.title), [e](){ options->Add(std::make_shared<ui::SidebarEntryCallback>(i18n::get(e.title), [e](){
App::Push(e.func()); App::Push(e.func(ui::menu::MenuFlag_None));
})); }));
} }
} }
@@ -1617,14 +1618,14 @@ void App::DisplayAdvancedOptions(bool left_side) {
menu_names.emplace_back(e.name); menu_names.emplace_back(e.name);
} }
ui::SidebarEntryArray::Items right_side_menu_items; ui::SidebarEntryArray::Items side_menu_items;
for (auto& str : menu_names) { for (auto& str : menu_names) {
right_side_menu_items.push_back(i18n::get(str)); side_menu_items.push_back(i18n::get(str));
} }
const auto it = std::find(menu_names.cbegin(), menu_names.cend(), g_app->m_right_side_menu.Get()); const auto it = std::find(menu_names.cbegin(), menu_names.cend(), g_app->m_right_menu.Get());
if (it == menu_names.cend()) { if (it == menu_names.cend()) {
g_app->m_right_side_menu.Set(menu_names[0]); g_app->m_right_menu.Set(menu_names[0]);
} }
options->Add(std::make_shared<ui::SidebarEntryBool>("Logging"_i18n, App::GetLogEnable(), [](bool& enable){ options->Add(std::make_shared<ui::SidebarEntryBool>("Logging"_i18n, App::GetLogEnable(), [](bool& enable){
@@ -1643,17 +1644,29 @@ void App::DisplayAdvancedOptions(bool left_side) {
App::SetTextScrollSpeed(index_out); App::SetTextScrollSpeed(index_out);
}, App::GetTextScrollSpeed())); }, App::GetTextScrollSpeed()));
options->Add(std::make_shared<ui::SidebarEntryArray>("Set right-side menu"_i18n, right_side_menu_items, [menu_names](s64& index_out){ options->Add(std::make_shared<ui::SidebarEntryArray>("Set left-side menu"_i18n, side_menu_items, [menu_names](s64& index_out){
const auto e = menu_names[index_out]; const auto e = menu_names[index_out];
if (g_app->m_right_side_menu.Get() != e) { if (g_app->m_left_menu.Get() != e) {
g_app->m_right_side_menu.Set(e); g_app->m_left_menu.Set(e);
App::Push(std::make_shared<ui::OptionBox>( App::Push(std::make_shared<ui::OptionBox>(
"Press OK to restart Sphaira"_i18n, "OK"_i18n, [](auto){ "Press OK to restart Sphaira"_i18n, "OK"_i18n, [](auto){
App::ExitRestart(); App::ExitRestart();
} }
)); ));
} }
}, i18n::get(g_app->m_right_side_menu.Get()))); }, i18n::get(g_app->m_left_menu.Get())));
options->Add(std::make_shared<ui::SidebarEntryArray>("Set right-side menu"_i18n, side_menu_items, [menu_names](s64& index_out){
const auto e = menu_names[index_out];
if (g_app->m_right_menu.Get() != e) {
g_app->m_right_menu.Set(e);
App::Push(std::make_shared<ui::OptionBox>(
"Press OK to restart Sphaira"_i18n, "OK"_i18n, [](auto){
App::ExitRestart();
}
));
}
}, i18n::get(g_app->m_right_menu.Get())));
options->Add(std::make_shared<ui::SidebarEntryCallback>("Install options"_i18n, [left_side](){ options->Add(std::make_shared<ui::SidebarEntryCallback>("Install options"_i18n, [left_side](){
App::DisplayInstallOptions(left_side); App::DisplayInstallOptions(left_side);

View File

@@ -603,7 +603,7 @@ auto FindCaseInsensitive(std::string_view base, std::string_view term) -> bool {
} // namespace } // namespace
EntryMenu::EntryMenu(Entry& entry, const LazyImage& default_icon, Menu& menu) EntryMenu::EntryMenu(Entry& entry, const LazyImage& default_icon, Menu& menu)
: MenuBase{entry.title} : MenuBase{entry.title, MenuFlag_None}
, m_entry{entry} , m_entry{entry}
, m_default_icon{default_icon} , m_default_icon{default_icon}
, m_menu{menu} { , m_menu{menu} {
@@ -852,7 +852,7 @@ void EntryMenu::SetIndex(s64 index) {
} }
} }
Menu::Menu() : grid::Menu{"AppStore"_i18n} { Menu::Menu(u32 flags) : grid::Menu{"AppStore"_i18n, flags} {
fs::FsNativeSd fs; fs::FsNativeSd fs;
fs.CreateDirectoryRecursively("/switch/sphaira/cache/appstore/icons"); fs.CreateDirectoryRecursively("/switch/sphaira/cache/appstore/icons");
fs.CreateDirectoryRecursively("/switch/sphaira/cache/appstore/banners"); fs.CreateDirectoryRecursively("/switch/sphaira/cache/appstore/banners");

View File

@@ -6,7 +6,7 @@ namespace {
} // namespace } // namespace
Menu::Menu(const fs::FsPath& path) : MenuBase{path}, m_path{path} { Menu::Menu(const fs::FsPath& path) : MenuBase{path, MenuFlag_None}, m_path{path} {
SetAction(Button::B, Action{"Back"_i18n, [this](){ SetAction(Button::B, Action{"Back"_i18n, [this](){
SetPop(); SetPop();
}}); }});

View File

@@ -382,6 +382,11 @@ FsView::FsView(Menu* menu, const fs::FsPath& path, const FsEntry& entry, ViewSid
}}), }}),
std::make_pair(Button::B, Action{"Back"_i18n, [this](){ std::make_pair(Button::B, Action{"Back"_i18n, [this](){
if (!m_menu->IsTab() && App::GetApp()->m_controller.GotHeld(Button::R2)) {
m_menu->PromptIfShouldExit();
return;
}
std::string_view view{m_path}; std::string_view view{m_path};
if (view != m_fs->Root()) { if (view != m_fs->Root()) {
const auto end = view.find_last_of('/'); const auto end = view.find_last_of('/');
@@ -392,6 +397,10 @@ FsView::FsView(Menu* menu, const fs::FsPath& path, const FsEntry& entry, ViewSid
} else { } else {
Scan(view.substr(0, end), true); Scan(view.substr(0, end), true);
} }
} else {
if (!m_menu->IsTab()) {
m_menu->PromptIfShouldExit();
}
} }
}}), }}),
@@ -1390,7 +1399,7 @@ auto FsView::CheckIfUpdateFolder() -> Result {
if (!m_daybreak_path.has_value()) { if (!m_daybreak_path.has_value()) {
auto daybreak_path = DAYBREAK_PATH; auto daybreak_path = DAYBREAK_PATH;
if (!m_fs->FileExists(DAYBREAK_PATH)) { if (!m_fs->FileExists(DAYBREAK_PATH)) {
if (auto e = nro_find(m_menu->m_nro_entries, "Daybreak", "Atmosphere-NX", {}); e.has_value()) { if (auto e = nro_find(homebrew::GetNroEntries(), "Daybreak", "Atmosphere-NX", {}); e.has_value()) {
daybreak_path = e.value().path; daybreak_path = e.value().path;
} else { } else {
log_write("failed to find daybreak\n"); log_write("failed to find daybreak\n");
@@ -1893,11 +1902,17 @@ void FsView::DisplayAdvancedOptions() {
})); }));
} }
Menu::Menu(const std::vector<NroEntry>& nro_entries) : MenuBase{"FileBrowser"_i18n}, m_nro_entries{nro_entries} { Menu::Menu(u32 flags) : MenuBase{"FileBrowser"_i18n, flags} {
SetAction(Button::L3, Action{"Split"_i18n, [this](){ SetAction(Button::L3, Action{"Split"_i18n, [this](){
SetSplitScreen(IsSplitScreen() ^ 1); SetSplitScreen(IsSplitScreen() ^ 1);
}}); }});
if (!IsTab()) {
SetAction(Button::SELECT, Action{"Close"_i18n, [this](){
PromptIfShouldExit();
}});
}
view = view_left = std::make_shared<FsView>(this, ViewSide::Left); view = view_left = std::make_shared<FsView>(this, ViewSide::Left);
} }
@@ -2063,7 +2078,7 @@ void Menu::LoadAssocEntriesPath(const fs::FsPath& path) {
file_exists = view->m_fs->FileExists(assoc.path); file_exists = view->m_fs->FileExists(assoc.path);
} else { } else {
const auto nro_name = assoc.name + ".nro"; const auto nro_name = assoc.name + ".nro";
for (const auto& nro : m_nro_entries) { for (const auto& nro : homebrew::GetNroEntries()) {
const auto len = std::strlen(nro.path); const auto len = std::strlen(nro.path);
if (len < nro_name.length()) { if (len < nro_name.length()) {
continue; continue;
@@ -2160,4 +2175,19 @@ void Menu::RefreshViews() {
} }
} }
void Menu::PromptIfShouldExit() {
if (IsTab()) {
return;
}
App::Push(std::make_shared<ui::OptionBox>(
"Close FileBrowser?"_i18n,
"No"_i18n, "Yes"_i18n, 1, [this](auto op_index){
if (op_index && *op_index) {
SetPop();
}
}
));
}
} // namespace sphaira::ui::menu::filebrowser } // namespace sphaira::ui::menu::filebrowser

View File

@@ -142,7 +142,7 @@ void StreamFtp::Disable() {
m_active = false; m_active = false;
} }
Menu::Menu() : MenuBase{"FTP Install (EXPERIMENTAL)"_i18n} { Menu::Menu(u32 flags) : MenuBase{"FTP Install (EXPERIMENTAL)"_i18n, flags} {
SetAction(Button::B, Action{"Back"_i18n, [this](){ SetAction(Button::B, Action{"Back"_i18n, [this](){
SetPop(); SetPop();
}}); }});

View File

@@ -691,7 +691,7 @@ void ThreadData::Pop(std::vector<ThreadResultData>& out) {
m_result.clear(); m_result.clear();
} }
Menu::Menu() : grid::Menu{"Games"_i18n} { Menu::Menu(u32 flags) : grid::Menu{"Games"_i18n, flags} {
this->SetActions( this->SetActions(
std::make_pair(Button::L3, Action{[this](){ std::make_pair(Button::L3, Action{[this](){
if (m_entries.empty()) { if (m_entries.empty()) {

View File

@@ -390,7 +390,7 @@ auto ApplicationEntry::GetSize() const -> s64 {
return size; return size;
} }
Menu::Menu() : MenuBase{"GameCard"_i18n} { Menu::Menu(u32 flags) : MenuBase{"GameCard"_i18n, flags} {
this->SetActions( this->SetActions(
std::make_pair(Button::B, Action{"Back"_i18n, [this](){ std::make_pair(Button::B, Action{"Back"_i18n, [this](){
SetPop(); SetPop();

View File

@@ -222,7 +222,7 @@ auto DownloadAssetJson(ProgressBox* pbox, const std::string& url, GhApiEntry& ou
} // namespace } // namespace
Menu::Menu() : MenuBase{"GitHub"_i18n} { Menu::Menu(u32 flags) : MenuBase{"GitHub"_i18n, flags} {
fs::FsNativeSd().CreateDirectoryRecursively(CACHE_PATH); fs::FsNativeSd().CreateDirectoryRecursively(CACHE_PATH);
this->SetActions( this->SetActions(

View File

@@ -18,6 +18,8 @@
namespace sphaira::ui::menu::homebrew { namespace sphaira::ui::menu::homebrew {
namespace { namespace {
Menu* g_menu{};
auto GenerateStarPath(const fs::FsPath& nro_path) -> fs::FsPath { auto GenerateStarPath(const fs::FsPath& nro_path) -> fs::FsPath {
fs::FsPath out{}; fs::FsPath out{};
const auto dilem = std::strrchr(nro_path.s, '/'); const auto dilem = std::strrchr(nro_path.s, '/');
@@ -32,7 +34,17 @@ void FreeEntry(NVGcontext* vg, NroEntry& e) {
} // namespace } // namespace
Menu::Menu() : grid::Menu{"Homebrew"_i18n} { auto GetNroEntries() -> std::span<const NroEntry> {
if (!g_menu) {
return {};
}
return g_menu->GetHomebrewList();
}
Menu::Menu() : grid::Menu{"Homebrew"_i18n, MenuFlag_Tab} {
g_menu = this;
this->SetActions( this->SetActions(
std::make_pair(Button::A, Action{"Launch"_i18n, [this](){ std::make_pair(Button::A, Action{"Launch"_i18n, [this](){
nro_launch(m_entries[m_index].path); nro_launch(m_entries[m_index].path);
@@ -129,6 +141,7 @@ Menu::Menu() : grid::Menu{"Homebrew"_i18n} {
} }
Menu::~Menu() { Menu::~Menu() {
g_menu = {};
FreeEntries(); FreeEntries();
} }

View File

@@ -75,7 +75,7 @@ void irsConvertConfigNormalToEx(const IrsImageTransferProcessorConfig* nor, IrsI
} // namespace } // namespace
Menu::Menu() : MenuBase{"Irs"_i18n} { Menu::Menu(u32 flags) : MenuBase{"Irs"_i18n, flags} {
SetAction(Button::B, Action{"Back"_i18n, [this](){ SetAction(Button::B, Action{"Back"_i18n, [this](){
SetPop(); SetPop();
}}); }});

View File

@@ -6,6 +6,8 @@
#include "ui/progress_box.hpp" #include "ui/progress_box.hpp"
#include "ui/error_box.hpp" #include "ui/error_box.hpp"
#include "ui/menus/homebrew.hpp"
#include "ui/menus/filebrowser.hpp"
#include "ui/menus/irs_menu.hpp" #include "ui/menus/irs_menu.hpp"
#include "ui/menus/themezer.hpp" #include "ui/menus/themezer.hpp"
#include "ui/menus/ghdl.hpp" #include "ui/menus/ghdl.hpp"
@@ -32,13 +34,14 @@ constexpr const char* GITHUB_URL{"https://api.github.com/repos/ITotalJustice/sph
constexpr fs::FsPath CACHE_PATH{"/switch/sphaira/cache/sphaira_latest.json"}; constexpr fs::FsPath CACHE_PATH{"/switch/sphaira/cache/sphaira_latest.json"};
template<typename T> template<typename T>
auto MiscMenuFuncGenerator() { auto MiscMenuFuncGenerator(u32 flags) {
return std::make_shared<T>(); return std::make_shared<T>(flags);
} }
const MiscMenuEntry MISC_MENU_ENTRIES[] = { const MiscMenuEntry MISC_MENU_ENTRIES[] = {
{ .name = "Appstore", .title = "Appstore", .func = MiscMenuFuncGenerator<ui::menu::appstore::Menu>, .flag = MiscMenuFlag_Shortcut }, { .name = "Appstore", .title = "Appstore", .func = MiscMenuFuncGenerator<ui::menu::appstore::Menu>, .flag = MiscMenuFlag_Shortcut },
{ .name = "Games", .title = "Games", .func = MiscMenuFuncGenerator<ui::menu::game::Menu>, .flag = MiscMenuFlag_Shortcut }, { .name = "Games", .title = "Games", .func = MiscMenuFuncGenerator<ui::menu::game::Menu>, .flag = MiscMenuFlag_Shortcut },
{ .name = "FileBrowser", .title = "FileBrowser", .func = MiscMenuFuncGenerator<ui::menu::filebrowser::Menu>, .flag = MiscMenuFlag_Shortcut },
{ .name = "Themezer", .title = "Themezer", .func = MiscMenuFuncGenerator<ui::menu::themezer::Menu>, .flag = MiscMenuFlag_Shortcut }, { .name = "Themezer", .title = "Themezer", .func = MiscMenuFuncGenerator<ui::menu::themezer::Menu>, .flag = MiscMenuFlag_Shortcut },
{ .name = "GitHub", .title = "GitHub", .func = MiscMenuFuncGenerator<ui::menu::gh::Menu>, .flag = MiscMenuFlag_Shortcut }, { .name = "GitHub", .title = "GitHub", .func = MiscMenuFuncGenerator<ui::menu::gh::Menu>, .flag = MiscMenuFlag_Shortcut },
{ .name = "FTP", .title = "FTP Install", .func = MiscMenuFuncGenerator<ui::menu::ftp::Menu>, .flag = MiscMenuFlag_Install }, { .name = "FTP", .title = "FTP Install", .func = MiscMenuFuncGenerator<ui::menu::ftp::Menu>, .flag = MiscMenuFlag_Install },
@@ -149,16 +152,41 @@ auto InstallUpdate(ProgressBox* pbox, const std::string url, const std::string v
R_SUCCEED(); R_SUCCEED();
} }
auto CreateRightSideMenu() -> std::shared_ptr<MenuBase> { auto CreateLeftSideMenu(std::string& name_out) -> std::shared_ptr<MenuBase> {
const auto name = App::GetApp()->m_right_side_menu.Get(); const auto name = App::GetApp()->m_left_menu.Get();
for (auto& e : GetMiscMenuEntries()) { for (auto& e : GetMiscMenuEntries()) {
if (e.name == name) { if (e.name == name) {
return e.func(); name_out = name;
return e.func(MenuFlag_Tab);
} }
} }
return std::make_shared<ui::menu::appstore::Menu>(); name_out = "FileBrowser";
return std::make_shared<ui::menu::filebrowser::Menu>(MenuFlag_Tab);
}
auto CreateRightSideMenu(std::string_view left_name) -> std::shared_ptr<MenuBase> {
const auto name = App::GetApp()->m_right_menu.Get();
// handle if the user tries to mount the same menu twice.
if (name == left_name) {
// check if we can mount the default.
if (left_name != "AppStore") {
return std::make_shared<ui::menu::appstore::Menu>(MenuFlag_Tab);
} else {
// otherwise, fallback to left side default.
return std::make_shared<ui::menu::filebrowser::Menu>(MenuFlag_Tab);
}
}
for (auto& e : GetMiscMenuEntries()) {
if (e.name == name) {
return e.func(MenuFlag_Tab);
}
}
return std::make_shared<ui::menu::appstore::Menu>(MenuFlag_Tab);
} }
} // namespace } // namespace
@@ -319,10 +347,13 @@ MainMenu::MainMenu() {
}}) }})
); );
m_homebrew_menu = std::make_shared<homebrew::Menu>(); m_centre_menu = std::make_shared<homebrew::Menu>();
m_filebrowser_menu = std::make_shared<filebrowser::Menu>(m_homebrew_menu->GetHomebrewList()); m_current_menu = m_centre_menu;
m_right_side_menu = CreateRightSideMenu();
m_current_menu = m_homebrew_menu;
std::string left_side_name;
m_left_menu = CreateLeftSideMenu(left_side_name);
m_right_menu = CreateRightSideMenu(left_side_name);
AddOnLRPress(); AddOnLRPress();
@@ -355,11 +386,11 @@ void MainMenu::OnFocusLost() {
void MainMenu::OnLRPress(std::shared_ptr<MenuBase> menu, Button b) { void MainMenu::OnLRPress(std::shared_ptr<MenuBase> menu, Button b) {
m_current_menu->OnFocusLost(); m_current_menu->OnFocusLost();
if (m_current_menu == m_homebrew_menu) { if (m_current_menu == m_centre_menu) {
m_current_menu = menu; m_current_menu = menu;
RemoveAction(b); RemoveAction(b);
} else { } else {
m_current_menu = m_homebrew_menu; m_current_menu = m_centre_menu;
} }
AddOnLRPress(); AddOnLRPress();
@@ -371,17 +402,17 @@ void MainMenu::OnLRPress(std::shared_ptr<MenuBase> menu, Button b) {
} }
void MainMenu::AddOnLRPress() { void MainMenu::AddOnLRPress() {
if (m_current_menu != m_filebrowser_menu) { if (m_current_menu != m_left_menu) {
const auto label = m_current_menu == m_homebrew_menu ? m_filebrowser_menu->GetShortTitle() : m_homebrew_menu->GetShortTitle(); const auto label = m_current_menu == m_centre_menu ? m_left_menu->GetShortTitle() : m_centre_menu->GetShortTitle();
SetAction(Button::L, Action{i18n::get(label), [this]{ SetAction(Button::L, Action{i18n::get(label), [this]{
OnLRPress(m_filebrowser_menu, Button::L); OnLRPress(m_left_menu, Button::L);
}}); }});
} }
if (m_current_menu != m_right_side_menu) { if (m_current_menu != m_right_menu) {
const auto label = m_current_menu == m_homebrew_menu ? m_right_side_menu->GetShortTitle() : m_homebrew_menu->GetShortTitle(); const auto label = m_current_menu == m_centre_menu ? m_right_menu->GetShortTitle() : m_centre_menu->GetShortTitle();
SetAction(Button::R, Action{i18n::get(label), [this]{ SetAction(Button::R, Action{i18n::get(label), [this]{
OnLRPress(m_right_side_menu, Button::R); OnLRPress(m_right_menu, Button::R);
}}); }});
} }
} }

View File

@@ -40,7 +40,7 @@ auto MenuBase::GetPolledData(bool force_refresh) -> PolledData {
return data; return data;
} }
MenuBase::MenuBase(std::string title) : m_title{title} { MenuBase::MenuBase(const std::string& title, u32 flags) : m_title{title}, m_flags{flags} {
// this->SetParent(this); // this->SetParent(this);
this->SetPos(30, 87, 1220 - 30, 646 - 87); this->SetPos(30, 87, 1220 - 30, 646 - 87);
SetAction(Button::START, Action{App::Exit}); SetAction(Button::START, Action{App::Exit});

View File

@@ -346,7 +346,7 @@ LazyImage::~LazyImage() {
} }
} }
Menu::Menu() : MenuBase{"Themezer"_i18n} { Menu::Menu(u32 flags) : MenuBase{"Themezer"_i18n, flags} {
fs::FsNativeSd().CreateDirectoryRecursively(CACHE_PATH); fs::FsNativeSd().CreateDirectoryRecursively(CACHE_PATH);
SetAction(Button::B, Action{"Back"_i18n, [this]{ SetAction(Button::B, Action{"Back"_i18n, [this]{

View File

@@ -51,7 +51,7 @@ void thread_func(void* user) {
} // namespace } // namespace
Menu::Menu() : MenuBase{"USB"_i18n} { Menu::Menu(u32 flags) : MenuBase{"USB"_i18n, flags} {
SetAction(Button::B, Action{"Back"_i18n, [this](){ SetAction(Button::B, Action{"Back"_i18n, [this](){
SetPop(); SetPop();
}}); }});