diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c5bc563..a1fdc20 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -16,8 +16,8 @@ jobs: - name: Update packages and install Python run: | sudo -n apt-get update - sudo -n apt-get upgrade -y patch autoconf automake diffutils pkgconf fakeroot git maven file tar bzip2 zstd python3 python3-pip - python3 -m pip install requests + sudo -n apt-get upgrade -y patch autoconf automake diffutils pkgconf fakeroot git maven file tar bzip2 zstd python python-pip + python -m pip install requests sudo -n dkp-pacman --noconfirm -U \ "https://wii.leseratte10.de/devkitPro/other-stuff/dkp-toolchain-vars-1.0.2-1-any.pkg.tar.xz" diff --git a/libs/Plutonium b/libs/Plutonium index b688aba..2af5676 160000 --- a/libs/Plutonium +++ b/libs/Plutonium @@ -1 +1 @@ -Subproject commit b688aba591fafc5a9c629027d33dde53ecef1577 +Subproject commit 2af5676542d83472c670a7e4973a220680d5d6af diff --git a/libs/uCommon/include/ul/cfg/cfg_Config.hpp b/libs/uCommon/include/ul/cfg/cfg_Config.hpp index 359cfdd..bddfe5b 100644 --- a/libs/uCommon/include/ul/cfg/cfg_Config.hpp +++ b/libs/uCommon/include/ul/cfg/cfg_Config.hpp @@ -20,9 +20,14 @@ namespace ul::cfg { std::string name; ThemeManifest manifest; - inline bool IsValid() { + inline bool IsValid() const { return !this->name.empty(); } + + inline bool IsSame(const Theme &other) const { + // Compare filenames, those must be unique + return other.name == this->name; + } }; enum class ConfigEntryId : u8 { diff --git a/projects/uMenu/romfs/lang/en.json b/projects/uMenu/romfs/lang/en.json index a1e22a5..fecae4d 100644 --- a/projects/uMenu/romfs/lang/en.json +++ b/projects/uMenu/romfs/lang/en.json @@ -79,7 +79,7 @@ "startup_welcome_info": "Welcome! Please select a user.", "startup_add_user": "Add user", "theme_info_text": "Available themes", - "theme_no_active": "You don't currently have a custom theme.", + "theme_no_active": "You don't currently have an active theme.", "theme_reset": "Reset theme (default theme)", "theme_reset_conf": "Would you like to return to uLaunch's default theme?", "theme_changed": "uLaunch's theme was reset.", diff --git a/projects/uMenu/source/ul/menu/ui/ui_ThemesMenuLayout.cpp b/projects/uMenu/source/ul/menu/ui/ui_ThemesMenuLayout.cpp index 8974214..6aec5dc 100644 --- a/projects/uMenu/source/ul/menu/ui/ui_ThemesMenuLayout.cpp +++ b/projects/uMenu/source/ul/menu/ui/ui_ThemesMenuLayout.cpp @@ -48,28 +48,43 @@ namespace ul::menu::ui { this->loaded_themes.clear(); this->loaded_themes = cfg::FindThemes(); - - auto theme_reset_item = pu::ui::elm::MenuItem::New(GetLanguageString("theme_reset")); - theme_reset_item->AddOnKey(std::bind(&ThemesMenuLayout::theme_DefaultKey, this)); - theme_reset_item->SetColor(g_MenuApplication->GetTextColor()); - theme_reset_item->SetIcon(GetLogoTexture()); - this->themes_menu->AddItem(theme_reset_item); + this->loaded_themes.insert(this->loaded_themes.begin(), cfg::Theme{}); // For the "default theme" entry + + // Move active theme to top + for(u32 i = 0; i < this->loaded_themes.size(); i++) { + const auto theme = this->loaded_themes.at(i); + if(theme.IsSame(g_ActiveTheme)) { + this->loaded_themes.erase(this->loaded_themes.begin() + i); + this->loaded_themes.insert(this->loaded_themes.begin(), theme); + break; + } + } for(const auto &theme: this->loaded_themes) { - std::string theme_icon_path; - const auto rc = cfg::TryCacheLoadThemeIcon(theme, theme_icon_path); - if(R_FAILED(rc)) { - UL_LOG_INFO("Theme '%s' unable to load image: %s", theme.name.c_str(), util::FormatResultDisplay(rc).c_str()); - } + if(theme.IsValid()) { + std::string theme_icon_path; + const auto rc = cfg::TryCacheLoadThemeIcon(theme, theme_icon_path); + if(R_FAILED(rc)) { + UL_LOG_WARN("Theme '%s' unable to load image: %s", theme.name.c_str(), util::FormatResultDisplay(rc).c_str()); + } - auto theme_icon = pu::sdl2::TextureHandle::New(pu::ui::render::LoadImage(theme_icon_path)); - this->loaded_theme_icons.push_back(theme_icon); + auto theme_icon = pu::sdl2::TextureHandle::New(pu::ui::render::LoadImage(theme_icon_path)); + this->loaded_theme_icons.push_back(theme_icon); - auto theme_item = pu::ui::elm::MenuItem::New(theme.manifest.name + " (v" + theme.manifest.release + ", " + theme.manifest.author + ")"); - theme_item->AddOnKey(std::bind(&ThemesMenuLayout::theme_DefaultKey, this)); - theme_item->SetColor(g_MenuApplication->GetTextColor()); - theme_item->SetIcon(theme_icon); - this->themes_menu->AddItem(theme_item); + auto theme_item = pu::ui::elm::MenuItem::New(theme.manifest.name + " (v" + theme.manifest.release + ", " + theme.manifest.author + ")"); + theme_item->AddOnKey(std::bind(&ThemesMenuLayout::theme_DefaultKey, this)); + theme_item->SetColor(g_MenuApplication->GetTextColor()); + theme_item->SetIcon(theme_icon); + this->themes_menu->AddItem(theme_item); + } + else { + this->loaded_theme_icons.emplace_back(); + auto theme_reset_item = pu::ui::elm::MenuItem::New(GetLanguageString("theme_reset")); + theme_reset_item->AddOnKey(std::bind(&ThemesMenuLayout::theme_DefaultKey, this)); + theme_reset_item->SetColor(g_MenuApplication->GetTextColor()); + theme_reset_item->SetIcon(GetLogoTexture()); + this->themes_menu->AddItem(theme_reset_item); + } } this->themes_menu->SetSelectedIndex(0); @@ -77,11 +92,19 @@ namespace ul::menu::ui { void ThemesMenuLayout::theme_DefaultKey() { const auto idx = this->themes_menu->GetSelectedIndex(); - if(idx == 0) { - if(g_ActiveTheme.IsValid()) { - const auto option = g_MenuApplication->DisplayDialog(GetLanguageString("theme_reset"), GetLanguageString("theme_reset_conf"), { GetLanguageString("yes"), GetLanguageString("cancel") }, true); + const auto &selected_theme = this->loaded_themes.at(idx); + if(selected_theme.IsValid()) { + if(selected_theme.IsSame(g_ActiveTheme)) { + g_MenuApplication->ShowNotification(GetLanguageString("theme_active_this")); + } + else { + std::string theme_conf_msg = selected_theme.manifest.name + "\n"; + theme_conf_msg += selected_theme.manifest.release + ", " + selected_theme.manifest.author + "\n\n"; + theme_conf_msg += GetLanguageString("theme_set_conf"); + + const auto option = g_MenuApplication->DisplayDialog(selected_theme.manifest.name, theme_conf_msg, { GetLanguageString("yes"), GetLanguageString("cancel") }, true, this->loaded_theme_icons.at(idx)); if(option == 0) { - g_ActiveTheme = {}; + g_ActiveTheme = selected_theme; UL_ASSERT_TRUE(g_Config.SetEntry(cfg::ConfigEntryId::ActiveThemeName, g_ActiveTheme.name)); cfg::SaveConfig(g_Config); g_MenuApplication->ShowNotification(GetLanguageString("theme_cache")); @@ -93,24 +116,12 @@ namespace ul::menu::ui { UL_RC_ASSERT(ul::menu::smi::RestartMenu()); } } - else { - g_MenuApplication->ShowNotification(GetLanguageString("theme_no_active")); - } } else { - const auto theme_i = idx - 1; - const auto selected_theme = this->loaded_themes.at(theme_i); - if(selected_theme.name == g_ActiveTheme.name) { - g_MenuApplication->ShowNotification(GetLanguageString("theme_active_this")); - } - else { - std::string theme_conf_msg = selected_theme.manifest.name + "\n"; - theme_conf_msg += selected_theme.manifest.release + ", " + selected_theme.manifest.author + "\n\n"; - theme_conf_msg += GetLanguageString("theme_set_conf"); - - const auto option = g_MenuApplication->DisplayDialog(selected_theme.manifest.name, theme_conf_msg, { GetLanguageString("yes"), GetLanguageString("cancel") }, true, this->loaded_theme_icons.at(theme_i)); + if(g_ActiveTheme.IsValid()) { + const auto option = g_MenuApplication->DisplayDialog(GetLanguageString("theme_reset"), GetLanguageString("theme_reset_conf"), { GetLanguageString("yes"), GetLanguageString("cancel") }, true); if(option == 0) { - g_ActiveTheme = selected_theme; + g_ActiveTheme = {}; UL_ASSERT_TRUE(g_Config.SetEntry(cfg::ConfigEntryId::ActiveThemeName, g_ActiveTheme.name)); cfg::SaveConfig(g_Config); g_MenuApplication->ShowNotification(GetLanguageString("theme_cache")); @@ -122,6 +133,9 @@ namespace ul::menu::ui { UL_RC_ASSERT(ul::menu::smi::RestartMenu()); } } + else { + g_MenuApplication->ShowNotification(GetLanguageString("theme_no_active")); + } } }