#pragma once #include #include #include #include #include #include #include "activities/ActivityWithSubactivity.h" #include "util/ButtonNavigator.h" class CrossPointSettings; enum class SettingType { TOGGLE, ENUM, ACTION, VALUE, STRING }; enum class SettingAction { None, RemapFrontButtons, KOReaderSync, OPDSBrowser, Network, ClearCache, CheckForUpdates, }; struct SettingInfo { const char* name; SettingType type; uint8_t CrossPointSettings::* valuePtr = nullptr; std::vector enumValues; SettingAction action = SettingAction::None; struct ValueRange { uint8_t min; uint8_t max; uint8_t step; }; ValueRange valueRange = {}; const char* key = nullptr; // JSON API key (nullptr for ACTION types) const char* category = nullptr; // Category for web UI grouping // Direct char[] string fields (for settings stored in CrossPointSettings) char* stringPtr = nullptr; size_t stringMaxLen = 0; // Dynamic accessors (for settings stored outside CrossPointSettings, e.g. KOReaderCredentialStore) std::function valueGetter; std::function valueSetter; std::function stringGetter; std::function stringSetter; static SettingInfo Toggle(const char* name, uint8_t CrossPointSettings::* ptr, const char* key = nullptr, const char* category = nullptr) { SettingInfo s; s.name = name; s.type = SettingType::TOGGLE; s.valuePtr = ptr; s.key = key; s.category = category; return s; } static SettingInfo Enum(const char* name, uint8_t CrossPointSettings::* ptr, std::vector values, const char* key = nullptr, const char* category = nullptr) { SettingInfo s; s.name = name; s.type = SettingType::ENUM; s.valuePtr = ptr; s.enumValues = std::move(values); s.key = key; s.category = category; return s; } static SettingInfo Action(const char* name, SettingAction action) { SettingInfo s; s.name = name; s.type = SettingType::ACTION; s.action = action; return s; } static SettingInfo Value(const char* name, uint8_t CrossPointSettings::* ptr, const ValueRange valueRange, const char* key = nullptr, const char* category = nullptr) { SettingInfo s; s.name = name; s.type = SettingType::VALUE; s.valuePtr = ptr; s.valueRange = valueRange; s.key = key; s.category = category; return s; } static SettingInfo String(const char* name, char* ptr, size_t maxLen, const char* key = nullptr, const char* category = nullptr) { SettingInfo s; s.name = name; s.type = SettingType::STRING; s.stringPtr = ptr; s.stringMaxLen = maxLen; s.key = key; s.category = category; return s; } static SettingInfo DynamicEnum(const char* name, std::vector values, std::function getter, std::function setter, const char* key = nullptr, const char* category = nullptr) { SettingInfo s; s.name = name; s.type = SettingType::ENUM; s.enumValues = std::move(values); s.valueGetter = std::move(getter); s.valueSetter = std::move(setter); s.key = key; s.category = category; return s; } static SettingInfo DynamicString(const char* name, std::function getter, std::function setter, const char* key = nullptr, const char* category = nullptr) { SettingInfo s; s.name = name; s.type = SettingType::STRING; s.stringGetter = std::move(getter); s.stringSetter = std::move(setter); s.key = key; s.category = category; return s; } }; class SettingsActivity final : public ActivityWithSubactivity { TaskHandle_t displayTaskHandle = nullptr; SemaphoreHandle_t renderingMutex = nullptr; ButtonNavigator buttonNavigator; bool updateRequired = false; int selectedCategoryIndex = 0; // Currently selected category int selectedSettingIndex = 0; int settingsCount = 0; // Per-category settings derived from shared list + device-only actions std::vector displaySettings; std::vector readerSettings; std::vector controlsSettings; std::vector systemSettings; const std::vector* currentSettings = nullptr; const std::function onGoHome; static constexpr int categoryCount = 4; static const char* categoryNames[categoryCount]; static void taskTrampoline(void* param); [[noreturn]] void displayTaskLoop(); void render() const; void enterCategory(int categoryIndex); void toggleCurrentSetting(); public: explicit SettingsActivity(GfxRenderer& renderer, MappedInputManager& mappedInput, const std::function& onGoHome) : ActivityWithSubactivity("Settings", renderer, mappedInput), onGoHome(onGoHome) {} void onEnter() override; void onExit() override; void loop() override; };