diff --git a/lib/I18n/translations/english.yaml b/lib/I18n/translations/english.yaml index 15f19f6d..b453bae4 100644 --- a/lib/I18n/translations/english.yaml +++ b/lib/I18n/translations/english.yaml @@ -60,7 +60,6 @@ STR_CALIBRE_INSTRUCTION_4: "\"Keep this screen open while sending\"" STR_CAT_DISPLAY: "Display" STR_CAT_READER: "Reader" STR_CAT_CONTROLS: "Controls" -STR_CAT_NETWORK: "Network" STR_CAT_SYSTEM: "System" STR_SLEEP_SCREEN: "Sleep Screen" STR_SLEEP_COVER_MODE: "Sleep Screen Cover Mode" @@ -469,10 +468,4 @@ STR_WEATHER_MOON_INFO: "Moon" STR_WEATHER_SUN_INFO: "Sun" STR_READER_TOOLS: "Tools" STR_READER_NAVIGATION: "Navigation" -STR_READER_APPEARANCE: "Appearance" -STR_SETTINGS_MENU_SYSTEM: "System" -STR_SETTINGS_MENU_TOOLS: "Tools" -STR_SETTINGS_MENU_NETWORK: "Network" -STR_SETTINGS_MENU_SETTINGS: "Behaviour" -STR_SETTINGS_MENU_SOURCES: "Online Sources" -STR_SETTINGS_MENU_SYNC: "Synchronisation" \ No newline at end of file +STR_READER_APPEARANCE: "Appearance" \ No newline at end of file diff --git a/src/activities/reader/EpubReaderMenuActivity.cpp b/src/activities/reader/EpubReaderMenuActivity.cpp index 3ac7bcf2..1a5bfef9 100644 --- a/src/activities/reader/EpubReaderMenuActivity.cpp +++ b/src/activities/reader/EpubReaderMenuActivity.cpp @@ -7,7 +7,6 @@ #include "MappedInputManager.h" #include "components/UITheme.h" #include "fontIds.h" -#include "util/MenuItemHelpers.h" EpubReaderMenuActivity::EpubReaderMenuActivity(GfxRenderer& renderer, MappedInputManager& mappedInput, const std::string& title, const int currentPage, const int totalPages, @@ -30,7 +29,7 @@ std::vector EpubReaderMenuActivity::buildMenuI std::vector items; items.reserve(18); // Navigation - items.push_back(makeSeparatorMenuItem(StrId::STR_READER_NAVIGATION)); + items.push_back({MenuAction::NONE, StrId::STR_READER_NAVIGATION, true}); items.push_back({MenuAction::SELECT_CHAPTER, StrId::STR_SELECT_CHAPTER}); items.push_back({MenuAction::GO_TO_PERCENT, StrId::STR_GO_TO_PERCENT}); if (hasFootnotes) { @@ -39,7 +38,7 @@ std::vector EpubReaderMenuActivity::buildMenuI items.push_back({MenuAction::AUTO_PAGE_TURN, StrId::STR_AUTO_TURN_PAGES_PER_MIN}); // Appearance - items.push_back(makeSeparatorMenuItem(StrId::STR_READER_APPEARANCE)); + items.push_back({MenuAction::NONE, StrId::STR_READER_APPEARANCE, true}); items.push_back({MenuAction::EMBEDDED_STYLE, StrId::STR_EMBEDDED_STYLE}); items.push_back({MenuAction::IMAGE_RENDERING, StrId::STR_IMAGES}); items.push_back({MenuAction::TEXT_DARKNESS, StrId::STR_TEXT_DARKNESS}); @@ -47,13 +46,13 @@ std::vector EpubReaderMenuActivity::buildMenuI // Synchronisation (only if credentials are set, to avoid confusion) if (KOREADER_STORE.hasCredentials()) { - items.push_back(makeSeparatorMenuItem(StrId::STR_KOREADER_SYNC)); + items.push_back({MenuAction::NONE, StrId::STR_KOREADER_SYNC, true}); items.push_back({MenuAction::PULL_REMOTE, StrId::STR_PULL_PROGRESS_FROM_OTHER_DEVICES}); items.push_back({MenuAction::PUSH_LOCAL, StrId::STR_PUSH_PROGRESS_FROM_THIS_DEVICE}); } // Tools - items.push_back(makeSeparatorMenuItem(StrId::STR_READER_TOOLS)); + items.push_back({MenuAction::NONE, StrId::STR_READER_TOOLS, true}); items.push_back({MenuAction::SCREENSHOT, StrId::STR_SCREENSHOT_BUTTON}); items.push_back({MenuAction::DISPLAY_QR, StrId::STR_DISPLAY_QR}); items.push_back({MenuAction::DELETE_CACHE, StrId::STR_DELETE_CACHE}); @@ -62,7 +61,9 @@ std::vector EpubReaderMenuActivity::buildMenuI } std::function EpubReaderMenuActivity::buildSelectablePredicate() const { - return makeSelectablePredicate(menuItems); + return [this](int index) { + return index >= 0 && index < static_cast(menuItems.size()) && !menuItems[index].isSeparator; + }; } void EpubReaderMenuActivity::onEnter() { diff --git a/src/activities/reader/EpubReaderMenuActivity.h b/src/activities/reader/EpubReaderMenuActivity.h index 681e6746..93bd66d8 100644 --- a/src/activities/reader/EpubReaderMenuActivity.h +++ b/src/activities/reader/EpubReaderMenuActivity.h @@ -2,7 +2,6 @@ #include #include -#include #include #include @@ -30,12 +29,6 @@ class EpubReaderMenuActivity final : public Activity { DELETE_CACHE }; - struct MenuItem { - MenuAction action; - StrId labelId; - bool isSeparator = false; - }; - explicit EpubReaderMenuActivity(GfxRenderer& renderer, MappedInputManager& mappedInput, const std::string& title, const int currentPage, const int totalPages, const int bookProgressPercent, const uint8_t currentOrientation, const bool hasFootnotes, @@ -47,10 +40,17 @@ class EpubReaderMenuActivity final : public Activity { void loop() override; void render(RenderLock&&) override; + private: + struct MenuItem { + MenuAction action; + StrId labelId; + bool isSeparator = false; + }; + static std::vector buildMenuItems(bool hasFootnotes); + std::function buildSelectablePredicate() const; - private: // Fixed menu layout const std::vector menuItems; diff --git a/src/activities/settings/ClockSettingsActivity.cpp b/src/activities/settings/ClockSettingsActivity.cpp index a09b76f2..95b533cc 100644 --- a/src/activities/settings/ClockSettingsActivity.cpp +++ b/src/activities/settings/ClockSettingsActivity.cpp @@ -10,7 +10,6 @@ #include "SyncTimeActivity.h" #include "components/UITheme.h" #include "fontIds.h" -#include "util/MenuItemHelpers.h" namespace { const StrId timeZoneNames[CrossPointSettings::TIMEZONE_COUNT] = { @@ -24,20 +23,22 @@ std::vector ClockSettingsActivity::buildMenuIte std::vector items; items.reserve(7); // Settings - items.push_back(makeSeparatorMenuItem(StrId::STR_SETTINGS_TITLE)); + items.push_back({Action::NONE, StrId::STR_SETTINGS_TITLE, true}); items.push_back({Action::USE_CLOCK, StrId::STR_USE_CLOCK}); - items.push_back({Action::CLOCK_FORMAT, StrId::STR_CLOCK_FORMAT}); + items.push_back({Action::CLOCK_FORMAT, StrId::STR_CLOCK_FORMAT}); items.push_back({Action::TIMEZONE, StrId::STR_TIMEZONE}); // Tools - items.push_back(makeSeparatorMenuItem(StrId::STR_READER_TOOLS)); + items.push_back({Action::NONE, StrId::STR_READER_TOOLS, true}); items.push_back({Action::DETECT_TIMEZONE, StrId::STR_DETECT_TIMEZONE}); - items.push_back({Action::SYNC_TIME, StrId::STR_SYNC_TIME}); + items.push_back({Action::SYNC_TIME, StrId::STR_SYNC_TIME}); return items; } std::function ClockSettingsActivity::buildSelectablePredicate() const { - return makeSelectablePredicate(menuItems); + return [this](int index) { + return index >= 0 && index < static_cast(menuItems.size()) && !menuItems[index].isSeparator; + }; } void ClockSettingsActivity::onEnter() { @@ -123,7 +124,8 @@ void ClockSettingsActivity::render(RenderLock&&) { const int contentHeight = pageHeight - contentTop - metrics.buttonHintsHeight - metrics.verticalSpacing * 2; GUI.drawList( - renderer, Rect{0, contentTop, pageWidth, contentHeight}, static_cast(menuItems.size()), selectedIndex, + renderer, Rect{0, contentTop, pageWidth, contentHeight}, static_cast(menuItems.size()), + selectedIndex, [this](int index) { const auto title = I18N.get(menuItems[index].labelId); return menuItems[index].isSeparator ? UITheme::makeSeparatorTitle(title) : title; diff --git a/src/activities/settings/ClockSettingsActivity.h b/src/activities/settings/ClockSettingsActivity.h index ffeea5d9..974259e4 100644 --- a/src/activities/settings/ClockSettingsActivity.h +++ b/src/activities/settings/ClockSettingsActivity.h @@ -1,14 +1,21 @@ #pragma once -#include - #include #include +#include + #include "activities/Activity.h" #include "util/ButtonNavigator.h" class ClockSettingsActivity final : public Activity { - enum class Action { USE_CLOCK, CLOCK_FORMAT, TIMEZONE, SYNC_TIME, DETECT_TIMEZONE, NONE }; + enum class Action { + USE_CLOCK, + CLOCK_FORMAT, + TIMEZONE, + SYNC_TIME, + DETECT_TIMEZONE, + NONE + }; struct MenuItem { Action action; diff --git a/src/activities/settings/SettingsActivity.cpp b/src/activities/settings/SettingsActivity.cpp index 4afeece0..d64ed44f 100644 --- a/src/activities/settings/SettingsActivity.cpp +++ b/src/activities/settings/SettingsActivity.cpp @@ -22,11 +22,9 @@ #include "activities/weather/WeatherSettingsActivity.h" #include "components/UITheme.h" #include "fontIds.h" -#include "util/MenuItemHelpers.h" const StrId SettingsActivity::categoryNames[categoryCount] = {StrId::STR_CAT_DISPLAY, StrId::STR_CAT_READER, - StrId::STR_CAT_CONTROLS, StrId::STR_CAT_NETWORK, - StrId::STR_CAT_SYSTEM}; + StrId::STR_CAT_CONTROLS, StrId::STR_CAT_SYSTEM}; void SettingsActivity::onEnter() { Activity::onEnter(); @@ -35,9 +33,7 @@ void SettingsActivity::onEnter() { displaySettings.clear(); readerSettings.clear(); controlsSettings.clear(); - networkSettings.clear(); systemSettings.clear(); - systemSettings.push_back(SettingInfo::Separator(StrId::STR_SETTINGS_MENU_SETTINGS)); for (const auto& setting : getSettingsList()) { if (setting.category == StrId::STR_NONE_OPT) continue; @@ -54,8 +50,6 @@ void SettingsActivity::onEnter() { controlsSettings.push_back(setting); } else if (setting.category == StrId::STR_CAT_SYSTEM) { systemSettings.push_back(setting); - } else if (setting.category == StrId::STR_CAT_NETWORK) { - networkSettings.push_back(setting); } // Web-only categories (KOReader Sync, OPDS Browser) are skipped for device UI } @@ -63,26 +57,15 @@ void SettingsActivity::onEnter() { // Append device-only ACTION items controlsSettings.insert(controlsSettings.begin(), SettingInfo::Action(StrId::STR_REMAP_FRONT_BUTTONS, SettingAction::RemapFrontButtons)); - - networkSettings.push_back(SettingInfo::Separator(StrId::STR_SETTINGS_MENU_NETWORK)); - networkSettings.push_back(SettingInfo::Action(StrId::STR_WIFI_NETWORKS, SettingAction::Network)); - networkSettings.push_back(SettingInfo::Separator(StrId::STR_SETTINGS_MENU_SOURCES)); - networkSettings.push_back(SettingInfo::Action(StrId::STR_OPDS_BROWSER, SettingAction::OPDSBrowser)); - networkSettings.push_back(SettingInfo::Separator(StrId::STR_SETTINGS_MENU_SYNC)); - networkSettings.push_back(SettingInfo::Action(StrId::STR_KOREADER_SYNC, SettingAction::KOReaderSync)); - - // System settings with actions - systemSettings.push_back(SettingInfo::Action(StrId::STR_LANGUAGE, SettingAction::Language)); - - systemSettings.push_back(SettingInfo::Separator(StrId::STR_SETTINGS_MENU_TOOLS)); systemSettings.push_back(SettingInfo::Action(StrId::STR_CLOCK_SETTINGS, SettingAction::ClockSettings)); - systemSettings.push_back(SettingInfo::Action(StrId::STR_WEATHER_SETTINGS, SettingAction::Weather)); - - systemSettings.push_back(SettingInfo::Separator(StrId::STR_SETTINGS_MENU_SYSTEM)); + systemSettings.push_back(SettingInfo::Action(StrId::STR_WIFI_NETWORKS, SettingAction::Network)); + systemSettings.push_back(SettingInfo::Action(StrId::STR_KOREADER_SYNC, SettingAction::KOReaderSync)); + systemSettings.push_back(SettingInfo::Action(StrId::STR_OPDS_BROWSER, SettingAction::OPDSBrowser)); systemSettings.push_back(SettingInfo::Action(StrId::STR_CLEAR_READING_CACHE, SettingAction::ClearCache)); systemSettings.push_back(SettingInfo::Action(StrId::STR_CHECK_UPDATES, SettingAction::CheckForUpdates)); + systemSettings.push_back(SettingInfo::Action(StrId::STR_LANGUAGE, SettingAction::Language)); systemSettings.push_back(SettingInfo::Action(StrId::STR_SYSTEM_INFO, SettingAction::SystemInfo)); - + systemSettings.push_back(SettingInfo::Action(StrId::STR_WEATHER_SETTINGS, SettingAction::Weather)); readerSettings.push_back(SettingInfo::Action(StrId::STR_CUSTOMISE_STATUS_BAR, SettingAction::CustomiseStatusBar)); // Reset selection to first category @@ -92,16 +75,11 @@ void SettingsActivity::onEnter() { // Initialize with first category (Display) currentSettings = &displaySettings; settingsCount = static_cast(displaySettings.size()); - buttonNavigator.setSelectablePredicate(makeSelectablePredicate(*currentSettings, 1, true), settingsCount + 1); // Trigger first update requestUpdate(); } -std::function SettingsActivity::buildSelectablePredicate() const { - return makeSelectablePredicate(*currentSettings, 1, true); -} - void SettingsActivity::onExit() { Activity::onExit(); @@ -137,12 +115,12 @@ void SettingsActivity::loop() { // Handle navigation buttonNavigator.onNextRelease([this] { - selectedSettingIndex = buttonNavigator.nextIndex(selectedSettingIndex); + selectedSettingIndex = ButtonNavigator::nextIndex(selectedSettingIndex, settingsCount + 1); requestUpdate(); }); buttonNavigator.onPreviousRelease([this] { - selectedSettingIndex = buttonNavigator.previousIndex(selectedSettingIndex); + selectedSettingIndex = ButtonNavigator::previousIndex(selectedSettingIndex, settingsCount + 1); requestUpdate(); }); @@ -171,14 +149,10 @@ void SettingsActivity::loop() { currentSettings = &controlsSettings; break; case 3: - currentSettings = &networkSettings; - break; - case 4: currentSettings = &systemSettings; break; } settingsCount = static_cast(currentSettings->size()); - buttonNavigator.setSelectablePredicate(makeSelectablePredicate(*currentSettings, 1, true), settingsCount + 1); } } @@ -189,9 +163,6 @@ void SettingsActivity::toggleCurrentSetting() { } const auto& setting = (*currentSettings)[selectedSetting]; - if (setting.isSeparator) { - return; - } if (setting.type == SettingType::TOGGLE && setting.valuePtr != nullptr) { // Toggle the boolean value using the member pointer @@ -288,11 +259,7 @@ void SettingsActivity::render(RenderLock&&) { contentRect.height - (metrics.topPadding + metrics.headerHeight + metrics.tabBarHeight + metrics.verticalSpacing * 2)}, settingsCount, selectedSettingIndex - 1, - [&settings](int index) { - const auto title = I18N.get(settings[index].nameId); - return settings[index].isSeparator ? UITheme::makeSeparatorTitle(title) : title; - }, - nullptr, nullptr, + [&settings](int index) { return std::string(I18N.get(settings[index].nameId)); }, nullptr, nullptr, [&settings](int i) { const auto& setting = settings[i]; std::string valueText = ""; diff --git a/src/activities/settings/SettingsActivity.h b/src/activities/settings/SettingsActivity.h index 4c65f8da..1a1bf5f6 100644 --- a/src/activities/settings/SettingsActivity.h +++ b/src/activities/settings/SettingsActivity.h @@ -30,7 +30,6 @@ enum class SettingAction { struct SettingInfo { StrId nameId; - bool isSeparator = false; SettingType type; uint8_t CrossPointSettings::* valuePtr = nullptr; std::vector enumValues; @@ -85,21 +84,11 @@ struct SettingInfo { return s; } - static SettingInfo Action(StrId nameId, SettingAction action, bool isSeparator = false) { + static SettingInfo Action(StrId nameId, SettingAction action) { SettingInfo s; s.nameId = nameId; s.type = SettingType::ACTION; s.action = action; - s.isSeparator = isSeparator; - return s; - } - - static SettingInfo Separator(StrId nameId) { - SettingInfo s; - s.nameId = nameId; - s.type = SettingType::ACTION; - s.action = SettingAction::None; - s.isSeparator = true; return s; } @@ -166,16 +155,14 @@ class SettingsActivity final : public Activity { std::vector displaySettings; std::vector readerSettings; std::vector controlsSettings; - std::vector networkSettings; std::vector systemSettings; const std::vector* currentSettings = nullptr; - static constexpr int categoryCount = 5; + static constexpr int categoryCount = 4; static const StrId categoryNames[categoryCount]; void enterCategory(int categoryIndex); void toggleCurrentSetting(); - std::function buildSelectablePredicate() const; public: explicit SettingsActivity(GfxRenderer& renderer, MappedInputManager& mappedInput) diff --git a/src/components/UITheme.cpp b/src/components/UITheme.cpp index 67a09e16..7b76f617 100644 --- a/src/components/UITheme.cpp +++ b/src/components/UITheme.cpp @@ -98,11 +98,17 @@ Rect UITheme::getContentRect(const GfxRenderer& renderer, bool hasBottomHints, b return Rect{left, top, w - left - right, h - top - bottom}; } -std::string UITheme::makeSeparatorTitle(const std::string& title) { return std::string("__") + title; } +std::string UITheme::makeSeparatorTitle(const std::string& title) { + return std::string("__") + title; +} -std::string UITheme::makeSeparatorTitle(StrId labelId) { return std::string("__") + I18N.get(labelId); } +std::string UITheme::makeSeparatorTitle(StrId labelId) { + return std::string("__") + I18N.get(labelId); +} -bool UITheme::isSeparatorTitle(const std::string& title) { return title.rfind("__", 0) == 0; } +bool UITheme::isSeparatorTitle(const std::string& title) { + return title.rfind("__", 0) == 0; +} std::string UITheme::stripSeparatorTitle(const std::string& title) { return isSeparatorTitle(title) ? title.substr(2) : title; diff --git a/src/components/UITheme.h b/src/components/UITheme.h index abdc1906..17d5c997 100644 --- a/src/components/UITheme.h +++ b/src/components/UITheme.h @@ -1,10 +1,10 @@ #pragma once -#include - #include #include +#include + #include "CrossPointSettings.h" #include "components/themes/BaseTheme.h" diff --git a/src/util/ButtonNavigator.h b/src/util/ButtonNavigator.h index b76df714..11a17449 100644 --- a/src/util/ButtonNavigator.h +++ b/src/util/ButtonNavigator.h @@ -45,9 +45,9 @@ class ButtonNavigator final { [[nodiscard]] static int nextIndex(int currentIndex, const std::vector& selectable); [[nodiscard]] static int previousIndex(int currentIndex, const std::vector& selectable); [[nodiscard]] static int nextIndex(int currentIndex, int totalItems, - const std::function& isSelectable); + const std::function& isSelectable); [[nodiscard]] static int previousIndex(int currentIndex, int totalItems, - const std::function& isSelectable); + const std::function& isSelectable); [[nodiscard]] int nextIndex(int currentIndex) const; [[nodiscard]] int previousIndex(int currentIndex) const; diff --git a/src/util/MenuItemHelpers.h b/src/util/MenuItemHelpers.h deleted file mode 100644 index 5c89f7ba..00000000 --- a/src/util/MenuItemHelpers.h +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once - -#include - -#include -#include -#include - -// Generic helper for constructing separator rows in menu item vectors. -// The item type must have an `action`, an `isSeparator`, and either a `labelId` or `nameId` member. -template -inline ItemType makeSeparatorMenuItem(StrId labelId) { - ItemType item{}; - if constexpr (std::is_member_object_pointer_v) { - item.action = static_cast(0); - } - if constexpr (std::is_member_object_pointer_v) { - item.labelId = labelId; - } else if constexpr (std::is_member_object_pointer_v) { - item.nameId = labelId; - } else { - static_assert(sizeof(ItemType) == 0, - "makeSeparatorMenuItem requires ItemType with labelId or nameId member"); - } - item.isSeparator = true; - return item; -} - -// Generic helper for creating a selectable predicate for menu lists. -// The item type must have an `isSeparator` member. -template -inline std::function makeSelectablePredicate(const std::vector& items) { - return - [&items](int index) { return index >= 0 && index < static_cast(items.size()) && !items[index].isSeparator; }; -} - -template -inline std::function makeSelectablePredicate(const std::vector& items, int indexOffset, - bool firstIndexSelectable) { - return [&items, indexOffset, firstIndexSelectable](int index) { - if (firstIndexSelectable && index == 0) { - return true; - } - - const int itemIndex = index - indexOffset; - return itemIndex >= 0 && itemIndex < static_cast(items.size()) && !items[itemIndex].isSeparator; - }; -}