display install options by default, but warn the user that installing is disabled an instruct them on how to enable.

This commit is contained in:
ITotalJustice
2025-07-31 02:48:19 +01:00
parent 92d747a0f5
commit c67266fe1a
6 changed files with 98 additions and 45 deletions

View File

@@ -339,6 +339,10 @@ public:
double m_delta_time{};
static constexpr const char* INSTALL_DEPENDS_STR =
"Installing is disabled.\n\n"
"Enable in the options by selecting Menu (Y) -> Advanced -> Install options -> Enable.";
private: // from nanovg decko3d example by adubbz
static constexpr unsigned NumFramebuffers = 2;
static constexpr unsigned StaticCmdSize = 0x1000;

View File

@@ -11,17 +11,46 @@
namespace sphaira::ui {
class SidebarEntryBase : public Widget {
public:
using DependsCallback = std::function<bool(void)>;
public:
explicit SidebarEntryBase(const std::string& title, const std::string& info);
using Widget::Draw;
virtual void Draw(NVGcontext* vg, Theme* theme, const Vec4& root_pos, bool left);
void Depends(const DependsCallback& callback, const std::string& depends_info) {
m_depends_callback = callback;
m_depends_info = depends_info;
}
void Depends(bool& value, const std::string& depends_info) {
m_depends_callback = [&value](){ return value; };
m_depends_info = depends_info;
}
void Depends(option::OptionBool& value, const std::string& depends_info) {
m_depends_callback = [&value](){ return value.Get(); };
m_depends_info = depends_info;
}
protected:
auto IsEnabled() -> bool {
if (m_depends_callback) {
return m_depends_callback();
}
return true;
}
protected:
std::string m_title;
private:
std::string m_info;
std::string m_info{};
std::string m_depends_info{};
DependsCallback m_depends_callback{};
ScrollingText m_scolling_title{};
};
@@ -101,11 +130,11 @@ public:
auto OnFocusGained() noexcept -> void override;
auto OnFocusLost() noexcept -> void override;
void Add(std::unique_ptr<SidebarEntryBase>&& entry);
auto Add(std::unique_ptr<SidebarEntryBase>&& entry) -> SidebarEntryBase*;
template<DerivedFromSidebarBase T, typename... Args>
void Add(Args&&... args) {
Add(std::make_unique<T>(std::forward<Args>(args)...));
auto Add(Args&&... args) -> SidebarEntryBase* {
return Add(std::make_unique<T>(std::forward<Args>(args)...));
}
private:

View File

@@ -1658,13 +1658,15 @@ void App::DisplayMiscOptions(bool left_side) {
continue;
} else if (e.name == g_app->m_right_menu.Get()) {
continue;
} else if (e.IsInstall() && !App::GetInstallEnable()) {
continue;
}
options->Add<ui::SidebarEntryCallback>(i18n::get(e.title), [e](){
auto entry = options->Add<ui::SidebarEntryCallback>(i18n::get(e.title), [e](){
App::Push(e.func(ui::menu::MenuFlag_None));
}, i18n::get(e.info));
if (e.IsInstall()) {
entry->Depends(App::GetInstallEnable, i18n::get(App::INSTALL_DEPENDS_STR));
}
}
if (App::IsApplication()) {
@@ -1714,10 +1716,6 @@ void App::DisplayAdvancedOptions(bool left_side) {
continue;
}
if (e.IsInstall() && !App::GetInstallEnable()) {
continue;
}
menu_names.emplace_back(e.name);
menu_items.push_back(i18n::get(e.name));
}

View File

@@ -359,7 +359,7 @@ FsView::FsView(Menu* menu, const fs::FsPath& path, const FsEntry& entry, ViewSid
nro_launch(GetNewPathCurrent());
}
});
} else if (App::GetInstallEnable() && IsExtension(entry.GetExtension(), INSTALL_EXTENSIONS)) {
} else if (IsExtension(entry.GetExtension(), INSTALL_EXTENSIONS)) {
InstallFiles();
} else if (IsSd()) {
const auto assoc_list = m_menu->FindFileAssocFor();
@@ -703,6 +703,16 @@ void FsView::InstallForwarder() {
}
void FsView::InstallFiles() {
if (!App::GetInstallEnable()) {
App::Push<ui::OptionBox>(
"Install disabled...\n"
"Please enable installing via the install options."_i18n,
"OK"_i18n
);
return;
}
const auto targets = GetSelectedEntries();
App::Push<OptionBox>("Install Selected files?"_i18n, "No"_i18n, "Yes"_i18n, 0, [this, targets](auto op_index){
@@ -1674,17 +1684,18 @@ void FsView::DisplayOptions() {
};
// if install is enabled, check if all currently selected files are installable.
if (m_entries_current.size() && App::GetInstallEnable()) {
if (m_entries_current.size()) {
if (check_all_ext(INSTALL_EXTENSIONS)) {
options->Add<SidebarEntryCallback>("Install"_i18n, [this](){
auto entry = options->Add<SidebarEntryCallback>("Install"_i18n, [this](){
InstallFiles();
});
entry->Depends(App::GetInstallEnable, i18n::get(App::INSTALL_DEPENDS_STR));
}
}
if (IsSd() && m_entries_current.size() && !m_selected_count) {
if (App::GetInstallEnable() && GetEntry().IsFile() && (IsSamePath(GetEntry().GetExtension(), "nro") || !m_menu->FindFileAssocFor().empty())) {
options->Add<SidebarEntryCallback>("Install Forwarder"_i18n, [this](){;
if (GetEntry().IsFile() && (IsSamePath(GetEntry().GetExtension(), "nro") || !m_menu->FindFileAssocFor().empty())) {
auto entry = options->Add<SidebarEntryCallback>("Install Forwarder"_i18n, [this](){;
if (App::GetInstallPrompt()) {
App::Push<OptionBox>(
"WARNING: Installing forwarders will lead to a ban!"_i18n,
@@ -1698,6 +1709,7 @@ void FsView::DisplayOptions() {
InstallForwarder();
}
});
entry->Depends(App::GetInstallEnable, i18n::get(App::INSTALL_DEPENDS_STR));
}
}

View File

@@ -123,22 +123,22 @@ Menu::Menu() : grid::Menu{"Homebrew"_i18n, MenuFlag_Tab} {
);
}, true);
if (App::GetInstallEnable()) {
options->Add<SidebarEntryCallback>("Install Forwarder"_i18n, [this](){
if (App::GetInstallPrompt()) {
App::Push<OptionBox>(
"WARNING: Installing forwarders will lead to a ban!"_i18n,
"Back"_i18n, "Install"_i18n, 0, [this](auto op_index){
if (op_index && *op_index) {
InstallHomebrew();
}
}, m_entries[m_index].image
);
} else {
InstallHomebrew();
}
}, true);
}
auto forwarder_entry = options->Add<SidebarEntryCallback>("Install Forwarder"_i18n, [this](){
if (App::GetInstallPrompt()) {
App::Push<OptionBox>(
"WARNING: Installing forwarders will lead to a ban!"_i18n,
"Back"_i18n, "Install"_i18n, 0, [this](auto op_index){
if (op_index && *op_index) {
InstallHomebrew();
}
}, m_entries[m_index].image
);
} else {
InstallHomebrew();
}
}, true);
forwarder_entry->Depends(App::GetInstallEnable, i18n::get(App::INSTALL_DEPENDS_STR));
}
}})
);

View File

@@ -35,7 +35,9 @@ void SidebarEntryBase::Draw(NVGcontext* vg, Theme* theme, const Vec4& root_pos,
if (HasFocus()) {
gfx::drawRectOutline(vg, theme, 4.f, m_pos);
if (!m_info.empty()) {
const auto& info = IsEnabled() ? m_info : m_depends_info;
if (!info.empty()) {
// reset clip here as the box will draw oob.
nvgSave(vg);
nvgScissor(vg, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
@@ -62,7 +64,7 @@ void SidebarEntryBase::Draw(NVGcontext* vg, Theme* theme, const Vec4& root_pos,
nvgFontSize(vg, info_font_size);
nvgTextAlign(vg, NVG_ALIGN_LEFT | NVG_ALIGN_TOP);
nvgTextLineHeight(vg, 1.7);
nvgTextBoxBounds(vg, 0, 0, end_w, m_info.c_str(), nullptr, bounds);
nvgTextBoxBounds(vg, 0, 0, end_w, info.c_str(), nullptr, bounds);
info_box.h = pad_after_title + info_pad * 2 + bounds[3] - bounds[1];
gfx::drawRect(vg, info_box, theme->GetColour(ThemeEntryID_SIDEBAR), 5);
@@ -71,7 +73,7 @@ void SidebarEntryBase::Draw(NVGcontext* vg, Theme* theme, const Vec4& root_pos,
m_scolling_title.Draw(vg, true, x, y, end_w, title_font_size, NVG_ALIGN_LEFT | NVG_ALIGN_TOP, theme->GetColour(ThemeEntryID_TEXT), m_title.c_str());
y += pad_after_title;
gfx::drawTextBox(vg, x, y, info_font_size, end_w, theme->GetColour(ThemeEntryID_TEXT), m_info.c_str());
gfx::drawTextBox(vg, x, y, info_font_size, end_w, theme->GetColour(ThemeEntryID_TEXT), info.c_str());
}
}
}
@@ -91,9 +93,10 @@ SidebarEntryBool::SidebarEntryBool(const std::string& title, bool option, Callba
}
SetAction(Button::A, Action{"OK"_i18n, [this](){
if (IsEnabled()) {
m_option ^= 1;
m_callback(m_option);
}
} }
});
}
@@ -126,7 +129,8 @@ void SidebarEntryBool::Draw(NVGcontext* vg, Theme* theme, const Vec4& root_pos,
// } else {
// }
gfx::drawText(vg, Vec2{m_pos.x + 15.f, m_pos.y + (m_pos.h / 2.f)}, 20.f, theme->GetColour(ThemeEntryID_TEXT), m_title.c_str(), NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE);
const auto colour_id = IsEnabled() ? ThemeEntryID_TEXT : ThemeEntryID_TEXT_INFO;
gfx::drawText(vg, Vec2{m_pos.x + 15.f, m_pos.y + (m_pos.h / 2.f)}, 20.f, theme->GetColour(colour_id), m_title.c_str(), NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE);
if (m_option == true) {
gfx::drawText(vg, Vec2{m_pos.x + m_pos.w - 15.f, m_pos.y + (m_pos.h / 2.f)}, 20.f, theme->GetColour(ThemeEntryID_TEXT_SELECTED), m_true_str.c_str(), NVG_ALIGN_RIGHT | NVG_ALIGN_MIDDLE);
@@ -140,11 +144,12 @@ SidebarEntryCallback::SidebarEntryCallback(const std::string& title, Callback cb
, m_callback{cb}
, m_pop_on_click{pop_on_click} {
SetAction(Button::A, Action{"OK"_i18n, [this](){
if (IsEnabled()) {
m_callback();
if (m_pop_on_click) {
SetPop();
}
}
}}
});
}
@@ -156,10 +161,11 @@ SidebarEntryCallback::SidebarEntryCallback(const std::string& title, Callback cb
void SidebarEntryCallback::Draw(NVGcontext* vg, Theme* theme, const Vec4& root_pos, bool left) {
SidebarEntryBase::Draw(vg, theme, root_pos, left);
const auto colour_id = IsEnabled() ? ThemeEntryID_TEXT : ThemeEntryID_TEXT_INFO;
// if (HasFocus()) {
// gfx::drawText(vg, Vec2{m_pos.x + 15.f, m_pos.y + (m_pos.h / 2.f)}, 20.f, theme->GetColour(ThemeEntryID_TEXT_SELECTED), m_title.c_str(), NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE);
// } else {
gfx::drawText(vg, Vec2{m_pos.x + 15.f, m_pos.y + (m_pos.h / 2.f)}, 20.f, theme->GetColour(ThemeEntryID_TEXT), m_title.c_str(), NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE);
gfx::drawText(vg, Vec2{m_pos.x + 15.f, m_pos.y + (m_pos.h / 2.f)}, 20.f, theme->GetColour(colour_id), m_title.c_str(), NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE);
// }
}
@@ -205,15 +211,17 @@ SidebarEntryArray::SidebarEntryArray(const std::string& title, const Items& item
};
SetAction(Button::A, Action{"OK"_i18n, [this](){
if (IsEnabled()) {
// m_callback(m_index);
m_list_callback();
}
}}
});
}
void SidebarEntryArray::Draw(NVGcontext* vg, Theme* theme, const Vec4& root_pos, bool left) {
SidebarEntryBase::Draw(vg, theme, root_pos, left);
const auto colour_id = IsEnabled() ? ThemeEntryID_TEXT : ThemeEntryID_TEXT_INFO;
const auto& text_entry = m_items[m_index];
// scrolling text
@@ -251,7 +259,7 @@ void SidebarEntryArray::Draw(NVGcontext* vg, Theme* theme, const Vec4& root_pos,
}
const Vec2 key_text_pos{m_pos.x + 15.f, m_pos.y + (m_pos.h / 2.f)};
gfx::drawText(vg, key_text_pos, 20.f, theme->GetColour(ThemeEntryID_TEXT), m_title.c_str(), NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE);
gfx::drawText(vg, key_text_pos, 20.f, theme->GetColour(colour_id), m_title.c_str(), NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE);
nvgSave(vg);
const float xpos = m_pos.x + m_pos.w - 15.f - std::min(max_off, bounds[2]);
@@ -389,15 +397,17 @@ auto Sidebar::OnFocusLost() noexcept -> void {
SetHidden(true);
}
void Sidebar::Add(std::unique_ptr<SidebarEntryBase>&& entry) {
m_items.emplace_back(std::forward<decltype(entry)>(entry));
m_items.back()->SetPos(m_base_pos);
auto Sidebar::Add(std::unique_ptr<SidebarEntryBase>&& _entry) -> SidebarEntryBase* {
auto& entry = m_items.emplace_back(std::forward<decltype(_entry)>(_entry));
entry->SetPos(m_base_pos);
// give focus to first entry.
if (m_items.size() == 1) {
m_items[m_index]->OnFocusGained();
entry->OnFocusGained();
SetupButtons();
}
return entry.get();
}
void Sidebar::SetIndex(s64 index) {