add (limited) sort options to game menu.

getting the list of title_ids is very fast (less than 1ms), however parsing the control info, such as title names
is very slow.
depending on how many games the user has, blocking until we read all control info can take several seconds...
we would only need to block if the user wants to sort by name.
normally, we lazy load the control data, so we don't suffer from slow load times at all.
i decided that its not worth slowing the whole system down just to give the option to sort by name.
This commit is contained in:
ITotalJustice
2025-05-03 15:08:25 +01:00
parent 16a2c84edd
commit ca47fc1f89
2 changed files with 84 additions and 5 deletions

View File

@@ -41,6 +41,15 @@ struct Entry {
}
};
enum SortType {
SortType_Updated,
};
enum OrderType {
OrderType_Descending,
OrderType_Ascending,
};
struct Menu final : MenuBase {
Menu();
~Menu();
@@ -53,6 +62,8 @@ struct Menu final : MenuBase {
private:
void SetIndex(s64 index);
void ScanHomebrew();
void Sort();
void SortAndFindLastFile();
void FreeEntries();
private:
@@ -61,12 +72,15 @@ private:
std::vector<Entry> m_entries{};
s64 m_index{}; // where i am in the array
std::unique_ptr<List> m_list{};
bool m_is_reversed{};
bool m_dirty{};
ScrollingText m_scroll_name{};
ScrollingText m_scroll_author{};
ScrollingText m_scroll_version{};
option::OptionLong m_sort{INI_SECTION, "sort", SortType::SortType_Updated};
option::OptionLong m_order{INI_SECTION, "order", OrderType::OrderType_Descending};
option::OptionBool m_hide_forwarders{INI_SECTION, "hide_forwarders", false};
};

View File

@@ -114,6 +114,33 @@ Menu::Menu() : MenuBase{"Games"_i18n} {
ON_SCOPE_EXIT(App::Push(options));
if (m_entries.size()) {
options->Add(std::make_shared<SidebarEntryCallback>("Sort By"_i18n, [this](){
auto options = std::make_shared<Sidebar>("Sort Options"_i18n, Sidebar::Side::RIGHT);
ON_SCOPE_EXIT(App::Push(options));
SidebarEntryArray::Items sort_items;
sort_items.push_back("Updated"_i18n);
SidebarEntryArray::Items order_items;
order_items.push_back("Descending"_i18n);
order_items.push_back("Ascending"_i18n);
options->Add(std::make_shared<SidebarEntryArray>("Sort"_i18n, sort_items, [this, sort_items](s64& index_out){
m_sort.Set(index_out);
SortAndFindLastFile();
}, m_sort.Get()));
options->Add(std::make_shared<SidebarEntryArray>("Order"_i18n, order_items, [this, order_items](s64& index_out){
m_order.Set(index_out);
SortAndFindLastFile();
}, m_order.Get()));
options->Add(std::make_shared<SidebarEntryBool>("Hide forwarders"_i18n, m_hide_forwarders.Get(), [this](bool& v_out){
m_hide_forwarders.Set(v_out);
m_dirty = true;
}));
}));
#if 0
options->Add(std::make_shared<SidebarEntryCallback>("Info"_i18n, [this](){
@@ -199,11 +226,6 @@ Menu::Menu() : MenuBase{"Games"_i18n} {
}, m_entries[m_index].image
));
}, true));
options->Add(std::make_shared<SidebarEntryBool>("Hide forwarders"_i18n, m_hide_forwarders.Get(), [this](bool& v_out){
m_hide_forwarders.Set(v_out);
m_dirty = true;
}));
}
}})
);
@@ -341,11 +363,54 @@ void Menu::ScanHomebrew() {
offset += record_count;
}
m_is_reversed = false;
m_dirty = false;
log_write("games found: %zu time_taken: %.2f seconds %zu ms %zu ns\n", m_entries.size(), ts.GetSecondsD(), ts.GetMs(), ts.GetNs());
this->Sort();
SetIndex(0);
}
void Menu::Sort() {
// const auto sort = m_sort.Get();
const auto order = m_order.Get();
if (order == OrderType_Ascending) {
if (!m_is_reversed) {
std::reverse(m_entries.begin(), m_entries.end());
m_is_reversed = true;
}
} else {
if (m_is_reversed) {
std::reverse(m_entries.begin(), m_entries.end());
m_is_reversed = false;
}
}
}
void Menu::SortAndFindLastFile() {
const auto app_id = m_entries[m_index].app_id;
Sort();
SetIndex(0);
s64 index = -1;
for (u64 i = 0; i < m_entries.size(); i++) {
if (app_id == m_entries[i].app_id) {
index = i;
break;
}
}
if (index >= 0) {
// guesstimate where the position is
if (index >= 9) {
m_list->SetYoff((((index - 9) + 3) / 3) * m_list->GetMaxY());
} else {
m_list->SetYoff(0);
}
SetIndex(index);
}
}
void Menu::FreeEntries() {
auto vg = App::GetVg();