feat: unify navigation handling with system-wide continuous navigation (#600)

This PR unifies navigation handling & adds system-wide support for
continuous navigation.

## Summary
Holding down a navigation button now continuously advances through items
until the button is released. This removes the need for repeated
press-and-release actions and makes navigation faster and smoother,
especially in long menus or documents.

When page-based navigation is available, it will navigate through pages.
If not, it will progress through menu items or similar list-based UI
elements.

Additionally, this PR fixes inconsistencies in wrap-around behavior and
navigation index calculations.

Places where the navigation system was updated:
- Home Page
- Settings Pages
- My Library Page
- WiFi Selection Page
- OPDS Browser Page
- Keyboard
- File Transfer Page
- XTC Chapter Selector Page
- EPUB Chapter Selector Page

I’ve tested this on the device as much as possible and tried to match
the existing behavior. Please let me know if I missed anything. Thanks 🙏


![crosspoint](https://github.com/user-attachments/assets/6a3c7482-f45e-4a77-b156-721bb3b679e6)

---

Following the request from @osteotek and @daveallie for system-wide
support, the old PR (#379) has been closed in favor of this
consolidated, system-wide implementation.

---

### AI Usage

Did you use AI tools to help write this code? _**PARTIALLY**_

---------

Co-authored-by: Dave Allie <dave@daveallie.com>
This commit is contained in:
Istiak Tridip
2026-02-09 20:19:34 +11:00
committed by GitHub
co-authored by Dave Allie
parent e73bb3213f
commit 64d161e88b
31 changed files with 408 additions and 266 deletions
@@ -17,7 +17,6 @@
namespace {
constexpr int PAGE_ITEMS = 23;
constexpr int SKIP_PAGE_MS = 700;
} // namespace
void OpdsBookBrowserActivity::taskTrampoline(void* param) {
@@ -118,12 +117,6 @@ void OpdsBookBrowserActivity::loop() {
// Handle browsing state
if (state == BrowserState::BROWSING) {
const bool prevReleased = mappedInput.wasReleased(MappedInputManager::Button::Up) ||
mappedInput.wasReleased(MappedInputManager::Button::Left);
const bool nextReleased = mappedInput.wasReleased(MappedInputManager::Button::Down) ||
mappedInput.wasReleased(MappedInputManager::Button::Right);
const bool skipPage = mappedInput.getHeldTime() > SKIP_PAGE_MS;
if (mappedInput.wasReleased(MappedInputManager::Button::Confirm)) {
if (!entries.empty()) {
const auto& entry = entries[selectorIndex];
@@ -135,20 +128,29 @@ void OpdsBookBrowserActivity::loop() {
}
} else if (mappedInput.wasReleased(MappedInputManager::Button::Back)) {
navigateBack();
} else if (prevReleased && !entries.empty()) {
if (skipPage) {
selectorIndex = ((selectorIndex / PAGE_ITEMS - 1) * PAGE_ITEMS + entries.size()) % entries.size();
} else {
selectorIndex = (selectorIndex + entries.size() - 1) % entries.size();
}
updateRequired = true;
} else if (nextReleased && !entries.empty()) {
if (skipPage) {
selectorIndex = ((selectorIndex / PAGE_ITEMS + 1) * PAGE_ITEMS) % entries.size();
} else {
selectorIndex = (selectorIndex + 1) % entries.size();
}
updateRequired = true;
}
// Handle navigation
if (!entries.empty()) {
buttonNavigator.onNextRelease([this] {
selectorIndex = ButtonNavigator::nextIndex(selectorIndex, entries.size());
updateRequired = true;
});
buttonNavigator.onPreviousRelease([this] {
selectorIndex = ButtonNavigator::previousIndex(selectorIndex, entries.size());
updateRequired = true;
});
buttonNavigator.onNextContinuous([this] {
selectorIndex = ButtonNavigator::nextPageIndex(selectorIndex, entries.size(), PAGE_ITEMS);
updateRequired = true;
});
buttonNavigator.onPreviousContinuous([this] {
selectorIndex = ButtonNavigator::previousPageIndex(selectorIndex, entries.size(), PAGE_ITEMS);
updateRequired = true;
});
}
}
}
@@ -9,6 +9,7 @@
#include <vector>
#include "../ActivityWithSubactivity.h"
#include "util/ButtonNavigator.h"
/**
* Activity for browsing and downloading books from an OPDS server.
@@ -37,6 +38,7 @@ class OpdsBookBrowserActivity final : public ActivityWithSubactivity {
private:
TaskHandle_t displayTaskHandle = nullptr;
SemaphoreHandle_t renderingMutex = nullptr;
ButtonNavigator buttonNavigator;
bool updateRequired = false;
BrowserState state = BrowserState::LOADING;
+10 -11
View File
@@ -196,13 +196,18 @@ void HomeActivity::freeCoverBuffer() {
}
void HomeActivity::loop() {
const bool prevPressed = mappedInput.wasPressed(MappedInputManager::Button::Up) ||
mappedInput.wasPressed(MappedInputManager::Button::Left);
const bool nextPressed = mappedInput.wasPressed(MappedInputManager::Button::Down) ||
mappedInput.wasPressed(MappedInputManager::Button::Right);
const int menuCount = getMenuItemCount();
buttonNavigator.onNext([this, menuCount] {
selectorIndex = ButtonNavigator::nextIndex(selectorIndex, menuCount);
updateRequired = true;
});
buttonNavigator.onPrevious([this, menuCount] {
selectorIndex = ButtonNavigator::previousIndex(selectorIndex, menuCount);
updateRequired = true;
});
if (mappedInput.wasReleased(MappedInputManager::Button::Confirm)) {
// Calculate dynamic indices based on which options are available
int idx = 0;
@@ -226,12 +231,6 @@ void HomeActivity::loop() {
} else if (menuSelectedIndex == settingsIdx) {
onSettingsOpen();
}
} else if (prevPressed) {
selectorIndex = (selectorIndex + menuCount - 1) % menuCount;
updateRequired = true;
} else if (nextPressed) {
selectorIndex = (selectorIndex + 1) % menuCount;
updateRequired = true;
}
}
+2
View File
@@ -8,6 +8,7 @@
#include "../Activity.h"
#include "./MyLibraryActivity.h"
#include "util/ButtonNavigator.h"
struct RecentBook;
struct Rect;
@@ -15,6 +16,7 @@ struct Rect;
class HomeActivity final : public Activity {
TaskHandle_t displayTaskHandle = nullptr;
SemaphoreHandle_t renderingMutex = nullptr;
ButtonNavigator buttonNavigator;
int selectorIndex = 0;
bool updateRequired = false;
bool recentsLoading = false;
+19 -22
View File
@@ -11,7 +11,6 @@
#include "util/StringUtils.h"
namespace {
constexpr int SKIP_PAGE_MS = 700;
constexpr unsigned long GO_HOME_MS = 1000;
} // namespace
@@ -109,13 +108,6 @@ void MyLibraryActivity::loop() {
return;
}
const bool upReleased = mappedInput.wasReleased(MappedInputManager::Button::Left) ||
mappedInput.wasReleased(MappedInputManager::Button::Up);
;
const bool downReleased = mappedInput.wasReleased(MappedInputManager::Button::Right) ||
mappedInput.wasReleased(MappedInputManager::Button::Down);
const bool skipPage = mappedInput.getHeldTime() > SKIP_PAGE_MS;
const int pageItems = UITheme::getInstance().getNumberOfItemsPerPage(renderer, true, false, true, false);
if (mappedInput.wasReleased(MappedInputManager::Button::Confirm)) {
@@ -157,21 +149,26 @@ void MyLibraryActivity::loop() {
}
int listSize = static_cast<int>(files.size());
if (upReleased) {
if (skipPage) {
selectorIndex = std::max(static_cast<int>((selectorIndex / pageItems - 1) * pageItems), 0);
} else {
selectorIndex = (selectorIndex + listSize - 1) % listSize;
}
buttonNavigator.onNextRelease([this, listSize] {
selectorIndex = ButtonNavigator::nextIndex(static_cast<int>(selectorIndex), listSize);
updateRequired = true;
} else if (downReleased) {
if (skipPage) {
selectorIndex = std::min(static_cast<int>((selectorIndex / pageItems + 1) * pageItems), listSize - 1);
} else {
selectorIndex = (selectorIndex + 1) % listSize;
}
});
buttonNavigator.onPreviousRelease([this, listSize] {
selectorIndex = ButtonNavigator::previousIndex(static_cast<int>(selectorIndex), listSize);
updateRequired = true;
}
});
buttonNavigator.onNextContinuous([this, listSize, pageItems] {
selectorIndex = ButtonNavigator::nextPageIndex(static_cast<int>(selectorIndex), listSize, pageItems);
updateRequired = true;
});
buttonNavigator.onPreviousContinuous([this, listSize, pageItems] {
selectorIndex = ButtonNavigator::previousPageIndex(static_cast<int>(selectorIndex), listSize, pageItems);
updateRequired = true;
});
}
void MyLibraryActivity::displayTaskLoop() {
@@ -217,4 +214,4 @@ size_t MyLibraryActivity::findEntry(const std::string& name) const {
for (size_t i = 0; i < files.size(); i++)
if (files[i] == name) return i;
return 0;
}
}
+3
View File
@@ -8,11 +8,14 @@
#include <vector>
#include "../Activity.h"
#include "RecentBooksStore.h"
#include "util/ButtonNavigator.h"
class MyLibraryActivity final : public Activity {
private:
TaskHandle_t displayTaskHandle = nullptr;
SemaphoreHandle_t renderingMutex = nullptr;
ButtonNavigator buttonNavigator;
size_t selectorIndex = 0;
bool updateRequired = false;
+18 -21
View File
@@ -12,7 +12,6 @@
#include "util/StringUtils.h"
namespace {
constexpr int SKIP_PAGE_MS = 700;
constexpr unsigned long GO_HOME_MS = 1000;
} // namespace
@@ -70,13 +69,6 @@ void RecentBooksActivity::onExit() {
}
void RecentBooksActivity::loop() {
const bool upReleased = mappedInput.wasReleased(MappedInputManager::Button::Left) ||
mappedInput.wasReleased(MappedInputManager::Button::Up);
;
const bool downReleased = mappedInput.wasReleased(MappedInputManager::Button::Right) ||
mappedInput.wasReleased(MappedInputManager::Button::Down);
const bool skipPage = mappedInput.getHeldTime() > SKIP_PAGE_MS;
const int pageItems = UITheme::getInstance().getNumberOfItemsPerPage(renderer, true, false, true, true);
if (mappedInput.wasReleased(MappedInputManager::Button::Confirm)) {
@@ -92,21 +84,26 @@ void RecentBooksActivity::loop() {
}
int listSize = static_cast<int>(recentBooks.size());
if (upReleased) {
if (skipPage) {
selectorIndex = std::max(static_cast<int>((selectorIndex / pageItems - 1) * pageItems), 0);
} else {
selectorIndex = (selectorIndex + listSize - 1) % listSize;
}
buttonNavigator.onNextRelease([this, listSize] {
selectorIndex = ButtonNavigator::nextIndex(static_cast<int>(selectorIndex), listSize);
updateRequired = true;
} else if (downReleased) {
if (skipPage) {
selectorIndex = std::min(static_cast<int>((selectorIndex / pageItems + 1) * pageItems), listSize - 1);
} else {
selectorIndex = (selectorIndex + 1) % listSize;
}
});
buttonNavigator.onPreviousRelease([this, listSize] {
selectorIndex = ButtonNavigator::previousIndex(static_cast<int>(selectorIndex), listSize);
updateRequired = true;
}
});
buttonNavigator.onNextContinuous([this, listSize, pageItems] {
selectorIndex = ButtonNavigator::nextPageIndex(static_cast<int>(selectorIndex), listSize, pageItems);
updateRequired = true;
});
buttonNavigator.onPreviousContinuous([this, listSize, pageItems] {
selectorIndex = ButtonNavigator::previousPageIndex(static_cast<int>(selectorIndex), listSize, pageItems);
updateRequired = true;
});
}
void RecentBooksActivity::displayTaskLoop() {
@@ -9,11 +9,13 @@
#include "../Activity.h"
#include "RecentBooksStore.h"
#include "util/ButtonNavigator.h"
class RecentBooksActivity final : public Activity {
private:
TaskHandle_t displayTaskHandle = nullptr;
SemaphoreHandle_t renderingMutex = nullptr;
ButtonNavigator buttonNavigator;
size_t selectorIndex = 0;
bool updateRequired = false;
@@ -73,18 +73,15 @@ void NetworkModeSelectionActivity::loop() {
}
// Handle navigation
const bool prevPressed = mappedInput.wasPressed(MappedInputManager::Button::Up) ||
mappedInput.wasPressed(MappedInputManager::Button::Left);
const bool nextPressed = mappedInput.wasPressed(MappedInputManager::Button::Down) ||
mappedInput.wasPressed(MappedInputManager::Button::Right);
buttonNavigator.onNext([this] {
selectedIndex = ButtonNavigator::nextIndex(selectedIndex, MENU_ITEM_COUNT);
updateRequired = true;
});
if (prevPressed) {
selectedIndex = (selectedIndex + MENU_ITEM_COUNT - 1) % MENU_ITEM_COUNT;
buttonNavigator.onPrevious([this] {
selectedIndex = ButtonNavigator::previousIndex(selectedIndex, MENU_ITEM_COUNT);
updateRequired = true;
} else if (nextPressed) {
selectedIndex = (selectedIndex + 1) % MENU_ITEM_COUNT;
updateRequired = true;
}
});
}
void NetworkModeSelectionActivity::displayTaskLoop() {
@@ -6,6 +6,7 @@
#include <functional>
#include "../Activity.h"
#include "util/ButtonNavigator.h"
// Enum for network mode selection
enum class NetworkMode { JOIN_NETWORK, CONNECT_CALIBRE, CREATE_HOTSPOT };
@@ -22,6 +23,8 @@ enum class NetworkMode { JOIN_NETWORK, CONNECT_CALIBRE, CREATE_HOTSPOT };
class NetworkModeSelectionActivity final : public Activity {
TaskHandle_t displayTaskHandle = nullptr;
SemaphoreHandle_t renderingMutex = nullptr;
ButtonNavigator buttonNavigator;
int selectedIndex = 0;
bool updateRequired = false;
const std::function<void(NetworkMode)> onModeSelected;
@@ -420,20 +420,16 @@ void WifiSelectionActivity::loop() {
return;
}
// Handle UP/DOWN navigation
if (mappedInput.wasPressed(MappedInputManager::Button::Up) ||
mappedInput.wasPressed(MappedInputManager::Button::Left)) {
if (selectedNetworkIndex > 0) {
selectedNetworkIndex--;
updateRequired = true;
}
} else if (mappedInput.wasPressed(MappedInputManager::Button::Down) ||
mappedInput.wasPressed(MappedInputManager::Button::Right)) {
if (!networks.empty() && selectedNetworkIndex < static_cast<int>(networks.size()) - 1) {
selectedNetworkIndex++;
updateRequired = true;
}
}
// Handle navigation
buttonNavigator.onNext([this] {
selectedNetworkIndex = ButtonNavigator::nextIndex(selectedNetworkIndex, networks.size());
updateRequired = true;
});
buttonNavigator.onPrevious([this] {
selectedNetworkIndex = ButtonNavigator::previousIndex(selectedNetworkIndex, networks.size());
updateRequired = true;
});
}
}
@@ -10,6 +10,7 @@
#include <vector>
#include "activities/ActivityWithSubactivity.h"
#include "util/ButtonNavigator.h"
// Structure to hold WiFi network information
struct WifiNetworkInfo {
@@ -45,6 +46,7 @@ enum class WifiSelectionState {
class WifiSelectionActivity final : public ActivityWithSubactivity {
TaskHandle_t displayTaskHandle = nullptr;
SemaphoreHandle_t renderingMutex = nullptr;
ButtonNavigator buttonNavigator;
bool updateRequired = false;
WifiSelectionState state = WifiSelectionState::SCANNING;
int selectedNetworkIndex = 0;
@@ -6,11 +6,6 @@
#include "components/UITheme.h"
#include "fontIds.h"
namespace {
// Time threshold for treating a long press as a page-up/page-down
constexpr int SKIP_PAGE_MS = 700;
} // namespace
int EpubReaderChapterSelectionActivity::getTotalItems() const { return epub->getTocItemsCount(); }
int EpubReaderChapterSelectionActivity::getPageItems() const {
@@ -77,12 +72,6 @@ void EpubReaderChapterSelectionActivity::loop() {
return;
}
const bool prevReleased = mappedInput.wasReleased(MappedInputManager::Button::Up) ||
mappedInput.wasReleased(MappedInputManager::Button::Left);
const bool nextReleased = mappedInput.wasReleased(MappedInputManager::Button::Down) ||
mappedInput.wasReleased(MappedInputManager::Button::Right);
const bool skipPage = mappedInput.getHeldTime() > SKIP_PAGE_MS;
const int pageItems = getPageItems();
const int totalItems = getTotalItems();
@@ -95,21 +84,27 @@ 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;
}
updateRequired = true;
} else if (nextReleased) {
if (skipPage) {
selectorIndex = ((selectorIndex / pageItems + 1) * pageItems) % totalItems;
} else {
selectorIndex = (selectorIndex + 1) % totalItems;
}
updateRequired = true;
}
buttonNavigator.onNextRelease([this, totalItems] {
selectorIndex = ButtonNavigator::nextIndex(selectorIndex, totalItems);
updateRequired = true;
});
buttonNavigator.onPreviousRelease([this, totalItems] {
selectorIndex = ButtonNavigator::previousIndex(selectorIndex, totalItems);
updateRequired = true;
});
buttonNavigator.onNextContinuous([this, totalItems, pageItems] {
selectorIndex = ButtonNavigator::nextPageIndex(selectorIndex, totalItems, pageItems);
updateRequired = true;
});
buttonNavigator.onPreviousContinuous([this, totalItems, pageItems] {
selectorIndex = ButtonNavigator::previousPageIndex(selectorIndex, totalItems, pageItems);
updateRequired = true;
});
}
void EpubReaderChapterSelectionActivity::displayTaskLoop() {
@@ -7,12 +7,14 @@
#include <memory>
#include "../ActivityWithSubactivity.h"
#include "util/ButtonNavigator.h"
class EpubReaderChapterSelectionActivity final : public ActivityWithSubactivity {
std::shared_ptr<Epub> epub;
std::string epubPath;
TaskHandle_t displayTaskHandle = nullptr;
SemaphoreHandle_t renderingMutex = nullptr;
ButtonNavigator buttonNavigator;
int currentSpineIndex = 0;
int currentPage = 0;
int totalPagesInSpine = 0;
@@ -48,16 +48,19 @@ void EpubReaderMenuActivity::loop() {
return;
}
// Handle navigation
buttonNavigator.onNext([this] {
selectedIndex = ButtonNavigator::nextIndex(selectedIndex, static_cast<int>(menuItems.size()));
updateRequired = true;
});
buttonNavigator.onPrevious([this] {
selectedIndex = ButtonNavigator::previousIndex(selectedIndex, static_cast<int>(menuItems.size()));
updateRequired = true;
});
// Use local variables for items we need to check after potential deletion
if (mappedInput.wasReleased(MappedInputManager::Button::Up) ||
mappedInput.wasReleased(MappedInputManager::Button::Left)) {
selectedIndex = (selectedIndex + menuItems.size() - 1) % menuItems.size();
updateRequired = true;
} else if (mappedInput.wasReleased(MappedInputManager::Button::Down) ||
mappedInput.wasReleased(MappedInputManager::Button::Right)) {
selectedIndex = (selectedIndex + 1) % menuItems.size();
updateRequired = true;
} else if (mappedInput.wasReleased(MappedInputManager::Button::Confirm)) {
if (mappedInput.wasReleased(MappedInputManager::Button::Confirm)) {
const auto selectedAction = menuItems[selectedIndex].action;
if (selectedAction == MenuAction::ROTATE_SCREEN) {
// Cycle orientation preview locally; actual rotation happens on menu exit.
@@ -9,6 +9,7 @@
#include <vector>
#include "../ActivityWithSubactivity.h"
#include "util/ButtonNavigator.h"
class EpubReaderMenuActivity final : public ActivityWithSubactivity {
public:
@@ -48,6 +49,7 @@ class EpubReaderMenuActivity final : public ActivityWithSubactivity {
bool updateRequired = false;
TaskHandle_t displayTaskHandle = nullptr;
SemaphoreHandle_t renderingMutex = nullptr;
ButtonNavigator buttonNavigator;
std::string title = "Reader Menu";
uint8_t pendingOrientation = 0;
const std::vector<const char*> orientationLabels = {"Portrait", "Landscape CW", "Inverted", "Landscape CCW"};
@@ -79,25 +79,11 @@ void EpubReaderPercentSelectionActivity::loop() {
return;
}
if (mappedInput.wasReleased(MappedInputManager::Button::Left)) {
adjustPercent(-kSmallStep);
return;
}
buttonNavigator.onPressAndContinuous({MappedInputManager::Button::Left}, [this] { adjustPercent(-kSmallStep); });
buttonNavigator.onPressAndContinuous({MappedInputManager::Button::Right}, [this] { adjustPercent(kSmallStep); });
if (mappedInput.wasReleased(MappedInputManager::Button::Right)) {
adjustPercent(kSmallStep);
return;
}
if (mappedInput.wasReleased(MappedInputManager::Button::Up)) {
adjustPercent(kLargeStep);
return;
}
if (mappedInput.wasReleased(MappedInputManager::Button::Down)) {
adjustPercent(-kLargeStep);
return;
}
buttonNavigator.onPressAndContinuous({MappedInputManager::Button::Up}, [this] { adjustPercent(kLargeStep); });
buttonNavigator.onPressAndContinuous({MappedInputManager::Button::Down}, [this] { adjustPercent(-kLargeStep); });
}
void EpubReaderPercentSelectionActivity::renderScreen() {
@@ -7,6 +7,7 @@
#include "MappedInputManager.h"
#include "activities/ActivityWithSubactivity.h"
#include "util/ButtonNavigator.h"
class EpubReaderPercentSelectionActivity final : public ActivityWithSubactivity {
public:
@@ -31,6 +32,7 @@ class EpubReaderPercentSelectionActivity final : public ActivityWithSubactivity
// FreeRTOS task and mutex for rendering.
TaskHandle_t displayTaskHandle = nullptr;
SemaphoreHandle_t renderingMutex = nullptr;
ButtonNavigator buttonNavigator;
// Callback invoked when the user confirms a percent.
const std::function<void(int)> onSelect;
@@ -8,10 +8,6 @@
#include "components/UITheme.h"
#include "fontIds.h"
namespace {
constexpr int SKIP_PAGE_MS = 700;
} // namespace
int XtcReaderChapterSelectionActivity::getPageItems() const {
constexpr int lineHeight = 30;
@@ -78,13 +74,8 @@ void XtcReaderChapterSelectionActivity::onExit() {
}
void XtcReaderChapterSelectionActivity::loop() {
const bool prevReleased = mappedInput.wasReleased(MappedInputManager::Button::Up) ||
mappedInput.wasReleased(MappedInputManager::Button::Left);
const bool nextReleased = mappedInput.wasReleased(MappedInputManager::Button::Down) ||
mappedInput.wasReleased(MappedInputManager::Button::Right);
const bool skipPage = mappedInput.getHeldTime() > SKIP_PAGE_MS;
const int pageItems = getPageItems();
const int totalItems = static_cast<int>(xtc->getChapters().size());
if (mappedInput.wasReleased(MappedInputManager::Button::Confirm)) {
const auto& chapters = xtc->getChapters();
@@ -93,29 +84,27 @@ void XtcReaderChapterSelectionActivity::loop() {
}
} else if (mappedInput.wasReleased(MappedInputManager::Button::Back)) {
onGoBack();
} else if (prevReleased) {
const int total = static_cast<int>(xtc->getChapters().size());
if (total == 0) {
return;
}
if (skipPage) {
selectorIndex = ((selectorIndex / pageItems - 1) * pageItems + total) % total;
} else {
selectorIndex = (selectorIndex + total - 1) % total;
}
updateRequired = true;
} else if (nextReleased) {
const int total = static_cast<int>(xtc->getChapters().size());
if (total == 0) {
return;
}
if (skipPage) {
selectorIndex = ((selectorIndex / pageItems + 1) * pageItems) % total;
} else {
selectorIndex = (selectorIndex + 1) % total;
}
updateRequired = true;
}
buttonNavigator.onNextRelease([this, totalItems] {
selectorIndex = ButtonNavigator::nextIndex(selectorIndex, totalItems);
updateRequired = true;
});
buttonNavigator.onPreviousRelease([this, totalItems] {
selectorIndex = ButtonNavigator::previousIndex(selectorIndex, totalItems);
updateRequired = true;
});
buttonNavigator.onNextContinuous([this, totalItems, pageItems] {
selectorIndex = ButtonNavigator::nextPageIndex(selectorIndex, totalItems, pageItems);
updateRequired = true;
});
buttonNavigator.onPreviousContinuous([this, totalItems, pageItems] {
selectorIndex = ButtonNavigator::previousPageIndex(selectorIndex, totalItems, pageItems);
updateRequired = true;
});
}
void XtcReaderChapterSelectionActivity::displayTaskLoop() {
@@ -7,11 +7,13 @@
#include <memory>
#include "../Activity.h"
#include "util/ButtonNavigator.h"
class XtcReaderChapterSelectionActivity final : public Activity {
std::shared_ptr<Xtc> xtc;
TaskHandle_t displayTaskHandle = nullptr;
SemaphoreHandle_t renderingMutex = nullptr;
ButtonNavigator buttonNavigator;
uint32_t currentPage = 0;
int selectorIndex = 0;
bool updateRequired = false;

Some files were not shown because too many files have changed in this diff Show More