## Summary
* Definition and use of a central LOG function, that can later be
extended or completely be removed (for public use where debugging
information may not be required) to save flash by suppressing the
-DENABLE_SERIAL_LOG like in the slim branch
* **What changes are included?**
## Additional Context
* By using the central logger the usual:
```
#include <HardwareSerial.h>
...
Serial.printf("[%lu] [WCS] Obfuscating/deobfuscating %zu bytes\n", millis(), data.size());
```
would then become
```
#include <Logging.h>
...
LOG_DBG("WCS", "Obfuscating/deobfuscating %zu bytes", data.size());
```
You do have ``LOG_DBG`` for debug messages, ``LOG_ERR`` for error
messages and ``LOG_INF`` for informational messages. Depending on the
verbosity level defined (see below) soe of these message types will be
suppressed/not-compiled.
* The normal compilation (default) will create a firmware.elf file of
42.194.356 bytes, the same code via slim will create 42.024.048 bytes -
170.308 bytes less
* Firmware.bin : 6.469.984 bytes for default, 6.418.672 bytes for slim -
51.312 bytes less
### 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_
---------
Co-authored-by: Xuan Son Nguyen <son@huggingface.co>
180 lines
5.5 KiB
C++
180 lines
5.5 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::taskTrampoline(void* param) {
|
|
auto* self = static_cast<ClearCacheActivity*>(param);
|
|
self->displayTaskLoop();
|
|
}
|
|
|
|
void ClearCacheActivity::onEnter() {
|
|
ActivityWithSubactivity::onEnter();
|
|
|
|
renderingMutex = xSemaphoreCreateMutex();
|
|
state = WARNING;
|
|
updateRequired = true;
|
|
|
|
xTaskCreate(&ClearCacheActivity::taskTrampoline, "ClearCacheActivityTask",
|
|
4096, // Stack size
|
|
this, // Parameters
|
|
1, // Priority
|
|
&displayTaskHandle // Task handle
|
|
);
|
|
}
|
|
|
|
void ClearCacheActivity::onExit() {
|
|
ActivityWithSubactivity::onExit();
|
|
|
|
// Wait until not rendering to delete task to avoid killing mid-instruction to EPD
|
|
xSemaphoreTake(renderingMutex, portMAX_DELAY);
|
|
if (displayTaskHandle) {
|
|
vTaskDelete(displayTaskHandle);
|
|
displayTaskHandle = nullptr;
|
|
}
|
|
vSemaphoreDelete(renderingMutex);
|
|
renderingMutex = nullptr;
|
|
}
|
|
|
|
void ClearCacheActivity::displayTaskLoop() {
|
|
while (true) {
|
|
if (updateRequired) {
|
|
updateRequired = false;
|
|
xSemaphoreTake(renderingMutex, portMAX_DELAY);
|
|
render();
|
|
xSemaphoreGive(renderingMutex);
|
|
}
|
|
vTaskDelay(10 / portTICK_PERIOD_MS);
|
|
}
|
|
}
|
|
|
|
void ClearCacheActivity::render() {
|
|
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;
|
|
updateRequired = true;
|
|
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;
|
|
updateRequired = true;
|
|
}
|
|
|
|
void ClearCacheActivity::loop() {
|
|
if (state == WARNING) {
|
|
if (mappedInput.wasPressed(MappedInputManager::Button::Confirm)) {
|
|
LOG_DBG("CLEAR_CACHE", "User confirmed, starting cache clear");
|
|
xSemaphoreTake(renderingMutex, portMAX_DELAY);
|
|
state = CLEARING;
|
|
xSemaphoreGive(renderingMutex);
|
|
updateRequired = true;
|
|
vTaskDelay(10 / portTICK_PERIOD_MS);
|
|
|
|
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;
|
|
}
|
|
}
|