diff --git a/src/activities/reader/EpubReaderActivity.cpp b/src/activities/reader/EpubReaderActivity.cpp index 28734ee8..7ebc4443 100644 --- a/src/activities/reader/EpubReaderActivity.cpp +++ b/src/activities/reader/EpubReaderActivity.cpp @@ -162,6 +162,28 @@ void EpubReaderActivity::loop() { return; } + // Detect long-press and schedule skip immediately + const bool prevPressed = mappedInput.isPressed(MappedInputManager::Button::PageBack) || + mappedInput.isPressed(MappedInputManager::Button::Left); + const bool nextPressed = mappedInput.isPressed(MappedInputManager::Button::PageForward) || + (SETTINGS.shortPwrBtn == CrossPointSettings::SHORT_PWRBTN::PAGE_TURN && + mappedInput.isPressed(MappedInputManager::Button::Power)) || + mappedInput.isPressed(MappedInputManager::Button::Right); + + if (SETTINGS.longPressChapterSkip && (prevPressed || nextPressed) && + mappedInput.getHeldTime() >= SETTINGS.getLongPressDurationMs() && !delayedSkipPending && + !awaitingReleaseAfterSkip) { + xSemaphoreTake(renderingMutex, portMAX_DELAY); + showSkipPopup("Skipping"); + delayedSkipPending = true; + delayedSkipDir = nextPressed ? +1 : -1; + delayedSkipExecuteAtMs = millis() + 500; + xSemaphoreGive(renderingMutex); + // Block release-based page change until unpressed + awaitingReleaseAfterSkip = true; + return; + } + const bool prevReleased = mappedInput.wasReleased(MappedInputManager::Button::PageBack) || mappedInput.wasReleased(MappedInputManager::Button::Left); const bool nextReleased = mappedInput.wasReleased(MappedInputManager::Button::PageForward) || @@ -173,6 +195,12 @@ void EpubReaderActivity::loop() { return; } + if (awaitingReleaseAfterSkip) { + awaitingReleaseAfterSkip = false; + skipUnpressed = true; + return; + } + // any botton press when at end of the book goes back to the last page if (currentSpineIndex > 0 && currentSpineIndex >= epub->getSpineItemsCount()) { currentSpineIndex = epub->getSpineItemsCount() - 1; @@ -181,20 +209,6 @@ void EpubReaderActivity::loop() { return; } - const bool skipChapter = SETTINGS.longPressChapterSkip && mappedInput.getHeldTime() > SETTINGS.getLongPressDurationMs(); - - if (skipChapter) { - // We don't want to delete the section mid-render, so grab the semaphore - xSemaphoreTake(renderingMutex, portMAX_DELAY); - // Show immediate feedback for long-press skip, then schedule delayed action (500ms) - showSkipPopup("Skipping"); - delayedSkipPending = true; - delayedSkipDir = nextReleased ? +1 : -1; - delayedSkipExecuteAtMs = millis() + 500; - xSemaphoreGive(renderingMutex); - // Do not perform the skip immediately; it will be executed in display loop after delay - return; - } // No current section, attempt to rerender the book if (!section) { diff --git a/src/activities/reader/EpubReaderActivity.h b/src/activities/reader/EpubReaderActivity.h index 2f3d6dbc..3b3aa41b 100644 --- a/src/activities/reader/EpubReaderActivity.h +++ b/src/activities/reader/EpubReaderActivity.h @@ -19,6 +19,8 @@ class EpubReaderActivity final : public ActivityWithSubactivity { bool delayedSkipPending = false; int delayedSkipDir = 0; uint32_t delayedSkipExecuteAtMs = 0; + bool awaitingReleaseAfterSkip = false; + bool skipUnpressed = false; const std::function onGoBack; const std::function onGoHome; diff --git a/src/activities/reader/XtcReaderActivity.cpp b/src/activities/reader/XtcReaderActivity.cpp index 21c2ef39..5251cc85 100644 --- a/src/activities/reader/XtcReaderActivity.cpp +++ b/src/activities/reader/XtcReaderActivity.cpp @@ -110,6 +110,29 @@ void XtcReaderActivity::loop() { return; } + // Detect long-press and schedule skip immediately + const bool prevPressed = mappedInput.isPressed(MappedInputManager::Button::PageBack) || + mappedInput.isPressed(MappedInputManager::Button::Left); + const bool nextPressed = mappedInput.isPressed(MappedInputManager::Button::PageForward) || + (SETTINGS.shortPwrBtn == CrossPointSettings::SHORT_PWRBTN::PAGE_TURN && + mappedInput.isPressed(MappedInputManager::Button::Power)) || + mappedInput.isPressed(MappedInputManager::Button::Right); + + if (SETTINGS.longPressChapterSkip && (prevPressed || nextPressed) && + mappedInput.getHeldTime() >= SETTINGS.getLongPressDurationMs() && !delayedSkipPending && + !awaitingReleaseAfterSkip) { + xSemaphoreTake(renderingMutex, portMAX_DELAY); + showSkipPopup("Skipping"); + delayedSkipPending = true; + delayedSkipDir = nextPressed ? +1 : -1; + delayedSkipAmount = 10; // long-press skip amount + delayedSkipExecuteAtMs = millis() + 500; + xSemaphoreGive(renderingMutex); + // Block release-based page change until unpressed + awaitingReleaseAfterSkip = true; + return; + } + const bool prevReleased = mappedInput.wasReleased(MappedInputManager::Button::PageBack) || mappedInput.wasReleased(MappedInputManager::Button::Left); const bool nextReleased = mappedInput.wasReleased(MappedInputManager::Button::PageForward) || @@ -121,6 +144,12 @@ void XtcReaderActivity::loop() { return; } + if (awaitingReleaseAfterSkip) { + awaitingReleaseAfterSkip = false; + skipUnpressed = true; + return; + } + // Handle end of book if (currentPage >= xtc->getPageCount()) { currentPage = xtc->getPageCount() - 1; @@ -128,38 +157,17 @@ void XtcReaderActivity::loop() { return; } - const bool skipPages = SETTINGS.longPressChapterSkip && mappedInput.getHeldTime() > SETTINGS.getLongPressDurationMs(); - const int skipAmount = skipPages ? 10 : 1; - if (prevReleased) { - if (skipPages) { - xSemaphoreTake(renderingMutex, portMAX_DELAY); - showSkipPopup("Skipping"); - delayedSkipPending = true; - delayedSkipDir = -1; - delayedSkipAmount = skipAmount; - delayedSkipExecuteAtMs = millis() + 500; - xSemaphoreGive(renderingMutex); - return; - } - if (currentPage >= static_cast(skipAmount)) { - currentPage -= skipAmount; + // Short press: single page back + if (currentPage >= 1) { + currentPage -= 1; } else { currentPage = 0; } updateRequired = true; } else if (nextReleased) { - if (skipPages) { - xSemaphoreTake(renderingMutex, portMAX_DELAY); - showSkipPopup("Skipping"); - delayedSkipPending = true; - delayedSkipDir = +1; - delayedSkipAmount = skipAmount; - delayedSkipExecuteAtMs = millis() + 500; - xSemaphoreGive(renderingMutex); - return; - } - currentPage += skipAmount; + // Short press: single page forward + currentPage += 1; if (currentPage >= xtc->getPageCount()) { currentPage = xtc->getPageCount(); // Allow showing "End of book" } diff --git a/src/activities/reader/XtcReaderActivity.h b/src/activities/reader/XtcReaderActivity.h index 6db673f1..75c20d01 100644 --- a/src/activities/reader/XtcReaderActivity.h +++ b/src/activities/reader/XtcReaderActivity.h @@ -25,6 +25,8 @@ class XtcReaderActivity final : public ActivityWithSubactivity { int delayedSkipDir = 0; uint32_t delayedSkipExecuteAtMs = 0; uint32_t delayedSkipAmount = 0; + bool awaitingReleaseAfterSkip = false; + bool skipUnpressed = false; const std::function onGoBack; const std::function onGoHome;