mirror of
https://github.com/daveallie/crosspoint-reader.git
synced 2026-02-08 00:27:39 +03:00
Compare commits
2 Commits
7ba522ed9e
...
328f78365d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
328f78365d | ||
|
|
111d4b8b16 |
@ -1,11 +1,15 @@
|
|||||||
#include "RecentBooksStore.h"
|
#include "RecentBooksStore.h"
|
||||||
|
|
||||||
|
#include <Epub.h>
|
||||||
#include <HardwareSerial.h>
|
#include <HardwareSerial.h>
|
||||||
#include <SDCardManager.h>
|
#include <SDCardManager.h>
|
||||||
#include <Serialization.h>
|
#include <Serialization.h>
|
||||||
|
#include <Xtc.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "util/StringUtils.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
constexpr uint8_t RECENT_BOOKS_FILE_VERSION = 3;
|
constexpr uint8_t RECENT_BOOKS_FILE_VERSION = 3;
|
||||||
constexpr char RECENT_BOOKS_FILE[] = "/.crosspoint/recent.bin";
|
constexpr char RECENT_BOOKS_FILE[] = "/.crosspoint/recent.bin";
|
||||||
@ -59,6 +63,34 @@ bool RecentBooksStore::saveToFile() const {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.printf("Loading recent book: %s\n", path.c_str());
|
||||||
|
|
||||||
|
// If epub, try to load the metadata for title/author and cover
|
||||||
|
if (StringUtils::checkFileExtension(lastBookFileName, ".epub")) {
|
||||||
|
Epub epub(path, "/.crosspoint");
|
||||||
|
epub.load(false);
|
||||||
|
return RecentBook{path, epub.getTitle(), epub.getAuthor(), epub.getThumbBmpPath()};
|
||||||
|
} else if (StringUtils::checkFileExtension(lastBookFileName, ".xtch") ||
|
||||||
|
StringUtils::checkFileExtension(lastBookFileName, ".xtc")) {
|
||||||
|
// Handle XTC file
|
||||||
|
Xtc xtc(path, "/.crosspoint");
|
||||||
|
if (xtc.load()) {
|
||||||
|
return RecentBook{path, xtc.getTitle(), xtc.getAuthor(), xtc.getThumbBmpPath()};
|
||||||
|
}
|
||||||
|
} else if (StringUtils::checkFileExtension(lastBookFileName, ".txt") ||
|
||||||
|
StringUtils::checkFileExtension(lastBookFileName, ".md")) {
|
||||||
|
return RecentBook{path, lastBookFileName, "", ""};
|
||||||
|
}
|
||||||
|
return RecentBook{path, "", "", ""};
|
||||||
|
}
|
||||||
|
|
||||||
bool RecentBooksStore::loadFromFile() {
|
bool RecentBooksStore::loadFromFile() {
|
||||||
FsFile inputFile;
|
FsFile inputFile;
|
||||||
if (!SdMan.openFileForRead("RBS", RECENT_BOOKS_FILE, inputFile)) {
|
if (!SdMan.openFileForRead("RBS", RECENT_BOOKS_FILE, inputFile)) {
|
||||||
@ -68,7 +100,7 @@ bool RecentBooksStore::loadFromFile() {
|
|||||||
uint8_t version;
|
uint8_t version;
|
||||||
serialization::readPod(inputFile, version);
|
serialization::readPod(inputFile, version);
|
||||||
if (version != RECENT_BOOKS_FILE_VERSION) {
|
if (version != RECENT_BOOKS_FILE_VERSION) {
|
||||||
if (version == 1) {
|
if (version == 1 || version == 2) {
|
||||||
// Old version, just read paths
|
// Old version, just read paths
|
||||||
uint8_t count;
|
uint8_t count;
|
||||||
serialization::readPod(inputFile, count);
|
serialization::readPod(inputFile, count);
|
||||||
@ -77,25 +109,18 @@ bool RecentBooksStore::loadFromFile() {
|
|||||||
for (uint8_t i = 0; i < count; i++) {
|
for (uint8_t i = 0; i < count; i++) {
|
||||||
std::string path;
|
std::string path;
|
||||||
serialization::readString(inputFile, path);
|
serialization::readString(inputFile, path);
|
||||||
// Title and author will be empty, they will be filled when the book is
|
|
||||||
// opened again
|
// load book to get missing data
|
||||||
std::string fileName = path.substr(path.rfind('/') + 1);
|
RecentBook book = getDataFromBook(path);
|
||||||
recentBooks.push_back({path, fileName, "", "-"});
|
if (book.title.empty() && book.author.empty() && version == 2) {
|
||||||
}
|
// Fall back to loading what we can from the store
|
||||||
} else if (version == 2) {
|
std::string title, author;
|
||||||
// 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, title);
|
||||||
serialization::readString(inputFile, author);
|
serialization::readString(inputFile, author);
|
||||||
// Title and author will be empty, they will be filled when the book is
|
recentBooks.push_back({path, title, author, ""});
|
||||||
// opened again
|
} else {
|
||||||
recentBooks.push_back({path, title, author, "-"});
|
recentBooks.push_back(book);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Serial.printf("[%lu] [RBS] Deserialization failed: Unknown version %u\n", millis(), version);
|
Serial.printf("[%lu] [RBS] Deserialization failed: Unknown version %u\n", millis(), version);
|
||||||
|
|||||||
@ -36,6 +36,7 @@ class RecentBooksStore {
|
|||||||
bool saveToFile() const;
|
bool saveToFile() const;
|
||||||
|
|
||||||
bool loadFromFile();
|
bool loadFromFile();
|
||||||
|
RecentBook getDataFromBook(std::string path) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Helper macro to access recent books store
|
// Helper macro to access recent books store
|
||||||
|
|||||||
@ -44,11 +44,8 @@ void HomeActivity::loadRecentBooks(int maxBooks, int coverHeight) {
|
|||||||
const auto& books = RECENT_BOOKS.getBooks();
|
const auto& books = RECENT_BOOKS.getBooks();
|
||||||
recentBooks.reserve(std::min(static_cast<int>(books.size()), maxBooks));
|
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;
|
int progress = 0;
|
||||||
for (const RecentBook& book : books) {
|
for (const RecentBook& book : books) {
|
||||||
bool mustLoadCover = false;
|
|
||||||
|
|
||||||
// Limit to maximum number of recent books
|
// Limit to maximum number of recent books
|
||||||
if (recentBooks.size() >= maxBooks) {
|
if (recentBooks.size() >= maxBooks) {
|
||||||
break;
|
break;
|
||||||
@ -59,16 +56,9 @@ void HomeActivity::loadRecentBooks(int maxBooks, int coverHeight) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (book.coverBmpPath == "-") {
|
if (!book.coverBmpPath.empty()) {
|
||||||
mustReloadRecents = true;
|
|
||||||
} else {
|
|
||||||
std::string coverPath = UITheme::getCoverThumbPath(book.coverBmpPath, coverHeight);
|
std::string coverPath = UITheme::getCoverThumbPath(book.coverBmpPath, coverHeight);
|
||||||
if (!SdMan.exists(coverPath.c_str())) {
|
if (!SdMan.exists(coverPath.c_str())) {
|
||||||
mustLoadCover = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mustReloadRecents || mustLoadCover) {
|
|
||||||
std::string lastBookFileName = "";
|
std::string lastBookFileName = "";
|
||||||
const size_t lastSlash = book.path.find_last_of('/');
|
const size_t lastSlash = book.path.find_last_of('/');
|
||||||
if (lastSlash != std::string::npos) {
|
if (lastSlash != std::string::npos) {
|
||||||
@ -87,14 +77,8 @@ void HomeActivity::loadRecentBooks(int maxBooks, int coverHeight) {
|
|||||||
showingLoading = true;
|
showingLoading = true;
|
||||||
popupRect = GUI.drawPopup(renderer, "Loading...");
|
popupRect = GUI.drawPopup(renderer, "Loading...");
|
||||||
}
|
}
|
||||||
GUI.fillPopupProgress(renderer, popupRect, progress * (100 / maxBooks));
|
GUI.fillPopupProgress(renderer, popupRect, progress * 30);
|
||||||
epub.generateThumbBmp(coverHeight);
|
epub.generateThumbBmp(coverHeight);
|
||||||
|
|
||||||
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") ||
|
} else if (StringUtils::checkFileExtension(lastBookFileName, ".xtch") ||
|
||||||
StringUtils::checkFileExtension(lastBookFileName, ".xtc")) {
|
StringUtils::checkFileExtension(lastBookFileName, ".xtc")) {
|
||||||
// Handle XTC file
|
// Handle XTC file
|
||||||
@ -105,24 +89,18 @@ void HomeActivity::loadRecentBooks(int maxBooks, int coverHeight) {
|
|||||||
showingLoading = true;
|
showingLoading = true;
|
||||||
popupRect = GUI.drawPopup(renderer, "Loading...");
|
popupRect = GUI.drawPopup(renderer, "Loading...");
|
||||||
}
|
}
|
||||||
GUI.fillPopupProgress(renderer, popupRect, progress * (100 / maxBooks));
|
GUI.fillPopupProgress(renderer, popupRect, progress * 30);
|
||||||
xtc.generateThumbBmp(coverHeight);
|
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()});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mustReloadRecents) {
|
|
||||||
recentBooks.push_back(book);
|
recentBooks.push_back(book);
|
||||||
}
|
|
||||||
progress++;
|
progress++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Serial.printf("Recent books loaded: %d\n", recentBooks.size());
|
||||||
recentsLoaded = true;
|
recentsLoaded = true;
|
||||||
recentsLoading = false;
|
recentsLoading = false;
|
||||||
updateRequired = true;
|
updateRequired = true;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user