From e1d623bd9cff536910d1604b7c5630dde0b31f03 Mon Sep 17 00:00:00 2001 From: jpirnay Date: Mon, 27 Apr 2026 13:42:39 +0200 Subject: [PATCH] Refactor duplicate/stale button handler Co-authored-by: Copilot --- src/activities/home/FileBrowserActivity.cpp | 195 +++++++++---------- src/activities/reader/EpubReaderActivity.cpp | 171 ++++++---------- src/activities/reader/MdReaderActivity.cpp | 94 ++++----- src/activities/reader/TxtReaderActivity.cpp | 88 +++++---- src/activities/reader/XtcReaderActivity.cpp | 71 +++---- src/activities/util/BmpViewerActivity.cpp | 22 ++- 6 files changed, 289 insertions(+), 352 deletions(-) diff --git a/src/activities/home/FileBrowserActivity.cpp b/src/activities/home/FileBrowserActivity.cpp index feb43aea..5f68645c 100644 --- a/src/activities/home/FileBrowserActivity.cpp +++ b/src/activities/home/FileBrowserActivity.cpp @@ -141,110 +141,109 @@ void FileBrowserActivity::clearFileMetadata(const std::string& fullPath) { void FileBrowserActivity::loop() { const int pageItems = UITheme::getInstance().getNumberOfItemsPerPage(renderer, true, false, true, false); - // Long press BACK always navigates to home - if (mappedInput.isPressed(MappedInputManager::Button::Back) && mappedInput.getHeldTime() >= GO_HOME_MS) { - onGoHome(); - return; - } - - // Short press BACK goes up one directory (if not root) or home (at root) - if (mappedInput.wasReleased(MappedInputManager::Button::Back) && mappedInput.getHeldTime() < GO_HOME_MS) { - if (basepath != "/") { - const std::string oldPath = basepath; - basepath.replace(basepath.find_last_of('/'), std::string::npos, ""); - if (basepath.empty()) basepath = "/"; - loadFiles(); - const auto pos = oldPath.find_last_of('/'); - const std::string dirName = oldPath.substr(pos + 1) + "/"; - const size_t idx = findEntry(dirName); - selectorIndex = (idx < files.size()) ? idx : 0; - requestUpdate(); - } else { - onGoHome(); - } - return; - } - - // Confirm short press opens selected entry; long press does nothing - if (mappedInput.wasReleased(MappedInputManager::Button::Confirm) && mappedInput.getHeldTime() < GO_HOME_MS) { - if (files.empty()) return; - - const std::string& entry = files[selectorIndex]; - const bool isDirectory = (entry.back() == '/'); - - if (isDirectory) { - if (basepath.back() != '/') basepath += "/"; - basepath += entry.substr(0, entry.length() - 1); - loadFiles(); - selectorIndex = 0; - requestUpdate(); - } else { - std::string fullPath = basepath; - if (fullPath.back() != '/') fullPath += "/"; - fullPath += entry; - ReturnHint hint; - hint.target = ReturnTo::FileBrowser; - hint.path = basepath; - hint.selectName = entry; - activityManager.replaceWithReader(std::move(fullPath), std::move(hint)); - } - return; - } - - // Left short press does nothing; long press deletes selected file after confirmation - if (mappedInput.wasReleased(MappedInputManager::Button::Left)) { - if (mappedInput.getHeldTime() < GO_HOME_MS || files.empty()) { - return; - } - - const std::string& entry = files[selectorIndex]; - const bool isDirectory = (entry.back() == '/'); - if (isDirectory) { - return; - } - - std::string cleanBase = basepath; - if (cleanBase.back() != '/') cleanBase += "/"; - const std::string fullPath = cleanBase + entry; - - auto handler = [this, fullPath](const ActivityResult& res) { - if (!res.isCancelled) { - LOG_DBG("FileBrowser", "Attempting to delete: %s", fullPath.c_str()); - clearFileMetadata(fullPath); - if (Storage.remove(fullPath.c_str())) { - LOG_DBG("FileBrowser", "Deleted successfully"); - loadFiles(); - if (files.empty()) { - selectorIndex = 0; - } else if (selectorIndex >= files.size()) { - selectorIndex = files.size() - 1; - } - requestUpdate(true); - } else { - LOG_ERR("FileBrowser", "Failed to delete file: %s", fullPath.c_str()); - } - } else { - LOG_DBG("FileBrowser", "Delete cancelled by user"); + ButtonEventManager::ButtonEvent ev; + while (buttonEvents.consumeEvent(ev)) { + if (ev.button == MappedInputManager::Button::Back) { + if (ev.type == ButtonEventManager::PressType::Long) { + onGoHome(); + return; } - }; + if (ev.type == ButtonEventManager::PressType::Short) { + if (basepath != "/") { + const std::string oldPath = basepath; + basepath.replace(basepath.find_last_of('/'), std::string::npos, ""); + if (basepath.empty()) basepath = "/"; + loadFiles(); + const auto pos = oldPath.find_last_of('/'); + const std::string dirName = oldPath.substr(pos + 1) + "/"; + const size_t idx = findEntry(dirName); + selectorIndex = (idx < files.size()) ? idx : 0; + requestUpdate(); + } else { + onGoHome(); + } + return; + } + } - startActivityForResult( - std::make_unique(renderer, mappedInput, tr(STR_DELETE) + std::string("? "), entry), - handler); - return; - } + if (ev.button == MappedInputManager::Button::Confirm && ev.type == ButtonEventManager::PressType::Short) { + if (files.empty()) return; + + const std::string& entry = files[selectorIndex]; + const bool isDirectory = (entry.back() == '/'); + + if (isDirectory) { + if (basepath.back() != '/') basepath += "/"; + basepath += entry.substr(0, entry.length() - 1); + loadFiles(); + selectorIndex = 0; + requestUpdate(); + } else { + std::string fullPath = basepath; + if (fullPath.back() != '/') fullPath += "/"; + fullPath += entry; + ReturnHint hint; + hint.target = ReturnTo::FileBrowser; + hint.path = basepath; + hint.selectName = entry; + activityManager.replaceWithReader(std::move(fullPath), std::move(hint)); + } + return; + } + + if (ev.button == MappedInputManager::Button::Left && ev.type == ButtonEventManager::PressType::Long) { + if (files.empty()) { + return; + } + + const std::string& entry = files[selectorIndex]; + const bool isDirectory = (entry.back() == '/'); + if (isDirectory) { + return; + } - // Right opens the info page for epub files - if (mappedInput.wasReleased(MappedInputManager::Button::Right)) { - if (files.empty()) return; - const std::string& entry = files[selectorIndex]; - if (entry.back() != '/' && (FsHelpers::hasEpubExtension(entry) || FsHelpers::hasXtcExtension(entry))) { std::string cleanBase = basepath; if (cleanBase.back() != '/') cleanBase += "/"; - startActivityForResult(std::make_unique(renderer, mappedInput, cleanBase + entry), - [this](const ActivityResult&) { requestUpdate(); }); + const std::string fullPath = cleanBase + entry; + + auto handler = [this, fullPath](const ActivityResult& res) { + if (!res.isCancelled) { + LOG_DBG("FileBrowser", "Attempting to delete: %s", fullPath.c_str()); + clearFileMetadata(fullPath); + if (Storage.remove(fullPath.c_str())) { + LOG_DBG("FileBrowser", "Deleted successfully"); + loadFiles(); + if (files.empty()) { + selectorIndex = 0; + } else if (selectorIndex >= files.size()) { + selectorIndex = files.size() - 1; + } + requestUpdate(true); + } else { + LOG_ERR("FileBrowser", "Failed to delete file: %s", fullPath.c_str()); + } + } else { + LOG_DBG("FileBrowser", "Delete cancelled by user"); + } + }; + + startActivityForResult( + std::make_unique(renderer, mappedInput, tr(STR_DELETE) + std::string("? "), entry), + handler); + return; + } + + if (ev.button == MappedInputManager::Button::Right && ev.type == ButtonEventManager::PressType::Short) { + if (files.empty()) return; + const std::string& entry = files[selectorIndex]; + if (entry.back() != '/' && (FsHelpers::hasEpubExtension(entry) || FsHelpers::hasXtcExtension(entry))) { + std::string cleanBase = basepath; + if (cleanBase.back() != '/') cleanBase += "/"; + startActivityForResult(std::make_unique(renderer, mappedInput, cleanBase + entry), + [this](const ActivityResult&) { requestUpdate(); }); + } + return; } - return; } // Up/Down side buttons navigate the list diff --git a/src/activities/reader/EpubReaderActivity.cpp b/src/activities/reader/EpubReaderActivity.cpp index 26621ec8..e9a2818e 100644 --- a/src/activities/reader/EpubReaderActivity.cpp +++ b/src/activities/reader/EpubReaderActivity.cpp @@ -248,66 +248,64 @@ void EpubReaderActivity::loop() { } } - // Long press CONFIRM (1s+) goes directly to KOReader sync when credentials are configured. - // We intentionally keep long-press on the richer compare flow so advanced - // conflict-resolution behavior stays available even after simplifying menu UX. - // Without credentials, fall through to the regular menu on release. - if (mappedInput.isPressed(MappedInputManager::Button::Confirm) && - mappedInput.getHeldTime() >= ReaderUtils::GO_HOME_MS && KOREADER_STORE.hasCredentials()) { - launchKOReaderSync(SyncLaunchMode::COMPARE); - return; - } - - // Short press CONFIRM enters reader menu activity. - if (mappedInput.wasReleased(MappedInputManager::Button::Confirm) && - mappedInput.getHeldTime() < ReaderUtils::GO_HOME_MS) { - const int currentPage = section ? section->currentPage + 1 : 0; - const int totalPages = section ? section->pageCount : 0; - float bookProgress = 0.0f; - if (epub->getBookSize() > 0 && section && section->pageCount > 0) { - const float chapterProgress = static_cast(section->currentPage) / static_cast(section->pageCount); - bookProgress = epub->calculateProgress(currentSpineIndex, chapterProgress) * 100.0f; + ButtonEventManager::ButtonEvent ev; + while (buttonEvents.consumeEvent(ev)) { + if (ev.button == MappedInputManager::Button::Confirm) { + if (ev.type == ButtonEventManager::PressType::Long && KOREADER_STORE.hasCredentials()) { + launchKOReaderSync(SyncLaunchMode::COMPARE); + return; + } + if (ev.type == ButtonEventManager::PressType::Short) { + const int currentPage = section ? section->currentPage + 1 : 0; + const int totalPages = section ? section->pageCount : 0; + float bookProgress = 0.0f; + if (epub->getBookSize() > 0 && section && section->pageCount > 0) { + const float chapterProgress = + static_cast(section->currentPage) / static_cast(section->pageCount); + bookProgress = epub->calculateProgress(currentSpineIndex, chapterProgress) * 100.0f; + } + const int bookProgressPercent = clampPercent(static_cast(bookProgress + 0.5f)); + const bool isCurrentPageStarred = section && bookmarkStore.has(static_cast(currentSpineIndex), + static_cast(section->currentPage)); + ReaderUtils::enforceExitFullRefresh(renderer); + startActivityForResult( + std::make_unique( + renderer, mappedInput, epub->getTitle(), currentPage, totalPages, bookProgressPercent, + SETTINGS.orientation, !currentPageFootnotes.empty(), bookEmbeddedStyleOverride, + bookImageRenderingOverride, bookFontFamilyOverride, bookFontSizeOverride, SETTINGS.textDarkness, + !bookmarkStore.isEmpty(), isCurrentPageStarred), + [this](const ActivityResult& result) { + // Always apply orientation/darkness change even if the menu was cancelled + const auto& menu = std::get(result.data); + applyOrientation(menu.orientation); + applyTextDarkness(menu.textDarkness); + toggleAutoPageTurn(menu.pageTurnOption); + applyBookReaderOverrides(menu.embeddedStyleOverride, menu.imageRenderingOverride, menu.fontFamilyOverride, + menu.fontSizeOverride); + if (!result.isCancelled) { + onReaderMenuConfirm(static_cast(menu.action)); + } + }); + return; + } } - const int bookProgressPercent = clampPercent(static_cast(bookProgress + 0.5f)); - const bool isCurrentPageStarred = section && bookmarkStore.has(static_cast(currentSpineIndex), - static_cast(section->currentPage)); - ReaderUtils::enforceExitFullRefresh(renderer); - startActivityForResult(std::make_unique( - renderer, mappedInput, epub->getTitle(), currentPage, totalPages, bookProgressPercent, - SETTINGS.orientation, !currentPageFootnotes.empty(), bookEmbeddedStyleOverride, - bookImageRenderingOverride, bookFontFamilyOverride, bookFontSizeOverride, - SETTINGS.textDarkness, !bookmarkStore.isEmpty(), isCurrentPageStarred), - [this](const ActivityResult& result) { - // Always apply orientation/darkness change even if the menu was cancelled - const auto& menu = std::get(result.data); - applyOrientation(menu.orientation); - applyTextDarkness(menu.textDarkness); - toggleAutoPageTurn(menu.pageTurnOption); - applyBookReaderOverrides(menu.embeddedStyleOverride, menu.imageRenderingOverride, - menu.fontFamilyOverride, menu.fontSizeOverride); - if (!result.isCancelled) { - onReaderMenuConfirm(static_cast(menu.action)); - } - }); - } - // Long press BACK (1s+) goes to home screen - if (mappedInput.isPressed(MappedInputManager::Button::Back) && mappedInput.getHeldTime() >= ReaderUtils::GO_HOME_MS) { - ReaderUtils::enforceExitFullRefresh(renderer); - onGoHome(); - return; - } - - // Short press BACK returns to the calling activity (or restores position if viewing footnote) - if (mappedInput.wasReleased(MappedInputManager::Button::Back) && - mappedInput.getHeldTime() < ReaderUtils::GO_HOME_MS) { - if (footnoteDepth > 0) { - restoreSavedPosition(); - return; + if (ev.button == MappedInputManager::Button::Back) { + if (ev.type == ButtonEventManager::PressType::Long) { + ReaderUtils::enforceExitFullRefresh(renderer); + onGoHome(); + return; + } + if (ev.type == ButtonEventManager::PressType::Short) { + if (footnoteDepth > 0) { + restoreSavedPosition(); + return; + } + ReaderUtils::enforceExitFullRefresh(renderer); + finish(); + return; + } } - ReaderUtils::enforceExitFullRefresh(renderer); - finish(); - return; } auto [prevTriggered, nextTriggered] = ReaderUtils::detectPageTurn(mappedInput); @@ -327,65 +325,6 @@ void EpubReaderActivity::loop() { return; } - const bool skipChapter = mappedInput.getHeldTime() > skipChapterMs; - - // Chapter skip navigates by TOC entries, not spine boundaries. - // Spine items without their own TOC entry inherit the previous spine's tocIndex - // (see BookMetadataCache), so they're treated as continuations of the last chapter. - // At the boundaries: skipping forward past the last TOC entry jumps to end-of-book - // (clamped in render()); skipping backward before the first TOC entry jumps to the - // spine before the current chapter's first spine (clamped to 0 in render()). - if (skipChapter) { - lastPageTurnTime = millis(); - { - RenderLock lock(*this); - - if (section && section->pageCount > 0) { - const int curTocIndex = section->getTocIndexForPage(section->currentPage); - const int nextTocIndex = nextTriggered ? curTocIndex + 1 : curTocIndex - 1; - - if (curTocIndex < 0) { - // No TOC entry for this spine, fall back to spine-level skip - nextPageNumber = 0; - currentSpineIndex = nextTriggered ? currentSpineIndex + 1 : currentSpineIndex - 1; - section.reset(); - } else if (nextTocIndex >= 0 && nextTocIndex < epub->getTocItemsCount()) { - const int newSpineIndex = epub->getSpineIndexForTocIndex(nextTocIndex); - - if (newSpineIndex == currentSpineIndex) { - if (const auto resolvedPage = section->getPageForTocIndex(nextTocIndex)) { - section->currentPage = *resolvedPage; - } else { - LOG_DBG("ERS", "No page boundary for TOC %d in spine %d, staying on current page", nextTocIndex, - currentSpineIndex); - } - } else { - pendingTocIndex = nextTocIndex; - nextPageNumber = 0; - currentSpineIndex = newSpineIndex; - section.reset(); - } - } else if (nextTriggered) { - // Beyond last TOC entry, go to end of book - nextPageNumber = 0; - currentSpineIndex = epub->getSpineItemsCount(); - section.reset(); - } else { - // Before first TOC entry, skip to spine before the current chapter - nextPageNumber = 0; - currentSpineIndex = epub->getTocItem(curTocIndex).spineIndex - 1; - section.reset(); - } - } else { - nextPageNumber = 0; - currentSpineIndex = nextTriggered ? currentSpineIndex + 1 : currentSpineIndex - 1; - section.reset(); - } - } - requestUpdate(); - return; - } - // No current section, attempt to rerender the book if (!section) { requestUpdate(); diff --git a/src/activities/reader/MdReaderActivity.cpp b/src/activities/reader/MdReaderActivity.cpp index 468c44a7..1446ea10 100644 --- a/src/activities/reader/MdReaderActivity.cpp +++ b/src/activities/reader/MdReaderActivity.cpp @@ -23,7 +23,6 @@ namespace { constexpr size_t CHUNK_SIZE = 8 * 1024; constexpr size_t MAX_LINE_LENGTH = 64 * 1024; -constexpr unsigned long HEADING_SKIP_MS = 700; constexpr uint32_t CACHE_MAGIC = 0x4D4B4449; // "MKDI" constexpr uint8_t CACHE_VERSION = 3; // Bumped: nested list indent + task checkboxes @@ -222,54 +221,55 @@ void MdReaderActivity::onExit() { } void MdReaderActivity::loop() { - if (mappedInput.isPressed(MappedInputManager::Button::Back) && mappedInput.getHeldTime() >= ReaderUtils::GO_HOME_MS) { - activityManager.goToFileBrowser(txt ? txt->getPath() : ""); - return; - } + ButtonEventManager::ButtonEvent ev; + while (buttonEvents.consumeEvent(ev)) { + if (ev.button == MappedInputManager::Button::Back) { + if (ev.type == ButtonEventManager::PressType::Long) { + activityManager.goToFileBrowser(txt ? txt->getPath() : ""); + return; + } + if (ev.type == ButtonEventManager::PressType::Short) { + onGoHome(); + return; + } + } - if (mappedInput.wasReleased(MappedInputManager::Button::Back) && - mappedInput.getHeldTime() < ReaderUtils::GO_HOME_MS) { - onGoHome(); - return; - } - - if (mappedInput.wasReleased(MappedInputManager::Button::Confirm) && !headings.empty()) { - currentHeadingIndex = getHeadingIndexForOffset(pageOffsets[currentPage]); - ReaderUtils::enforceExitFullRefresh(renderer); - startActivityForResult( - std::make_unique(renderer, mappedInput, headings, currentHeadingIndex), - [this](const ActivityResult& result) { - if (!result.isCancelled) { - currentPage = std::get(result.data).page; - currentHeadingIndex = getHeadingIndexForOffset(pageOffsets[currentPage]); - requestUpdate(); - } - }); - return; - } - - auto [prevTriggered, nextTriggered] = ReaderUtils::detectPageTurn(mappedInput); - if (!prevTriggered && !nextTriggered) { - return; - } - - const bool headingSkip = mappedInput.getHeldTime() > HEADING_SKIP_MS; - if (headingSkip && !headings.empty()) { - jumpToHeading(nextTriggered); - return; - } - - if (prevTriggered && currentPage > 0) { - currentPage--; - currentHeadingIndex = getHeadingIndexForOffset(pageOffsets[currentPage]); - requestUpdate(); - } else if (nextTriggered) { - if (currentPage < totalPages - 1) { - currentPage++; + if (!headings.empty() && ev.button == MappedInputManager::Button::Confirm && + ev.type == ButtonEventManager::PressType::Short) { currentHeadingIndex = getHeadingIndexForOffset(pageOffsets[currentPage]); - requestUpdate(); - } else { - onGoHome(); + ReaderUtils::enforceExitFullRefresh(renderer); + startActivityForResult( + std::make_unique(renderer, mappedInput, headings, currentHeadingIndex), + [this](const ActivityResult& result) { + if (!result.isCancelled) { + currentPage = std::get(result.data).page; + currentHeadingIndex = getHeadingIndexForOffset(pageOffsets[currentPage]); + requestUpdate(); + } + }); + return; + } + + if ((ev.button == MappedInputManager::Button::PageBack || ev.button == MappedInputManager::Button::Left) && + ev.type == ButtonEventManager::PressType::Short) { + if (currentPage > 0) { + currentPage--; + currentHeadingIndex = getHeadingIndexForOffset(pageOffsets[currentPage]); + requestUpdate(); + } + return; + } + + if ((ev.button == MappedInputManager::Button::PageForward || ev.button == MappedInputManager::Button::Right) && + ev.type == ButtonEventManager::PressType::Short) { + if (currentPage < totalPages - 1) { + currentPage++; + currentHeadingIndex = getHeadingIndexForOffset(pageOffsets[currentPage]); + requestUpdate(); + } else { + onGoHome(); + } + return; } } } diff --git a/src/activities/reader/TxtReaderActivity.cpp b/src/activities/reader/TxtReaderActivity.cpp index bed59e7b..2daeb920 100644 --- a/src/activities/reader/TxtReaderActivity.cpp +++ b/src/activities/reader/TxtReaderActivity.cpp @@ -140,51 +140,55 @@ void TxtReaderActivity::loop() { return; } - // Long press BACK (1s+) goes to home screen - if (mappedInput.isPressed(MappedInputManager::Button::Back) && mappedInput.getHeldTime() >= ReaderUtils::GO_HOME_MS) { - ReaderUtils::enforceExitFullRefresh(renderer); - onGoHome(); - return; - } + ButtonEventManager::ButtonEvent ev; + while (buttonEvents.consumeEvent(ev)) { + if (ev.button == MappedInputManager::Button::Back) { + if (ev.type == ButtonEventManager::PressType::Long) { + ReaderUtils::enforceExitFullRefresh(renderer); + onGoHome(); + return; + } + if (ev.type == ButtonEventManager::PressType::Short) { + ReaderUtils::enforceExitFullRefresh(renderer); + finish(); + return; + } + } - // Short press BACK returns to the calling activity - if (mappedInput.wasReleased(MappedInputManager::Button::Back) && - mappedInput.getHeldTime() < ReaderUtils::GO_HOME_MS) { - ReaderUtils::enforceExitFullRefresh(renderer); - finish(); - return; - } + if (!bookmarkStore.isEmpty() && ev.button == MappedInputManager::Button::Confirm && + ev.type == ButtonEventManager::PressType::Short) { + ReaderUtils::enforceExitFullRefresh(renderer); + startActivityForResult(std::make_unique(renderer, mappedInput, bookmarkStore), + [this](const ActivityResult& result) { + if (!result.isCancelled) { + const auto& starred = std::get(result.data); + currentPage = starred.pageNumber; + if (currentPage >= totalPages) currentPage = totalPages - 1; + if (currentPage < 0) currentPage = 0; + } + requestUpdate(); + }); + return; + } - // Open starred pages list via Confirm button - if (mappedInput.wasReleased(MappedInputManager::Button::Confirm) && !bookmarkStore.isEmpty()) { - ReaderUtils::enforceExitFullRefresh(renderer); - startActivityForResult(std::make_unique(renderer, mappedInput, bookmarkStore), - [this](const ActivityResult& result) { - if (!result.isCancelled) { - const auto& starred = std::get(result.data); - currentPage = starred.pageNumber; - if (currentPage >= totalPages) currentPage = totalPages - 1; - if (currentPage < 0) currentPage = 0; - } - requestUpdate(); - }); - return; - } + if ((ev.button == MappedInputManager::Button::PageBack || ev.button == MappedInputManager::Button::Left) && + ev.type == ButtonEventManager::PressType::Short) { + if (currentPage > 0) { + currentPage--; + requestUpdate(); + } + return; + } - auto [prevTriggered, nextTriggered] = ReaderUtils::detectPageTurn(mappedInput); - if (!prevTriggered && !nextTriggered) { - return; - } - - if (prevTriggered && currentPage > 0) { - currentPage--; - requestUpdate(); - } else if (nextTriggered) { - if (currentPage < totalPages - 1) { - currentPage++; - requestUpdate(); - } else { - finish(); + if ((ev.button == MappedInputManager::Button::PageForward || ev.button == MappedInputManager::Button::Right) && + ev.type == ButtonEventManager::PressType::Short) { + if (currentPage < totalPages - 1) { + currentPage++; + requestUpdate(); + } else { + finish(); + } + return; } } } diff --git a/src/activities/reader/XtcReaderActivity.cpp b/src/activities/reader/XtcReaderActivity.cpp index f9176e51..992788fd 100644 --- a/src/activities/reader/XtcReaderActivity.cpp +++ b/src/activities/reader/XtcReaderActivity.cpp @@ -23,7 +23,6 @@ #include "fontIds.h" namespace { -constexpr unsigned long skipPageMs = 700; constexpr unsigned long goHomeMs = 1000; } // namespace @@ -65,38 +64,37 @@ void XtcReaderActivity::loop() { return; } - // Enter chapter selection activity - if (mappedInput.wasReleased(MappedInputManager::Button::Confirm)) { - if (xtc && xtc->hasChapters() && !xtc->getChapters().empty()) { - ReaderUtils::enforceExitFullRefresh(renderer); - startActivityForResult( - std::make_unique(renderer, mappedInput, xtc, currentPage), - [this](const ActivityResult& result) { - if (!result.isCancelled) { - currentPage = std::get(result.data).page; - } - }); + ButtonEventManager::ButtonEvent ev; + while (buttonEvents.consumeEvent(ev)) { + if (ev.button == MappedInputManager::Button::Confirm && ev.type == ButtonEventManager::PressType::Short) { + if (xtc && xtc->hasChapters() && !xtc->getChapters().empty()) { + ReaderUtils::enforceExitFullRefresh(renderer); + startActivityForResult( + std::make_unique(renderer, mappedInput, xtc, currentPage), + [this](const ActivityResult& result) { + if (!result.isCancelled) { + currentPage = std::get(result.data).page; + } + }); + return; + } + } + + if (ev.button == MappedInputManager::Button::Back) { + if (ev.type == ButtonEventManager::PressType::Long) { + ReaderUtils::enforceExitFullRefresh(renderer); + onGoHome(); + return; + } + if (ev.type == ButtonEventManager::PressType::Short) { + ReaderUtils::enforceExitFullRefresh(renderer); + finish(); + return; + } } } - // Long press BACK (1s+) goes to home screen - if (mappedInput.isPressed(MappedInputManager::Button::Back) && mappedInput.getHeldTime() >= goHomeMs) { - ReaderUtils::enforceExitFullRefresh(renderer); - onGoHome(); - return; - } - - // Short press BACK returns to the calling activity - if (mappedInput.wasReleased(MappedInputManager::Button::Back) && mappedInput.getHeldTime() < goHomeMs) { - ReaderUtils::enforceExitFullRefresh(renderer); - finish(); - return; - } - - const bool prevTriggered = mappedInput.wasReleased(MappedInputManager::Button::PageBack) || - mappedInput.wasReleased(MappedInputManager::Button::Left); - const bool nextTriggered = mappedInput.wasReleased(MappedInputManager::Button::PageForward) || - mappedInput.wasReleased(MappedInputManager::Button::Right); + auto [prevTriggered, nextTriggered] = ReaderUtils::detectPageTurn(mappedInput); if (!prevTriggered && !nextTriggered) { return; @@ -113,18 +111,13 @@ void XtcReaderActivity::loop() { return; } - const bool skipPages = mappedInput.getHeldTime() > skipPageMs; - const int skipAmount = skipPages ? 10 : 1; - if (prevTriggered) { - if (currentPage >= static_cast(skipAmount)) { - currentPage -= skipAmount; - } else { - currentPage = 0; + if (currentPage > 0) { + currentPage--; + requestUpdate(); } - requestUpdate(); } else if (nextTriggered) { - currentPage += skipAmount; + currentPage++; if (currentPage >= xtc->getPageCount()) { currentPage = xtc->getPageCount(); // Allow showing "End of book" } diff --git a/src/activities/util/BmpViewerActivity.cpp b/src/activities/util/BmpViewerActivity.cpp index 6285ef3b..a2cb1ee0 100644 --- a/src/activities/util/BmpViewerActivity.cpp +++ b/src/activities/util/BmpViewerActivity.cpp @@ -389,16 +389,18 @@ void BmpViewerActivity::loop() { Activity::loop(); // Long press BACK (1s+) goes to home screen - if (mappedInput.isPressed(MappedInputManager::Button::Back) && mappedInput.getHeldTime() >= ReaderUtils::GO_HOME_MS) { - onGoHome(); - return; - } - - // Short press BACK returns to the calling activity - if (mappedInput.wasReleased(MappedInputManager::Button::Back) && - mappedInput.getHeldTime() < ReaderUtils::GO_HOME_MS) { - finish(); - return; + ButtonEventManager::ButtonEvent ev; + while (buttonEvents.consumeEvent(ev)) { + if (ev.button == MappedInputManager::Button::Back) { + if (ev.type == ButtonEventManager::PressType::Long) { + onGoHome(); + return; + } + if (ev.type == ButtonEventManager::PressType::Short) { + finish(); + return; + } + } } // Confirm: toggle between 1-bit B&W and 4-level grayscale display.