Something went wrong. Try again.
A fork of https://github.com/crosspoint-reader/crosspoint-reader
Something went wrong. Try again.
5.1 kB · 140 lines
C++
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141#include "RecentBooksStore.h"
#include <Epub.h>#include <FsHelpers.h>#include <HalStorage.h>#include <Logging.h>#include <Xtc.h>
#include <algorithm>#include <iterator>
void RecentBooksStore::toJson(JsonDocument& doc) const { JsonArray arr = doc["books"].to<JsonArray>(); for (const auto& book : recentBooks) { JsonObject obj = arr.add<JsonObject>(); obj["path"] = book.path; obj["title"] = book.title; obj["author"] = book.author; obj["coverBmpPath"] = book.coverBmpPath; }}
bool RecentBooksStore::fromJson(JsonVariantConst doc) { // Tolerate a missing/invalid 'books' key (treat as empty list); only a // JSON parse error is fatal. A null JsonArray iterates zero times. recentBooks.clear(); JsonArrayConst arr = doc["books"].as<JsonArrayConst>(); recentBooks.reserve(std::min(arr.size(), static_cast<size_t>(MAX_RECENT_BOOKS))); for (JsonObjectConst obj : arr) { if (getCount() >= MAX_RECENT_BOOKS) break; RecentBook book; book.path = obj["path"] | ""; book.title = obj["title"] | ""; book.author = obj["author"] | ""; book.coverBmpPath = obj["coverBmpPath"] | ""; recentBooks.push_back(book); }
LOG_DBG("RBS", "Recent books loaded from file (%d entries)", getCount()); return true;}
void RecentBooksStore::addBook(const std::string& path, const std::string& title, const std::string& author, const std::string& coverBmpPath) { // Drop stale entries first so a new add can't evict a valid book in their stead. pruneMissing();
// Remove existing entry if present auto it = std::find_if(recentBooks.begin(), recentBooks.end(), [&](const RecentBook& book) { return book.path == path; }); if (it != recentBooks.end()) { recentBooks.erase(it); }
// Add to front recentBooks.insert(recentBooks.begin(), {path, title, author, coverBmpPath});
// Trim to max size if (recentBooks.size() > MAX_RECENT_BOOKS) { recentBooks.resize(MAX_RECENT_BOOKS); }
saveToFile();}
void RecentBooksStore::updateBook(const std::string& path, const std::string& title, const std::string& author, const std::string& coverBmpPath) { auto it = std::find_if(recentBooks.begin(), recentBooks.end(), [&](const RecentBook& book) { return book.path == path; }); if (it != recentBooks.end()) { RecentBook& book = *it; book.title = title; book.author = author; book.coverBmpPath = coverBmpPath; saveToFile(); }}
bool RecentBooksStore::removeByPath(const std::string& path) { auto it = std::find_if(recentBooks.begin(), recentBooks.end(), [&](const RecentBook& book) { return book.path == path; }); if (it == recentBooks.end()) { return false; } recentBooks.erase(it); if (!saveToFile()) { LOG_ERR("RBS", "Failed to persist removal of recent book: %s", path.c_str()); } return true;}
void RecentBooksStore::updatePath(const std::string& oldPath, const std::string& newPath, const std::string& oldCachePath, const std::string& newCachePath) { auto it = std::find_if(recentBooks.begin(), recentBooks.end(), [&](const RecentBook& book) { return book.path == oldPath; }); if (it == recentBooks.end()) { return; } it->path = newPath; if (!oldCachePath.empty() && !it->coverBmpPath.empty() && it->coverBmpPath.rfind(oldCachePath, 0) == 0) { it->coverBmpPath = newCachePath + it->coverBmpPath.substr(oldCachePath.size()); } saveToFile();}
bool RecentBooksStore::isMissing(const RecentBook& book) { return !Storage.exists(book.path.c_str()); }
bool RecentBooksStore::pruneMissing() { const size_t before = recentBooks.size(); recentBooks.erase(std::remove_if(recentBooks.begin(), recentBooks.end(), &isMissing), recentBooks.end()); return recentBooks.size() != before;}
RecentBook RecentBooksStore::getDataFromBook(std::string path) const { std::string lastBookFileName = ""; const size_t lastSlash = path.find_last_of('/'); if (lastSlash != std::string::npos) { lastBookFileName = path.substr(lastSlash + 1); }
LOG_DBG("RBS", "Loading recent book: %s", path.c_str());
// If epub, try to load the metadata for title/author and cover. // Use buildIfMissing=false to avoid heavy epub loading on boot; getTitle()/getAuthor() may be // blank until the book is opened, and entries with missing title are omitted from recent list. if (FsHelpers::hasEpubExtension(lastBookFileName)) { Epub epub(path, "/.crosspoint"); epub.load(false, true); return RecentBook{path, epub.getTitle(), epub.getAuthor(), 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()}; } } else if (FsHelpers::hasTxtExtension(lastBookFileName) || FsHelpers::hasMarkdownExtension(lastBookFileName)) { return RecentBook{path, lastBookFileName, "", ""}; } return RecentBook{path, "", "", ""};}