From 7f40c3f477a383c122b8496c55f250b257777821 Mon Sep 17 00:00:00 2001 From: Xuan-Son Nguyen Date: Sun, 8 Feb 2026 21:29:14 +0100 Subject: [PATCH] feat: add HalStorage (#656) ## Summary Continue my changes to introduce the HAL infrastructure from https://github.com/crosspoint-reader/crosspoint-reader/pull/522 This PR touches quite a lot of files, but most of them are just name changing. It should not have any impacts to the end behavior. ## Additional Context My plan is to firstly add this small shim layer, which sounds useless at first, but then I'll implement an emulated driver which can be helpful for testing and for development. Currently, on my fork, I'm using a FS driver that allow "mounting" a local directory from my computer to the device, much like the `-v` mount option on docker. This allows me to quickly reset `.crosspoint` directory if anything goes wrong. I plan to upstream this feature when this PR get merged. --- ### AI Usage While CrossPoint doesn't have restrictions on AI tools in contributing, please be transparent about their usage as it helps set the right context for reviewers. Did you use AI tools to help write this code? NO --- lib/Epub/Epub.cpp | 62 +++++++++--------- lib/Epub/Epub/BookMetadataCache.cpp | 22 +++---- lib/Epub/Epub/BookMetadataCache.h | 2 +- lib/Epub/Epub/Page.h | 2 +- lib/Epub/Epub/Section.cpp | 30 ++++----- lib/Epub/Epub/blocks/TextBlock.h | 2 +- lib/Epub/Epub/css/CssParser.h | 2 +- .../Epub/parsers/ChapterHtmlSlimParser.cpp | 4 +- lib/Epub/Epub/parsers/ContentOpfParser.cpp | 10 +-- lib/GfxRenderer/Bitmap.h | 2 +- lib/JpegToBmpConverter/JpegToBmpConverter.cpp | 2 +- lib/KOReaderSync/KOReaderCredentialStore.cpp | 8 +-- lib/KOReaderSync/KOReaderDocumentId.cpp | 4 +- lib/Serialization/Serialization.h | 2 +- lib/Txt/Txt.cpp | 30 ++++----- lib/Txt/Txt.h | 2 +- lib/Xtc/Xtc.cpp | 26 ++++---- lib/Xtc/Xtc/XtcParser.cpp | 6 +- lib/Xtc/Xtc/XtcParser.h | 2 +- lib/ZipFile/ZipFile.cpp | 4 +- lib/ZipFile/ZipFile.h | 2 +- lib/hal/HalStorage.cpp | 65 +++++++++++++++++++ lib/hal/HalStorage.h | 54 +++++++++++++++ src/CrossPointSettings.cpp | 8 +-- src/CrossPointState.cpp | 6 +- src/RecentBooksStore.cpp | 8 +-- src/WifiCredentialStore.cpp | 8 +-- src/activities/boot_sleep/SleepActivity.cpp | 10 +-- src/activities/home/HomeActivity.cpp | 6 +- src/activities/home/MyLibraryActivity.cpp | 4 +- src/activities/home/RecentBooksActivity.cpp | 4 +- src/activities/reader/EpubReaderActivity.cpp | 6 +- src/activities/reader/ReaderActivity.cpp | 8 ++- src/activities/reader/TxtReaderActivity.cpp | 10 +-- src/activities/reader/XtcReaderActivity.cpp | 6 +- .../settings/ClearCacheActivity.cpp | 6 +- src/components/themes/BaseTheme.cpp | 4 +- src/components/themes/lyra/LyraTheme.cpp | 4 +- src/main.cpp | 4 +- src/network/CrossPointWebServer.cpp | 52 +++++++-------- src/network/CrossPointWebServer.h | 2 +- src/network/HttpDownloader.cpp | 12 ++-- src/network/HttpDownloader.h | 2 +- 43 files changed, 318 insertions(+), 197 deletions(-) create mode 100644 lib/hal/HalStorage.cpp create mode 100644 lib/hal/HalStorage.h diff --git a/lib/Epub/Epub.cpp b/lib/Epub/Epub.cpp index 64890ac0e..e003f45cf 100644 --- a/lib/Epub/Epub.cpp +++ b/lib/Epub/Epub.cpp @@ -1,9 +1,9 @@ #include "Epub.h" #include +#include #include #include -#include #include #include "Epub/parsers/ContainerParser.h" @@ -105,12 +105,12 @@ bool Epub::parseTocNcxFile() const { const auto tmpNcxPath = getCachePath() + "/toc.ncx"; FsFile tempNcxFile; - if (!SdMan.openFileForWrite("EBP", tmpNcxPath, tempNcxFile)) { + if (!Storage.openFileForWrite("EBP", tmpNcxPath, tempNcxFile)) { return false; } readItemContentsToStream(tocNcxItem, tempNcxFile, 1024); tempNcxFile.close(); - if (!SdMan.openFileForRead("EBP", tmpNcxPath, tempNcxFile)) { + if (!Storage.openFileForRead("EBP", tmpNcxPath, tempNcxFile)) { return false; } const auto ncxSize = tempNcxFile.size(); @@ -145,7 +145,7 @@ bool Epub::parseTocNcxFile() const { free(ncxBuffer); tempNcxFile.close(); - SdMan.remove(tmpNcxPath.c_str()); + Storage.remove(tmpNcxPath.c_str()); Serial.printf("[%lu] [EBP] Parsed TOC items\n", millis()); return true; @@ -162,12 +162,12 @@ bool Epub::parseTocNavFile() const { const auto tmpNavPath = getCachePath() + "/toc.nav"; FsFile tempNavFile; - if (!SdMan.openFileForWrite("EBP", tmpNavPath, tempNavFile)) { + if (!Storage.openFileForWrite("EBP", tmpNavPath, tempNavFile)) { return false; } readItemContentsToStream(tocNavItem, tempNavFile, 1024); tempNavFile.close(); - if (!SdMan.openFileForRead("EBP", tmpNavPath, tempNavFile)) { + if (!Storage.openFileForRead("EBP", tmpNavPath, tempNavFile)) { return false; } const auto navSize = tempNavFile.size(); @@ -202,7 +202,7 @@ bool Epub::parseTocNavFile() const { free(navBuffer); tempNavFile.close(); - SdMan.remove(tmpNavPath.c_str()); + Storage.remove(tmpNavPath.c_str()); Serial.printf("[%lu] [EBP] Parsed TOC nav items\n", millis()); return true; @@ -212,7 +212,7 @@ std::string Epub::getCssRulesCache() const { return cachePath + "/css_rules.cach bool Epub::loadCssRulesFromCache() const { FsFile cssCacheFile; - if (SdMan.openFileForRead("EBP", getCssRulesCache(), cssCacheFile)) { + if (Storage.openFileForRead("EBP", getCssRulesCache(), cssCacheFile)) { if (cssParser->loadFromCache(cssCacheFile)) { cssCacheFile.close(); Serial.printf("[%lu] [EBP] Loaded CSS rules from cache\n", millis()); @@ -238,32 +238,32 @@ void Epub::parseCssFiles() const { // Extract CSS file to temp location const auto tmpCssPath = getCachePath() + "/.tmp.css"; FsFile tempCssFile; - if (!SdMan.openFileForWrite("EBP", tmpCssPath, tempCssFile)) { + if (!Storage.openFileForWrite("EBP", tmpCssPath, tempCssFile)) { Serial.printf("[%lu] [EBP] Could not create temp CSS file\n", millis()); continue; } if (!readItemContentsToStream(cssPath, tempCssFile, 1024)) { Serial.printf("[%lu] [EBP] Could not read CSS file: %s\n", millis(), cssPath.c_str()); tempCssFile.close(); - SdMan.remove(tmpCssPath.c_str()); + Storage.remove(tmpCssPath.c_str()); continue; } tempCssFile.close(); // Parse the CSS file - if (!SdMan.openFileForRead("EBP", tmpCssPath, tempCssFile)) { + if (!Storage.openFileForRead("EBP", tmpCssPath, tempCssFile)) { Serial.printf("[%lu] [EBP] Could not open temp CSS file for reading\n", millis()); - SdMan.remove(tmpCssPath.c_str()); + Storage.remove(tmpCssPath.c_str()); continue; } cssParser->loadFromStream(tempCssFile); tempCssFile.close(); - SdMan.remove(tmpCssPath.c_str()); + Storage.remove(tmpCssPath.c_str()); } // Save to cache for next time FsFile cssCacheFile; - if (SdMan.openFileForWrite("EBP", getCssRulesCache(), cssCacheFile)) { + if (Storage.openFileForWrite("EBP", getCssRulesCache(), cssCacheFile)) { cssParser->saveToCache(cssCacheFile); cssCacheFile.close(); } @@ -399,12 +399,12 @@ bool Epub::load(const bool buildIfMissing, const bool skipLoadingCss) { } bool Epub::clearCache() const { - if (!SdMan.exists(cachePath.c_str())) { + if (!Storage.exists(cachePath.c_str())) { Serial.printf("[%lu] [EPB] Cache does not exist, no action needed\n", millis()); return true; } - if (!SdMan.removeDir(cachePath.c_str())) { + if (!Storage.removeDir(cachePath.c_str())) { Serial.printf("[%lu] [EPB] Failed to clear cache\n", millis()); return false; } @@ -414,11 +414,11 @@ bool Epub::clearCache() const { } void Epub::setupCacheDir() const { - if (SdMan.exists(cachePath.c_str())) { + if (Storage.exists(cachePath.c_str())) { return; } - SdMan.mkdir(cachePath.c_str()); + Storage.mkdir(cachePath.c_str()); } const std::string& Epub::getCachePath() const { return cachePath; } @@ -459,7 +459,7 @@ std::string Epub::getCoverBmpPath(bool cropped) const { bool Epub::generateCoverBmp(bool cropped) const { // Already generated, return true - if (SdMan.exists(getCoverBmpPath(cropped).c_str())) { + if (Storage.exists(getCoverBmpPath(cropped).c_str())) { return true; } @@ -480,29 +480,29 @@ bool Epub::generateCoverBmp(bool cropped) const { const auto coverJpgTempPath = getCachePath() + "/.cover.jpg"; FsFile coverJpg; - if (!SdMan.openFileForWrite("EBP", coverJpgTempPath, coverJpg)) { + if (!Storage.openFileForWrite("EBP", coverJpgTempPath, coverJpg)) { return false; } readItemContentsToStream(coverImageHref, coverJpg, 1024); coverJpg.close(); - if (!SdMan.openFileForRead("EBP", coverJpgTempPath, coverJpg)) { + if (!Storage.openFileForRead("EBP", coverJpgTempPath, coverJpg)) { return false; } FsFile coverBmp; - if (!SdMan.openFileForWrite("EBP", getCoverBmpPath(cropped), coverBmp)) { + if (!Storage.openFileForWrite("EBP", getCoverBmpPath(cropped), coverBmp)) { coverJpg.close(); return false; } const bool success = JpegToBmpConverter::jpegFileToBmpStream(coverJpg, coverBmp, cropped); coverJpg.close(); coverBmp.close(); - SdMan.remove(coverJpgTempPath.c_str()); + Storage.remove(coverJpgTempPath.c_str()); if (!success) { Serial.printf("[%lu] [EBP] Failed to generate BMP from JPG cover image\n", millis()); - SdMan.remove(getCoverBmpPath(cropped).c_str()); + Storage.remove(getCoverBmpPath(cropped).c_str()); } Serial.printf("[%lu] [EBP] Generated BMP from JPG cover image, success: %s\n", millis(), success ? "yes" : "no"); return success; @@ -518,7 +518,7 @@ std::string Epub::getThumbBmpPath(int height) const { return cachePath + "/thumb bool Epub::generateThumbBmp(int height) const { // Already generated, return true - if (SdMan.exists(getThumbBmpPath(height).c_str())) { + if (Storage.exists(getThumbBmpPath(height).c_str())) { return true; } @@ -536,18 +536,18 @@ bool Epub::generateThumbBmp(int height) const { const auto coverJpgTempPath = getCachePath() + "/.cover.jpg"; FsFile coverJpg; - if (!SdMan.openFileForWrite("EBP", coverJpgTempPath, coverJpg)) { + if (!Storage.openFileForWrite("EBP", coverJpgTempPath, coverJpg)) { return false; } readItemContentsToStream(coverImageHref, coverJpg, 1024); coverJpg.close(); - if (!SdMan.openFileForRead("EBP", coverJpgTempPath, coverJpg)) { + if (!Storage.openFileForRead("EBP", coverJpgTempPath, coverJpg)) { return false; } FsFile thumbBmp; - if (!SdMan.openFileForWrite("EBP", getThumbBmpPath(height), thumbBmp)) { + if (!Storage.openFileForWrite("EBP", getThumbBmpPath(height), thumbBmp)) { coverJpg.close(); return false; } @@ -559,11 +559,11 @@ bool Epub::generateThumbBmp(int height) const { THUMB_TARGET_HEIGHT); coverJpg.close(); thumbBmp.close(); - SdMan.remove(coverJpgTempPath.c_str()); + Storage.remove(coverJpgTempPath.c_str()); if (!success) { Serial.printf("[%lu] [EBP] Failed to generate thumb BMP from JPG cover image\n", millis()); - SdMan.remove(getThumbBmpPath(height).c_str()); + Storage.remove(getThumbBmpPath(height).c_str()); } Serial.printf("[%lu] [EBP] Generated thumb BMP from JPG cover image, success: %s\n", millis(), success ? "yes" : "no"); @@ -574,7 +574,7 @@ bool Epub::generateThumbBmp(int height) const { // Write an empty bmp file to avoid generation attempts in the future FsFile thumbBmp; - SdMan.openFileForWrite("EBP", getThumbBmpPath(height), thumbBmp); + Storage.openFileForWrite("EBP", getThumbBmpPath(height), thumbBmp); thumbBmp.close(); return false; } diff --git a/lib/Epub/Epub/BookMetadataCache.cpp b/lib/Epub/Epub/BookMetadataCache.cpp index e7242138a..c8ba7db59 100644 --- a/lib/Epub/Epub/BookMetadataCache.cpp +++ b/lib/Epub/Epub/BookMetadataCache.cpp @@ -29,7 +29,7 @@ bool BookMetadataCache::beginContentOpfPass() { Serial.printf("[%lu] [BMC] Beginning content opf pass\n", millis()); // Open spine file for writing - return SdMan.openFileForWrite("BMC", cachePath + tmpSpineBinFile, spineFile); + return Storage.openFileForWrite("BMC", cachePath + tmpSpineBinFile, spineFile); } bool BookMetadataCache::endContentOpfPass() { @@ -40,10 +40,10 @@ bool BookMetadataCache::endContentOpfPass() { bool BookMetadataCache::beginTocPass() { Serial.printf("[%lu] [BMC] Beginning toc pass\n", millis()); - if (!SdMan.openFileForRead("BMC", cachePath + tmpSpineBinFile, spineFile)) { + if (!Storage.openFileForRead("BMC", cachePath + tmpSpineBinFile, spineFile)) { return false; } - if (!SdMan.openFileForWrite("BMC", cachePath + tmpTocBinFile, tocFile)) { + if (!Storage.openFileForWrite("BMC", cachePath + tmpTocBinFile, tocFile)) { spineFile.close(); return false; } @@ -98,16 +98,16 @@ bool BookMetadataCache::endWrite() { bool BookMetadataCache::buildBookBin(const std::string& epubPath, const BookMetadata& metadata) { // Open all three files, writing to meta, reading from spine and toc - if (!SdMan.openFileForWrite("BMC", cachePath + bookBinFile, bookFile)) { + if (!Storage.openFileForWrite("BMC", cachePath + bookBinFile, bookFile)) { return false; } - if (!SdMan.openFileForRead("BMC", cachePath + tmpSpineBinFile, spineFile)) { + if (!Storage.openFileForRead("BMC", cachePath + tmpSpineBinFile, spineFile)) { bookFile.close(); return false; } - if (!SdMan.openFileForRead("BMC", cachePath + tmpTocBinFile, tocFile)) { + if (!Storage.openFileForRead("BMC", cachePath + tmpTocBinFile, tocFile)) { bookFile.close(); spineFile.close(); return false; @@ -275,11 +275,11 @@ bool BookMetadataCache::buildBookBin(const std::string& epubPath, const BookMeta } bool BookMetadataCache::cleanupTmpFiles() const { - if (SdMan.exists((cachePath + tmpSpineBinFile).c_str())) { - SdMan.remove((cachePath + tmpSpineBinFile).c_str()); + if (Storage.exists((cachePath + tmpSpineBinFile).c_str())) { + Storage.remove((cachePath + tmpSpineBinFile).c_str()); } - if (SdMan.exists((cachePath + tmpTocBinFile).c_str())) { - SdMan.remove((cachePath + tmpTocBinFile).c_str()); + if (Storage.exists((cachePath + tmpTocBinFile).c_str())) { + Storage.remove((cachePath + tmpTocBinFile).c_str()); } return true; } @@ -364,7 +364,7 @@ void BookMetadataCache::createTocEntry(const std::string& title, const std::stri /* ============= READING / LOADING FUNCTIONS ================ */ bool BookMetadataCache::load() { - if (!SdMan.openFileForRead("BMC", cachePath + bookBinFile, bookFile)) { + if (!Storage.openFileForRead("BMC", cachePath + bookBinFile, bookFile)) { return false; } diff --git a/lib/Epub/Epub/BookMetadataCache.h b/lib/Epub/Epub/BookMetadataCache.h index 20ce65593..9439b37fe 100644 --- a/lib/Epub/Epub/BookMetadataCache.h +++ b/lib/Epub/Epub/BookMetadataCache.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include diff --git a/lib/Epub/Epub/Page.h b/lib/Epub/Epub/Page.h index 200619417..590e288d4 100644 --- a/lib/Epub/Epub/Page.h +++ b/lib/Epub/Epub/Page.h @@ -1,5 +1,5 @@ #pragma once -#include +#include #include #include diff --git a/lib/Epub/Epub/Section.cpp b/lib/Epub/Epub/Section.cpp index 18e0faef2..6b9b49fdb 100644 --- a/lib/Epub/Epub/Section.cpp +++ b/lib/Epub/Epub/Section.cpp @@ -1,6 +1,6 @@ #include "Section.h" -#include +#include #include #include "Page.h" @@ -60,7 +60,7 @@ void Section::writeSectionFileHeader(const int fontId, const float lineCompressi bool Section::loadSectionFile(const int fontId, const float lineCompression, const bool extraParagraphSpacing, const uint8_t paragraphAlignment, const uint16_t viewportWidth, const uint16_t viewportHeight, const bool hyphenationEnabled, const bool embeddedStyle) { - if (!SdMan.openFileForRead("SCT", filePath, file)) { + if (!Storage.openFileForRead("SCT", filePath, file)) { return false; } @@ -110,12 +110,12 @@ bool Section::loadSectionFile(const int fontId, const float lineCompression, con // Your updated class method (assuming you are using the 'SD' object, which is a wrapper for a specific filesystem) bool Section::clearCache() const { - if (!SdMan.exists(filePath.c_str())) { + if (!Storage.exists(filePath.c_str())) { Serial.printf("[%lu] [SCT] Cache does not exist, no action needed\n", millis()); return true; } - if (!SdMan.remove(filePath.c_str())) { + if (!Storage.remove(filePath.c_str())) { Serial.printf("[%lu] [SCT] Failed to clear cache\n", millis()); return false; } @@ -134,7 +134,7 @@ bool Section::createSectionFile(const int fontId, const float lineCompression, c // Create cache directory if it doesn't exist { const auto sectionsDir = epub->getCachePath() + "/sections"; - SdMan.mkdir(sectionsDir.c_str()); + Storage.mkdir(sectionsDir.c_str()); } // Retry logic for SD card timing issues @@ -147,12 +147,12 @@ bool Section::createSectionFile(const int fontId, const float lineCompression, c } // Remove any incomplete file from previous attempt before retrying - if (SdMan.exists(tmpHtmlPath.c_str())) { - SdMan.remove(tmpHtmlPath.c_str()); + if (Storage.exists(tmpHtmlPath.c_str())) { + Storage.remove(tmpHtmlPath.c_str()); } FsFile tmpHtml; - if (!SdMan.openFileForWrite("SCT", tmpHtmlPath, tmpHtml)) { + if (!Storage.openFileForWrite("SCT", tmpHtmlPath, tmpHtml)) { continue; } success = epub->readItemContentsToStream(localPath, tmpHtml, 1024); @@ -160,8 +160,8 @@ bool Section::createSectionFile(const int fontId, const float lineCompression, c tmpHtml.close(); // If streaming failed, remove the incomplete file immediately - if (!success && SdMan.exists(tmpHtmlPath.c_str())) { - SdMan.remove(tmpHtmlPath.c_str()); + if (!success && Storage.exists(tmpHtmlPath.c_str())) { + Storage.remove(tmpHtmlPath.c_str()); Serial.printf("[%lu] [SCT] Removed incomplete temp file after failed attempt\n", millis()); } } @@ -173,7 +173,7 @@ bool Section::createSectionFile(const int fontId, const float lineCompression, c Serial.printf("[%lu] [SCT] Streamed temp HTML to %s (%d bytes)\n", millis(), tmpHtmlPath.c_str(), fileSize); - if (!SdMan.openFileForWrite("SCT", filePath, file)) { + if (!Storage.openFileForWrite("SCT", filePath, file)) { return false; } writeSectionFileHeader(fontId, lineCompression, extraParagraphSpacing, paragraphAlignment, viewportWidth, @@ -188,11 +188,11 @@ bool Section::createSectionFile(const int fontId, const float lineCompression, c Hyphenator::setPreferredLanguage(epub->getLanguage()); success = visitor.parseAndBuildPages(); - SdMan.remove(tmpHtmlPath.c_str()); + Storage.remove(tmpHtmlPath.c_str()); if (!success) { Serial.printf("[%lu] [SCT] Failed to parse XML and build pages\n", millis()); file.close(); - SdMan.remove(filePath.c_str()); + Storage.remove(filePath.c_str()); return false; } @@ -210,7 +210,7 @@ bool Section::createSectionFile(const int fontId, const float lineCompression, c if (hasFailedLutRecords) { Serial.printf("[%lu] [SCT] Failed to write LUT due to invalid page positions\n", millis()); file.close(); - SdMan.remove(filePath.c_str()); + Storage.remove(filePath.c_str()); return false; } @@ -223,7 +223,7 @@ bool Section::createSectionFile(const int fontId, const float lineCompression, c } std::unique_ptr Section::loadPageFromSectionFile() { - if (!SdMan.openFileForRead("SCT", filePath, file)) { + if (!Storage.openFileForRead("SCT", filePath, file)) { return nullptr; } diff --git a/lib/Epub/Epub/blocks/TextBlock.h b/lib/Epub/Epub/blocks/TextBlock.h index e233f77f1..059d136ab 100644 --- a/lib/Epub/Epub/blocks/TextBlock.h +++ b/lib/Epub/Epub/blocks/TextBlock.h @@ -1,6 +1,6 @@ #pragma once #include -#include +#include #include #include diff --git a/lib/Epub/Epub/css/CssParser.h b/lib/Epub/Epub/css/CssParser.h index 0e5a1b340..5605553d6 100644 --- a/lib/Epub/Epub/css/CssParser.h +++ b/lib/Epub/Epub/css/CssParser.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include diff --git a/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp b/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp index 043cfca7e..6022e0eef 100644 --- a/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp +++ b/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp @@ -1,8 +1,8 @@ #include "ChapterHtmlSlimParser.h" #include +#include #include -#include #include #include "../Page.h" @@ -482,7 +482,7 @@ bool ChapterHtmlSlimParser::parseAndBuildPages() { } FsFile file; - if (!SdMan.openFileForRead("EHP", filepath, file)) { + if (!Storage.openFileForRead("EHP", filepath, file)) { XML_ParserFree(parser); return false; } diff --git a/lib/Epub/Epub/parsers/ContentOpfParser.cpp b/lib/Epub/Epub/parsers/ContentOpfParser.cpp index c6cdec4e2..ae7e61a53 100644 --- a/lib/Epub/Epub/parsers/ContentOpfParser.cpp +++ b/lib/Epub/Epub/parsers/ContentOpfParser.cpp @@ -36,8 +36,8 @@ ContentOpfParser::~ContentOpfParser() { if (tempItemStore) { tempItemStore.close(); } - if (SdMan.exists((cachePath + itemCacheFile).c_str())) { - SdMan.remove((cachePath + itemCacheFile).c_str()); + if (Storage.exists((cachePath + itemCacheFile).c_str())) { + Storage.remove((cachePath + itemCacheFile).c_str()); } itemIndex.clear(); itemIndex.shrink_to_fit(); @@ -118,7 +118,7 @@ void XMLCALL ContentOpfParser::startElement(void* userData, const XML_Char* name if (self->state == IN_PACKAGE && (strcmp(name, "manifest") == 0 || strcmp(name, "opf:manifest") == 0)) { self->state = IN_MANIFEST; - if (!SdMan.openFileForWrite("COF", self->cachePath + itemCacheFile, self->tempItemStore)) { + if (!Storage.openFileForWrite("COF", self->cachePath + itemCacheFile, self->tempItemStore)) { Serial.printf( "[%lu] [COF] Couldn't open temp items file for writing. This is probably going to be a fatal error.\n", millis()); @@ -128,7 +128,7 @@ void XMLCALL ContentOpfParser::startElement(void* userData, const XML_Char* name if (self->state == IN_PACKAGE && (strcmp(name, "spine") == 0 || strcmp(name, "opf:spine") == 0)) { self->state = IN_SPINE; - if (!SdMan.openFileForRead("COF", self->cachePath + itemCacheFile, self->tempItemStore)) { + if (!Storage.openFileForRead("COF", self->cachePath + itemCacheFile, self->tempItemStore)) { Serial.printf( "[%lu] [COF] Couldn't open temp items file for reading. This is probably going to be a fatal error.\n", millis()); @@ -149,7 +149,7 @@ void XMLCALL ContentOpfParser::startElement(void* userData, const XML_Char* name self->state = IN_GUIDE; // TODO Remove print Serial.printf("[%lu] [COF] Entering guide state.\n", millis()); - if (!SdMan.openFileForRead("COF", self->cachePath + itemCacheFile, self->tempItemStore)) { + if (!Storage.openFileForRead("COF", self->cachePath + itemCacheFile, self->tempItemStore)) { Serial.printf( "[%lu] [COF] Couldn't open temp items file for reading. This is probably going to be a fatal error.\n", millis()); diff --git a/lib/GfxRenderer/Bitmap.h b/lib/GfxRenderer/Bitmap.h index 544869c19..102283de6 100644 --- a/lib/GfxRenderer/Bitmap.h +++ b/lib/GfxRenderer/Bitmap.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include diff --git a/lib/JpegToBmpConverter/JpegToBmpConverter.cpp b/lib/JpegToBmpConverter/JpegToBmpConverter.cpp index 0b1541b48..e21256612 100644 --- a/lib/JpegToBmpConverter/JpegToBmpConverter.cpp +++ b/lib/JpegToBmpConverter/JpegToBmpConverter.cpp @@ -1,7 +1,7 @@ #include "JpegToBmpConverter.h" +#include #include -#include #include #include diff --git a/lib/KOReaderSync/KOReaderCredentialStore.cpp b/lib/KOReaderSync/KOReaderCredentialStore.cpp index c57378093..01cb6c6bd 100644 --- a/lib/KOReaderSync/KOReaderCredentialStore.cpp +++ b/lib/KOReaderSync/KOReaderCredentialStore.cpp @@ -1,8 +1,8 @@ #include "KOReaderCredentialStore.h" +#include #include #include -#include #include // Initialize the static instance @@ -32,10 +32,10 @@ void KOReaderCredentialStore::obfuscate(std::string& data) const { bool KOReaderCredentialStore::saveToFile() const { // Make sure the directory exists - SdMan.mkdir("/.crosspoint"); + Storage.mkdir("/.crosspoint"); FsFile file; - if (!SdMan.openFileForWrite("KRS", KOREADER_FILE, file)) { + if (!Storage.openFileForWrite("KRS", KOREADER_FILE, file)) { return false; } @@ -64,7 +64,7 @@ bool KOReaderCredentialStore::saveToFile() const { bool KOReaderCredentialStore::loadFromFile() { FsFile file; - if (!SdMan.openFileForRead("KRS", KOREADER_FILE, file)) { + if (!Storage.openFileForRead("KRS", KOREADER_FILE, file)) { Serial.printf("[%lu] [KRS] No credentials file found\n", millis()); return false; } diff --git a/lib/KOReaderSync/KOReaderDocumentId.cpp b/lib/KOReaderSync/KOReaderDocumentId.cpp index b33beb754..4cc259ceb 100644 --- a/lib/KOReaderSync/KOReaderDocumentId.cpp +++ b/lib/KOReaderSync/KOReaderDocumentId.cpp @@ -1,8 +1,8 @@ #include "KOReaderDocumentId.h" +#include #include #include -#include namespace { // Extract filename from path (everything after last '/') @@ -43,7 +43,7 @@ size_t KOReaderDocumentId::getOffset(int i) { std::string KOReaderDocumentId::calculate(const std::string& filePath) { FsFile file; - if (!SdMan.openFileForRead("KODoc", filePath, file)) { + if (!Storage.openFileForRead("KODoc", filePath, file)) { Serial.printf("[%lu] [KODoc] Failed to open file: %s\n", millis(), filePath.c_str()); return ""; } diff --git a/lib/Serialization/Serialization.h b/lib/Serialization/Serialization.h index afea56466..1308822f8 100644 --- a/lib/Serialization/Serialization.h +++ b/lib/Serialization/Serialization.h @@ -1,5 +1,5 @@ #pragma once -#include +#include #include diff --git a/lib/Txt/Txt.cpp b/lib/Txt/Txt.cpp index 52c75ed7e..28bb9395a 100644 --- a/lib/Txt/Txt.cpp +++ b/lib/Txt/Txt.cpp @@ -15,13 +15,13 @@ bool Txt::load() { return true; } - if (!SdMan.exists(filepath.c_str())) { + if (!Storage.exists(filepath.c_str())) { Serial.printf("[%lu] [TXT] File does not exist: %s\n", millis(), filepath.c_str()); return false; } FsFile file; - if (!SdMan.openFileForRead("TXT", filepath, file)) { + if (!Storage.openFileForRead("TXT", filepath, file)) { Serial.printf("[%lu] [TXT] Failed to open file: %s\n", millis(), filepath.c_str()); return false; } @@ -48,11 +48,11 @@ std::string Txt::getTitle() const { } void Txt::setupCacheDir() const { - if (!SdMan.exists(cacheBasePath.c_str())) { - SdMan.mkdir(cacheBasePath.c_str()); + if (!Storage.exists(cacheBasePath.c_str())) { + Storage.mkdir(cacheBasePath.c_str()); } - if (!SdMan.exists(cachePath.c_str())) { - SdMan.mkdir(cachePath.c_str()); + if (!Storage.exists(cachePath.c_str())) { + Storage.mkdir(cachePath.c_str()); } } @@ -73,7 +73,7 @@ std::string Txt::findCoverImage() const { // First priority: look for image with same name as txt file (e.g., mybook.jpg) for (const auto& ext : extensions) { std::string coverPath = folder + "/" + baseName + ext; - if (SdMan.exists(coverPath.c_str())) { + if (Storage.exists(coverPath.c_str())) { Serial.printf("[%lu] [TXT] Found matching cover image: %s\n", millis(), coverPath.c_str()); return coverPath; } @@ -84,7 +84,7 @@ std::string Txt::findCoverImage() const { for (const auto& name : coverNames) { for (const auto& ext : extensions) { std::string coverPath = folder + "/" + std::string(name) + ext; - if (SdMan.exists(coverPath.c_str())) { + if (Storage.exists(coverPath.c_str())) { Serial.printf("[%lu] [TXT] Found fallback cover image: %s\n", millis(), coverPath.c_str()); return coverPath; } @@ -98,7 +98,7 @@ std::string Txt::getCoverBmpPath() const { return cachePath + "/cover.bmp"; } bool Txt::generateCoverBmp() const { // Already generated, return true - if (SdMan.exists(getCoverBmpPath().c_str())) { + if (Storage.exists(getCoverBmpPath().c_str())) { return true; } @@ -122,10 +122,10 @@ bool Txt::generateCoverBmp() const { // Copy BMP file to cache Serial.printf("[%lu] [TXT] Copying BMP cover image to cache\n", millis()); FsFile src, dst; - if (!SdMan.openFileForRead("TXT", coverImagePath, src)) { + if (!Storage.openFileForRead("TXT", coverImagePath, src)) { return false; } - if (!SdMan.openFileForWrite("TXT", getCoverBmpPath(), dst)) { + if (!Storage.openFileForWrite("TXT", getCoverBmpPath(), dst)) { src.close(); return false; } @@ -144,10 +144,10 @@ bool Txt::generateCoverBmp() const { // Convert JPG/JPEG to BMP (same approach as Epub) Serial.printf("[%lu] [TXT] Generating BMP from JPG cover image\n", millis()); FsFile coverJpg, coverBmp; - if (!SdMan.openFileForRead("TXT", coverImagePath, coverJpg)) { + if (!Storage.openFileForRead("TXT", coverImagePath, coverJpg)) { return false; } - if (!SdMan.openFileForWrite("TXT", getCoverBmpPath(), coverBmp)) { + if (!Storage.openFileForWrite("TXT", getCoverBmpPath(), coverBmp)) { coverJpg.close(); return false; } @@ -157,7 +157,7 @@ bool Txt::generateCoverBmp() const { if (!success) { Serial.printf("[%lu] [TXT] Failed to generate BMP from JPG cover image\n", millis()); - SdMan.remove(getCoverBmpPath().c_str()); + Storage.remove(getCoverBmpPath().c_str()); } else { Serial.printf("[%lu] [TXT] Generated BMP from JPG cover image\n", millis()); } @@ -175,7 +175,7 @@ bool Txt::readContent(uint8_t* buffer, size_t offset, size_t length) const { } FsFile file; - if (!SdMan.openFileForRead("TXT", filepath, file)) { + if (!Storage.openFileForRead("TXT", filepath, file)) { return false; } diff --git a/lib/Txt/Txt.h b/lib/Txt/Txt.h index b75c77385..b342ca881 100644 --- a/lib/Txt/Txt.h +++ b/lib/Txt/Txt.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include diff --git a/lib/Xtc/Xtc.cpp b/lib/Xtc/Xtc.cpp index 717bb6707..e01e4f0a0 100644 --- a/lib/Xtc/Xtc.cpp +++ b/lib/Xtc/Xtc.cpp @@ -7,8 +7,8 @@ #include "Xtc.h" +#include #include -#include bool Xtc::load() { Serial.printf("[%lu] [XTC] Loading XTC: %s\n", millis(), filepath.c_str()); @@ -30,12 +30,12 @@ bool Xtc::load() { } bool Xtc::clearCache() const { - if (!SdMan.exists(cachePath.c_str())) { + if (!Storage.exists(cachePath.c_str())) { Serial.printf("[%lu] [XTC] Cache does not exist, no action needed\n", millis()); return true; } - if (!SdMan.removeDir(cachePath.c_str())) { + if (!Storage.removeDir(cachePath.c_str())) { Serial.printf("[%lu] [XTC] Failed to clear cache\n", millis()); return false; } @@ -45,17 +45,17 @@ bool Xtc::clearCache() const { } void Xtc::setupCacheDir() const { - if (SdMan.exists(cachePath.c_str())) { + if (Storage.exists(cachePath.c_str())) { return; } // Create directories recursively for (size_t i = 1; i < cachePath.length(); i++) { if (cachePath[i] == '/') { - SdMan.mkdir(cachePath.substr(0, i).c_str()); + Storage.mkdir(cachePath.substr(0, i).c_str()); } } - SdMan.mkdir(cachePath.c_str()); + Storage.mkdir(cachePath.c_str()); } std::string Xtc::getTitle() const { @@ -114,7 +114,7 @@ std::string Xtc::getCoverBmpPath() const { return cachePath + "/cover.bmp"; } bool Xtc::generateCoverBmp() const { // Already generated - if (SdMan.exists(getCoverBmpPath().c_str())) { + if (Storage.exists(getCoverBmpPath().c_str())) { return true; } @@ -166,7 +166,7 @@ bool Xtc::generateCoverBmp() const { // Create BMP file FsFile coverBmp; - if (!SdMan.openFileForWrite("XTC", getCoverBmpPath(), coverBmp)) { + if (!Storage.openFileForWrite("XTC", getCoverBmpPath(), coverBmp)) { Serial.printf("[%lu] [XTC] Failed to create cover BMP file\n", millis()); free(pageBuffer); return false; @@ -306,7 +306,7 @@ std::string Xtc::getThumbBmpPath(int height) const { return cachePath + "/thumb_ bool Xtc::generateThumbBmp(int height) const { // Already generated - if (SdMan.exists(getThumbBmpPath(height).c_str())) { + if (Storage.exists(getThumbBmpPath(height).c_str())) { return true; } @@ -348,8 +348,8 @@ bool Xtc::generateThumbBmp(int height) const { // Copy cover.bmp to thumb.bmp if (generateCoverBmp()) { FsFile src, dst; - if (SdMan.openFileForRead("XTC", getCoverBmpPath(), src)) { - if (SdMan.openFileForWrite("XTC", getThumbBmpPath(height), dst)) { + if (Storage.openFileForRead("XTC", getCoverBmpPath(), src)) { + if (Storage.openFileForWrite("XTC", getThumbBmpPath(height), dst)) { uint8_t buffer[512]; while (src.available()) { size_t bytesRead = src.read(buffer, sizeof(buffer)); @@ -360,7 +360,7 @@ bool Xtc::generateThumbBmp(int height) const { src.close(); } Serial.printf("[%lu] [XTC] Copied cover to thumb (no scaling needed)\n", millis()); - return SdMan.exists(getThumbBmpPath(height).c_str()); + return Storage.exists(getThumbBmpPath(height).c_str()); } return false; } @@ -394,7 +394,7 @@ bool Xtc::generateThumbBmp(int height) const { // Create thumbnail BMP file - use 1-bit format for fast home screen rendering (no gray passes) FsFile thumbBmp; - if (!SdMan.openFileForWrite("XTC", getThumbBmpPath(height), thumbBmp)) { + if (!Storage.openFileForWrite("XTC", getThumbBmpPath(height), thumbBmp)) { Serial.printf("[%lu] [XTC] Failed to create thumb BMP file\n", millis()); free(pageBuffer); return false; diff --git a/lib/Xtc/Xtc/XtcParser.cpp b/lib/Xtc/Xtc/XtcParser.cpp index 8db3dead2..a604b645e 100644 --- a/lib/Xtc/Xtc/XtcParser.cpp +++ b/lib/Xtc/Xtc/XtcParser.cpp @@ -8,8 +8,8 @@ #include "XtcParser.h" #include +#include #include -#include #include @@ -34,7 +34,7 @@ XtcError XtcParser::open(const char* filepath) { } // Open file - if (!SdMan.openFileForRead("XTC", filepath, m_file)) { + if (!Storage.openFileForRead("XTC", filepath, m_file)) { m_lastError = XtcError::FILE_NOT_FOUND; return m_lastError; } @@ -444,7 +444,7 @@ XtcError XtcParser::loadPageStreaming(uint32_t pageIndex, bool XtcParser::isValidXtcFile(const char* filepath) { FsFile file; - if (!SdMan.openFileForRead("XTC", filepath, file)) { + if (!Storage.openFileForRead("XTC", filepath, file)) { return false; } diff --git a/lib/Xtc/Xtc/XtcParser.h b/lib/Xtc/Xtc/XtcParser.h index b00335424..19f3b75dc 100644 --- a/lib/Xtc/Xtc/XtcParser.h +++ b/lib/Xtc/Xtc/XtcParser.h @@ -7,7 +7,7 @@ #pragma once -#include +#include #include #include diff --git a/lib/ZipFile/ZipFile.cpp b/lib/ZipFile/ZipFile.cpp index a5f65ea33..a2e92762b 100644 --- a/lib/ZipFile/ZipFile.cpp +++ b/lib/ZipFile/ZipFile.cpp @@ -1,7 +1,7 @@ #include "ZipFile.h" +#include #include -#include #include #include @@ -279,7 +279,7 @@ bool ZipFile::loadZipDetails() { } bool ZipFile::open() { - if (!SdMan.openFileForRead("ZIP", filePath, file)) { + if (!Storage.openFileForRead("ZIP", filePath, file)) { return false; } return true; diff --git a/lib/ZipFile/ZipFile.h b/lib/ZipFile/ZipFile.h index 0c82e5a04..bc97559dd 100644 --- a/lib/ZipFile/ZipFile.h +++ b/lib/ZipFile/ZipFile.h @@ -1,5 +1,5 @@ #pragma once -#include +#include #include #include diff --git a/lib/hal/HalStorage.cpp b/lib/hal/HalStorage.cpp new file mode 100644 index 000000000..fa5d7f41a --- /dev/null +++ b/lib/hal/HalStorage.cpp @@ -0,0 +1,65 @@ +#include "HalStorage.h" + +#include + +#define SDCard SDCardManager::getInstance() + +HalStorage HalStorage::instance; + +HalStorage::HalStorage() {} + +bool HalStorage::begin() { return SDCard.begin(); } + +bool HalStorage::ready() const { return SDCard.ready(); } + +std::vector HalStorage::listFiles(const char* path, int maxFiles) { return SDCard.listFiles(path, maxFiles); } + +String HalStorage::readFile(const char* path) { return SDCard.readFile(path); } + +bool HalStorage::readFileToStream(const char* path, Print& out, size_t chunkSize) { + return SDCard.readFileToStream(path, out, chunkSize); +} + +size_t HalStorage::readFileToBuffer(const char* path, char* buffer, size_t bufferSize, size_t maxBytes) { + return SDCard.readFileToBuffer(path, buffer, bufferSize, maxBytes); +} + +bool HalStorage::writeFile(const char* path, const String& content) { return SDCard.writeFile(path, content); } + +bool HalStorage::ensureDirectoryExists(const char* path) { return SDCard.ensureDirectoryExists(path); } + +FsFile HalStorage::open(const char* path, const oflag_t oflag) { return SDCard.open(path, oflag); } + +bool HalStorage::mkdir(const char* path, const bool pFlag) { return SDCard.mkdir(path, pFlag); } + +bool HalStorage::exists(const char* path) { return SDCard.exists(path); } + +bool HalStorage::remove(const char* path) { return SDCard.remove(path); } + +bool HalStorage::rmdir(const char* path) { return SDCard.rmdir(path); } + +bool HalStorage::openFileForRead(const char* moduleName, const char* path, FsFile& file) { + return SDCard.openFileForRead(moduleName, path, file); +} + +bool HalStorage::openFileForRead(const char* moduleName, const std::string& path, FsFile& file) { + return openFileForRead(moduleName, path.c_str(), file); +} + +bool HalStorage::openFileForRead(const char* moduleName, const String& path, FsFile& file) { + return openFileForRead(moduleName, path.c_str(), file); +} + +bool HalStorage::openFileForWrite(const char* moduleName, const char* path, FsFile& file) { + return SDCard.openFileForWrite(moduleName, path, file); +} + +bool HalStorage::openFileForWrite(const char* moduleName, const std::string& path, FsFile& file) { + return openFileForWrite(moduleName, path.c_str(), file); +} + +bool HalStorage::openFileForWrite(const char* moduleName, const String& path, FsFile& file) { + return openFileForWrite(moduleName, path.c_str(), file); +} + +bool HalStorage::removeDir(const char* path) { return SDCard.removeDir(path); } \ No newline at end of file diff --git a/lib/hal/HalStorage.h b/lib/hal/HalStorage.h new file mode 100644 index 000000000..02f8eb448 --- /dev/null +++ b/lib/hal/HalStorage.h @@ -0,0 +1,54 @@ +#pragma once + +#include + +#include + +class HalStorage { + public: + HalStorage(); + bool begin(); + bool ready() const; + std::vector listFiles(const char* path = "/", int maxFiles = 200); + // Read the entire file at `path` into a String. Returns empty string on failure. + String readFile(const char* path); + // Low-memory helpers: + // Stream the file contents to a `Print` (e.g. `Serial`, or any `Print`-derived object). + // Returns true on success, false on failure. + bool readFileToStream(const char* path, Print& out, size_t chunkSize = 256); + // Read up to `bufferSize-1` bytes into `buffer`, null-terminating it. Returns bytes read. + size_t readFileToBuffer(const char* path, char* buffer, size_t bufferSize, size_t maxBytes = 0); + // Write a string to `path` on the SD card. Overwrites existing file. + // Returns true on success. + bool writeFile(const char* path, const String& content); + // Ensure a directory exists, creating it if necessary. Returns true on success. + bool ensureDirectoryExists(const char* path); + + FsFile open(const char* path, const oflag_t oflag = O_RDONLY); + bool mkdir(const char* path, const bool pFlag = true); + bool exists(const char* path); + bool remove(const char* path); + bool rmdir(const char* path); + + bool openFileForRead(const char* moduleName, const char* path, FsFile& file); + bool openFileForRead(const char* moduleName, const std::string& path, FsFile& file); + bool openFileForRead(const char* moduleName, const String& path, FsFile& file); + bool openFileForWrite(const char* moduleName, const char* path, FsFile& file); + bool openFileForWrite(const char* moduleName, const std::string& path, FsFile& file); + bool openFileForWrite(const char* moduleName, const String& path, FsFile& file); + bool removeDir(const char* path); + + static HalStorage& getInstance() { return instance; } + + private: + static HalStorage instance; + + bool initialized = false; +}; + +#define Storage HalStorage::getInstance() + +// Downstream code must use Storage instead of SdMan +#ifdef SdMan +#undef SdMan +#endif diff --git a/src/CrossPointSettings.cpp b/src/CrossPointSettings.cpp index 28a357e90..ffeef2b9f 100644 --- a/src/CrossPointSettings.cpp +++ b/src/CrossPointSettings.cpp @@ -1,7 +1,7 @@ #include "CrossPointSettings.h" +#include #include -#include #include #include @@ -79,10 +79,10 @@ void applyLegacyFrontButtonLayout(CrossPointSettings& settings) { bool CrossPointSettings::saveToFile() const { // Make sure the directory exists - SdMan.mkdir("/.crosspoint"); + Storage.mkdir("/.crosspoint"); FsFile outputFile; - if (!SdMan.openFileForWrite("CPS", SETTINGS_FILE, outputFile)) { + if (!Storage.openFileForWrite("CPS", SETTINGS_FILE, outputFile)) { return false; } @@ -127,7 +127,7 @@ bool CrossPointSettings::saveToFile() const { bool CrossPointSettings::loadFromFile() { FsFile inputFile; - if (!SdMan.openFileForRead("CPS", SETTINGS_FILE, inputFile)) { + if (!Storage.openFileForRead("CPS", SETTINGS_FILE, inputFile)) { return false; } diff --git a/src/CrossPointState.cpp b/src/CrossPointState.cpp index d97344f22..5ca3cb45c 100644 --- a/src/CrossPointState.cpp +++ b/src/CrossPointState.cpp @@ -1,7 +1,7 @@ #include "CrossPointState.h" +#include #include -#include #include namespace { @@ -13,7 +13,7 @@ CrossPointState CrossPointState::instance; bool CrossPointState::saveToFile() const { FsFile outputFile; - if (!SdMan.openFileForWrite("CPS", STATE_FILE, outputFile)) { + if (!Storage.openFileForWrite("CPS", STATE_FILE, outputFile)) { return false; } @@ -28,7 +28,7 @@ bool CrossPointState::saveToFile() const { bool CrossPointState::loadFromFile() { FsFile inputFile; - if (!SdMan.openFileForRead("CPS", STATE_FILE, inputFile)) { + if (!Storage.openFileForRead("CPS", STATE_FILE, inputFile)) { return false; } diff --git a/src/RecentBooksStore.cpp b/src/RecentBooksStore.cpp index 99586b79c..9885fcdb6 100644 --- a/src/RecentBooksStore.cpp +++ b/src/RecentBooksStore.cpp @@ -1,8 +1,8 @@ #include "RecentBooksStore.h" #include +#include #include -#include #include #include @@ -53,10 +53,10 @@ void RecentBooksStore::updateBook(const std::string& path, const std::string& ti bool RecentBooksStore::saveToFile() const { // Make sure the directory exists - SdMan.mkdir("/.crosspoint"); + Storage.mkdir("/.crosspoint"); FsFile outputFile; - if (!SdMan.openFileForWrite("RBS", RECENT_BOOKS_FILE, outputFile)) { + if (!Storage.openFileForWrite("RBS", RECENT_BOOKS_FILE, outputFile)) { return false; } @@ -106,7 +106,7 @@ RecentBook RecentBooksStore::getDataFromBook(std::string path) const { bool RecentBooksStore::loadFromFile() { FsFile inputFile; - if (!SdMan.openFileForRead("RBS", RECENT_BOOKS_FILE, inputFile)) { + if (!Storage.openFileForRead("RBS", RECENT_BOOKS_FILE, inputFile)) { return false; } diff --git a/src/WifiCredentialStore.cpp b/src/WifiCredentialStore.cpp index be865b86a..59c3a7d35 100644 --- a/src/WifiCredentialStore.cpp +++ b/src/WifiCredentialStore.cpp @@ -1,7 +1,7 @@ #include "WifiCredentialStore.h" +#include #include -#include #include // Initialize the static instance @@ -29,10 +29,10 @@ void WifiCredentialStore::obfuscate(std::string& data) const { bool WifiCredentialStore::saveToFile() const { // Make sure the directory exists - SdMan.mkdir("/.crosspoint"); + Storage.mkdir("/.crosspoint"); FsFile file; - if (!SdMan.openFileForWrite("WCS", WIFI_FILE, file)) { + if (!Storage.openFileForWrite("WCS", WIFI_FILE, file)) { return false; } @@ -60,7 +60,7 @@ bool WifiCredentialStore::saveToFile() const { bool WifiCredentialStore::loadFromFile() { FsFile file; - if (!SdMan.openFileForRead("WCS", WIFI_FILE, file)) { + if (!Storage.openFileForRead("WCS", WIFI_FILE, file)) { return false; } diff --git a/src/activities/boot_sleep/SleepActivity.cpp b/src/activities/boot_sleep/SleepActivity.cpp index 81b55cc67..846df22d8 100644 --- a/src/activities/boot_sleep/SleepActivity.cpp +++ b/src/activities/boot_sleep/SleepActivity.cpp @@ -2,7 +2,7 @@ #include #include -#include +#include #include #include @@ -32,7 +32,7 @@ void SleepActivity::onEnter() { void SleepActivity::renderCustomSleepScreen() const { // Check if we have a /sleep directory - auto dir = SdMan.open("/sleep"); + auto dir = Storage.open("/sleep"); if (dir && dir.isDirectory()) { std::vector files; char name[500]; @@ -75,7 +75,7 @@ void SleepActivity::renderCustomSleepScreen() const { APP_STATE.saveToFile(); const auto filename = "/sleep/" + files[randomFileIndex]; FsFile file; - if (SdMan.openFileForRead("SLP", filename, file)) { + if (Storage.openFileForRead("SLP", filename, file)) { Serial.printf("[%lu] [SLP] Randomly loading: /sleep/%s\n", millis(), files[randomFileIndex].c_str()); delay(100); Bitmap bitmap(file, true); @@ -92,7 +92,7 @@ void SleepActivity::renderCustomSleepScreen() const { // Look for sleep.bmp on the root of the sd card to determine if we should // render a custom sleep screen instead of the default. FsFile file; - if (SdMan.openFileForRead("SLP", "/sleep.bmp", file)) { + if (Storage.openFileForRead("SLP", "/sleep.bmp", file)) { Bitmap bitmap(file, true); if (bitmap.parseHeaders() == BmpReaderError::Ok) { Serial.printf("[%lu] [SLP] Loading: /sleep.bmp\n", millis()); @@ -262,7 +262,7 @@ void SleepActivity::renderCoverSleepScreen() const { } FsFile file; - if (SdMan.openFileForRead("SLP", coverBmpPath, file)) { + if (Storage.openFileForRead("SLP", coverBmpPath, file)) { Bitmap bitmap(file); if (bitmap.parseHeaders() == BmpReaderError::Ok) { Serial.printf("[SLP] Rendering sleep cover: %s\n", coverBmpPath.c_str()); diff --git a/src/activities/home/HomeActivity.cpp b/src/activities/home/HomeActivity.cpp index 15a59bfc2..4155799c8 100644 --- a/src/activities/home/HomeActivity.cpp +++ b/src/activities/home/HomeActivity.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #include @@ -47,7 +47,7 @@ void HomeActivity::loadRecentBooks(int maxBooks) { } // Skip if file no longer exists - if (!SdMan.exists(book.path.c_str())) { + if (!Storage.exists(book.path.c_str())) { continue; } @@ -64,7 +64,7 @@ void HomeActivity::loadRecentCovers(int coverHeight) { for (RecentBook& book : recentBooks) { if (!book.coverBmpPath.empty()) { std::string coverPath = UITheme::getCoverThumbPath(book.coverBmpPath, coverHeight); - if (!SdMan.exists(coverPath.c_str())) { + if (!Storage.exists(coverPath.c_str())) { // If epub, try to load the metadata for title/author and cover if (StringUtils::checkFileExtension(book.path, ".epub")) { Epub epub(book.path, "/.crosspoint"); diff --git a/src/activities/home/MyLibraryActivity.cpp b/src/activities/home/MyLibraryActivity.cpp index 7523e5428..e0a36b979 100644 --- a/src/activities/home/MyLibraryActivity.cpp +++ b/src/activities/home/MyLibraryActivity.cpp @@ -1,7 +1,7 @@ #include "MyLibraryActivity.h" #include -#include +#include #include @@ -33,7 +33,7 @@ void MyLibraryActivity::taskTrampoline(void* param) { void MyLibraryActivity::loadFiles() { files.clear(); - auto root = SdMan.open(basepath.c_str()); + auto root = Storage.open(basepath.c_str()); if (!root || !root.isDirectory()) { if (root) root.close(); return; diff --git a/src/activities/home/RecentBooksActivity.cpp b/src/activities/home/RecentBooksActivity.cpp index 1be0e1e0c..4add9b842 100644 --- a/src/activities/home/RecentBooksActivity.cpp +++ b/src/activities/home/RecentBooksActivity.cpp @@ -1,7 +1,7 @@ #include "RecentBooksActivity.h" #include -#include +#include #include @@ -28,7 +28,7 @@ void RecentBooksActivity::loadRecentBooks() { for (const auto& book : books) { // Skip if file no longer exists - if (!SdMan.exists(book.path.c_str())) { + if (!Storage.exists(book.path.c_str())) { continue; } recentBooks.push_back(book); diff --git a/src/activities/reader/EpubReaderActivity.cpp b/src/activities/reader/EpubReaderActivity.cpp index cd045c8e4..fb68d62b3 100644 --- a/src/activities/reader/EpubReaderActivity.cpp +++ b/src/activities/reader/EpubReaderActivity.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include "CrossPointSettings.h" #include "CrossPointState.h" @@ -77,7 +77,7 @@ void EpubReaderActivity::onEnter() { epub->setupCacheDir(); FsFile f; - if (SdMan.openFileForRead("ERS", epub->getCachePath() + "/progress.bin", f)) { + if (Storage.openFileForRead("ERS", epub->getCachePath() + "/progress.bin", f)) { uint8_t data[6]; int dataSize = f.read(data, 6); if (dataSize == 4 || dataSize == 6) { @@ -654,7 +654,7 @@ void EpubReaderActivity::renderScreen() { void EpubReaderActivity::saveProgress(int spineIndex, int currentPage, int pageCount) { FsFile f; - if (SdMan.openFileForWrite("ERS", epub->getCachePath() + "/progress.bin", f)) { + if (Storage.openFileForWrite("ERS", epub->getCachePath() + "/progress.bin", f)) { uint8_t data[6]; data[0] = currentSpineIndex & 0xFF; data[1] = (currentSpineIndex >> 8) & 0xFF; diff --git a/src/activities/reader/ReaderActivity.cpp b/src/activities/reader/ReaderActivity.cpp index 0b004f349..dd3ea2e9d 100644 --- a/src/activities/reader/ReaderActivity.cpp +++ b/src/activities/reader/ReaderActivity.cpp @@ -1,5 +1,7 @@ #include "ReaderActivity.h" +#include + #include "Epub.h" #include "EpubReaderActivity.h" #include "Txt.h" @@ -27,7 +29,7 @@ bool ReaderActivity::isTxtFile(const std::string& path) { } std::unique_ptr ReaderActivity::loadEpub(const std::string& path) { - if (!SdMan.exists(path.c_str())) { + if (!Storage.exists(path.c_str())) { Serial.printf("[%lu] [ ] File does not exist: %s\n", millis(), path.c_str()); return nullptr; } @@ -42,7 +44,7 @@ std::unique_ptr ReaderActivity::loadEpub(const std::string& path) { } std::unique_ptr ReaderActivity::loadXtc(const std::string& path) { - if (!SdMan.exists(path.c_str())) { + if (!Storage.exists(path.c_str())) { Serial.printf("[%lu] [ ] File does not exist: %s\n", millis(), path.c_str()); return nullptr; } @@ -57,7 +59,7 @@ std::unique_ptr ReaderActivity::loadXtc(const std::string& path) { } std::unique_ptr ReaderActivity::loadTxt(const std::string& path) { - if (!SdMan.exists(path.c_str())) { + if (!Storage.exists(path.c_str())) { Serial.printf("[%lu] [ ] File does not exist: %s\n", millis(), path.c_str()); return nullptr; } diff --git a/src/activities/reader/TxtReaderActivity.cpp b/src/activities/reader/TxtReaderActivity.cpp index 2032518a6..441d5700d 100644 --- a/src/activities/reader/TxtReaderActivity.cpp +++ b/src/activities/reader/TxtReaderActivity.cpp @@ -1,7 +1,7 @@ #include "TxtReaderActivity.h" #include -#include +#include #include #include @@ -565,7 +565,7 @@ void TxtReaderActivity::renderStatusBar(const int orientedMarginRight, const int void TxtReaderActivity::saveProgress() const { FsFile f; - if (SdMan.openFileForWrite("TRS", txt->getCachePath() + "/progress.bin", f)) { + if (Storage.openFileForWrite("TRS", txt->getCachePath() + "/progress.bin", f)) { uint8_t data[4]; data[0] = currentPage & 0xFF; data[1] = (currentPage >> 8) & 0xFF; @@ -578,7 +578,7 @@ void TxtReaderActivity::saveProgress() const { void TxtReaderActivity::loadProgress() { FsFile f; - if (SdMan.openFileForRead("TRS", txt->getCachePath() + "/progress.bin", f)) { + if (Storage.openFileForRead("TRS", txt->getCachePath() + "/progress.bin", f)) { uint8_t data[4]; if (f.read(data, 4) == 4) { currentPage = data[0] + (data[1] << 8); @@ -609,7 +609,7 @@ bool TxtReaderActivity::loadPageIndexCache() { std::string cachePath = txt->getCachePath() + "/index.bin"; FsFile f; - if (!SdMan.openFileForRead("TRS", cachePath, f)) { + if (!Storage.openFileForRead("TRS", cachePath, f)) { Serial.printf("[%lu] [TRS] No page index cache found\n", millis()); return false; } @@ -701,7 +701,7 @@ bool TxtReaderActivity::loadPageIndexCache() { void TxtReaderActivity::savePageIndexCache() const { std::string cachePath = txt->getCachePath() + "/index.bin"; FsFile f; - if (!SdMan.openFileForWrite("TRS", cachePath, f)) { + if (!Storage.openFileForWrite("TRS", cachePath, f)) { Serial.printf("[%lu] [TRS] Failed to save page index cache\n", millis()); return; } diff --git a/src/activities/reader/XtcReaderActivity.cpp b/src/activities/reader/XtcReaderActivity.cpp index c28f6f441..31795fa82 100644 --- a/src/activities/reader/XtcReaderActivity.cpp +++ b/src/activities/reader/XtcReaderActivity.cpp @@ -9,7 +9,7 @@ #include #include -#include +#include #include "CrossPointSettings.h" #include "CrossPointState.h" @@ -372,7 +372,7 @@ void XtcReaderActivity::renderPage() { void XtcReaderActivity::saveProgress() const { FsFile f; - if (SdMan.openFileForWrite("XTR", xtc->getCachePath() + "/progress.bin", f)) { + if (Storage.openFileForWrite("XTR", xtc->getCachePath() + "/progress.bin", f)) { uint8_t data[4]; data[0] = currentPage & 0xFF; data[1] = (currentPage >> 8) & 0xFF; @@ -385,7 +385,7 @@ void XtcReaderActivity::saveProgress() const { void XtcReaderActivity::loadProgress() { FsFile f; - if (SdMan.openFileForRead("XTR", xtc->getCachePath() + "/progress.bin", f)) { + if (Storage.openFileForRead("XTR", xtc->getCachePath() + "/progress.bin", f)) { uint8_t data[4]; if (f.read(data, 4) == 4) { currentPage = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24); diff --git a/src/activities/settings/ClearCacheActivity.cpp b/src/activities/settings/ClearCacheActivity.cpp index f00472b17..b17627dc6 100644 --- a/src/activities/settings/ClearCacheActivity.cpp +++ b/src/activities/settings/ClearCacheActivity.cpp @@ -1,8 +1,8 @@ #include "ClearCacheActivity.h" #include +#include #include -#include #include "MappedInputManager.h" #include "components/UITheme.h" @@ -107,7 +107,7 @@ void ClearCacheActivity::clearCache() { Serial.printf("[%lu] [CLEAR_CACHE] Clearing cache...\n", millis()); // Open .crosspoint directory - auto root = SdMan.open("/.crosspoint"); + auto root = Storage.open("/.crosspoint"); if (!root || !root.isDirectory()) { Serial.printf("[%lu] [CLEAR_CACHE] Failed to open cache directory\n", millis()); if (root) root.close(); @@ -132,7 +132,7 @@ void ClearCacheActivity::clearCache() { file.close(); // Close before attempting to delete - if (SdMan.removeDir(fullPath.c_str())) { + if (Storage.removeDir(fullPath.c_str())) { clearedCount++; } else { Serial.printf("[%lu] [CLEAR_CACHE] Failed to remove: %s\n", millis(), fullPath.c_str()); diff --git a/src/components/themes/BaseTheme.cpp b/src/components/themes/BaseTheme.cpp index 9253953e5..14783e558 100644 --- a/src/components/themes/BaseTheme.cpp +++ b/src/components/themes/BaseTheme.cpp @@ -1,7 +1,7 @@ #include "BaseTheme.h" #include -#include +#include #include #include @@ -308,7 +308,7 @@ void BaseTheme::drawRecentBookCover(GfxRenderer& renderer, Rect rect, const std: // First time: load cover from SD and render FsFile file; - if (SdMan.openFileForRead("HOME", coverBmpPath, file)) { + if (Storage.openFileForRead("HOME", coverBmpPath, file)) { Bitmap bitmap(file); if (bitmap.parseHeaders() == BmpReaderError::Ok) { Serial.printf("Rendering bmp\n"); diff --git a/src/components/themes/lyra/LyraTheme.cpp b/src/components/themes/lyra/LyraTheme.cpp index c07e7a5f3..2e3ad4cd8 100644 --- a/src/components/themes/lyra/LyraTheme.cpp +++ b/src/components/themes/lyra/LyraTheme.cpp @@ -1,7 +1,7 @@ #include "LyraTheme.h" #include -#include +#include #include #include @@ -283,7 +283,7 @@ void LyraTheme::drawRecentBookCover(GfxRenderer& renderer, Rect rect, const std: // First time: load cover from SD and render FsFile file; - if (SdMan.openFileForRead("HOME", coverBmpPath, file)) { + if (Storage.openFileForRead("HOME", coverBmpPath, file)) { Bitmap bitmap(file); if (bitmap.parseHeaders() == BmpReaderError::Ok) { float coverHeight = static_cast(bitmap.getHeight()); diff --git a/src/main.cpp b/src/main.cpp index 4895be383..33515bce9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #include @@ -293,7 +293,7 @@ void setup() { // SD Card Initialization // We need 6 open files concurrently when parsing a new chapter - if (!SdMan.begin()) { + if (!Storage.begin()) { Serial.printf("[%lu] [ ] SD card initialization failed\n", millis()); setupDisplayAndFonts(); exitActivity(); diff --git a/src/network/CrossPointWebServer.cpp b/src/network/CrossPointWebServer.cpp index 6a0c2e863..d29edb5a9 100644 --- a/src/network/CrossPointWebServer.cpp +++ b/src/network/CrossPointWebServer.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #include @@ -316,7 +316,7 @@ void CrossPointWebServer::handleStatus() const { } void CrossPointWebServer::scanFiles(const char* path, const std::function& callback) const { - FsFile root = SdMan.open(path); + FsFile root = Storage.open(path); if (!root) { Serial.printf("[%lu] [WEB] Failed to open directory: %s\n", millis(), path); return; @@ -458,12 +458,12 @@ void CrossPointWebServer::handleDownload() const { } } - if (!SdMan.exists(itemPath.c_str())) { + if (!Storage.exists(itemPath.c_str())) { server->send(404, "text/plain", "Item not found"); return; } - FsFile file = SdMan.open(itemPath.c_str()); + FsFile file = Storage.open(itemPath.c_str()); if (!file) { server->send(500, "text/plain", "Failed to open file"); return; @@ -574,15 +574,15 @@ void CrossPointWebServer::handleUpload(UploadState& state) const { // Check if file already exists - SD operations can be slow esp_task_wdt_reset(); - if (SdMan.exists(filePath.c_str())) { + if (Storage.exists(filePath.c_str())) { Serial.printf("[%lu] [WEB] [UPLOAD] Overwriting existing file: %s\n", millis(), filePath.c_str()); esp_task_wdt_reset(); - SdMan.remove(filePath.c_str()); + Storage.remove(filePath.c_str()); } // Open file for writing - this can be slow due to FAT cluster allocation esp_task_wdt_reset(); - if (!SdMan.openFileForWrite("WEB", filePath, state.file)) { + if (!Storage.openFileForWrite("WEB", filePath, state.file)) { state.error = "Failed to create file on SD card"; Serial.printf("[%lu] [WEB] [UPLOAD] FAILED to create file: %s\n", millis(), filePath.c_str()); return; @@ -660,7 +660,7 @@ void CrossPointWebServer::handleUpload(UploadState& state) const { String filePath = state.path; if (!filePath.endsWith("/")) filePath += "/"; filePath += state.fileName; - SdMan.remove(filePath.c_str()); + Storage.remove(filePath.c_str()); } state.error = "Upload aborted"; Serial.printf("[%lu] [WEB] Upload aborted\n", millis()); @@ -711,13 +711,13 @@ void CrossPointWebServer::handleCreateFolder() const { Serial.printf("[%lu] [WEB] Creating folder: %s\n", millis(), folderPath.c_str()); // Check if already exists - if (SdMan.exists(folderPath.c_str())) { + if (Storage.exists(folderPath.c_str())) { server->send(400, "text/plain", "Folder already exists"); return; } // Create the folder - if (SdMan.mkdir(folderPath.c_str())) { + if (Storage.mkdir(folderPath.c_str())) { Serial.printf("[%lu] [WEB] Folder created successfully: %s\n", millis(), folderPath.c_str()); server->send(200, "text/plain", "Folder created: " + folderName); } else { @@ -763,12 +763,12 @@ void CrossPointWebServer::handleRename() const { return; } - if (!SdMan.exists(itemPath.c_str())) { + if (!Storage.exists(itemPath.c_str())) { server->send(404, "text/plain", "Item not found"); return; } - FsFile file = SdMan.open(itemPath.c_str()); + FsFile file = Storage.open(itemPath.c_str()); if (!file) { server->send(500, "text/plain", "Failed to open file"); return; @@ -789,7 +789,7 @@ void CrossPointWebServer::handleRename() const { } newPath += newName; - if (SdMan.exists(newPath.c_str())) { + if (Storage.exists(newPath.c_str())) { file.close(); server->send(409, "text/plain", "Target already exists"); return; @@ -839,12 +839,12 @@ void CrossPointWebServer::handleMove() const { } } - if (!SdMan.exists(itemPath.c_str())) { + if (!Storage.exists(itemPath.c_str())) { server->send(404, "text/plain", "Item not found"); return; } - FsFile file = SdMan.open(itemPath.c_str()); + FsFile file = Storage.open(itemPath.c_str()); if (!file) { server->send(500, "text/plain", "Failed to open file"); return; @@ -855,12 +855,12 @@ void CrossPointWebServer::handleMove() const { return; } - if (!SdMan.exists(destPath.c_str())) { + if (!Storage.exists(destPath.c_str())) { file.close(); server->send(404, "text/plain", "Destination not found"); return; } - FsFile destDir = SdMan.open(destPath.c_str()); + FsFile destDir = Storage.open(destPath.c_str()); if (!destDir || !destDir.isDirectory()) { if (destDir) { destDir.close(); @@ -882,7 +882,7 @@ void CrossPointWebServer::handleMove() const { server->send(200, "text/plain", "Already in destination"); return; } - if (SdMan.exists(newPath.c_str())) { + if (Storage.exists(newPath.c_str())) { file.close(); server->send(409, "text/plain", "Target already exists"); return; @@ -942,7 +942,7 @@ void CrossPointWebServer::handleDelete() const { } // Check if item exists - if (!SdMan.exists(itemPath.c_str())) { + if (!Storage.exists(itemPath.c_str())) { Serial.printf("[%lu] [WEB] Delete failed - item not found: %s\n", millis(), itemPath.c_str()); server->send(404, "text/plain", "Item not found"); return; @@ -954,7 +954,7 @@ void CrossPointWebServer::handleDelete() const { if (itemType == "folder") { // For folders, try to remove (will fail if not empty) - FsFile dir = SdMan.open(itemPath.c_str()); + FsFile dir = Storage.open(itemPath.c_str()); if (dir && dir.isDirectory()) { // Check if folder is empty FsFile entry = dir.openNextFile(); @@ -968,10 +968,10 @@ void CrossPointWebServer::handleDelete() const { } dir.close(); } - success = SdMan.rmdir(itemPath.c_str()); + success = Storage.rmdir(itemPath.c_str()); } else { // For files, use remove - success = SdMan.remove(itemPath.c_str()); + success = Storage.remove(itemPath.c_str()); } if (success) { @@ -1007,7 +1007,7 @@ void CrossPointWebServer::onWebSocketEvent(uint8_t num, WStype_t type, uint8_t* String filePath = wsUploadPath; if (!filePath.endsWith("/")) filePath += "/"; filePath += wsUploadFileName; - SdMan.remove(filePath.c_str()); + Storage.remove(filePath.c_str()); Serial.printf("[%lu] [WS] Deleted incomplete upload: %s\n", millis(), filePath.c_str()); } wsUploadInProgress = false; @@ -1051,13 +1051,13 @@ void CrossPointWebServer::onWebSocketEvent(uint8_t num, WStype_t type, uint8_t* // Check if file exists and remove it esp_task_wdt_reset(); - if (SdMan.exists(filePath.c_str())) { - SdMan.remove(filePath.c_str()); + if (Storage.exists(filePath.c_str())) { + Storage.remove(filePath.c_str()); } // Open file for writing esp_task_wdt_reset(); - if (!SdMan.openFileForWrite("WS", filePath, wsUploadFile)) { + if (!Storage.openFileForWrite("WS", filePath, wsUploadFile)) { wsServer->sendTXT(num, "ERROR:Failed to create file"); wsUploadInProgress = false; return; diff --git a/src/network/CrossPointWebServer.h b/src/network/CrossPointWebServer.h index f7bc85860..db318d0a1 100644 --- a/src/network/CrossPointWebServer.h +++ b/src/network/CrossPointWebServer.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include #include diff --git a/src/network/HttpDownloader.cpp b/src/network/HttpDownloader.cpp index b7718c2d9..8ca07b2b4 100644 --- a/src/network/HttpDownloader.cpp +++ b/src/network/HttpDownloader.cpp @@ -100,13 +100,13 @@ HttpDownloader::DownloadError HttpDownloader::downloadToFile(const std::string& Serial.printf("[%lu] [HTTP] Content-Length: %zu\n", millis(), contentLength); // Remove existing file if present - if (SdMan.exists(destPath.c_str())) { - SdMan.remove(destPath.c_str()); + if (Storage.exists(destPath.c_str())) { + Storage.remove(destPath.c_str()); } // Open file for writing FsFile file; - if (!SdMan.openFileForWrite("HTTP", destPath.c_str(), file)) { + if (!Storage.openFileForWrite("HTTP", destPath.c_str(), file)) { Serial.printf("[%lu] [HTTP] Failed to open file for writing\n", millis()); http.end(); return FILE_ERROR; @@ -117,7 +117,7 @@ HttpDownloader::DownloadError HttpDownloader::downloadToFile(const std::string& if (!stream) { Serial.printf("[%lu] [HTTP] Failed to get stream\n", millis()); file.close(); - SdMan.remove(destPath.c_str()); + Storage.remove(destPath.c_str()); http.end(); return HTTP_ERROR; } @@ -145,7 +145,7 @@ HttpDownloader::DownloadError HttpDownloader::downloadToFile(const std::string& if (written != bytesRead) { Serial.printf("[%lu] [HTTP] Write failed: wrote %zu of %zu bytes\n", millis(), written, bytesRead); file.close(); - SdMan.remove(destPath.c_str()); + Storage.remove(destPath.c_str()); http.end(); return FILE_ERROR; } @@ -165,7 +165,7 @@ HttpDownloader::DownloadError HttpDownloader::downloadToFile(const std::string& // Verify download size if known if (contentLength > 0 && downloaded != contentLength) { Serial.printf("[%lu] [HTTP] Size mismatch: got %zu, expected %zu\n", millis(), downloaded, contentLength); - SdMan.remove(destPath.c_str()); + Storage.remove(destPath.c_str()); return HTTP_ERROR; } diff --git a/src/network/HttpDownloader.h b/src/network/HttpDownloader.h index ac520a42a..fd18dd4cb 100644 --- a/src/network/HttpDownloader.h +++ b/src/network/HttpDownloader.h @@ -1,5 +1,5 @@ #pragma once -#include +#include #include #include