Use and populate metadata

This commit is contained in:
jpirnay
2026-03-07 18:02:21 +01:00
parent 87e5cc4fe1
commit 3ed96a7e49
8 changed files with 43 additions and 13 deletions
+2
View File
@@ -301,6 +301,7 @@ bool JsonSettingsIO::saveRecentBooks(const RecentBooksStore& store, const char*
obj["path"] = book.path;
obj["title"] = book.title;
obj["author"] = book.author;
obj["series"] = book.series;
obj["coverBmpPath"] = book.coverBmpPath;
}
@@ -325,6 +326,7 @@ bool JsonSettingsIO::loadRecentBooks(RecentBooksStore& store, const char* json)
book.path = obj["path"] | std::string("");
book.title = obj["title"] | std::string("");
book.author = obj["author"] | std::string("");
book.series = obj["series"] | std::string("");
book.coverBmpPath = obj["coverBmpPath"] | std::string("");
store.recentBooks.push_back(book);
}
+8 -7
View File
@@ -21,7 +21,7 @@ constexpr int MAX_RECENT_BOOKS = 10;
RecentBooksStore RecentBooksStore::instance;
void RecentBooksStore::addBook(const std::string& path, const std::string& title, const std::string& author,
const std::string& coverBmpPath) {
const std::string& series, const std::string& coverBmpPath) {
// Remove existing entry if present
auto it =
std::find_if(recentBooks.begin(), recentBooks.end(), [&](const RecentBook& book) { return book.path == path; });
@@ -30,7 +30,7 @@ void RecentBooksStore::addBook(const std::string& path, const std::string& title
}
// Add to front
recentBooks.insert(recentBooks.begin(), {path, title, author, coverBmpPath});
recentBooks.insert(recentBooks.begin(), {path, title, author, series, coverBmpPath});
// Trim to max size
if (recentBooks.size() > MAX_RECENT_BOOKS) {
@@ -73,17 +73,18 @@ RecentBook RecentBooksStore::getDataFromBook(std::string path) const {
if (FsHelpers::hasEpubExtension(lastBookFileName)) {
Epub epub(path, "/.crosspoint");
epub.load(false, true);
return RecentBook{path, epub.getTitle(), epub.getAuthor(), epub.getThumbBmpPath()};
std::string series = epub.getSeries();
if (!series.empty() && !epub.getSeriesIndex().empty()) series += " #" + epub.getSeriesIndex();
return RecentBook{path, epub.getTitle(), epub.getAuthor(), series, epub.getThumbBmpPath()};
} else if (FsHelpers::hasXtcExtension(lastBookFileName)) {
// Handle XTC file
Xtc xtc(path, "/.crosspoint");
if (xtc.load()) {
return RecentBook{path, xtc.getTitle(), xtc.getAuthor(), xtc.getThumbBmpPath()};
return RecentBook{path, xtc.getTitle(), xtc.getAuthor(), "", xtc.getThumbBmpPath()};
}
} else if (FsHelpers::hasTxtExtension(lastBookFileName) || FsHelpers::hasMarkdownExtension(lastBookFileName)) {
return RecentBook{path, lastBookFileName, "", ""};
return RecentBook{path, lastBookFileName, "", "", ""};
}
return RecentBook{path, "", "", ""};
return RecentBook{path, "", "", "", ""};
}
bool RecentBooksStore::loadFromFile() {
+2 -1
View File
@@ -6,6 +6,7 @@ struct RecentBook {
std::string path;
std::string title;
std::string author;
std::string series;
std::string coverBmpPath;
bool operator==(const RecentBook& other) const { return path == other.path; }
@@ -31,7 +32,7 @@ class RecentBooksStore {
static RecentBooksStore& getInstance() { return instance; }
// Add a book to the recent list (moves to front if already exists)
void addBook(const std::string& path, const std::string& title, const std::string& author,
void addBook(const std::string& path, const std::string& title, const std::string& author, const std::string& series,
const std::string& coverBmpPath);
void updateBook(const std::string& path, const std::string& title, const std::string& author,
+3 -1
View File
@@ -103,7 +103,9 @@ void EpubReaderActivity::onEnter() {
// Save current epub as last opened epub and add to recent books
APP_STATE.openEpubPath = epub->getPath();
APP_STATE.saveToFile();
RECENT_BOOKS.addBook(epub->getPath(), epub->getTitle(), epub->getAuthor(), epub->getThumbBmpPath());
std::string series = epub->getSeries();
if (!series.empty() && !epub->getSeriesIndex().empty()) series += " #" + epub->getSeriesIndex();
RECENT_BOOKS.addBook(epub->getPath(), epub->getTitle(), epub->getAuthor(), series, epub->getThumbBmpPath());
// Trigger first update
requestUpdate();
+1 -1
View File
@@ -54,7 +54,7 @@ void TxtReaderActivity::onEnter() {
auto fileName = filePath.substr(filePath.rfind('/') + 1);
APP_STATE.openEpubPath = filePath;
APP_STATE.saveToFile();
RECENT_BOOKS.addBook(filePath, fileName, "", "");
RECENT_BOOKS.addBook(filePath, fileName, "", "", "");
// Trigger first update
requestUpdate();
+1 -1
View File
@@ -40,7 +40,7 @@ void XtcReaderActivity::onEnter() {
// Save current XTC as last opened book and add to recent books
APP_STATE.openEpubPath = xtc->getPath();
APP_STATE.saveToFile();
RECENT_BOOKS.addBook(xtc->getPath(), xtc->getTitle(), xtc->getAuthor(), xtc->getThumbBmpPath());
RECENT_BOOKS.addBook(xtc->getPath(), xtc->getTitle(), xtc->getAuthor(), "", xtc->getThumbBmpPath());
// Trigger first update
requestUpdate();
+19 -1
View File
@@ -482,6 +482,7 @@ void BaseTheme::drawRecentBookCover(GfxRenderer& renderer, Rect rect, const std:
if (hasContinueReading) {
const std::string& lastBookTitle = recentBooks[0].title;
const std::string& lastBookAuthor = recentBooks[0].author;
const std::string& lastBookSeries = recentBooks[0].series;
// Invert text colors based on selection state:
// - With cover: selected = white text on black box, unselected = black text on white box
@@ -494,6 +495,9 @@ void BaseTheme::drawRecentBookCover(GfxRenderer& renderer, Rect rect, const std:
if (!lastBookAuthor.empty()) {
totalTextHeight += renderer.getLineHeight(UI_10_FONT_ID) * 3 / 2;
}
if (!lastBookSeries.empty()) {
totalTextHeight += renderer.getLineHeight(UI_12_FONT_ID);
}
// Vertically center the title block within the card
int titleYStart = bookY + (bookHeight - totalTextHeight) / 2;
@@ -501,8 +505,11 @@ void BaseTheme::drawRecentBookCover(GfxRenderer& renderer, Rect rect, const std:
const auto truncatedAuthor = lastBookAuthor.empty()
? std::string{}
: renderer.truncatedText(UI_10_FONT_ID, lastBookAuthor.c_str(), bookWidth - 40);
const auto truncatedSeries = lastBookSeries.empty()
? std::string{}
: renderer.truncatedText(UI_12_FONT_ID, lastBookSeries.c_str(), bookWidth - 40);
// If cover image was rendered, draw box behind title and author
// If cover image was rendered, draw box behind title, author, and series
if (coverRendered) {
constexpr int boxPadding = 8;
// Calculate the max text width for the box
@@ -519,6 +526,12 @@ void BaseTheme::drawRecentBookCover(GfxRenderer& renderer, Rect rect, const std:
maxTextWidth = authorWidth;
}
}
if (!truncatedSeries.empty()) {
const int seriesWidth = renderer.getTextWidth(UI_12_FONT_ID, truncatedSeries.c_str());
if (seriesWidth > maxTextWidth) {
maxTextWidth = seriesWidth;
}
}
const int boxWidth = maxTextWidth + boxPadding * 2;
const int boxHeight = totalTextHeight + boxPadding * 2;
@@ -539,6 +552,11 @@ void BaseTheme::drawRecentBookCover(GfxRenderer& renderer, Rect rect, const std:
if (!truncatedAuthor.empty()) {
titleYStart += renderer.getLineHeight(UI_10_FONT_ID) / 2;
renderer.drawCenteredText(UI_10_FONT_ID, titleYStart, truncatedAuthor.c_str(), !bookSelected);
titleYStart += renderer.getLineHeight(UI_10_FONT_ID);
}
if (!truncatedSeries.empty()) {
renderer.drawCenteredText(UI_12_FONT_ID, titleYStart, truncatedSeries.c_str(), !bookSelected);
}
// "Continue Reading" label at the bottom
+7 -1
View File
@@ -487,10 +487,12 @@ void LyraTheme::drawRecentBookCover(GfxRenderer& renderer, Rect rect, const std:
auto titleLines = renderer.wrappedText(UI_12_FONT_ID, book.title.c_str(), textWidth, 3, EpdFontFamily::BOLD);
auto author = renderer.truncatedText(UI_10_FONT_ID, book.author.c_str(), textWidth);
auto series = renderer.truncatedText(UI_12_FONT_ID, book.series.c_str(), textWidth);
const int titleLineHeight = renderer.getLineHeight(UI_12_FONT_ID);
const int titleBlockHeight = titleLineHeight * static_cast<int>(titleLines.size());
const int authorHeight = book.author.empty() ? 0 : (renderer.getLineHeight(UI_10_FONT_ID) * 3 / 2);
const int totalBlockHeight = titleBlockHeight + authorHeight;
const int seriesHeight = book.series.empty() ? 0 : renderer.getLineHeight(UI_12_FONT_ID);
const int totalBlockHeight = titleBlockHeight + authorHeight + seriesHeight;
int titleY = tileY + tileHeight / 2 - totalBlockHeight / 2;
const int textX = tileX + hPaddingInSelection + coverWidth + LyraMetrics::values.verticalSpacing;
for (const auto& line : titleLines) {
@@ -500,6 +502,10 @@ void LyraTheme::drawRecentBookCover(GfxRenderer& renderer, Rect rect, const std:
if (!book.author.empty()) {
titleY += renderer.getLineHeight(UI_10_FONT_ID) / 2;
renderer.drawText(UI_10_FONT_ID, textX, titleY, author.c_str(), true);
titleY += renderer.getLineHeight(UI_10_FONT_ID);
}
if (!book.series.empty()) {
renderer.drawText(UI_12_FONT_ID, textX, titleY, series.c_str(), true);
}
} else {
drawEmptyRecents(renderer, rect);