From f39ba7037f6657041523a0484b64a1ca5d2594ec Mon Sep 17 00:00:00 2001 From: Julia Date: Thu, 21 May 2026 21:06:51 -0400 Subject: [PATCH] fix(settings): preserve quick resume timeout preference (#2101) ## Summary ### **What is the goal of this PR?** This fixes an unintended settings side effect when cycling the `Sleep Screen` option through `Quick Resume`. Previously, selecting `Sleep Screen = Quick Resume` globally forced `Quick Resume on Timeout = ON` and left it enabled even after the user toggled `Sleep Screen` to another option within the same settings session. Now the auto-enable behavior is scoped to the Settings screen session: - If `Quick Resume on Timeout` was already `ON` when entering Settings, it stays `ON`. - If it was `OFF`, selecting `Sleep Screen = Quick Resume` temporarily turns it `ON`. - If the user then switches away from `Quick Resume`, it turns back `OFF`. ### **What changes are included?** - Removes the global logic that permanently forced `Quick Resume on Timeout` to `ON` whenever `Sleep Screen` was set to `Quick Resume`, even if it was just due to toggling through the options. - Adds Settings-screen session tracking so `Quick Resume on Timeout` is only auto-enabled while the user has `Sleep Screen = Quick Resume`. - Restores `Quick Resume on Timeout` back to `OFF` when the user switches away, but only if it was `OFF` when they entered Settings. - Preserves existing `ON` timeout preferences. - Same behavior applies to the web settings ## Additional Context - Tested this on device and via the settings UI --- ### AI Usage While CrossPoint doesn't have restrictions on AI tools in contributing, please be transparent about their usage as it helps set the right context for reviewers. Did you use AI tools to help write this code? _**< YES >**_ --- src/CrossPointSettings.cpp | 6 -- src/CrossPointSettings.h | 1 - src/JsonSettingsIO.cpp | 4 - src/activities/settings/SettingsActivity.cpp | 31 +++++- src/activities/settings/SettingsActivity.h | 4 + src/network/CrossPointWebServer.cpp | 1 - src/network/html/SettingsPage.html | 108 ++++++++++++++++++- 7 files changed, 138 insertions(+), 17 deletions(-) diff --git a/src/CrossPointSettings.cpp b/src/CrossPointSettings.cpp index abe879f2..7dd9051d 100644 --- a/src/CrossPointSettings.cpp +++ b/src/CrossPointSettings.cpp @@ -79,12 +79,6 @@ void CrossPointSettings::validateFrontButtonMapping(CrossPointSettings& settings } } -void CrossPointSettings::normalizeDependentSettings(CrossPointSettings& settings) { - if (settings.sleepScreen == SLEEP_SCREEN_MODE::QUICK_RESUME) { - settings.quickResumeSleepScreen = QUICK_RESUME_SLEEP_SCREEN::QUICK_RESUME_AFTER_TIMEOUT; - } -} - bool CrossPointSettings::saveToFile() const { Storage.mkdir("/.crosspoint"); return JsonSettingsIO::saveSettings(*this, SETTINGS_FILE_JSON); diff --git a/src/CrossPointSettings.h b/src/CrossPointSettings.h index 86b379d7..ba12a473 100644 --- a/src/CrossPointSettings.h +++ b/src/CrossPointSettings.h @@ -275,7 +275,6 @@ class CrossPointSettings { bool loadFromFile(); static void validateFrontButtonMapping(CrossPointSettings& settings); - static void normalizeDependentSettings(CrossPointSettings& settings); private: bool loadFromBinaryFile(); diff --git a/src/JsonSettingsIO.cpp b/src/JsonSettingsIO.cpp index ebe52ff1..065c6e51 100644 --- a/src/JsonSettingsIO.cpp +++ b/src/JsonSettingsIO.cpp @@ -223,10 +223,6 @@ bool JsonSettingsIO::loadSettings(CrossPointSettings& s, const char* json, bool* } } - const uint8_t quickResumeBeforeNormalize = s.quickResumeSleepScreen; - CrossPointSettings::normalizeDependentSettings(s); - if (s.quickResumeSleepScreen != quickResumeBeforeNormalize && needsResave) *needsResave = true; - // Front button remap — managed by RemapFrontButtons sub-activity, not in SettingsList. using S = CrossPointSettings; s.frontButtonBack = diff --git a/src/activities/settings/SettingsActivity.cpp b/src/activities/settings/SettingsActivity.cpp index 834e338d..8a5888d9 100644 --- a/src/activities/settings/SettingsActivity.cpp +++ b/src/activities/settings/SettingsActivity.cpp @@ -86,6 +86,10 @@ void SettingsActivity::onEnter() { // Reset selection to first category selectedCategoryIndex = 0; selectedSettingIndex = 0; + preserveQuickResumeTimeoutOn = + SETTINGS.quickResumeSleepScreen == CrossPointSettings::QUICK_RESUME_SLEEP_SCREEN::QUICK_RESUME_AFTER_TIMEOUT; + quickResumeTimeoutAutoEnabled = false; + syncQuickResumeTimeoutForSleepScreen(/*sleepScreenChanged=*/true, /*quickResumeTimeoutChanged=*/false); rebuildSettingsLists(); @@ -176,6 +180,8 @@ void SettingsActivity::toggleCurrentSetting() { } const auto& setting = (*currentSettings)[selectedSetting]; + const bool sleepScreenChanged = setting.valuePtr == &CrossPointSettings::sleepScreen; + const bool quickResumeTimeoutChanged = setting.valuePtr == &CrossPointSettings::quickResumeSleepScreen; if (setting.type == SettingType::TOGGLE && setting.valuePtr != nullptr) { // Toggle the boolean value using the member pointer @@ -253,10 +259,33 @@ void SettingsActivity::toggleCurrentSetting() { return; } - CrossPointSettings::normalizeDependentSettings(SETTINGS); + syncQuickResumeTimeoutForSleepScreen(sleepScreenChanged, quickResumeTimeoutChanged); SETTINGS.saveToFile(); } +void SettingsActivity::syncQuickResumeTimeoutForSleepScreen(bool sleepScreenChanged, bool quickResumeTimeoutChanged) { + if (quickResumeTimeoutChanged) { + preserveQuickResumeTimeoutOn = + SETTINGS.quickResumeSleepScreen == CrossPointSettings::QUICK_RESUME_SLEEP_SCREEN::QUICK_RESUME_AFTER_TIMEOUT; + quickResumeTimeoutAutoEnabled = false; + } + + if (SETTINGS.sleepScreen == CrossPointSettings::SLEEP_SCREEN_MODE::QUICK_RESUME) { + if (SETTINGS.quickResumeSleepScreen != CrossPointSettings::QUICK_RESUME_SLEEP_SCREEN::QUICK_RESUME_AFTER_TIMEOUT) { + SETTINGS.quickResumeSleepScreen = CrossPointSettings::QUICK_RESUME_SLEEP_SCREEN::QUICK_RESUME_AFTER_TIMEOUT; + quickResumeTimeoutAutoEnabled = !preserveQuickResumeTimeoutOn; + } else if (sleepScreenChanged && !preserveQuickResumeTimeoutOn) { + quickResumeTimeoutAutoEnabled = true; + } + return; + } + + if (sleepScreenChanged && quickResumeTimeoutAutoEnabled && !preserveQuickResumeTimeoutOn) { + SETTINGS.quickResumeSleepScreen = CrossPointSettings::QUICK_RESUME_SLEEP_SCREEN::QUICK_RESUME_NEVER; + quickResumeTimeoutAutoEnabled = false; + } +} + void SettingsActivity::render(RenderLock&&) { renderer.clearScreen(); diff --git a/src/activities/settings/SettingsActivity.h b/src/activities/settings/SettingsActivity.h index 1767272c..44a22ea9 100644 --- a/src/activities/settings/SettingsActivity.h +++ b/src/activities/settings/SettingsActivity.h @@ -156,12 +156,16 @@ class SettingsActivity final : public Activity { std::vector systemSettings; const std::vector* currentSettings = nullptr; + bool preserveQuickResumeTimeoutOn = false; + bool quickResumeTimeoutAutoEnabled = false; + static constexpr int categoryCount = 4; static const StrId categoryNames[categoryCount]; void enterCategory(int categoryIndex); void toggleCurrentSetting(); void rebuildSettingsLists(); + void syncQuickResumeTimeoutForSleepScreen(bool sleepScreenChanged, bool quickResumeTimeoutChanged); public: explicit SettingsActivity(GfxRenderer& renderer, MappedInputManager& mappedInput) diff --git a/src/network/CrossPointWebServer.cpp b/src/network/CrossPointWebServer.cpp index 87210b11..41606f8d 100644 --- a/src/network/CrossPointWebServer.cpp +++ b/src/network/CrossPointWebServer.cpp @@ -1265,7 +1265,6 @@ void CrossPointWebServer::handlePostSettings() { } } - CrossPointSettings::normalizeDependentSettings(SETTINGS); SETTINGS.saveToFile(); LOG_DBG("WEB", "Applied %d setting(s)", applied); diff --git a/src/network/html/SettingsPage.html b/src/network/html/SettingsPage.html index 0a73f9bd..4291a21b 100644 --- a/src/network/html/SettingsPage.html +++ b/src/network/html/SettingsPage.html @@ -312,6 +312,11 @@