#pragma once #include #include #include struct CacheEntry { std::string key; /* hex hash of the URL */ std::string url; std::string path; /* full SD card path */ size_t size; /* file size in bytes, 0 if unknown */ }; class CacheManager { public: CacheManager(); /* Returns the SD-card path for url if cached, or empty string if not. */ std::string getCachedPath(const std::string& url) const; /* Enqueue an async FreeRTOS task that downloads url and caches it. * onComplete is called (from the download task) when done or on error. */ void downloadAsync(const std::string& url, std::function onComplete = nullptr); /* List all cached entries. */ std::vector listEntries() const; /* Delete a single cache entry by key (hex hash). Returns true if deleted. */ bool deleteEntry(const std::string& key); /* Delete the entire cache directory. */ void deleteAll(); /* Total bytes used by cache. */ size_t totalBytes() const; private: static constexpr const char* CACHE_DIR = "/sdcard/cache"; std::string urlToKey(const std::string& url) const; std::string urlExtension(const std::string& url) const; std::string keyToPath(const std::string& key, const std::string& ext) const; std::string findFileByKey(const std::string& key) const; static void downloadTask(void* arg); };