From bc1ba7277f2e6cf30af4d78f9d3f6d0a56db2c26 Mon Sep 17 00:00:00 2001 From: pablohc Date: Fri, 20 Feb 2026 06:35:58 +0100 Subject: [PATCH] fix: continue reading card classic theme (#990) ## Summary * **What is the goal of this PR?** * **What changes are included?** - Adapt card width to cover image aspect ratio in Classic theme - Increase homeTopPadding from 20px to 40px to avoid overlap with battery icon - Card width now calculated from BMP dimensions instead of fixed 240px - Maximum card width limited to 90% of screen width - Falls back to original behavior (half screen width) when no cover available ## Additional Context * Solve conflicts in PR #683 Before: image PR: ![Screenshot_2026-02-19-14-22-36-68_99c04817c0de5652397fc8b56c3b3817](https://github.com/user-attachments/assets/81505728-d42e-41bd-bd77-44848e05b1eb) --- ### 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? _**< YES >**_ --- src/components/themes/BaseTheme.cpp | 79 +++++++++++++++++++---------- src/components/themes/BaseTheme.h | 2 +- 2 files changed, 53 insertions(+), 28 deletions(-) diff --git a/src/components/themes/BaseTheme.cpp b/src/components/themes/BaseTheme.cpp index 950b79f3..15f613d3 100644 --- a/src/components/themes/BaseTheme.cpp +++ b/src/components/themes/BaseTheme.cpp @@ -341,14 +341,57 @@ void BaseTheme::drawTabBar(const GfxRenderer& renderer, const Rect rect, const s void BaseTheme::drawRecentBookCover(GfxRenderer& renderer, Rect rect, const std::vector& recentBooks, const int selectorIndex, bool& coverRendered, bool& coverBufferStored, bool& bufferRestored, std::function storeCoverBuffer) const { - // --- Top "book" card for the current title (selectorIndex == 0) --- - const int bookWidth = rect.width / 2; - const int bookHeight = rect.height; - const int bookX = (rect.width - bookWidth) / 2; - const int bookY = rect.y; const bool hasContinueReading = !recentBooks.empty(); const bool bookSelected = hasContinueReading && selectorIndex == 0; + // --- Top "book" card for the current title (selectorIndex == 0) --- + // When there's no cover image, use fixed size (half screen) + // When there's cover image, adapt width to image aspect ratio, keep height fixed at 400px + const int baseHeight = rect.height; // Fixed height (400px) + + int bookWidth, bookX; + bool hasCoverImage = false; + + if (hasContinueReading && !recentBooks[0].coverBmpPath.empty()) { + // Try to get actual image dimensions from BMP header + const std::string coverBmpPath = + UITheme::getCoverThumbPath(recentBooks[0].coverBmpPath, BaseMetrics::values.homeCoverHeight); + + FsFile file; + if (Storage.openFileForRead("HOME", coverBmpPath, file)) { + Bitmap bitmap(file); + if (bitmap.parseHeaders() == BmpReaderError::Ok) { + hasCoverImage = true; + const int imgWidth = bitmap.getWidth(); + const int imgHeight = bitmap.getHeight(); + + // Calculate width based on aspect ratio, maintaining baseHeight + if (imgWidth > 0 && imgHeight > 0) { + const float aspectRatio = static_cast(imgWidth) / static_cast(imgHeight); + bookWidth = static_cast(baseHeight * aspectRatio); + + // Ensure width doesn't exceed reasonable limits (max 90% of screen width) + const int maxWidth = static_cast(rect.width * 0.9f); + if (bookWidth > maxWidth) { + bookWidth = maxWidth; + } + } else { + bookWidth = rect.width / 2; // Fallback + } + } + file.close(); + } + } + + if (!hasCoverImage) { + // No cover: use half screen size + bookWidth = rect.width / 2; + } + + bookX = rect.x + (rect.width - bookWidth) / 2; + const int bookY = rect.y; + const int bookHeight = baseHeight; + // Bookmark dimensions (used in multiple places) const int bookmarkWidth = bookWidth / 8; const int bookmarkHeight = bookHeight / 5; @@ -370,27 +413,9 @@ void BaseTheme::drawRecentBookCover(GfxRenderer& renderer, Rect rect, const std: Bitmap bitmap(file); if (bitmap.parseHeaders() == BmpReaderError::Ok) { LOG_DBG("THEME", "Rendering bmp"); - // Calculate position to center image within the book card - int coverX, coverY; - if (bitmap.getWidth() > bookWidth || bitmap.getHeight() > bookHeight) { - const float imgRatio = static_cast(bitmap.getWidth()) / static_cast(bitmap.getHeight()); - const float boxRatio = static_cast(bookWidth) / static_cast(bookHeight); - - if (imgRatio > boxRatio) { - coverX = bookX; - coverY = bookY + (bookHeight - static_cast(bookWidth / imgRatio)) / 2; - } else { - coverX = bookX + (bookWidth - static_cast(bookHeight * imgRatio)) / 2; - coverY = bookY; - } - } else { - coverX = bookX + (bookWidth - bitmap.getWidth()) / 2; - coverY = bookY + (bookHeight - bitmap.getHeight()) / 2; - } - - // Draw the cover image centered within the book card - renderer.drawBitmap(bitmap, coverX, coverY, bookWidth, bookHeight); + // Draw the cover image (bookWidth and bookHeight already match image aspect ratio) + renderer.drawBitmap(bitmap, bookX, bookY, bookWidth, bookHeight); // Draw border around the card renderer.drawRect(bookX, bookY, bookWidth, bookHeight); @@ -573,7 +598,7 @@ void BaseTheme::drawRecentBookCover(GfxRenderer& renderer, Rect rect, const std: const int boxWidth = maxTextWidth + boxPadding * 2; const int boxHeight = totalTextHeight + boxPadding * 2; - const int boxX = (rect.width - boxWidth) / 2; + const int boxX = rect.x + (rect.width - boxWidth) / 2; const int boxY = titleYStart - boxPadding; // Draw box (inverted when selected: black box instead of white) @@ -616,7 +641,7 @@ void BaseTheme::drawRecentBookCover(GfxRenderer& renderer, Rect rect, const std: constexpr int continuePadding = 6; const int continueBoxWidth = continueTextWidth + continuePadding * 2; const int continueBoxHeight = renderer.getLineHeight(UI_10_FONT_ID) + continuePadding; - const int continueBoxX = (rect.width - continueBoxWidth) / 2; + const int continueBoxX = rect.x + (rect.width - continueBoxWidth) / 2; const int continueBoxY = continueY - continuePadding / 2; renderer.fillRect(continueBoxX, continueBoxY, continueBoxWidth, continueBoxHeight, bookSelected); renderer.drawRect(continueBoxX, continueBoxY, continueBoxWidth, continueBoxHeight, !bookSelected); diff --git a/src/components/themes/BaseTheme.h b/src/components/themes/BaseTheme.h index 91193d39..92397f5b 100644 --- a/src/components/themes/BaseTheme.h +++ b/src/components/themes/BaseTheme.h @@ -82,7 +82,7 @@ constexpr ThemeMetrics values = {.batteryWidth = 15, .tabBarHeight = 50, .scrollBarWidth = 4, .scrollBarRightOffset = 5, - .homeTopPadding = 20, + .homeTopPadding = 40, .homeCoverHeight = 400, .homeCoverTileHeight = 400, .homeRecentBooksCount = 1,