Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
c6c6bd3
feat: add home cover settings with timeout and per-book control
pablohc Mar 24, 2026
d79bc5c
feat: coverDisabled state machine, per-book cover menu action
pablohc Mar 24, 2026
79ebb57
feat: Classic theme — hide title/author overlay when cover present, m…
pablohc Mar 24, 2026
1042f74
fix: resolve cppcheck warnings — unused vars and raw loops
pablohc Mar 25, 2026
475a575
fix: address CodeRabbit review — millis rollover, onExit write-back, …
pablohc Mar 25, 2026
f55a501
fix: force-render bypasses Storage.exists check and clears stale BMP
pablohc Mar 25, 2026
490226b
fix: clear forceRenderCoverPath when user disables cover in Reader Menu
pablohc Mar 25, 2026
be20a6a
fix: ZipFile::readFileToStream resource leak and unchecked write
pablohc Mar 25, 2026
cb834e9
refactor: deduplicate RecentBook lookup and loading popup calls
pablohc Mar 26, 2026
ad90fd3
feat: set COVER_ENABLED as default for home cover setting
pablohc Mar 26, 2026
b231983
fix: initialize per-book cover state from global mode on first open
pablohc Mar 27, 2026
3cb0a2a
feat: add classical book cover placeholder for Classic/BaseTheme
pablohc Mar 27, 2026
98193a9
fix: decouple coverRendered from cache write and clear stale pixels o…
pablohc Mar 28, 2026
33f0e6b
fix: reset coverRendered and coverBufferStored when clearing stale bu…
pablohc Mar 28, 2026
ae40cfd
fix: reset coverRendered on HomeActivity::onEnter and delay coverDisa…
pablohc Mar 28, 2026
ba31b05
Replace picojpeg with jpegdec; thread deadline through callback
jpirnay Mar 28, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ build
.history/
/.venv
*.local*
/plans
29 changes: 21 additions & 8 deletions lib/Epub/Epub.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -611,7 +611,7 @@ bool Epub::generateCoverBmp(bool cropped) const {
std::string Epub::getThumbBmpPath() const { return cachePath + "/thumb_[HEIGHT].bmp"; }
std::string Epub::getThumbBmpPath(int height) const { return cachePath + "/thumb_" + std::to_string(height) + ".bmp"; }

bool Epub::generateThumbBmp(int height) const {
bool Epub::generateThumbBmp(int height, uint32_t deadline) const {
// Already generated, return true
if (Storage.exists(getThumbBmpPath(height).c_str())) {
return true;
Expand All @@ -633,9 +633,15 @@ bool Epub::generateThumbBmp(int height) const {
if (!Storage.openFileForWrite("EBP", coverJpgTempPath, coverJpg)) {
return false;
}
readItemContentsToStream(coverImageHref, coverJpg, 1024);
const bool extractedJpg = readItemContentsToStream(coverImageHref, coverJpg, 1024, deadline);
coverJpg.close();

if (!extractedJpg) {
LOG_ERR("EBP", "Failed to extract JPG cover (deadline or error)");
Storage.remove(coverJpgTempPath.c_str());
return false;
}

if (!Storage.openFileForRead("EBP", coverJpgTempPath, coverJpg)) {
return false;
}
Expand All @@ -650,7 +656,7 @@ bool Epub::generateThumbBmp(int height) const {
int THUMB_TARGET_WIDTH = height * 0.6;
int THUMB_TARGET_HEIGHT = height;
const bool success = JpegToBmpConverter::jpegFileTo1BitBmpStreamWithSize(coverJpg, thumbBmp, THUMB_TARGET_WIDTH,
THUMB_TARGET_HEIGHT);
THUMB_TARGET_HEIGHT, deadline);
coverJpg.close();
thumbBmp.close();
Storage.remove(coverJpgTempPath.c_str());
Expand All @@ -669,9 +675,15 @@ bool Epub::generateThumbBmp(int height) const {
if (!Storage.openFileForWrite("EBP", coverPngTempPath, coverPng)) {
return false;
}
readItemContentsToStream(coverImageHref, coverPng, 1024);
const bool extractedPng = readItemContentsToStream(coverImageHref, coverPng, 1024, deadline);
coverPng.close();

if (!extractedPng) {
LOG_ERR("EBP", "Failed to extract PNG cover (deadline or error)");
Storage.remove(coverPngTempPath.c_str());
return false;
}

if (!Storage.openFileForRead("EBP", coverPngTempPath, coverPng)) {
return false;
}
Expand All @@ -683,8 +695,8 @@ bool Epub::generateThumbBmp(int height) const {
}
int THUMB_TARGET_WIDTH = height * 0.6;
int THUMB_TARGET_HEIGHT = height;
const bool success =
PngToBmpConverter::pngFileTo1BitBmpStreamWithSize(coverPng, thumbBmp, THUMB_TARGET_WIDTH, THUMB_TARGET_HEIGHT);
const bool success = PngToBmpConverter::pngFileTo1BitBmpStreamWithSize(coverPng, thumbBmp, THUMB_TARGET_WIDTH,
THUMB_TARGET_HEIGHT, deadline);
coverPng.close();
thumbBmp.close();
Storage.remove(coverPngTempPath.c_str());
Expand Down Expand Up @@ -723,14 +735,15 @@ uint8_t* Epub::readItemContentsToBytes(const std::string& itemHref, size_t* size
return content;
}

bool Epub::readItemContentsToStream(const std::string& itemHref, Print& out, const size_t chunkSize) const {
bool Epub::readItemContentsToStream(const std::string& itemHref, Print& out, const size_t chunkSize,
uint32_t deadline) const {
if (itemHref.empty()) {
LOG_DBG("EBP", "Failed to read item, empty href");
return false;
}

const std::string path = FsHelpers::normalisePath(itemHref);
return ZipFile(filepath).readFileToStream(path.c_str(), out, chunkSize);
return ZipFile(filepath).readFileToStream(path.c_str(), out, chunkSize, deadline);
}

bool Epub::getItemSize(const std::string& itemHref, size_t* size) const {
Expand Down
4 changes: 2 additions & 2 deletions lib/Epub/Epub.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,10 @@ class Epub {
bool generateCoverBmp(bool cropped = false) const;
std::string getThumbBmpPath() const;
std::string getThumbBmpPath(int height) const;
bool generateThumbBmp(int height) const;
bool generateThumbBmp(int height, uint32_t deadline = 0) const;
uint8_t* readItemContentsToBytes(const std::string& itemHref, size_t* size = nullptr,
bool trailingNullByte = false) const;
bool readItemContentsToStream(const std::string& itemHref, Print& out, size_t chunkSize) const;
bool readItemContentsToStream(const std::string& itemHref, Print& out, size_t chunkSize, uint32_t deadline = 0) const;
bool getItemSize(const std::string& itemHref, size_t* size) const;
BookMetadataCache::SpineEntry getSpineItem(int spineIndex) const;
BookMetadataCache::TocEntry getTocItem(int tocIndex) const;
Expand Down
7 changes: 7 additions & 0 deletions lib/I18n/translations/english.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,13 @@ STR_THEME_CLASSIC: "Classic"
STR_THEME_LYRA: "Lyra"
STR_THEME_LYRA_EXTENDED: "Lyra Extended"
STR_SUNLIGHT_FADING_FIX: "Sunlight Fading Fix"
STR_HOME_COVER: "Home cover"
STR_COVER_ENABLED: "Enabled"
STR_COVER_TIMEOUT: "Timeout (3s)"
STR_COVER_DISABLED: "Disabled"
STR_COVER_ACTION_DISABLE: "Disable cover"
STR_COVER_ACTION_ENABLE: "Enable cover"
STR_COVER_ACTION_GENERATE: "Generate cover"
STR_REMAP_FRONT_BUTTONS: "Remap Front Buttons"
STR_OPDS_BROWSER: "OPDS Browser"
STR_COVER_CUSTOM: "Cover + Custom"
Expand Down
Loading
Loading