Follow-up to https://github.com/crosspoint-reader/crosspoint-reader/pull/774 --- 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** <!-- This is an auto-generated comment: release notes by coderabbit.ai --> * **Refactor** * Modernized internal synchronization mechanisms across multiple components to improve code reliability and maintainability. All functionality remains unchanged. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
144 lines
4.4 KiB
C++
144 lines
4.4 KiB
C++
#include "ClearCacheActivity.h"
|
|
|
|
#include <GfxRenderer.h>
|
|
#include <HalStorage.h>
|
|
#include <Logging.h>
|
|
|
|
#include "MappedInputManager.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&&) {
|
|
const auto pageHeight = renderer.getScreenHeight();
|
|
|
|
renderer.clearScreen();
|
|
renderer.drawCenteredText(UI_12_FONT_ID, 15, "Clear Cache", true, EpdFontFamily::BOLD);
|
|
|
|
if (state == WARNING) {
|
|
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2 - 60, "This will clear all cached book data.", true);
|
|
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2 - 30, "All reading progress will be lost!", true,
|
|
EpdFontFamily::BOLD);
|
|
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2 + 10, "Books will need to be re-indexed", true);
|
|
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2 + 30, "when opened again.", true);
|
|
|
|
const auto labels = mappedInput.mapLabels("« Cancel", "Clear", "", "");
|
|
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, "Clearing cache...", true, EpdFontFamily::BOLD);
|
|
renderer.displayBuffer();
|
|
return;
|
|
}
|
|
|
|
if (state == SUCCESS) {
|
|
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2 - 20, "Cache Cleared", true, EpdFontFamily::BOLD);
|
|
String resultText = String(clearedCount) + " items removed";
|
|
if (failedCount > 0) {
|
|
resultText += ", " + String(failedCount) + " failed";
|
|
}
|
|
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2 + 10, resultText.c_str());
|
|
|
|
const auto labels = mappedInput.mapLabels("« 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, "Failed to clear cache", true, EpdFontFamily::BOLD);
|
|
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2 + 10, "Check serial output for details");
|
|
|
|
const auto labels = mappedInput.mapLabels("« 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);
|
|
|
|
// Only delete directories starting with epub_ or xtc_
|
|
if (file.isDirectory() && (itemName.startsWith("epub_") || itemName.startsWith("xtc_"))) {
|
|
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();
|
|
|
|
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;
|
|
}
|
|
}
|