refactor: unify book cache clearing for epub, txt, and xtc files (#1875)
This commit is contained in:
@@ -155,6 +155,21 @@ bool Txt::generateCoverBmp() const {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Txt::clearCache() const {
|
||||||
|
if (!Storage.exists(cachePath.c_str())) {
|
||||||
|
LOG_DBG("TXT", "Cache does not exist, no action needed");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Storage.removeDir(cachePath.c_str())) {
|
||||||
|
LOG_ERR("TXT", "Failed to clear cache");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_DBG("TXT", "Cache cleared successfully");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool Txt::readContent(uint8_t* buffer, size_t offset, size_t length) const {
|
bool Txt::readContent(uint8_t* buffer, size_t offset, size_t length) const {
|
||||||
if (!loaded) {
|
if (!loaded) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ class Txt {
|
|||||||
[[nodiscard]] size_t getFileSize() const { return fileSize; }
|
[[nodiscard]] size_t getFileSize() const { return fileSize; }
|
||||||
|
|
||||||
void setupCacheDir() const;
|
void setupCacheDir() const;
|
||||||
|
bool clearCache() const;
|
||||||
|
|
||||||
// Cover image support - looks for cover.bmp/jpg/jpeg/png in same folder as txt file
|
// Cover image support - looks for cover.bmp/jpg/jpeg/png in same folder as txt file
|
||||||
[[nodiscard]] std::string getCoverBmpPath() const;
|
[[nodiscard]] std::string getCoverBmpPath() const;
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
#include "OpdsBookBrowserActivity.h"
|
#include "OpdsBookBrowserActivity.h"
|
||||||
|
|
||||||
#include <Epub.h>
|
|
||||||
#include <GfxRenderer.h>
|
#include <GfxRenderer.h>
|
||||||
#include <I18n.h>
|
#include <I18n.h>
|
||||||
#include <Logging.h>
|
#include <Logging.h>
|
||||||
@@ -14,6 +13,7 @@
|
|||||||
#include "components/UITheme.h"
|
#include "components/UITheme.h"
|
||||||
#include "fontIds.h"
|
#include "fontIds.h"
|
||||||
#include "network/HttpDownloader.h"
|
#include "network/HttpDownloader.h"
|
||||||
|
#include "util/BookCacheUtils.h"
|
||||||
#include "util/StringUtils.h"
|
#include "util/StringUtils.h"
|
||||||
#include "util/UrlUtils.h"
|
#include "util/UrlUtils.h"
|
||||||
|
|
||||||
@@ -283,7 +283,7 @@ void OpdsBookBrowserActivity::downloadBook(const OpdsEntry& book) {
|
|||||||
nullptr, server.username, server.password);
|
nullptr, server.username, server.password);
|
||||||
|
|
||||||
if (result == HttpDownloader::OK) {
|
if (result == HttpDownloader::OK) {
|
||||||
Epub(filename, "/.crosspoint").clearCache();
|
clearBookCache(filename);
|
||||||
state = BrowserState::BROWSING;
|
state = BrowserState::BROWSING;
|
||||||
} else {
|
} else {
|
||||||
state = BrowserState::ERROR;
|
state = BrowserState::ERROR;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "MappedInputManager.h"
|
#include "MappedInputManager.h"
|
||||||
#include "components/UITheme.h"
|
#include "components/UITheme.h"
|
||||||
#include "fontIds.h"
|
#include "fontIds.h"
|
||||||
|
#include "util/BookCacheUtils.h"
|
||||||
|
|
||||||
void ClearCacheActivity::onEnter() {
|
void ClearCacheActivity::onEnter() {
|
||||||
Activity::onEnter();
|
Activity::onEnter();
|
||||||
@@ -94,8 +95,8 @@ void ClearCacheActivity::clearCache() {
|
|||||||
file.getName(name, sizeof(name));
|
file.getName(name, sizeof(name));
|
||||||
String itemName(name);
|
String itemName(name);
|
||||||
|
|
||||||
// Only delete directories starting with epub_ or xtc_
|
// Only delete directories matching known book cache names.
|
||||||
if (file.isDirectory() && (itemName.startsWith("epub_") || itemName.startsWith("xtc_"))) {
|
if (file.isDirectory() && isBookCacheDirectoryName(itemName.c_str())) {
|
||||||
String fullPath = "/.crosspoint/" + itemName;
|
String fullPath = "/.crosspoint/" + itemName;
|
||||||
LOG_DBG("CLEAR_CACHE", "Removing cache: %s", fullPath.c_str());
|
LOG_DBG("CLEAR_CACHE", "Removing cache: %s", fullPath.c_str());
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#include "CrossPointWebServer.h"
|
#include "CrossPointWebServer.h"
|
||||||
|
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <Epub.h>
|
|
||||||
#include <FsHelpers.h>
|
#include <FsHelpers.h>
|
||||||
#include <HalGPIO.h>
|
#include <HalGPIO.h>
|
||||||
#include <HalStorage.h>
|
#include <HalStorage.h>
|
||||||
@@ -23,6 +22,7 @@
|
|||||||
#include "html/HomePageHtml.generated.h"
|
#include "html/HomePageHtml.generated.h"
|
||||||
#include "html/SettingsPageHtml.generated.h"
|
#include "html/SettingsPageHtml.generated.h"
|
||||||
#include "html/js/jszip_minJs.generated.h"
|
#include "html/js/jszip_minJs.generated.h"
|
||||||
|
#include "util/BookCacheUtils.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
// Folders/files to hide from the web interface file browser
|
// Folders/files to hide from the web interface file browser
|
||||||
@@ -48,15 +48,6 @@ String wsLastCompleteName;
|
|||||||
size_t wsLastCompleteSize = 0;
|
size_t wsLastCompleteSize = 0;
|
||||||
unsigned long wsLastCompleteAt = 0;
|
unsigned long wsLastCompleteAt = 0;
|
||||||
|
|
||||||
// Helper function to clear epub cache after upload
|
|
||||||
void clearEpubCacheIfNeeded(const String& filePath) {
|
|
||||||
// Only clear cache for .epub files
|
|
||||||
if (FsHelpers::hasEpubExtension(filePath)) {
|
|
||||||
Epub(filePath.c_str(), "/.crosspoint").clearCache();
|
|
||||||
LOG_DBG("WEB", "Cleared epub cache for: %s", filePath.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String normalizeWebPath(const String& inputPath) {
|
String normalizeWebPath(const String& inputPath) {
|
||||||
if (inputPath.isEmpty() || inputPath == "/") {
|
if (inputPath.isEmpty() || inputPath == "/") {
|
||||||
return "/";
|
return "/";
|
||||||
@@ -732,7 +723,7 @@ void CrossPointWebServer::handleUpload(UploadState& state) const {
|
|||||||
String filePath = state.path;
|
String filePath = state.path;
|
||||||
if (!filePath.endsWith("/")) filePath += "/";
|
if (!filePath.endsWith("/")) filePath += "/";
|
||||||
filePath += state.fileName;
|
filePath += state.fileName;
|
||||||
clearEpubCacheIfNeeded(filePath);
|
clearBookCache(filePath.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (upload.status == UPLOAD_FILE_ABORTED) {
|
} else if (upload.status == UPLOAD_FILE_ABORTED) {
|
||||||
@@ -878,7 +869,7 @@ void CrossPointWebServer::handleRename() const {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
clearEpubCacheIfNeeded(itemPath);
|
clearBookCache(itemPath.c_str());
|
||||||
const bool success = file.rename(newPath.c_str());
|
const bool success = file.rename(newPath.c_str());
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
@@ -971,7 +962,7 @@ void CrossPointWebServer::handleMove() const {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
clearEpubCacheIfNeeded(itemPath);
|
clearBookCache(itemPath.c_str());
|
||||||
const bool success = file.rename(newPath.c_str());
|
const bool success = file.rename(newPath.c_str());
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
@@ -1090,7 +1081,7 @@ void CrossPointWebServer::handleDelete() const {
|
|||||||
// It's a file (or couldn't open as dir) — remove file
|
// It's a file (or couldn't open as dir) — remove file
|
||||||
if (f) f.close();
|
if (f) f.close();
|
||||||
success = Storage.remove(itemPath.c_str());
|
success = Storage.remove(itemPath.c_str());
|
||||||
clearEpubCacheIfNeeded(itemPath);
|
clearBookCache(itemPath.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
@@ -1636,7 +1627,7 @@ void CrossPointWebServer::onWebSocketEvent(uint8_t num, WStype_t type, uint8_t*
|
|||||||
wsLastCompleteSize = 0;
|
wsLastCompleteSize = 0;
|
||||||
wsLastCompleteAt = millis();
|
wsLastCompleteAt = millis();
|
||||||
LOG_DBG("WS", "Zero-byte upload complete: %s", filePath.c_str());
|
LOG_DBG("WS", "Zero-byte upload complete: %s", filePath.c_str());
|
||||||
clearEpubCacheIfNeeded(filePath);
|
clearBookCache(filePath.c_str());
|
||||||
wsServer->sendTXT(num, "DONE");
|
wsServer->sendTXT(num, "DONE");
|
||||||
wsLastProgressSent = 0;
|
wsLastProgressSent = 0;
|
||||||
break;
|
break;
|
||||||
@@ -1705,7 +1696,7 @@ void CrossPointWebServer::onWebSocketEvent(uint8_t num, WStype_t type, uint8_t*
|
|||||||
String filePath = wsUploadPath;
|
String filePath = wsUploadPath;
|
||||||
if (!filePath.endsWith("/")) filePath += "/";
|
if (!filePath.endsWith("/")) filePath += "/";
|
||||||
filePath += wsUploadFileName;
|
filePath += wsUploadFileName;
|
||||||
clearEpubCacheIfNeeded(filePath);
|
clearBookCache(filePath.c_str());
|
||||||
|
|
||||||
wsServer->sendTXT(num, "DONE");
|
wsServer->sendTXT(num, "DONE");
|
||||||
wsLastProgressSent = 0;
|
wsLastProgressSent = 0;
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
#include "WebDAVHandler.h"
|
#include "WebDAVHandler.h"
|
||||||
|
|
||||||
#include <Epub.h>
|
|
||||||
#include <FsHelpers.h>
|
#include <FsHelpers.h>
|
||||||
#include <HalStorage.h>
|
#include <HalStorage.h>
|
||||||
#include <Logging.h>
|
#include <Logging.h>
|
||||||
#include <esp_task_wdt.h>
|
#include <esp_task_wdt.h>
|
||||||
|
|
||||||
|
#include "util/BookCacheUtils.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
constexpr const char* HIDDEN_ITEMS[] = {"System Volume Information", "XTCache"};
|
constexpr const char* HIDDEN_ITEMS[] = {"System Volume Information", "XTCache"};
|
||||||
|
|
||||||
@@ -384,7 +385,7 @@ void WebDAVHandler::handlePut(WebServer& s) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
clearEpubCacheIfNeeded(path);
|
clearBookCache(path.c_str());
|
||||||
s.send(_putExisted ? 204 : 201);
|
s.send(_putExisted ? 204 : 201);
|
||||||
LOG_DBG("DAV", "PUT complete: %s", path.c_str());
|
LOG_DBG("DAV", "PUT complete: %s", path.c_str());
|
||||||
}
|
}
|
||||||
@@ -433,7 +434,7 @@ void WebDAVHandler::handleDelete(WebServer& s) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
file.close();
|
file.close();
|
||||||
clearEpubCacheIfNeeded(path);
|
clearBookCache(path.c_str());
|
||||||
if (Storage.remove(path.c_str())) {
|
if (Storage.remove(path.c_str())) {
|
||||||
s.send(204);
|
s.send(204);
|
||||||
} else {
|
} else {
|
||||||
@@ -542,7 +543,7 @@ void WebDAVHandler::handleMove(WebServer& s) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
clearEpubCacheIfNeeded(srcPath);
|
clearBookCache(srcPath.c_str());
|
||||||
bool success = file.rename(dstPath.c_str());
|
bool success = file.rename(dstPath.c_str());
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
@@ -797,13 +798,6 @@ bool WebDAVHandler::getOverwrite(WebServer& s) const {
|
|||||||
return true; // Default is T
|
return true; // Default is T
|
||||||
}
|
}
|
||||||
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String WebDAVHandler::getMimeType(const String& path) const {
|
String WebDAVHandler::getMimeType(const String& path) const {
|
||||||
if (FsHelpers::hasEpubExtension(path)) return "application/epub+zip";
|
if (FsHelpers::hasEpubExtension(path)) return "application/epub+zip";
|
||||||
if (FsHelpers::checkFileExtension(path, ".pdf")) return "application/pdf";
|
if (FsHelpers::checkFileExtension(path, ".pdf")) return "application/pdf";
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ class WebDAVHandler : public RequestHandler {
|
|||||||
bool isProtectedPath(const String& path) const;
|
bool isProtectedPath(const String& path) const;
|
||||||
int getDepth(WebServer& s) const;
|
int getDepth(WebServer& s) const;
|
||||||
bool getOverwrite(WebServer& s) const;
|
bool getOverwrite(WebServer& s) const;
|
||||||
void clearEpubCacheIfNeeded(const String& path) const;
|
|
||||||
void sendPropEntry(WebServer& s, const String& href, bool isDir, size_t size, const String& lastModified) const;
|
void sendPropEntry(WebServer& s, const String& href, bool isDir, size_t size, const String& lastModified) const;
|
||||||
String getMimeType(const String& path) const;
|
String getMimeType(const String& path) const;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
#include "BookCacheUtils.h"
|
||||||
|
|
||||||
|
#include <Epub.h>
|
||||||
|
#include <FsHelpers.h>
|
||||||
|
#include <Logging.h>
|
||||||
|
#include <Txt.h>
|
||||||
|
#include <Xtc.h>
|
||||||
|
|
||||||
|
bool isBookCacheDirectoryName(const char* name) {
|
||||||
|
if (!name) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr char EPUB_PREFIX[] = "epub_";
|
||||||
|
constexpr char TXT_PREFIX[] = "txt_";
|
||||||
|
constexpr char XTC_PREFIX[] = "xtc_";
|
||||||
|
|
||||||
|
return strncmp(name, EPUB_PREFIX, std::size(EPUB_PREFIX) - 1) == 0 ||
|
||||||
|
strncmp(name, TXT_PREFIX, std::size(TXT_PREFIX) - 1) == 0 ||
|
||||||
|
strncmp(name, XTC_PREFIX, std::size(XTC_PREFIX) - 1) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clearBookCache(const std::string& path) {
|
||||||
|
if (FsHelpers::hasEpubExtension(path)) {
|
||||||
|
Epub(path, "/.crosspoint").clearCache();
|
||||||
|
} else if (FsHelpers::hasXtcExtension(path)) {
|
||||||
|
Xtc(path, "/.crosspoint").clearCache();
|
||||||
|
} else if (FsHelpers::hasTxtExtension(path)) {
|
||||||
|
Txt(path, "/.crosspoint").clearCache();
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LOG_DBG("BookCache", "Done checking metadata cache for: %s", path.c_str());
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
// Clears the reading cache for a book file if its extension is recognised
|
||||||
|
// (EPUB, XTC, or TXT). Does nothing for other file types.
|
||||||
|
void clearBookCache(const std::string& path);
|
||||||
|
|
||||||
|
// Returns true if the directory name matches a book cache entry.
|
||||||
|
bool isBookCacheDirectoryName(const char* name);
|
||||||
Reference in New Issue
Block a user