Files
crosspoint-reader-mod/src/activities/settings/SettingsActivity.h
Eliz 98e6789626 feat: Connect to last wifi by default (#752)
## Summary

* **What is the goal of this PR?** 

Use last connected network as default

* **What changes are included?**

- Refactor how an action type of Settings are handled
- Add a new System Settings option → Network
- Add the ability to forget a network in the Network Selection Screen
- Add the ability to Refresh network list
- Save the last connected network SSID
- Use the last connection whenever network is needed (OPDS, Koreader
sync, update etc)

## Additional Context

* Add any other information that might be helpful for the reviewer
(e.g., performance implications, potential risks,
  specific areas to focus on).


![IMG_6504](https://github.com/user-attachments/assets/e48fb013-b5c3-45c0-b284-e183e6fd5a68)

![IMG_6503](https://github.com/user-attachments/assets/78c4b6b6-4e7b-4656-b356-19d65ff6aa12)




https://github.com/user-attachments/assets/95bf34a8-44ce-4279-8cd8-f78524ce745b





---

### AI Usage

Did you use AI tools to help write this code? _** PARTIALLY: I wrote
most of it but I also used Gemini as assist.

---------

Co-authored-by: Eliz Kilic <elizk@google.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-10 20:41:44 +11:00

171 lines
5.2 KiB
C++

#pragma once
#include <freertos/FreeRTOS.h>
#include <freertos/semphr.h>
#include <freertos/task.h>
#include <functional>
#include <string>
#include <vector>
#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<std::string> 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<uint8_t()> valueGetter;
std::function<void(uint8_t)> valueSetter;
std::function<std::string()> stringGetter;
std::function<void(const std::string&)> 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<std::string> 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<std::string> values, std::function<uint8_t()> getter,
std::function<void(uint8_t)> 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<std::string()> getter,
std::function<void(const std::string&)> 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<SettingInfo> displaySettings;
std::vector<SettingInfo> readerSettings;
std::vector<SettingInfo> controlsSettings;
std::vector<SettingInfo> systemSettings;
const std::vector<SettingInfo>* currentSettings = nullptr;
const std::function<void()> 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<void()>& onGoHome)
: ActivityWithSubactivity("Settings", renderer, mappedInput), onGoHome(onGoHome) {}
void onEnter() override;
void onExit() override;
void loop() override;
};