diff --git a/chat-summaries/2026-03-08_23-00-summary.md b/chat-summaries/2026-03-08_23-00-summary.md index 901d3d9b..02555ec6 100644 --- a/chat-summaries/2026-03-08_23-00-summary.md +++ b/chat-summaries/2026-03-08_23-00-summary.md @@ -36,9 +36,17 @@ - Display order: Title, Author, Series, Publisher, Date, Subjects, Rating (N/5), Language, ISBN, Contributor, File Size, Rights, Description - Rating displayed as `N / 5` (Calibre stores 0-10, divided by 2) +### 6. BookInfoActivity UI Integration (`src/activities/home/BookInfoActivity.cpp`) +- Added `GUI.drawHeader()` call to show the standard header bar (clock, battery, "Book Info" title) +- Replaced hardcoded `MARGIN = 20` with theme metrics (`contentSidePadding`, `topPadding`, `headerHeight`, etc.) +- Content now starts below the header bar using `metrics.topPadding + metrics.headerHeight + metrics.verticalSpacing` +- Y-culling stops content above button hints using `pageH - metrics.buttonHintsHeight - metrics.verticalSpacing` +- `contentHeight` includes bottom padding for button hints so scrolling accounts for the reserved hint area + ## Commits - `8025e6f` — `feat: parse and display all available EPUB metadata fields` -- (pending) — `refactor: consolidate Epub blank strings, simplify BookInfo buildLayout` +- `efa727e` — `refactor: consolidate Epub blank strings, simplify BookInfo buildLayout` +- (pending) — `fix: add header bar and fix bottom spacing in BookInfo` ## Follow-up - Existing book caches will auto-invalidate (version 6 → 7) and regenerate on next load diff --git a/src/activities/home/BookInfoActivity.cpp b/src/activities/home/BookInfoActivity.cpp index 9bd409a1..1d81841d 100644 --- a/src/activities/home/BookInfoActivity.cpp +++ b/src/activities/home/BookInfoActivity.cpp @@ -16,7 +16,6 @@ #include "fontIds.h" namespace { -constexpr int MARGIN = 20; constexpr int LABEL_VALUE_GAP = 4; constexpr int SECTION_GAP = 14; constexpr int MAX_WRAPPED_LINES = 60; @@ -132,7 +131,9 @@ void BookInfoActivity::onEnter() { void BookInfoActivity::onExit() { Activity::onExit(); } void BookInfoActivity::buildLayout(const BookMetadataCache::BookMetadata& meta, size_t fileSize) { - const int contentW = renderer.getScreenWidth() - MARGIN * 2; + const auto& metrics = UITheme::getInstance().getMetrics(); + const int sidePad = metrics.contentSidePadding; + const int contentW = renderer.getScreenWidth() - sidePad * 2; fields.reserve(13); auto addField = [&](const char* label, const std::string& text, bool bold, EpdFontFamily::Style style) { @@ -181,7 +182,8 @@ void BookInfoActivity::buildLayout(const BookMetadataCache::BookMetadata& meta, const int lineH10 = renderer.getLineHeight(UI_10_FONT_ID); const int lineH12 = renderer.getLineHeight(UI_12_FONT_ID); - int h = MARGIN; + const int contentTop = metrics.topPadding + metrics.headerHeight + metrics.verticalSpacing; + int h = contentTop; if (!coverBmpPath.empty()) { FsFile file; @@ -205,6 +207,7 @@ void BookInfoActivity::buildLayout(const BookMetadataCache::BookMetadata& meta, h += static_cast(field.lines.size()) * lineH12; h += SECTION_GAP; } + h += metrics.buttonHintsHeight + metrics.verticalSpacing; contentHeight = h; } @@ -243,20 +246,28 @@ void BookInfoActivity::loop() { void BookInfoActivity::render(RenderLock&&) { renderer.clearScreen(); + const auto& metrics = UITheme::getInstance().getMetrics(); + const int pageW = renderer.getScreenWidth(); const int pageH = renderer.getScreenHeight(); + const int sidePad = metrics.contentSidePadding; const int lineH10 = renderer.getLineHeight(UI_10_FONT_ID); const int lineH12 = renderer.getLineHeight(UI_12_FONT_ID); - int y = MARGIN - scrollOffset; + const int contentTop = metrics.topPadding + metrics.headerHeight + metrics.verticalSpacing; + const int contentBottom = pageH - metrics.buttonHintsHeight - metrics.verticalSpacing; + + GUI.drawHeader(renderer, Rect(0, metrics.topPadding, pageW, metrics.headerHeight), tr(STR_BOOK_INFO)); + + int y = contentTop - scrollOffset; - // Cover image — only draw if at least partially visible if (!coverBmpPath.empty() && coverDisplayHeight > 0) { - if (y + coverDisplayHeight > 0 && y < pageH) { + if (y + coverDisplayHeight > contentTop && y < contentBottom) { FsFile file; if (Storage.openFileForRead("BIF", coverBmpPath, file)) { Bitmap bitmap(file); if (bitmap.parseHeaders() == BmpReaderError::Ok) { - const int coverX = (renderer.getScreenWidth() - coverDisplayWidth) / 2; - renderer.drawBitmap1Bit(bitmap, coverX, y, coverDisplayWidth, std::min(coverDisplayHeight, pageH - y)); + const int coverX = (pageW - coverDisplayWidth) / 2; + renderer.drawBitmap1Bit(bitmap, coverX, y, coverDisplayWidth, + std::min(coverDisplayHeight, contentBottom - y)); } file.close(); } @@ -265,20 +276,20 @@ void BookInfoActivity::render(RenderLock&&) { } for (const auto& field : fields) { - if (y >= pageH) break; + if (y >= contentBottom) break; if (field.label) { - if (y + lineH10 > 0 && y < pageH) { - renderer.drawText(UI_10_FONT_ID, MARGIN, y, field.label, true, EpdFontFamily::BOLD); + if (y + lineH10 > contentTop && y < contentBottom) { + renderer.drawText(UI_10_FONT_ID, sidePad, y, field.label, true, EpdFontFamily::BOLD); } y += lineH10 + LABEL_VALUE_GAP; } const auto style = field.bold ? EpdFontFamily::BOLD : EpdFontFamily::REGULAR; for (const auto& line : field.lines) { - if (y >= pageH) break; - if (y + lineH12 > 0) { - renderer.drawText(UI_12_FONT_ID, MARGIN, y, line.c_str(), true, style); + if (y >= contentBottom) break; + if (y + lineH12 > contentTop) { + renderer.drawText(UI_12_FONT_ID, sidePad, y, line.c_str(), true, style); } y += lineH12; }