fix: Scrolling page items calculation (#716)

## Summary

Fix for the page skip issue detected
https://github.com/crosspoint-reader/crosspoint-reader/pull/700#issuecomment-3856374323
by user @whyte-j

Skipping down on the last page now skips to the last item, and up on the
first page to the first item, rather than wrapping around the list in a
weird way.

## Additional Context

The calculation was outdated after several changes were added afterwards

---

### 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? _**NO**_
This commit is contained in:
CaptainFrito
2026-02-09 00:58:46 +07:00
committed by GitHub
parent 67ddd60fce
commit 5b90b68e99
4 changed files with 14 additions and 10 deletions

View File

@@ -3,6 +3,8 @@
#include <GfxRenderer.h>
#include <SDCardManager.h>
#include <algorithm>
#include "MappedInputManager.h"
#include "components/UITheme.h"
#include "fontIds.h"
@@ -114,7 +116,7 @@ void MyLibraryActivity::loop() {
mappedInput.wasReleased(MappedInputManager::Button::Down);
const bool skipPage = mappedInput.getHeldTime() > SKIP_PAGE_MS;
const int pageItems = UITheme::getInstance().getNumberOfItemsPerPage(renderer, true, false, true, true);
const int pageItems = UITheme::getInstance().getNumberOfItemsPerPage(renderer, true, false, true, false);
if (mappedInput.wasReleased(MappedInputManager::Button::Confirm)) {
if (files.empty()) {
@@ -157,14 +159,14 @@ void MyLibraryActivity::loop() {
int listSize = static_cast<int>(files.size());
if (upReleased) {
if (skipPage) {
selectorIndex = ((selectorIndex / pageItems - 1) * pageItems + listSize) % listSize;
selectorIndex = std::max(static_cast<int>((selectorIndex / pageItems - 1) * pageItems), 0);
} else {
selectorIndex = (selectorIndex + listSize - 1) % listSize;
}
updateRequired = true;
} else if (downReleased) {
if (skipPage) {
selectorIndex = ((selectorIndex / pageItems + 1) * pageItems) % listSize;
selectorIndex = std::min(static_cast<int>((selectorIndex / pageItems + 1) * pageItems), listSize - 1);
} else {
selectorIndex = (selectorIndex + 1) % listSize;
}
@@ -195,7 +197,7 @@ void MyLibraryActivity::render() const {
GUI.drawHeader(renderer, Rect{0, metrics.topPadding, pageWidth, metrics.headerHeight}, folderName);
const int contentTop = metrics.topPadding + metrics.headerHeight + metrics.verticalSpacing;
const int contentHeight = pageHeight - contentTop - metrics.buttonHintsHeight - metrics.verticalSpacing * 2;
const int contentHeight = pageHeight - contentTop - metrics.buttonHintsHeight - metrics.verticalSpacing;
if (files.empty()) {
renderer.drawText(UI_10_FONT_ID, metrics.contentSidePadding, contentTop + 20, "No books found");
} else {

View File

@@ -3,6 +3,8 @@
#include <GfxRenderer.h>
#include <SDCardManager.h>
#include <algorithm>
#include "MappedInputManager.h"
#include "RecentBooksStore.h"
#include "components/UITheme.h"
@@ -92,14 +94,14 @@ void RecentBooksActivity::loop() {
int listSize = static_cast<int>(recentBooks.size());
if (upReleased) {
if (skipPage) {
selectorIndex = ((selectorIndex / pageItems - 1) * pageItems + listSize) % listSize;
selectorIndex = std::max(static_cast<int>((selectorIndex / pageItems - 1) * pageItems), 0);
} else {
selectorIndex = (selectorIndex + listSize - 1) % listSize;
}
updateRequired = true;
} else if (downReleased) {
if (skipPage) {
selectorIndex = ((selectorIndex / pageItems + 1) * pageItems) % listSize;
selectorIndex = std::min(static_cast<int>((selectorIndex / pageItems + 1) * pageItems), listSize - 1);
} else {
selectorIndex = (selectorIndex + 1) % listSize;
}
@@ -129,7 +131,7 @@ void RecentBooksActivity::render() const {
GUI.drawHeader(renderer, Rect{0, metrics.topPadding, pageWidth, metrics.headerHeight}, "Recent Books");
const int contentTop = metrics.topPadding + metrics.headerHeight + metrics.verticalSpacing;
const int contentHeight = pageHeight - contentTop - metrics.buttonHintsHeight - metrics.verticalSpacing * 2;
const int contentHeight = pageHeight - contentTop - metrics.buttonHintsHeight - metrics.verticalSpacing;
// Recent tab
if (recentBooks.empty()) {

View File

@@ -40,10 +40,10 @@ int UITheme::getNumberOfItemsPerPage(const GfxRenderer& renderer, bool hasHeader
const ThemeMetrics& metrics = UITheme::getInstance().getMetrics();
int reservedHeight = metrics.topPadding;
if (hasHeader) {
reservedHeight += metrics.headerHeight;
reservedHeight += metrics.headerHeight + metrics.verticalSpacing;
}
if (hasTabBar) {
reservedHeight += metrics.tabBarHeight + metrics.verticalSpacing;
reservedHeight += metrics.tabBarHeight;
}
if (hasButtonHints) {
reservedHeight += metrics.verticalSpacing + metrics.buttonHintsHeight;

View File

@@ -174,7 +174,7 @@ void BaseTheme::drawList(const GfxRenderer& renderer, Rect rect, int itemCount,
const int centerX = rect.x + rect.width - indicatorWidth / 2 - margin;
const int indicatorTop = rect.y; // Offset to avoid overlapping side button hints
const int indicatorBottom = rect.y + rect.height - 30;
const int indicatorBottom = rect.y + rect.height - arrowSize;
// Draw up arrow at top (^) - narrow point at top, wide base at bottom
for (int i = 0; i < arrowSize; ++i) {