From ca47fc1f8904f9b125aad0899e8809f723b6a0c6 Mon Sep 17 00:00:00 2001 From: ITotalJustice <47043333+ITotalJustice@users.noreply.github.com> Date: Sat, 3 May 2025 15:08:25 +0100 Subject: [PATCH] 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. --- sphaira/include/ui/menus/game_menu.hpp | 14 +++++ sphaira/source/ui/menus/game_menu.cpp | 75 ++++++++++++++++++++++++-- 2 files changed, 84 insertions(+), 5 deletions(-) diff --git a/sphaira/include/ui/menus/game_menu.hpp b/sphaira/include/ui/menus/game_menu.hpp index 0166924..45bad0c 100644 --- a/sphaira/include/ui/menus/game_menu.hpp +++ b/sphaira/include/ui/menus/game_menu.hpp @@ -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 m_entries{}; s64 m_index{}; // where i am in the array std::unique_ptr 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}; }; diff --git a/sphaira/source/ui/menus/game_menu.cpp b/sphaira/source/ui/menus/game_menu.cpp index 02ae0c7..04ff129 100644 --- a/sphaira/source/ui/menus/game_menu.cpp +++ b/sphaira/source/ui/menus/game_menu.cpp @@ -114,6 +114,33 @@ Menu::Menu() : MenuBase{"Games"_i18n} { ON_SCOPE_EXIT(App::Push(options)); if (m_entries.size()) { + options->Add(std::make_shared("Sort By"_i18n, [this](){ + auto options = std::make_shared("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("Sort"_i18n, sort_items, [this, sort_items](s64& index_out){ + m_sort.Set(index_out); + SortAndFindLastFile(); + }, m_sort.Get())); + + options->Add(std::make_shared("Order"_i18n, order_items, [this, order_items](s64& index_out){ + m_order.Set(index_out); + SortAndFindLastFile(); + }, m_order.Get())); + + options->Add(std::make_shared("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("Info"_i18n, [this](){ @@ -199,11 +226,6 @@ Menu::Menu() : MenuBase{"Games"_i18n} { }, m_entries[m_index].image )); }, true)); - - options->Add(std::make_shared("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();