Compare commits

..

3 Commits

Author SHA1 Message Date
CaptainFrito
7ba522ed9e
Merge 9572fc3fb2 into f67c544e16 2026-02-02 22:26:39 +07:00
CaptainFrito
9572fc3fb2 Fixed recent books migration 2026-02-02 22:26:23 +07:00
CaptainFrito
8a82397a79 Fixes recents 2026-02-02 18:14:28 +07:00
3 changed files with 72 additions and 32 deletions

View File

@ -7,7 +7,7 @@
#include <algorithm>
namespace {
constexpr uint8_t RECENT_BOOKS_FILE_VERSION = 2;
constexpr uint8_t RECENT_BOOKS_FILE_VERSION = 3;
constexpr char RECENT_BOOKS_FILE[] = "/.crosspoint/recent.bin";
constexpr int MAX_RECENT_BOOKS = 10;
} // namespace
@ -79,7 +79,23 @@ bool RecentBooksStore::loadFromFile() {
serialization::readString(inputFile, path);
// Title and author will be empty, they will be filled when the book is
// opened again
recentBooks.push_back({path, "", "", ""});
std::string fileName = path.substr(path.rfind('/') + 1);
recentBooks.push_back({path, fileName, "", "-"});
}
} else if (version == 2) {
// Old version, just read paths, titles and authors
uint8_t count;
serialization::readPod(inputFile, count);
recentBooks.clear();
recentBooks.reserve(count);
for (uint8_t i = 0; i < count; i++) {
std::string path, title, author;
serialization::readString(inputFile, path);
serialization::readString(inputFile, title);
serialization::readString(inputFile, author);
// Title and author will be empty, they will be filled when the book is
// opened again
recentBooks.push_back({path, title, author, "-"});
}
} else {
Serial.printf("[%lu] [RBS] Deserialization failed: Unknown version %u\n", millis(), version);

View File

@ -44,8 +44,11 @@ void HomeActivity::loadRecentBooks(int maxBooks, int coverHeight) {
const auto& books = RECENT_BOOKS.getBooks();
recentBooks.reserve(std::min(static_cast<int>(books.size()), maxBooks));
bool mustReloadRecents = false; // We're migrating from an older version of recent books
int progress = 0;
for (const RecentBook& book : books) {
bool mustLoadCover = false;
// Limit to maximum number of recent books
if (recentBooks.size() >= maxBooks) {
break;
@ -56,51 +59,70 @@ void HomeActivity::loadRecentBooks(int maxBooks, int coverHeight) {
continue;
}
if (!book.coverBmpPath.empty()) {
if (book.coverBmpPath == "-") {
mustReloadRecents = true;
} else {
std::string coverPath = UITheme::getCoverThumbPath(book.coverBmpPath, coverHeight);
if (!SdMan.exists(coverPath.c_str())) {
std::string lastBookFileName = "";
const size_t lastSlash = book.path.find_last_of('/');
if (lastSlash != std::string::npos) {
lastBookFileName = book.path.substr(lastSlash + 1);
mustLoadCover = true;
}
}
if (mustReloadRecents || mustLoadCover) {
std::string lastBookFileName = "";
const size_t lastSlash = book.path.find_last_of('/');
if (lastSlash != std::string::npos) {
lastBookFileName = book.path.substr(lastSlash + 1);
}
Serial.printf("Loading recent book: %s\n", book.path.c_str());
// If epub, try to load the metadata for title/author and cover
if (StringUtils::checkFileExtension(lastBookFileName, ".epub")) {
Epub epub(book.path, "/.crosspoint");
epub.load(false);
// Try to generate thumbnail image for Continue Reading card
if (!showingLoading) {
showingLoading = true;
popupRect = GUI.drawPopup(renderer, "Loading...");
}
GUI.fillPopupProgress(renderer, popupRect, progress * (100 / maxBooks));
epub.generateThumbBmp(coverHeight);
Serial.printf("Loading recent book: %s\n", book.path.c_str());
// If epub, try to load the metadata for title/author and cover
if (StringUtils::checkFileExtension(lastBookFileName, ".epub")) {
Epub epub(book.path, "/.crosspoint");
epub.load(false);
if (mustReloadRecents) {
// Update recent book entry with title/author/cover path
RECENT_BOOKS.addBook(book.path, epub.getTitle(), epub.getAuthor(), epub.getThumbBmpPath());
recentBooks.push_back({book.path, epub.getTitle(), epub.getAuthor(), epub.getThumbBmpPath()});
}
} else if (StringUtils::checkFileExtension(lastBookFileName, ".xtch") ||
StringUtils::checkFileExtension(lastBookFileName, ".xtc")) {
// Handle XTC file
Xtc xtc(book.path, "/.crosspoint");
if (xtc.load()) {
// Try to generate thumbnail image for Continue Reading card
if (!showingLoading) {
showingLoading = true;
popupRect = GUI.drawPopup(renderer, "Loading...");
}
GUI.fillPopupProgress(renderer, popupRect, progress * 30);
epub.generateThumbBmp(coverHeight);
} else if (StringUtils::checkFileExtension(lastBookFileName, ".xtch") ||
StringUtils::checkFileExtension(lastBookFileName, ".xtc")) {
// Handle XTC file
Xtc xtc(book.path, "/.crosspoint");
if (xtc.load()) {
// Try to generate thumbnail image for Continue Reading card
if (!showingLoading) {
showingLoading = true;
popupRect = GUI.drawPopup(renderer, "Loading...");
}
GUI.fillPopupProgress(renderer, popupRect, progress * 30);
xtc.generateThumbBmp(coverHeight);
GUI.fillPopupProgress(renderer, popupRect, progress * (100 / maxBooks));
xtc.generateThumbBmp(coverHeight);
if (mustReloadRecents) {
// Update recent book entry with title/author/cover path
RECENT_BOOKS.addBook(book.path, xtc.getTitle(), xtc.getAuthor(), xtc.getThumbBmpPath());
recentBooks.push_back({book.path, xtc.getTitle(), xtc.getAuthor(), xtc.getThumbBmpPath()});
}
}
}
}
recentBooks.push_back(book);
if (!mustReloadRecents) {
recentBooks.push_back(book);
}
progress++;
}
Serial.printf("Recent books loaded: %d\n", recentBooks.size());
recentsLoaded = true;
recentsLoading = false;
updateRequired = true;

View File

@ -58,9 +58,11 @@ void TxtReaderActivity::onEnter() {
txt->setupCacheDir();
// Save current txt as last opened file and add to recent books
APP_STATE.openEpubPath = txt->getPath();
auto filePath = txt->getPath();
auto fileName = filePath.substr(filePath.rfind('/') + 1);
APP_STATE.openEpubPath = filePath;
APP_STATE.saveToFile();
RECENT_BOOKS.addBook(txt->getPath(), "", "", "");
RECENT_BOOKS.addBook(filePath, fileName, "", "");
// Trigger first update
updateRequired = true;