Consolidate cache directories
This commit is contained in:
@@ -28,11 +28,8 @@
|
||||
#include "fontIds.h"
|
||||
|
||||
namespace {
|
||||
// Convert a sidecar JPG/PNG cover to a 1-bit BMP in the cache and return the BMP path, or "" on failure.
|
||||
// fileName is the basename of the output file (without directory), e.g. "340x540.bmp" or "400.bmp".
|
||||
std::string convertSidecarToBmp(const std::string& bookPath, const std::string& sidecarPath, int width, int height,
|
||||
std::string convertSidecarToBmp(const std::string& cacheDir, const std::string& sidecarPath, int width, int height,
|
||||
const std::string& fileName) {
|
||||
const std::string cacheDir = "/.crosspoint/sidecar_" + std::to_string(std::hash<std::string>{}(bookPath));
|
||||
Storage.mkdir(cacheDir.c_str());
|
||||
const std::string bmpPath = cacheDir + "/" + fileName;
|
||||
if (Storage.exists(bmpPath.c_str())) return bmpPath;
|
||||
@@ -180,8 +177,9 @@ void HomeActivity::loadRecentBooks(int maxBooks) {
|
||||
// Also catches books registered before sidecar support (empty coverBmpPath).
|
||||
const std::string sidecar = ReaderActivity::sidecarCoverPath(book.path);
|
||||
if (!sidecar.empty()) {
|
||||
const std::string bookCache = ReaderActivity::bookCacheDir(book.path);
|
||||
const bool sidecarAlreadyStored =
|
||||
book.coverBmpPath == sidecar || book.coverBmpPath.find("sidecar_") != std::string::npos;
|
||||
book.coverBmpPath == sidecar || book.coverBmpPath.find(bookCache) != std::string::npos;
|
||||
LOG_DBG("HOME", "Sidecar for %s: stored=%s alreadyStored=%d", book.path.c_str(), book.coverBmpPath.c_str(),
|
||||
sidecarAlreadyStored ? 1 : 0);
|
||||
if (!sidecarAlreadyStored) {
|
||||
@@ -222,13 +220,13 @@ void HomeActivity::loadRecentCovers(int coverHeight) {
|
||||
// The cache will be rebuilt on the next render.
|
||||
UITheme::getInstance().getMutableTheme().invalidateFrameCache();
|
||||
|
||||
const std::string cacheBase = "/.crosspoint/sidecar_" + std::to_string(std::hash<std::string>{}(book.path));
|
||||
const std::string cacheBase = ReaderActivity::bookCacheDir(book.path);
|
||||
const std::string placeholder = cacheBase + "/[HEIGHT].bmp";
|
||||
bool success = true;
|
||||
if (!thumbSizes.empty()) {
|
||||
for (const auto& sz : thumbSizes) {
|
||||
const std::string name = std::to_string(sz.first) + "x" + std::to_string(sz.second) + ".bmp";
|
||||
if (convertSidecarToBmp(book.path, book.coverBmpPath, sz.first, sz.second, name).empty()) {
|
||||
if (convertSidecarToBmp(cacheBase, book.coverBmpPath, sz.first, sz.second, name).empty()) {
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
@@ -236,7 +234,7 @@ void HomeActivity::loadRecentCovers(int coverHeight) {
|
||||
} else {
|
||||
const int w = coverHeight * 6 / 10;
|
||||
const std::string name = std::to_string(coverHeight) + ".bmp";
|
||||
if (convertSidecarToBmp(book.path, book.coverBmpPath, w, coverHeight, name).empty()) success = false;
|
||||
if (convertSidecarToBmp(cacheBase, book.coverBmpPath, w, coverHeight, name).empty()) success = false;
|
||||
}
|
||||
if (success) {
|
||||
LOG_DBG("HOME", "Sidecar converted, placeholder: %s", placeholder.c_str());
|
||||
|
||||
@@ -65,9 +65,8 @@ std::string findUniquePathWithSuffix(const std::string& basePath) {
|
||||
|
||||
std::string findUniqueCompletedSidecarPath(const std::string& basePath) { return findUniquePathWithSuffix(basePath); }
|
||||
|
||||
std::string convertSidecarToBmp(const std::string& bookPath, const std::string& sidecarPath, int width, int height,
|
||||
std::string convertSidecarToBmp(const std::string& cacheDir, const std::string& sidecarPath, int width, int height,
|
||||
const std::string& fileName) {
|
||||
const std::string cacheDir = "/.crosspoint/sidecar_" + std::to_string(std::hash<std::string>{}(bookPath));
|
||||
if (!Storage.exists(cacheDir.c_str())) {
|
||||
Storage.mkdir(cacheDir.c_str());
|
||||
}
|
||||
@@ -120,7 +119,7 @@ std::string getSidecarCoverBmpPath(const std::string& bookPath, int width, int h
|
||||
}
|
||||
|
||||
const std::string fileName = "thumb_" + std::to_string(width) + "x" + std::to_string(height) + ".bmp";
|
||||
return convertSidecarToBmp(bookPath, sidecarPath, width, height, fileName);
|
||||
return convertSidecarToBmp(ReaderActivity::bookCacheDir(bookPath), sidecarPath, width, height, fileName);
|
||||
}
|
||||
|
||||
bool moveSidecarFilesToCompleted(const std::string& currentBookPath, const std::string& targetBookPath) {
|
||||
|
||||
@@ -71,6 +71,12 @@ std::string ReaderActivity::sidecarCoverPath(const std::string& bookPath) {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string ReaderActivity::bookCacheDir(const std::string& bookPath) {
|
||||
if (FsHelpers::hasEpubExtension(bookPath)) return Epub(bookPath, "/.crosspoint").getCachePath();
|
||||
if (FsHelpers::hasXtcExtension(bookPath)) return Xtc(bookPath, "/.crosspoint").getCachePath();
|
||||
return Txt(bookPath, "/.crosspoint").getCachePath();
|
||||
}
|
||||
|
||||
std::unique_ptr<Epub> ReaderActivity::loadEpub(const std::string& path) {
|
||||
if (!Storage.exists(path.c_str())) {
|
||||
LOG_ERR("READER", "File does not exist: %s", path.c_str());
|
||||
|
||||
@@ -31,6 +31,7 @@ class ReaderActivity final : public Activity {
|
||||
|
||||
public:
|
||||
static std::string sidecarCoverPath(const std::string& bookPath);
|
||||
static std::string bookCacheDir(const std::string& bookPath);
|
||||
|
||||
explicit ReaderActivity(GfxRenderer& renderer, MappedInputManager& mappedInput, std::string initialBookPath)
|
||||
: Activity("Reader", renderer, mappedInput), initialBookPath(std::move(initialBookPath)) {}
|
||||
|
||||
@@ -105,8 +105,8 @@ void ClearCacheActivity::clearCache() {
|
||||
file.getName(name, sizeof(name));
|
||||
String itemName(name);
|
||||
|
||||
// Only delete directories starting with epub_ or xtc_
|
||||
if (file.isDirectory() && (itemName.startsWith("epub_") || itemName.startsWith("xtc_"))) {
|
||||
if (file.isDirectory() &&
|
||||
(itemName.startsWith("epub_") || itemName.startsWith("xtc_") || itemName.startsWith("txt_"))) {
|
||||
String fullPath = "/.crosspoint/" + itemName;
|
||||
LOG_DBG("CLEAR_CACHE", "Removing cache: %s", fullPath.c_str());
|
||||
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
#include <FsHelpers.h>
|
||||
#include <HalStorage.h>
|
||||
#include <Logging.h>
|
||||
#include <Txt.h>
|
||||
#include <WiFi.h>
|
||||
#include <Xtc.h>
|
||||
#include <esp_task_wdt.h>
|
||||
|
||||
#include <algorithm>
|
||||
@@ -58,16 +60,25 @@ String wsLastCompleteName;
|
||||
size_t wsLastCompleteSize = 0;
|
||||
unsigned long wsLastCompleteAt = 0;
|
||||
|
||||
// Helper function to clear epub cache after upload
|
||||
void clearEpubCacheIfNeeded(const String& filePath) {
|
||||
void clearBookCacheIfNeeded(const String& filePath) {
|
||||
if (FsHelpers::hasEpubExtension(filePath)) {
|
||||
Epub(filePath.c_str(), "/.crosspoint").clearCache();
|
||||
LOG_DBG("WEB", "Cleared epub cache for: %s", filePath.c_str());
|
||||
} else if (FsHelpers::hasXtcExtension(filePath)) {
|
||||
Xtc(filePath.c_str(), "/.crosspoint").clearCache();
|
||||
LOG_DBG("WEB", "Cleared xtc cache for: %s", filePath.c_str());
|
||||
} else if (FsHelpers::hasTxtExtension(filePath) || FsHelpers::hasMarkdownExtension(filePath)) {
|
||||
const Txt txt(filePath.c_str(), "/.crosspoint");
|
||||
const String cachePath = txt.getCachePath().c_str();
|
||||
if (Storage.exists(cachePath.c_str())) {
|
||||
Storage.removeDir(cachePath.c_str());
|
||||
LOG_DBG("WEB", "Cleared txt cache for: %s", filePath.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Recursively clear epub caches for all EPUBs inside a directory
|
||||
void clearEpubCachesInDirectory(const String& dirPath) {
|
||||
// Recursively clear book caches for all ebooks inside a directory
|
||||
void clearBookCachesInDirectory(const String& dirPath) {
|
||||
esp_task_wdt_reset();
|
||||
yield();
|
||||
FsFile dir = Storage.open(dirPath.c_str());
|
||||
@@ -86,10 +97,10 @@ void clearEpubCachesInDirectory(const String& dirPath) {
|
||||
childPath += name;
|
||||
if (entry.isDirectory()) {
|
||||
entry.close();
|
||||
clearEpubCachesInDirectory(childPath);
|
||||
clearBookCachesInDirectory(childPath);
|
||||
} else {
|
||||
entry.close();
|
||||
clearEpubCacheIfNeeded(childPath);
|
||||
clearBookCacheIfNeeded(childPath);
|
||||
}
|
||||
entry = dir.openNextFile();
|
||||
}
|
||||
@@ -1210,7 +1221,7 @@ void CrossPointWebServer::handleDelete() const {
|
||||
// It's a file (or couldn't open as dir) — remove file
|
||||
if (f) f.close();
|
||||
success = Storage.remove(itemPath.c_str());
|
||||
clearEpubCacheIfNeeded(itemPath);
|
||||
clearBookCacheIfNeeded(itemPath);
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#include <FsHelpers.h>
|
||||
#include <HalStorage.h>
|
||||
#include <Logging.h>
|
||||
#include <Txt.h>
|
||||
#include <Xtc.h>
|
||||
#include <esp_task_wdt.h>
|
||||
|
||||
namespace {
|
||||
@@ -802,6 +804,16 @@ void WebDAVHandler::clearEpubCacheIfNeeded(const String& path) const {
|
||||
if (FsHelpers::hasEpubExtension(path)) {
|
||||
Epub(path.c_str(), "/.crosspoint").clearCache();
|
||||
LOG_DBG("DAV", "Cleared epub cache for: %s", path.c_str());
|
||||
} else if (FsHelpers::hasXtcExtension(path)) {
|
||||
Xtc(path.c_str(), "/.crosspoint").clearCache();
|
||||
LOG_DBG("DAV", "Cleared xtc cache for: %s", path.c_str());
|
||||
} else if (FsHelpers::hasTxtExtension(path) || FsHelpers::hasMarkdownExtension(path)) {
|
||||
const Txt txt(path.c_str(), "/.crosspoint");
|
||||
const String cachePath = txt.getCachePath().c_str();
|
||||
if (Storage.exists(cachePath.c_str())) {
|
||||
Storage.removeDir(cachePath.c_str());
|
||||
LOG_DBG("DAV", "Cleared txt cache for: %s", path.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user