From cfd79d32cab8e1325193f2bd7cd1429eb3db1d1d Mon Sep 17 00:00:00 2001 From: jpirnay Date: Thu, 26 Mar 2026 19:55:56 +0100 Subject: [PATCH] Updates for better setting grouping --- lib/I18n/translations/english.yaml | 3 +- src/CrossPointSettings.h | 6 +- src/SettingsList.h | 3 +- src/activities/ActivityManager.cpp | 9 +- .../settings/ClockSettingsActivity.cpp | 117 ++++++++++++++++++ .../settings/ClockSettingsActivity.h | 20 +++ src/activities/settings/SettingsActivity.cpp | 16 ++- src/activities/settings/SettingsActivity.h | 1 + .../settings/StatusBarSettingsActivity.cpp | 20 ++- src/components/UITheme.cpp | 2 +- src/components/themes/BaseTheme.cpp | 4 +- src/components/themes/lyra/LyraTheme.cpp | 2 +- src/main.cpp | 4 +- 13 files changed, 183 insertions(+), 24 deletions(-) create mode 100644 src/activities/settings/ClockSettingsActivity.cpp create mode 100644 src/activities/settings/ClockSettingsActivity.h diff --git a/lib/I18n/translations/english.yaml b/lib/I18n/translations/english.yaml index 9047748c..9a99039e 100644 --- a/lib/I18n/translations/english.yaml +++ b/lib/I18n/translations/english.yaml @@ -82,7 +82,8 @@ STR_PARA_ALIGNMENT: "Reader Paragraph Alignment" STR_HYPHENATION: "Hyphenation" STR_TIME_TO_SLEEP: "Time to Sleep" STR_SHOW_HIDDEN_FILES: "Show Hidden Files" -STR_KEEP_CLOCK_ALIVE: "Keep Clock Alive" +STR_USE_CLOCK: "Use Clock" +STR_CLOCK_SETTINGS: "Clock Settings" STR_CLOCK: "Clock" STR_CLOCK_FORMAT: "Clock Format" STR_TIMEZONE: "Timezone" diff --git a/src/CrossPointSettings.h b/src/CrossPointSettings.h index 269a866d..3280b063 100644 --- a/src/CrossPointSettings.h +++ b/src/CrossPointSettings.h @@ -226,9 +226,9 @@ class CrossPointSettings { uint8_t clockFormat12h = 0; // Timezone selection (applies POSIX TZ rules for DST) uint8_t timeZone = TZ_UTC; - // Keep the LP timer running during deep sleep (GPIO13 HIGH) so the clock - // can be accurately restored on wake. Increases sleep current by ~3-4 mA. - uint8_t keepClockAlive = 0; + // Use clock and keep the LP timer running during deep sleep (GPIO13 HIGH) + // so time can be accurately restored on wake. Increases sleep current by ~3-4 mA. + uint8_t useClock = 0; ~CrossPointSettings() = default; diff --git a/src/SettingsList.h b/src/SettingsList.h index d01119d1..4bcbc754 100644 --- a/src/SettingsList.h +++ b/src/SettingsList.h @@ -88,8 +88,7 @@ inline const std::vector& getSettingsList() { StrId::STR_TZ_UTC_PLUS9, StrId::STR_TZ_AEST, StrId::STR_TZ_NZST, StrId::STR_TZ_UTC_MINUS3, StrId::STR_TZ_EST, StrId::STR_TZ_CST, StrId::STR_TZ_MST, StrId::STR_TZ_PST}, "timeZone", StrId::STR_CAT_SYSTEM), - SettingInfo::Toggle(StrId::STR_KEEP_CLOCK_ALIVE, &CrossPointSettings::keepClockAlive, "keepClockAlive", - StrId::STR_CAT_SYSTEM), + SettingInfo::Toggle(StrId::STR_USE_CLOCK, &CrossPointSettings::useClock, "useClock", StrId::STR_CAT_SYSTEM), // --- KOReader Sync (web-only, uses KOReaderCredentialStore) --- SettingInfo::DynamicString( diff --git a/src/activities/ActivityManager.cpp b/src/activities/ActivityManager.cpp index e1a01cea..a94e1e52 100644 --- a/src/activities/ActivityManager.cpp +++ b/src/activities/ActivityManager.cpp @@ -1,5 +1,6 @@ #include "ActivityManager.h" +#include #include #include @@ -57,13 +58,13 @@ void ActivityManager::loop() { currentActivity->loop(); } - if (SETTINGS.statusBarClock && HalClock::isSynced()) { - static time_t lastClockMinute = 0; + if (SETTINGS.useClock && HalClock::isSynced()) { + static time_t lastMinute = -1; time_t now = HalClock::now(); if (now > 0) { time_t minute = now / 60; - if (minute != lastClockMinute) { - lastClockMinute = minute; + if (minute != lastMinute) { + lastMinute = minute; requestUpdate(); } } diff --git a/src/activities/settings/ClockSettingsActivity.cpp b/src/activities/settings/ClockSettingsActivity.cpp new file mode 100644 index 00000000..abd70ccb --- /dev/null +++ b/src/activities/settings/ClockSettingsActivity.cpp @@ -0,0 +1,117 @@ +#include "ClockSettingsActivity.h" + +#include +#include +#include + +#include "CrossPointSettings.h" +#include "DetectTimezoneActivity.h" +#include "MappedInputManager.h" +#include "SyncTimeActivity.h" +#include "components/UITheme.h" +#include "fontIds.h" + +namespace { +constexpr int MENU_ITEMS = 5; +const StrId menuNames[MENU_ITEMS] = {StrId::STR_USE_CLOCK, StrId::STR_CLOCK_FORMAT, StrId::STR_TIMEZONE, + StrId::STR_SYNC_TIME, StrId::STR_DETECT_TIMEZONE}; + +const StrId timeZoneNames[CrossPointSettings::TIMEZONE_COUNT] = { + StrId::STR_TZ_UTC, StrId::STR_TZ_CET, StrId::STR_TZ_EET, StrId::STR_TZ_MSK, + StrId::STR_TZ_UTC_PLUS4, StrId::STR_TZ_IST, StrId::STR_TZ_UTC_PLUS7, StrId::STR_TZ_UTC_PLUS8, + StrId::STR_TZ_UTC_PLUS9, StrId::STR_TZ_AEST, StrId::STR_TZ_NZST, StrId::STR_TZ_UTC_MINUS3, + StrId::STR_TZ_EST, StrId::STR_TZ_CST, StrId::STR_TZ_MST, StrId::STR_TZ_PST}; +} // namespace + +void ClockSettingsActivity::onEnter() { + Activity::onEnter(); + selectedIndex = 0; + requestUpdate(); +} + +void ClockSettingsActivity::onExit() { Activity::onExit(); } + +void ClockSettingsActivity::loop() { + if (mappedInput.wasPressed(MappedInputManager::Button::Back)) { + finish(); + return; + } + + if (mappedInput.wasPressed(MappedInputManager::Button::Confirm)) { + handleSelection(); + requestUpdate(); + return; + } + + buttonNavigator.onNextRelease([this] { + selectedIndex = ButtonNavigator::nextIndex(selectedIndex, MENU_ITEMS); + requestUpdate(); + }); + + buttonNavigator.onPreviousRelease([this] { + selectedIndex = ButtonNavigator::previousIndex(selectedIndex, MENU_ITEMS); + requestUpdate(); + }); +} + +void ClockSettingsActivity::handleSelection() { + if (selectedIndex == 0) { + SETTINGS.useClock = (SETTINGS.useClock + 1) % 2; + if (!SETTINGS.useClock) { + SETTINGS.statusBarClock = 0; + } + SETTINGS.saveToFile(); + } else if (selectedIndex == 1) { + SETTINGS.clockFormat12h = (SETTINGS.clockFormat12h + 1) % 2; + SETTINGS.saveToFile(); + } else if (selectedIndex == 2) { + SETTINGS.timeZone = (SETTINGS.timeZone + 1) % CrossPointSettings::TIMEZONE_COUNT; + HalClock::applyTimezone(SETTINGS.timeZone); + SETTINGS.saveToFile(); + } else if (selectedIndex == 3) { + auto resultHandler = [](const ActivityResult&) { SETTINGS.saveToFile(); }; + startActivityForResult(std::make_unique(renderer, mappedInput), resultHandler); + } else if (selectedIndex == 4) { + auto resultHandler = [](const ActivityResult&) { SETTINGS.saveToFile(); }; + startActivityForResult(std::make_unique(renderer, mappedInput), resultHandler); + } +} + +void ClockSettingsActivity::render(RenderLock&&) { + renderer.clearScreen(); + + const auto& metrics = UITheme::getInstance().getMetrics(); + const auto pageWidth = renderer.getScreenWidth(); + const auto pageHeight = renderer.getScreenHeight(); + + GUI.drawHeader(renderer, Rect{0, metrics.topPadding, pageWidth, metrics.headerHeight}, tr(STR_CLOCK_SETTINGS)); + + const int contentTop = metrics.topPadding + metrics.headerHeight + metrics.verticalSpacing; + const int contentHeight = pageHeight - contentTop - metrics.buttonHintsHeight - metrics.verticalSpacing * 2; + + GUI.drawList( + renderer, Rect{0, contentTop, pageWidth, contentHeight}, MENU_ITEMS, selectedIndex, + [](int index) { return std::string(I18N.get(menuNames[index])); }, nullptr, nullptr, + [](int index) { + if (index == 0) { + return std::string(SETTINGS.useClock ? tr(STR_STATE_ON) : tr(STR_STATE_OFF)); + } + if (index == 1) { + return std::string(SETTINGS.clockFormat12h ? tr(STR_12H) : tr(STR_24H)); + } + if (index == 2) { + const auto tzIndex = static_cast(SETTINGS.timeZone); + if (tzIndex < (sizeof(timeZoneNames) / sizeof(timeZoneNames[0]))) { + return std::string(I18N.get(timeZoneNames[tzIndex])); + } + return std::string(tr(STR_TZ_UTC)); + } + return std::string(""); + }, + true); + + const auto labels = mappedInput.mapLabels(tr(STR_BACK), tr(STR_SELECT), tr(STR_DIR_UP), tr(STR_DIR_DOWN)); + GUI.drawButtonHints(renderer, labels.btn1, labels.btn2, labels.btn3, labels.btn4); + + renderer.displayBuffer(); +} diff --git a/src/activities/settings/ClockSettingsActivity.h b/src/activities/settings/ClockSettingsActivity.h new file mode 100644 index 00000000..e1f491bc --- /dev/null +++ b/src/activities/settings/ClockSettingsActivity.h @@ -0,0 +1,20 @@ +#pragma once +#include + +#include "activities/Activity.h" +#include "util/ButtonNavigator.h" + +class ClockSettingsActivity final : public Activity { + ButtonNavigator buttonNavigator; + int selectedIndex = 0; + + void handleSelection(); + + public: + explicit ClockSettingsActivity(GfxRenderer& renderer, MappedInputManager& mappedInput) + : Activity("ClockSettings", renderer, mappedInput) {} + void onEnter() override; + void onExit() override; + void loop() override; + void render(RenderLock&&) override; +}; diff --git a/src/activities/settings/SettingsActivity.cpp b/src/activities/settings/SettingsActivity.cpp index 783c5e50..d0be195a 100644 --- a/src/activities/settings/SettingsActivity.cpp +++ b/src/activities/settings/SettingsActivity.cpp @@ -7,6 +7,7 @@ #include "ButtonRemapActivity.h" #include "CalibreSettingsActivity.h" #include "ClearCacheActivity.h" +#include "ClockSettingsActivity.h" #include "CrossPointSettings.h" #include "DetectTimezoneActivity.h" #include "KOReaderSettingsActivity.h" @@ -34,6 +35,11 @@ void SettingsActivity::onEnter() { for (const auto& setting : getSettingsList()) { if (setting.category == StrId::STR_NONE_OPT) continue; + if (setting.category == StrId::STR_CAT_SYSTEM && + (setting.nameId == StrId::STR_USE_CLOCK || setting.nameId == StrId::STR_CLOCK_FORMAT || + setting.nameId == StrId::STR_TIMEZONE)) { + continue; + } if (setting.category == StrId::STR_CAT_DISPLAY) { displaySettings.push_back(setting); } else if (setting.category == StrId::STR_CAT_READER) { @@ -49,8 +55,7 @@ void SettingsActivity::onEnter() { // Append device-only ACTION items controlsSettings.insert(controlsSettings.begin(), SettingInfo::Action(StrId::STR_REMAP_FRONT_BUTTONS, SettingAction::RemapFrontButtons)); - systemSettings.push_back(SettingInfo::Action(StrId::STR_SYNC_TIME, SettingAction::SyncTime)); - systemSettings.push_back(SettingInfo::Action(StrId::STR_DETECT_TIMEZONE, SettingAction::DetectTimezone)); + systemSettings.push_back(SettingInfo::Action(StrId::STR_CLOCK_SETTINGS, SettingAction::ClockSettings)); 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)); @@ -179,6 +184,9 @@ void SettingsActivity::toggleCurrentSetting() { case SettingAction::CustomiseStatusBar: startActivityForResult(std::make_unique(renderer, mappedInput), resultHandler); break; + case SettingAction::ClockSettings: + startActivityForResult(std::make_unique(renderer, mappedInput), resultHandler); + break; case SettingAction::KOReaderSync: startActivityForResult(std::make_unique(renderer, mappedInput), resultHandler); break; @@ -216,6 +224,10 @@ void SettingsActivity::toggleCurrentSetting() { HalClock::applyTimezone(SETTINGS.timeZone); } + if (setting.nameId == StrId::STR_USE_CLOCK && !SETTINGS.useClock) { + SETTINGS.statusBarClock = 0; + } + SETTINGS.saveToFile(); } diff --git a/src/activities/settings/SettingsActivity.h b/src/activities/settings/SettingsActivity.h index 28116197..ef9a4dbb 100644 --- a/src/activities/settings/SettingsActivity.h +++ b/src/activities/settings/SettingsActivity.h @@ -15,6 +15,7 @@ enum class SettingAction { None, RemapFrontButtons, CustomiseStatusBar, + ClockSettings, KOReaderSync, OPDSBrowser, Network, diff --git a/src/activities/settings/StatusBarSettingsActivity.cpp b/src/activities/settings/StatusBarSettingsActivity.cpp index 979041b1..990a47b8 100644 --- a/src/activities/settings/StatusBarSettingsActivity.cpp +++ b/src/activities/settings/StatusBarSettingsActivity.cpp @@ -38,6 +38,9 @@ void StatusBarSettingsActivity::onEnter() { Activity::onEnter(); selectedIndex = 0; + if (!SETTINGS.useClock && selectedIndex >= MENU_ITEMS - 1) { + selectedIndex = 0; + } // Clamp statusBarProgressBar and statusBarTitle in case of corrupt/migrated data if (SETTINGS.statusBarProgressBar >= PROGRESS_BAR_ITEMS) { @@ -71,22 +74,26 @@ void StatusBarSettingsActivity::loop() { // Handle navigation buttonNavigator.onNextRelease([this] { - selectedIndex = ButtonNavigator::nextIndex(selectedIndex, MENU_ITEMS); + const int menuCount = SETTINGS.useClock ? MENU_ITEMS : MENU_ITEMS - 1; + selectedIndex = ButtonNavigator::nextIndex(selectedIndex, menuCount); requestUpdate(); }); buttonNavigator.onPreviousRelease([this] { - selectedIndex = ButtonNavigator::previousIndex(selectedIndex, MENU_ITEMS); + const int menuCount = SETTINGS.useClock ? MENU_ITEMS : MENU_ITEMS - 1; + selectedIndex = ButtonNavigator::previousIndex(selectedIndex, menuCount); requestUpdate(); }); buttonNavigator.onNextContinuous([this] { - selectedIndex = ButtonNavigator::nextIndex(selectedIndex, MENU_ITEMS); + const int menuCount = SETTINGS.useClock ? MENU_ITEMS : MENU_ITEMS - 1; + selectedIndex = ButtonNavigator::nextIndex(selectedIndex, menuCount); requestUpdate(); }); buttonNavigator.onPreviousContinuous([this] { - selectedIndex = ButtonNavigator::previousIndex(selectedIndex, MENU_ITEMS); + const int menuCount = SETTINGS.useClock ? MENU_ITEMS : MENU_ITEMS - 1; + selectedIndex = ButtonNavigator::previousIndex(selectedIndex, menuCount); requestUpdate(); }); } @@ -111,7 +118,7 @@ void StatusBarSettingsActivity::handleSelection() { } else if (selectedIndex == 5) { // Show Battery SETTINGS.statusBarBattery = (SETTINGS.statusBarBattery + 1) % 2; - } else if (selectedIndex == 6) { + } else if (selectedIndex == 6 && SETTINGS.useClock) { // Show Clock SETTINGS.statusBarClock = (SETTINGS.statusBarClock + 1) % 2; } @@ -129,8 +136,9 @@ void StatusBarSettingsActivity::render(RenderLock&&) { const int contentTop = metrics.topPadding + metrics.headerHeight + metrics.verticalSpacing; const int contentHeight = pageHeight - contentTop - metrics.buttonHintsHeight - metrics.verticalSpacing * 2; + const int menuCount = SETTINGS.useClock ? MENU_ITEMS : MENU_ITEMS - 1; GUI.drawList( - renderer, Rect{0, contentTop, pageWidth, contentHeight}, static_cast(MENU_ITEMS), + renderer, Rect{0, contentTop, pageWidth, contentHeight}, static_cast(menuCount), static_cast(selectedIndex), [](int index) { return std::string(I18N.get(menuNames[index])); }, nullptr, nullptr, [this](int index) { diff --git a/src/components/UITheme.cpp b/src/components/UITheme.cpp index 79fb603a..a600145e 100644 --- a/src/components/UITheme.cpp +++ b/src/components/UITheme.cpp @@ -96,7 +96,7 @@ int UITheme::getStatusBarHeight() { // Add status bar margin const bool showStatusBar = SETTINGS.statusBarChapterPageCount || SETTINGS.statusBarBookProgressPercentage || SETTINGS.statusBarTitle != CrossPointSettings::STATUS_BAR_TITLE::HIDE_TITLE || - SETTINGS.statusBarBattery || SETTINGS.statusBarClock; + SETTINGS.statusBarBattery || (SETTINGS.useClock && SETTINGS.statusBarClock); const bool showProgressBar = SETTINGS.statusBarProgressBar != CrossPointSettings::STATUS_BAR_PROGRESS_BAR::HIDE_PROGRESS; return (showStatusBar ? (metrics.statusBarVerticalMargin) : 0) + diff --git a/src/components/themes/BaseTheme.cpp b/src/components/themes/BaseTheme.cpp index c2b8d229..67ea1757 100644 --- a/src/components/themes/BaseTheme.cpp +++ b/src/components/themes/BaseTheme.cpp @@ -296,7 +296,7 @@ void BaseTheme::drawHeader(const GfxRenderer& renderer, Rect rect, const char* t showBatteryPercentage); // Draw clock in header - { + if (SETTINGS.useClock) { char clockStr[16]; HalClock::formatTime(clockStr, sizeof(clockStr), !SETTINGS.clockFormat12h); renderer.drawText(SMALL_FONT_ID, rect.x + BaseMetrics::values.contentSidePadding, rect.y + 5, clockStr); @@ -725,7 +725,7 @@ void BaseTheme::drawStatusBar(GfxRenderer& renderer, const float bookProgress, c // Draw Clock int clockTextWidth = 0; - if (SETTINGS.statusBarClock) { + if (SETTINGS.useClock && SETTINGS.statusBarClock) { char clockStr[16]; HalClock::formatTime(clockStr, sizeof(clockStr), !SETTINGS.clockFormat12h); clockTextWidth = renderer.getTextWidth(SMALL_FONT_ID, clockStr); diff --git a/src/components/themes/lyra/LyraTheme.cpp b/src/components/themes/lyra/LyraTheme.cpp index 7e62f5b4..77e00e9b 100644 --- a/src/components/themes/lyra/LyraTheme.cpp +++ b/src/components/themes/lyra/LyraTheme.cpp @@ -169,7 +169,7 @@ void LyraTheme::drawHeader(const GfxRenderer& renderer, Rect rect, const char* t showBatteryPercentage); // Draw clock in header - { + if (SETTINGS.useClock) { char clockStr[16]; HalClock::formatTime(clockStr, sizeof(clockStr), !SETTINGS.clockFormat12h); renderer.drawText(SMALL_FONT_ID, rect.x + LyraMetrics::values.contentSidePadding, rect.y + 5, clockStr); diff --git a/src/main.cpp b/src/main.cpp index fa24aa8e..4cc63aaa 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -185,7 +185,7 @@ void waitForPowerRelease() { void enterDeepSleep() { HalPowerManager::Lock powerLock; // Ensure we are at normal CPU frequency for sleep preparation APP_STATE.lastSleepFromReader = activityManager.isReaderActivity(); - HalClock::saveBeforeSleep(SETTINGS.keepClockAlive); + HalClock::saveBeforeSleep(SETTINGS.useClock); APP_STATE.saveToFile(); activityManager.goToSleep(); @@ -194,7 +194,7 @@ void enterDeepSleep() { LOG_DBG("MAIN", "Power button press calibration value: %lu ms", t2 - t1); LOG_DBG("MAIN", "Entering deep sleep"); - powerManager.startDeepSleep(gpio, SETTINGS.keepClockAlive); + powerManager.startDeepSleep(gpio, SETTINGS.useClock); } void setupDisplayAndFonts() {