mod: Phase 2c-e — GfxRenderer, themes, SleepActivity, SettingsActivity, platformio

- Add drawPixelGray to GfxRenderer for letterbox fill rendering
- Add PRERENDER_THUMB_HEIGHTS to UITheme for placeholder cover generation
- Add [env:mod] build environment to platformio.ini
- Implement sleep screen letterbox fill (solid/dithered) with edge
  caching in SleepActivity, including placeholder cover fallback
- Add Clock settings category to SettingsActivity with timezone,
  NTP sync, and set-time actions; replace CalibreSettings with
  OpdsServerListActivity; add DynamicEnum rendering support
- Add long-press book management to RecentBooksActivity

Made-with: Cursor
This commit is contained in:
cottongin
2026-03-07 15:52:46 -05:00
parent d1ee45592e
commit 30473c27d3
10 changed files with 485 additions and 30 deletions

View File

@@ -3,14 +3,21 @@
#include <GfxRenderer.h>
#include <Logging.h>
#include <algorithm>
#include <cstdlib>
#include <ctime>
#include "ButtonRemapActivity.h"
#include "CalibreSettingsActivity.h"
#include "ClearCacheActivity.h"
#include "CrossPointSettings.h"
#include "KOReaderSettingsActivity.h"
#include "LanguageSelectActivity.h"
#include "MappedInputManager.h"
#include "NtpSyncActivity.h"
#include "OpdsServerListActivity.h"
#include "OtaUpdateActivity.h"
#include "SetTimeActivity.h"
#include "SetTimezoneOffsetActivity.h"
#include "SettingsList.h"
#include "StatusBarSettingsActivity.h"
#include "activities/network/WifiSelectionActivity.h"
@@ -18,13 +25,15 @@
#include "fontIds.h"
const StrId SettingsActivity::categoryNames[categoryCount] = {StrId::STR_CAT_DISPLAY, StrId::STR_CAT_READER,
StrId::STR_CAT_CONTROLS, StrId::STR_CAT_SYSTEM};
StrId::STR_CAT_CONTROLS, StrId::STR_CAT_SYSTEM,
StrId::STR_CAT_CLOCK};
void SettingsActivity::onEnter() {
Activity::onEnter();
// Build per-category vectors from the shared settings list
displaySettings.clear();
clockSettings.clear();
readerSettings.clear();
controlsSettings.clear();
systemSettings.clear();
@@ -33,6 +42,8 @@ void SettingsActivity::onEnter() {
if (setting.category == StrId::STR_NONE_OPT) continue;
if (setting.category == StrId::STR_CAT_DISPLAY) {
displaySettings.push_back(setting);
} else if (setting.category == StrId::STR_CAT_CLOCK) {
clockSettings.push_back(setting);
} else if (setting.category == StrId::STR_CAT_READER) {
readerSettings.push_back(setting);
} else if (setting.category == StrId::STR_CAT_CONTROLS) {
@@ -40,10 +51,10 @@ void SettingsActivity::onEnter() {
} else if (setting.category == StrId::STR_CAT_SYSTEM) {
systemSettings.push_back(setting);
}
// Web-only categories (KOReader Sync, OPDS Browser) are skipped for device UI
}
// Append device-only ACTION items
rebuildClockActions();
controlsSettings.insert(controlsSettings.begin(),
SettingInfo::Action(StrId::STR_REMAP_FRONT_BUTTONS, SettingAction::RemapFrontButtons));
systemSettings.push_back(SettingInfo::Action(StrId::STR_WIFI_NETWORKS, SettingAction::Network));
@@ -132,6 +143,9 @@ void SettingsActivity::loop() {
case 3:
currentSettings = &systemSettings;
break;
case 4:
currentSettings = &clockSettings;
break;
}
settingsCount = static_cast<int>(currentSettings->size());
}
@@ -173,7 +187,7 @@ void SettingsActivity::toggleCurrentSetting() {
startActivityForResult(std::make_unique<KOReaderSettingsActivity>(renderer, mappedInput), resultHandler);
break;
case SettingAction::OPDSBrowser:
startActivityForResult(std::make_unique<CalibreSettingsActivity>(renderer, mappedInput), resultHandler);
startActivityForResult(std::make_unique<OpdsServerListActivity>(renderer, mappedInput, false), resultHandler);
break;
case SettingAction::Network:
startActivityForResult(std::make_unique<WifiSelectionActivity>(renderer, mappedInput, false), resultHandler);
@@ -187,16 +201,51 @@ void SettingsActivity::toggleCurrentSetting() {
case SettingAction::Language:
startActivityForResult(std::make_unique<LanguageSelectActivity>(renderer, mappedInput), resultHandler);
break;
case SettingAction::SetTime:
startActivityForResult(std::make_unique<SetTimeActivity>(renderer, mappedInput), resultHandler);
break;
case SettingAction::SetTimezoneOffset:
startActivityForResult(std::make_unique<SetTimezoneOffsetActivity>(renderer, mappedInput), resultHandler);
break;
case SettingAction::SyncClock:
startActivityForResult(std::make_unique<NtpSyncActivity>(renderer, mappedInput), resultHandler);
break;
case SettingAction::None:
// Do nothing
break;
}
return; // Results will be handled in the result handler, so we can return early here
return;
} else if (setting.type == SettingType::ENUM && setting.valueGetter && setting.valueSetter) {
const uint8_t currentValue = setting.valueGetter();
setting.valueSetter((currentValue + 1) % static_cast<uint8_t>(setting.enumValues.size()));
} else {
return;
}
SETTINGS.saveToFile();
setenv("TZ", SETTINGS.getTimezonePosixStr(), 1);
tzset();
rebuildClockActions();
}
void SettingsActivity::rebuildClockActions() {
clockSettings.erase(std::remove_if(clockSettings.begin(), clockSettings.end(),
[](const SettingInfo& s) { return s.type == SettingType::ACTION; }),
clockSettings.end());
clockSettings.push_back(SettingInfo::Action(StrId::STR_SYNC_CLOCK, SettingAction::SyncClock));
clockSettings.push_back(SettingInfo::Action(StrId::STR_SET_TIME, SettingAction::SetTime));
if (SETTINGS.timezone == CrossPointSettings::TZ_CUSTOM) {
clockSettings.push_back(SettingInfo::Action(StrId::STR_SET_UTC_OFFSET, SettingAction::SetTimezoneOffset));
}
if (currentSettings == &clockSettings) {
settingsCount = static_cast<int>(clockSettings.size());
if (selectedSettingIndex > settingsCount) {
selectedSettingIndex = settingsCount;
}
}
}
void SettingsActivity::render(RenderLock&&) {
@@ -235,6 +284,11 @@ void SettingsActivity::render(RenderLock&&) {
} else if (setting.type == SettingType::ENUM && setting.valuePtr != nullptr) {
const uint8_t value = SETTINGS.*(setting.valuePtr);
valueText = I18N.get(setting.enumValues[value]);
} else if (setting.type == SettingType::ENUM && setting.valueGetter) {
const uint8_t value = setting.valueGetter();
if (value < setting.enumValues.size()) {
valueText = I18N.get(setting.enumValues[value]);
}
} else if (setting.type == SettingType::VALUE && setting.valuePtr != nullptr) {
valueText = std::to_string(SETTINGS.*(setting.valuePtr));
}