Paginate through bookinfo if required
This commit is contained in:
@@ -234,6 +234,8 @@ STR_FETCH_FEED_FAILED: "Failed to fetch feed"
|
||||
STR_PARSE_FEED_FAILED: "Failed to parse feed"
|
||||
STR_NEXT_PAGE: "Next Page »"
|
||||
STR_PREV_PAGE: "« Previous Page"
|
||||
STR_NEXT: "Next"
|
||||
STR_PREV: "Prev"
|
||||
STR_SEARCH: "Search"
|
||||
STR_NETWORK_PREFIX: "Network: "
|
||||
STR_IP_ADDRESS_PREFIX: "IP Address: "
|
||||
|
||||
@@ -98,6 +98,7 @@ void BookInfoActivity::loadData() {
|
||||
|
||||
void BookInfoActivity::onEnter() {
|
||||
Activity::onEnter();
|
||||
fullRenderDone = false;
|
||||
{
|
||||
RenderLock lock(*this);
|
||||
renderLoading();
|
||||
@@ -109,10 +110,33 @@ void BookInfoActivity::onEnter() {
|
||||
void BookInfoActivity::loop() {
|
||||
if (mappedInput.wasReleased(MappedInputManager::Button::Back)) {
|
||||
finish();
|
||||
} else if (mappedInput.wasReleased(MappedInputManager::Button::Left)) {
|
||||
if (descPage > 0) {
|
||||
descPage--;
|
||||
requestUpdate(true);
|
||||
}
|
||||
} else if (mappedInput.wasReleased(MappedInputManager::Button::Right)) {
|
||||
if (descPage + 1 < descTotalPages) {
|
||||
descPage++;
|
||||
requestUpdate(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BookInfoActivity::render(RenderLock&&) {
|
||||
// Fast path: only the description page / button hints changed. Reuse the
|
||||
// already-rendered header/cover/meta by clearing just those two bands. Cap
|
||||
// consecutive partial renders to bound e-ink ghosting buildup.
|
||||
if (fullRenderDone && loadSucceeded && !description.empty() && partialRenderCount < MAX_PARTIAL_RENDERS) {
|
||||
renderer.fillRect(descBandX, descBandY, descBandWidth, descBandHeight, false);
|
||||
renderer.fillRect(0, hintsBandY, renderer.getScreenWidth(), hintsBandHeight, false);
|
||||
renderDescriptionAndHints();
|
||||
++partialRenderCount;
|
||||
renderer.displayBuffer();
|
||||
return;
|
||||
}
|
||||
|
||||
partialRenderCount = 0;
|
||||
renderer.clearScreen();
|
||||
|
||||
const auto& metrics = UITheme::getInstance().getMetrics();
|
||||
@@ -240,28 +264,66 @@ void BookInfoActivity::render(RenderLock&&) {
|
||||
|
||||
topSectionBottom = std::max(topSectionBottom, metaY);
|
||||
|
||||
// --- Description: full width below the top section ---
|
||||
// --- Description: full width below the top section, paged via Left/Right ---
|
||||
descTotalPages = 0;
|
||||
descLinesPerPage = 0;
|
||||
descBandX = textX;
|
||||
descBandWidth = textWidth;
|
||||
descBandY = contentBottom;
|
||||
descBandHeight = 0;
|
||||
if (!description.empty()) {
|
||||
int y = topSectionBottom + metrics.verticalSpacing;
|
||||
if (y + lineHeightSmall + 4 < contentBottom) {
|
||||
renderer.drawLine(textX, y, contentRect.x + contentRect.width - metrics.contentSidePadding, y);
|
||||
y += 4;
|
||||
|
||||
const int descMaxLines = (contentBottom - y) / lineHeightSmall;
|
||||
if (descMaxLines > 0) {
|
||||
const auto lines = renderer.wrappedText(UI_10_FONT_ID, description.c_str(), textWidth, descMaxLines);
|
||||
for (const auto& line : lines) {
|
||||
if (y + lineHeightSmall > contentBottom) break;
|
||||
renderer.drawText(UI_10_FONT_ID, textX, y, line.c_str());
|
||||
y += lineHeightSmall;
|
||||
}
|
||||
// Record the description band (below the separator) for partial redraws.
|
||||
descBandY = y;
|
||||
descBandHeight = contentBottom - y;
|
||||
}
|
||||
}
|
||||
|
||||
// Hints band spans from the bottom of the content area to the screen bottom.
|
||||
hintsBandY = contentRect.y + contentRect.height;
|
||||
hintsBandHeight = renderer.getScreenHeight() - hintsBandY;
|
||||
|
||||
renderDescriptionAndHints();
|
||||
|
||||
fullRenderDone = true;
|
||||
renderer.displayBuffer();
|
||||
}
|
||||
|
||||
void BookInfoActivity::renderDescriptionAndHints() {
|
||||
const int lineHeightSmall = renderer.getLineHeight(UI_10_FONT_ID);
|
||||
|
||||
descTotalPages = 0;
|
||||
descLinesPerPage = 0;
|
||||
|
||||
if (!description.empty() && descBandHeight > 0) {
|
||||
descLinesPerPage = descBandHeight / lineHeightSmall;
|
||||
if (descLinesPerPage > 0) {
|
||||
if (descLines.empty() || descWrappedWidth != descBandWidth) {
|
||||
descLines = renderer.wrappedText(UI_10_FONT_ID, description.c_str(), descBandWidth, 1000);
|
||||
descWrappedWidth = descBandWidth;
|
||||
}
|
||||
const int totalLines = static_cast<int>(descLines.size());
|
||||
descTotalPages = (totalLines + descLinesPerPage - 1) / descLinesPerPage;
|
||||
if (descPage >= descTotalPages) descPage = std::max(0, descTotalPages - 1);
|
||||
|
||||
const int startLine = descPage * descLinesPerPage;
|
||||
const int endLine = std::min(totalLines, startLine + descLinesPerPage);
|
||||
int y = descBandY;
|
||||
const int bandBottom = descBandY + descBandHeight;
|
||||
for (int i = startLine; i < endLine; ++i) {
|
||||
if (y + lineHeightSmall > bandBottom) break;
|
||||
renderer.drawText(UI_10_FONT_ID, descBandX, y, descLines[i].c_str());
|
||||
y += lineHeightSmall;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Button hints
|
||||
const auto labels = mappedInput.mapLabels(tr(STR_BACK), "", "", "");
|
||||
const char* prevLabel = (descPage > 0) ? tr(STR_PREV) : "";
|
||||
const char* nextLabel = (descPage + 1 < descTotalPages) ? tr(STR_NEXT) : "";
|
||||
const auto labels = mappedInput.mapLabels(tr(STR_BACK), "", prevLabel, nextLabel);
|
||||
GUI.drawButtonHints(renderer, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
|
||||
|
||||
renderer.displayBuffer();
|
||||
}
|
||||
|
||||
@@ -19,9 +19,29 @@ class BookInfoActivity final : public Activity {
|
||||
bool loadSucceeded = false;
|
||||
size_t fileSizeBytes = 0;
|
||||
|
||||
// Description paging (populated lazily on first render)
|
||||
std::vector<std::string> descLines;
|
||||
int descWrappedWidth = 0;
|
||||
int descPage = 0;
|
||||
int descLinesPerPage = 0;
|
||||
int descTotalPages = 0;
|
||||
|
||||
// Partial-render caches: set on the first full render, reused when only the
|
||||
// description page changes.
|
||||
bool fullRenderDone = false;
|
||||
int descBandX = 0;
|
||||
int descBandY = 0;
|
||||
int descBandWidth = 0;
|
||||
int descBandHeight = 0;
|
||||
int hintsBandY = 0;
|
||||
int hintsBandHeight = 0;
|
||||
int partialRenderCount = 0;
|
||||
static constexpr int MAX_PARTIAL_RENDERS = 10;
|
||||
|
||||
static std::string formatFileSize(size_t bytes);
|
||||
void renderLoading();
|
||||
void loadData();
|
||||
void renderDescriptionAndHints();
|
||||
|
||||
public:
|
||||
explicit BookInfoActivity(GfxRenderer& renderer, MappedInputManager& mappedInput, std::string filePath)
|
||||
|
||||
Reference in New Issue
Block a user