Add txt_* prefix to the directory check so TXT book caches are also removed. After clearing all cache directories, call RECENT_BOOKS.clear() to remove stale entries that would show missing covers on the home screen. Co-authored-by: Cursor <cursoragent@cursor.com>
153 lines
4.8 KiB
C++
153 lines
4.8 KiB
C++
#include "ClearCacheActivity.h"
|
|
|
|
#include <GfxRenderer.h>
|
|
#include <HalStorage.h>
|
|
#include <I18n.h>
|
|
#include <Logging.h>
|
|
|
|
#include "MappedInputManager.h"
|
|
#include "RecentBooksStore.h"
|
|
#include "components/UITheme.h"
|
|
#include "fontIds.h"
|
|
|
|
void ClearCacheActivity::onEnter() {
|
|
ActivityWithSubactivity::onEnter();
|
|
|
|
state = WARNING;
|
|
requestUpdate();
|
|
}
|
|
|
|
void ClearCacheActivity::onExit() { ActivityWithSubactivity::onExit(); }
|
|
|
|
void ClearCacheActivity::render(Activity::RenderLock&&) {
|
|
auto metrics = UITheme::getInstance().getMetrics();
|
|
const auto pageWidth = renderer.getScreenWidth();
|
|
const auto pageHeight = renderer.getScreenHeight();
|
|
|
|
renderer.clearScreen();
|
|
|
|
GUI.drawHeader(renderer, Rect{0, metrics.topPadding, pageWidth, metrics.headerHeight}, tr(STR_CLEAR_READING_CACHE));
|
|
|
|
if (state == WARNING) {
|
|
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2 - 60, tr(STR_CLEAR_CACHE_WARNING_1), true);
|
|
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2 - 30, tr(STR_CLEAR_CACHE_WARNING_2), true,
|
|
EpdFontFamily::BOLD);
|
|
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2 + 10, tr(STR_CLEAR_CACHE_WARNING_3), true);
|
|
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2 + 30, tr(STR_CLEAR_CACHE_WARNING_4), true);
|
|
|
|
const auto labels = mappedInput.mapLabels(tr(STR_CANCEL), tr(STR_CLEAR_BUTTON), "", "");
|
|
GUI.drawButtonHints(renderer, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
|
|
renderer.displayBuffer();
|
|
return;
|
|
}
|
|
|
|
if (state == CLEARING) {
|
|
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2, tr(STR_CLEARING_CACHE));
|
|
renderer.displayBuffer();
|
|
return;
|
|
}
|
|
|
|
if (state == SUCCESS) {
|
|
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2 - 20, tr(STR_CACHE_CLEARED), true, EpdFontFamily::BOLD);
|
|
std::string resultText = std::to_string(clearedCount) + " " + std::string(tr(STR_ITEMS_REMOVED));
|
|
if (failedCount > 0) {
|
|
resultText += ", " + std::to_string(failedCount) + " " + std::string(tr(STR_FAILED_LOWER));
|
|
}
|
|
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2 + 10, resultText.c_str());
|
|
|
|
const auto labels = mappedInput.mapLabels(tr(STR_BACK), "", "", "");
|
|
GUI.drawButtonHints(renderer, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
|
|
renderer.displayBuffer();
|
|
return;
|
|
}
|
|
|
|
if (state == FAILED) {
|
|
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2 - 20, tr(STR_CLEAR_CACHE_FAILED), true,
|
|
EpdFontFamily::BOLD);
|
|
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2 + 10, tr(STR_CHECK_SERIAL_OUTPUT));
|
|
|
|
const auto labels = mappedInput.mapLabels(tr(STR_BACK), "", "", "");
|
|
GUI.drawButtonHints(renderer, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
|
|
renderer.displayBuffer();
|
|
return;
|
|
}
|
|
}
|
|
|
|
void ClearCacheActivity::clearCache() {
|
|
LOG_DBG("CLEAR_CACHE", "Clearing cache...");
|
|
|
|
// Open .crosspoint directory
|
|
auto root = Storage.open("/.crosspoint");
|
|
if (!root || !root.isDirectory()) {
|
|
LOG_DBG("CLEAR_CACHE", "Failed to open cache directory");
|
|
if (root) root.close();
|
|
state = FAILED;
|
|
requestUpdate();
|
|
return;
|
|
}
|
|
|
|
clearedCount = 0;
|
|
failedCount = 0;
|
|
char name[128];
|
|
|
|
// Iterate through all entries in the directory
|
|
for (auto file = root.openNextFile(); file; file = root.openNextFile()) {
|
|
file.getName(name, sizeof(name));
|
|
String itemName(name);
|
|
|
|
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());
|
|
|
|
file.close(); // Close before attempting to delete
|
|
|
|
if (Storage.removeDir(fullPath.c_str())) {
|
|
clearedCount++;
|
|
} else {
|
|
LOG_ERR("CLEAR_CACHE", "Failed to remove: %s", fullPath.c_str());
|
|
failedCount++;
|
|
}
|
|
} else {
|
|
file.close();
|
|
}
|
|
}
|
|
root.close();
|
|
|
|
// Clear recents since all cached data (covers, progress) is gone
|
|
RECENT_BOOKS.clear();
|
|
|
|
LOG_DBG("CLEAR_CACHE", "Cache cleared: %d removed, %d failed", clearedCount, failedCount);
|
|
|
|
state = SUCCESS;
|
|
requestUpdate();
|
|
}
|
|
|
|
void ClearCacheActivity::loop() {
|
|
if (state == WARNING) {
|
|
if (mappedInput.wasPressed(MappedInputManager::Button::Confirm)) {
|
|
LOG_DBG("CLEAR_CACHE", "User confirmed, starting cache clear");
|
|
{
|
|
RenderLock lock(*this);
|
|
state = CLEARING;
|
|
}
|
|
requestUpdateAndWait();
|
|
|
|
clearCache();
|
|
}
|
|
|
|
if (mappedInput.wasPressed(MappedInputManager::Button::Back)) {
|
|
LOG_DBG("CLEAR_CACHE", "User cancelled");
|
|
goBack();
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (state == SUCCESS || state == FAILED) {
|
|
if (mappedInput.wasPressed(MappedInputManager::Button::Back)) {
|
|
goBack();
|
|
}
|
|
return;
|
|
}
|
|
}
|