diff --git a/src/activities/reader/EpubReaderChapterSelectionActivity.cpp b/src/activities/reader/EpubReaderChapterSelectionActivity.cpp index 1b35e143..0a38b1d6 100644 --- a/src/activities/reader/EpubReaderChapterSelectionActivity.cpp +++ b/src/activities/reader/EpubReaderChapterSelectionActivity.cpp @@ -9,7 +9,8 @@ namespace { // Time threshold for treating a long press as a page-up/page-down -constexpr int SKIP_PAGE_MS = 700; +constexpr int RAPID_NAV_START_MS = 500; +constexpr int RAPID_NAV_DELAY_MS = 700; } // namespace bool EpubReaderChapterSelectionActivity::hasSyncOption() const { return KOREADER_STORE.hasCredentials(); } @@ -124,10 +125,20 @@ void EpubReaderChapterSelectionActivity::loop() { const bool nextReleased = mappedInput.wasReleased(MappedInputManager::Button::Down) || mappedInput.wasReleased(MappedInputManager::Button::Right); - const bool skipPage = mappedInput.getHeldTime() > SKIP_PAGE_MS; + const bool prevPressed = + mappedInput.isPressed(MappedInputManager::Button::Up) || mappedInput.isPressed(MappedInputManager::Button::Left); + const bool nextPressed = mappedInput.isPressed(MappedInputManager::Button::Down) || + mappedInput.isPressed(MappedInputManager::Button::Right); + const int pageItems = getPageItems(); const int totalItems = getTotalItems(); + const int currentTocPage = selectorIndex / pageItems; + const int lastTocPage = (epub->getTocItemsCount() - 1) / pageItems; + + const bool shouldNavigateRapidly = mappedInput.getHeldTime() > RAPID_NAV_START_MS; + const bool isRapidNavigationDue = (millis() - lastRapidNavTime) > RAPID_NAV_DELAY_MS; + if (mappedInput.wasReleased(MappedInputManager::Button::Confirm)) { // Check if sync option is selected (first or last item) if (isSyncItem(selectorIndex)) { @@ -146,19 +157,29 @@ void EpubReaderChapterSelectionActivity::loop() { } else if (mappedInput.wasReleased(MappedInputManager::Button::Back)) { onGoBack(); } else if (prevReleased) { - if (skipPage) { - selectorIndex = ((selectorIndex / pageItems - 1) * pageItems + totalItems) % totalItems; - } else { - selectorIndex = (selectorIndex + totalItems - 1) % totalItems; + if (lastRapidNavTime != 0) { + lastRapidNavTime = 0; + return; } + + selectorIndex = (selectorIndex + totalItems - 1) % totalItems; updateRequired = true; } else if (nextReleased) { - if (skipPage) { - selectorIndex = ((selectorIndex / pageItems + 1) * pageItems) % totalItems; - } else { - selectorIndex = (selectorIndex + 1) % totalItems; + if (lastRapidNavTime != 0) { + lastRapidNavTime = 0; + return; } + + selectorIndex = (selectorIndex + 1) % totalItems; updateRequired = true; + } else if (prevPressed && shouldNavigateRapidly && isRapidNavigationDue) { + selectorIndex = currentTocPage > 0 ? (currentTocPage - 1) * pageItems : lastTocPage * pageItems; + updateRequired = true; + lastRapidNavTime = millis(); + } else if (nextPressed && shouldNavigateRapidly && isRapidNavigationDue) { + selectorIndex = currentTocPage < lastTocPage ? (currentTocPage + 1) * pageItems : 0; + updateRequired = true; + lastRapidNavTime = millis(); } } diff --git a/src/activities/reader/EpubReaderChapterSelectionActivity.h b/src/activities/reader/EpubReaderChapterSelectionActivity.h index 255f0cea..08cc58c1 100644 --- a/src/activities/reader/EpubReaderChapterSelectionActivity.h +++ b/src/activities/reader/EpubReaderChapterSelectionActivity.h @@ -18,6 +18,7 @@ class EpubReaderChapterSelectionActivity final : public ActivityWithSubactivity int totalPagesInSpine = 0; int selectorIndex = 0; bool updateRequired = false; + unsigned long lastRapidNavTime = 0; const std::function onGoBack; const std::function onSelectSpineIndex; const std::function onSyncPosition; diff --git a/src/activities/reader/XtcReaderChapterSelectionActivity.cpp b/src/activities/reader/XtcReaderChapterSelectionActivity.cpp index b2cfecaa..3ed1db95 100644 --- a/src/activities/reader/XtcReaderChapterSelectionActivity.cpp +++ b/src/activities/reader/XtcReaderChapterSelectionActivity.cpp @@ -6,7 +6,8 @@ #include "fontIds.h" namespace { -constexpr int SKIP_PAGE_MS = 700; +constexpr int RAPID_NAV_START_MS = 500; +constexpr int RAPID_NAV_DELAY_MS = 700; } // namespace int XtcReaderChapterSelectionActivity::getPageItems() const { @@ -80,8 +81,18 @@ void XtcReaderChapterSelectionActivity::loop() { const bool nextReleased = mappedInput.wasReleased(MappedInputManager::Button::Down) || mappedInput.wasReleased(MappedInputManager::Button::Right); - const bool skipPage = mappedInput.getHeldTime() > SKIP_PAGE_MS; + const bool prevPressed = + mappedInput.isPressed(MappedInputManager::Button::Up) || mappedInput.isPressed(MappedInputManager::Button::Left); + const bool nextPressed = mappedInput.isPressed(MappedInputManager::Button::Down) || + mappedInput.isPressed(MappedInputManager::Button::Right); + const int pageItems = getPageItems(); + const int currentTocPage = selectorIndex / pageItems; + const int total = static_cast(xtc->getChapters().size()); + const int lastTocPage = total > 0 ? (total - 1) / pageItems : 0; + + const bool shouldNavigateRapidly = mappedInput.getHeldTime() > RAPID_NAV_START_MS; + const bool isRapidNavigationDue = (millis() - lastRapidNavTime) > RAPID_NAV_DELAY_MS; if (mappedInput.wasReleased(MappedInputManager::Button::Confirm)) { const auto& chapters = xtc->getChapters(); @@ -91,27 +102,37 @@ void XtcReaderChapterSelectionActivity::loop() { } else if (mappedInput.wasReleased(MappedInputManager::Button::Back)) { onGoBack(); } else if (prevReleased) { - const int total = static_cast(xtc->getChapters().size()); - if (total == 0) { + if (total == 0 || lastRapidNavTime != 0) { + lastRapidNavTime = 0; return; } - if (skipPage) { - selectorIndex = ((selectorIndex / pageItems - 1) * pageItems + total) % total; - } else { - selectorIndex = (selectorIndex + total - 1) % total; - } + + selectorIndex = (selectorIndex + total - 1) % total; updateRequired = true; } else if (nextReleased) { - const int total = static_cast(xtc->getChapters().size()); + if (total == 0 || lastRapidNavTime != 0) { + lastRapidNavTime = 0; + return; + } + + selectorIndex = (selectorIndex + 1) % total; + updateRequired = true; + } else if (prevPressed && shouldNavigateRapidly && isRapidNavigationDue) { if (total == 0) { return; } - if (skipPage) { - selectorIndex = ((selectorIndex / pageItems + 1) * pageItems) % total; - } else { - selectorIndex = (selectorIndex + 1) % total; - } + + selectorIndex = currentTocPage > 0 ? (currentTocPage - 1) * pageItems : lastTocPage * pageItems; updateRequired = true; + lastRapidNavTime = millis(); + } else if (nextPressed && shouldNavigateRapidly && isRapidNavigationDue) { + if (total == 0) { + return; + } + + selectorIndex = currentTocPage < lastTocPage ? (currentTocPage + 1) * pageItems : 0; + updateRequired = true; + lastRapidNavTime = millis(); } } diff --git a/src/activities/reader/XtcReaderChapterSelectionActivity.h b/src/activities/reader/XtcReaderChapterSelectionActivity.h index f0fe06bb..5796142c 100644 --- a/src/activities/reader/XtcReaderChapterSelectionActivity.h +++ b/src/activities/reader/XtcReaderChapterSelectionActivity.h @@ -15,6 +15,7 @@ class XtcReaderChapterSelectionActivity final : public Activity { uint32_t currentPage = 0; int selectorIndex = 0; bool updateRequired = false; + unsigned long lastRapidNavTime = 0; const std::function onGoBack; const std::function onSelectPage;