# Port PR #838 and PR #907 into fork ## Task Cherry-pick / manually port two upstream PRs into the fork: - **PR #907**: Cover image outlines to improve legibility - **PR #838**: Fallback logic for epub cover extraction ## Changes Made ### PR #907 (cover outlines) — `src/components/themes/lyra/LyraTheme.cpp` - Always draw a rectangle outline around cover tiles before drawing the bitmap on top - Removed `hasCover` flag — simplified logic so outline is always present, preventing low-contrast covers from blending into the background ### PR #838 (cover fallback logic) — 3 files #### `lib/Epub/Epub.h` - Added declarations for 4 new methods: `generateInvalidFormatCoverBmp`, `generateInvalidFormatThumbBmp`, `isValidThumbnailBmp` (static), `getCoverCandidates` (private) - Added doc comments on existing `generateCoverBmp` and `generateThumbBmp` #### `lib/Epub/Epub.cpp` - Added `#include ` and `#include ` - **`generateCoverBmp`**: Added invalid BMP detection/retry, cover fallback candidate probing (`getCoverCandidates`), case-insensitive extension checking. Returns `false` on failure (no internal X-pattern fallback) so callers control the fallback chain - **`generateThumbBmp`**: Same changes as `generateCoverBmp` — invalid BMP detection, fallback probing, case-insensitive check. Returns `false` on failure (no internal X-pattern fallback) so callers control the fallback chain - **`generateInvalidFormatThumbBmp`** (new): Creates 1-bit BMP with X pattern as thumbnail marker - **`generateInvalidFormatCoverBmp`** (new): Creates 1-bit BMP with X pattern as cover marker, using display dimensions - **`isValidThumbnailBmp`** (new, static): Validates BMP by checking file size > 0 and 'BM' header - **`getCoverCandidates`** (new, private): Returns list of common cover filenames to probe #### `src/activities/home/HomeActivity.cpp` - Replaced `Storage.exists()` check with `Epub::isValidThumbnailBmp()` to catch corrupt/empty thumbnails - Added epub.load retry logic (cache-only first, then full build) - After successful thumbnail generation, update `RECENT_BOOKS` with the new thumb path - Thumbnail fallback chain: Real Cover → PlaceholderCoverGenerator → X-Pattern marker (epub only; xtc/other formats fall back to placeholder only) ## Adaptations from upstream PR - All `Serial.printf` calls converted to `LOG_DBG`/`LOG_ERR` macros (fork convention) - No `#include ` (not needed with Logging.h) - Retained fork's `bookMetadataCache` null-check guards - HomeActivity changes manually adapted to fork's `loadRecentCovers()` structure (upstream has inline code in a different method) - Fork's `PlaceholderCoverGenerator` is the preferred fallback; X-pattern marker is last resort only #### `src/activities/boot_sleep/SleepActivity.cpp` - EPUB sleep screen cover now follows Real Cover → Placeholder → X-Pattern fallback chain - Upgraded `Storage.exists()` check to `Epub::isValidThumbnailBmp()` for the epub cover path #### `src/activities/reader/EpubReaderActivity.cpp` - Cover and thumbnail pre-rendering now follows Real Cover → Placeholder → X-Pattern fallback chain - Upgraded all `Storage.exists()` checks to `Epub::isValidThumbnailBmp()` for cover/thumb paths ## Follow-up Items - Build and test on device to verify cover generation pipeline works end-to-end