diff --git a/src/activities/Activity.h b/src/activities/Activity.h index dfe6714..90a2eb1 100644 --- a/src/activities/Activity.h +++ b/src/activities/Activity.h @@ -1,19 +1,22 @@ #pragma once #include +#include + class GfxRenderer; class Activity { protected: + std::string name; GfxRenderer& renderer; InputManager& inputManager; public: - explicit Activity(GfxRenderer& renderer, InputManager& inputManager) - : renderer(renderer), inputManager(inputManager) {} + explicit Activity(std::string name, GfxRenderer& renderer, InputManager& inputManager) + : name(std::move(name)), renderer(renderer), inputManager(inputManager) {} virtual ~Activity() = default; - virtual void onEnter() {} - virtual void onExit() {} + virtual void onEnter() { Serial.printf("[%lu] [ACT] Entering activity: %s\n", millis(), name.c_str()); } + virtual void onExit() { Serial.printf("[%lu] [ACT] Exiting activity: %s\n", millis(), name.c_str()); } virtual void loop() {} virtual bool skipLoopDelay() { return false; } }; diff --git a/src/activities/ActivityWithSubactivity.cpp b/src/activities/ActivityWithSubactivity.cpp index 56dccd9..61b1fc1 100644 --- a/src/activities/ActivityWithSubactivity.cpp +++ b/src/activities/ActivityWithSubactivity.cpp @@ -18,4 +18,7 @@ void ActivityWithSubactivity::loop() { } } -void ActivityWithSubactivity::onExit() { exitActivity(); } +void ActivityWithSubactivity::onExit() { + Activity::onExit(); + exitActivity(); +} diff --git a/src/activities/ActivityWithSubactivity.h b/src/activities/ActivityWithSubactivity.h index b3a6873..af55987 100644 --- a/src/activities/ActivityWithSubactivity.h +++ b/src/activities/ActivityWithSubactivity.h @@ -10,8 +10,8 @@ class ActivityWithSubactivity : public Activity { void enterNewActivity(Activity* activity); public: - explicit ActivityWithSubactivity(GfxRenderer& renderer, InputManager& inputManager) - : Activity(renderer, inputManager) {} + explicit ActivityWithSubactivity(std::string name, GfxRenderer& renderer, InputManager& inputManager) + : Activity(std::move(name), renderer, inputManager) {} void loop() override; void onExit() override; }; diff --git a/src/activities/boot_sleep/BootActivity.cpp b/src/activities/boot_sleep/BootActivity.cpp index a76cb7c..78a1248 100644 --- a/src/activities/boot_sleep/BootActivity.cpp +++ b/src/activities/boot_sleep/BootActivity.cpp @@ -6,6 +6,8 @@ #include "images/CrossLarge.h" void BootActivity::onEnter() { + Activity::onEnter(); + const auto pageWidth = GfxRenderer::getScreenWidth(); const auto pageHeight = GfxRenderer::getScreenHeight(); diff --git a/src/activities/boot_sleep/BootActivity.h b/src/activities/boot_sleep/BootActivity.h index dd647ce..a14d0c7 100644 --- a/src/activities/boot_sleep/BootActivity.h +++ b/src/activities/boot_sleep/BootActivity.h @@ -3,6 +3,6 @@ class BootActivity final : public Activity { public: - explicit BootActivity(GfxRenderer& renderer, InputManager& inputManager) : Activity(renderer, inputManager) {} + explicit BootActivity(GfxRenderer& renderer, InputManager& inputManager) : Activity("Boot", renderer, inputManager) {} void onEnter() override; }; diff --git a/src/activities/boot_sleep/SleepActivity.cpp b/src/activities/boot_sleep/SleepActivity.cpp index 4200c4e..ca72aeb 100644 --- a/src/activities/boot_sleep/SleepActivity.cpp +++ b/src/activities/boot_sleep/SleepActivity.cpp @@ -12,6 +12,7 @@ #include "images/CrossLarge.h" void SleepActivity::onEnter() { + Activity::onEnter(); renderPopup("Entering Sleep..."); if (SETTINGS.sleepScreen == CrossPointSettings::SLEEP_SCREEN_MODE::CUSTOM) { @@ -170,11 +171,16 @@ void SleepActivity::renderBitmapSleepScreen(const Bitmap& bitmap) const { } void SleepActivity::renderCoverSleepScreen() const { + if (APP_STATE.openEpubPath.empty()) { + return renderDefaultSleepScreen(); + } + Epub lastEpub(APP_STATE.openEpubPath, "/.crosspoint"); if (!lastEpub.load()) { Serial.println("[SLP] Failed to load last epub"); return renderDefaultSleepScreen(); } + if (!lastEpub.generateCoverBmp()) { Serial.println("[SLP] Failed to generate cover bmp"); return renderDefaultSleepScreen(); diff --git a/src/activities/boot_sleep/SleepActivity.h b/src/activities/boot_sleep/SleepActivity.h index 2112199..774fd25 100644 --- a/src/activities/boot_sleep/SleepActivity.h +++ b/src/activities/boot_sleep/SleepActivity.h @@ -5,7 +5,8 @@ class Bitmap; class SleepActivity final : public Activity { public: - explicit SleepActivity(GfxRenderer& renderer, InputManager& inputManager) : Activity(renderer, inputManager) {} + explicit SleepActivity(GfxRenderer& renderer, InputManager& inputManager) + : Activity("Sleep", renderer, inputManager) {} void onEnter() override; private: diff --git a/src/activities/home/HomeActivity.cpp b/src/activities/home/HomeActivity.cpp index 82d57cc..9cfa185 100644 --- a/src/activities/home/HomeActivity.cpp +++ b/src/activities/home/HomeActivity.cpp @@ -15,6 +15,8 @@ void HomeActivity::taskTrampoline(void* param) { } void HomeActivity::onEnter() { + Activity::onEnter(); + renderingMutex = xSemaphoreCreateMutex(); selectorIndex = 0; @@ -31,6 +33,8 @@ void HomeActivity::onEnter() { } void HomeActivity::onExit() { + Activity::onExit(); + // Wait until not rendering to delete task to avoid killing mid-instruction to EPD xSemaphoreTake(renderingMutex, portMAX_DELAY); if (displayTaskHandle) { diff --git a/src/activities/home/HomeActivity.h b/src/activities/home/HomeActivity.h index 5dd26ec..943a466 100644 --- a/src/activities/home/HomeActivity.h +++ b/src/activities/home/HomeActivity.h @@ -23,7 +23,7 @@ class HomeActivity final : public Activity { public: explicit HomeActivity(GfxRenderer& renderer, InputManager& inputManager, const std::function& onReaderOpen, const std::function& onSettingsOpen, const std::function& onFileTransferOpen) - : Activity(renderer, inputManager), + : Activity("Home", renderer, inputManager), onReaderOpen(onReaderOpen), onSettingsOpen(onSettingsOpen), onFileTransferOpen(onFileTransferOpen) {} diff --git a/src/activities/network/CrossPointWebServerActivity.cpp b/src/activities/network/CrossPointWebServerActivity.cpp index bb0f39a..d02411f 100644 --- a/src/activities/network/CrossPointWebServerActivity.cpp +++ b/src/activities/network/CrossPointWebServerActivity.cpp @@ -11,7 +11,8 @@ void CrossPointWebServerActivity::taskTrampoline(void* param) { } void CrossPointWebServerActivity::onEnter() { - Serial.printf("[%lu] [WEBACT] ========== CrossPointWebServerActivity onEnter ==========\n", millis()); + ActivityWithSubactivity::onEnter(); + Serial.printf("[%lu] [WEBACT] [MEM] Free heap at onEnter: %d bytes\n", millis(), ESP.getFreeHeap()); renderingMutex = xSemaphoreCreateMutex(); @@ -36,13 +37,13 @@ void CrossPointWebServerActivity::onEnter() { // Launch WiFi selection subactivity Serial.printf("[%lu] [WEBACT] Launching WifiSelectionActivity...\n", millis()); - wifiSelection.reset(new WifiSelectionActivity(renderer, inputManager, - [this](bool connected) { onWifiSelectionComplete(connected); })); - wifiSelection->onEnter(); + enterNewActivity(new WifiSelectionActivity(renderer, inputManager, + [this](const bool connected) { onWifiSelectionComplete(connected); })); } void CrossPointWebServerActivity::onExit() { - Serial.printf("[%lu] [WEBACT] ========== CrossPointWebServerActivity onExit START ==========\n", millis()); + ActivityWithSubactivity::onExit(); + Serial.printf("[%lu] [WEBACT] [MEM] Free heap at onExit start: %d bytes\n", millis(), ESP.getFreeHeap()); state = WebServerActivityState::SHUTTING_DOWN; @@ -50,14 +51,6 @@ void CrossPointWebServerActivity::onExit() { // Stop the web server first (before disconnecting WiFi) stopWebServer(); - // Exit WiFi selection subactivity if still active - if (wifiSelection) { - Serial.printf("[%lu] [WEBACT] Exiting WifiSelectionActivity...\n", millis()); - wifiSelection->onExit(); - wifiSelection.reset(); - Serial.printf("[%lu] [WEBACT] WifiSelectionActivity exited\n", millis()); - } - // CRITICAL: Wait for LWIP stack to flush any pending packets Serial.printf("[%lu] [WEBACT] Waiting 500ms for network stack to flush pending packets...\n", millis()); delay(500); @@ -92,20 +85,17 @@ void CrossPointWebServerActivity::onExit() { Serial.printf("[%lu] [WEBACT] Mutex deleted\n", millis()); Serial.printf("[%lu] [WEBACT] [MEM] Free heap at onExit end: %d bytes\n", millis(), ESP.getFreeHeap()); - Serial.printf("[%lu] [WEBACT] ========== CrossPointWebServerActivity onExit COMPLETE ==========\n", millis()); } -void CrossPointWebServerActivity::onWifiSelectionComplete(bool connected) { +void CrossPointWebServerActivity::onWifiSelectionComplete(const bool connected) { Serial.printf("[%lu] [WEBACT] WifiSelectionActivity completed, connected=%d\n", millis(), connected); if (connected) { // Get connection info before exiting subactivity - connectedIP = wifiSelection->getConnectedIP(); + connectedIP = static_cast(subActivity.get())->getConnectedIP(); connectedSSID = WiFi.SSID().c_str(); - // Exit the wifi selection subactivity - wifiSelection->onExit(); - wifiSelection.reset(); + exitActivity(); // Start the web server startWebServer(); @@ -150,47 +140,40 @@ void CrossPointWebServerActivity::stopWebServer() { } void CrossPointWebServerActivity::loop() { + if (subActivity) { + // Forward loop to subactivity + subActivity->loop(); + return; + } + // Handle different states - switch (state) { - case WebServerActivityState::WIFI_SELECTION: - // Forward loop to WiFi selection subactivity - if (wifiSelection) { - wifiSelection->loop(); - } - break; + if (state == WebServerActivityState::SERVER_RUNNING) { + // Handle web server requests - call handleClient multiple times per loop + // to improve responsiveness and upload throughput + if (webServer && webServer->isRunning()) { + const unsigned long timeSinceLastHandleClient = millis() - lastHandleClientTime; - case WebServerActivityState::SERVER_RUNNING: - // Handle web server requests - call handleClient multiple times per loop - // to improve responsiveness and upload throughput - if (webServer && webServer->isRunning()) { - unsigned long timeSinceLastHandleClient = millis() - lastHandleClientTime; - - // Log if there's a significant gap between handleClient calls (>100ms) - if (lastHandleClientTime > 0 && timeSinceLastHandleClient > 100) { - Serial.printf("[%lu] [WEBACT] WARNING: %lu ms gap since last handleClient\n", millis(), - timeSinceLastHandleClient); - } - - // Call handleClient multiple times to process pending requests faster - // This is critical for upload performance - HTTP file uploads send data - // in chunks and each handleClient() call processes incoming data - constexpr int HANDLE_CLIENT_ITERATIONS = 10; - for (int i = 0; i < HANDLE_CLIENT_ITERATIONS && webServer->isRunning(); i++) { - webServer->handleClient(); - } - lastHandleClientTime = millis(); + // Log if there's a significant gap between handleClient calls (>100ms) + if (lastHandleClientTime > 0 && timeSinceLastHandleClient > 100) { + Serial.printf("[%lu] [WEBACT] WARNING: %lu ms gap since last handleClient\n", millis(), + timeSinceLastHandleClient); } - // Handle exit on Back button - if (inputManager.wasPressed(InputManager::BTN_BACK)) { - onGoBack(); - return; + // Call handleClient multiple times to process pending requests faster + // This is critical for upload performance - HTTP file uploads send data + // in chunks and each handleClient() call processes incoming data + constexpr int HANDLE_CLIENT_ITERATIONS = 10; + for (int i = 0; i < HANDLE_CLIENT_ITERATIONS && webServer->isRunning(); i++) { + webServer->handleClient(); } - break; + lastHandleClientTime = millis(); + } - case WebServerActivityState::SHUTTING_DOWN: - // Do nothing - waiting for cleanup - break; + // Handle exit on Back button + if (inputManager.wasPressed(InputManager::BTN_BACK)) { + onGoBack(); + return; + } } } diff --git a/src/activities/network/CrossPointWebServerActivity.h b/src/activities/network/CrossPointWebServerActivity.h index ad41dcd..76d19f1 100644 --- a/src/activities/network/CrossPointWebServerActivity.h +++ b/src/activities/network/CrossPointWebServerActivity.h @@ -9,6 +9,7 @@ #include "../Activity.h" #include "WifiSelectionActivity.h" +#include "activities/ActivityWithSubactivity.h" #include "server/CrossPointWebServer.h" // Web server activity states @@ -26,16 +27,13 @@ enum class WebServerActivityState { * - Handles client requests in its loop() function * - Cleans up the server and shuts down WiFi on exit */ -class CrossPointWebServerActivity final : public Activity { +class CrossPointWebServerActivity final : public ActivityWithSubactivity { TaskHandle_t displayTaskHandle = nullptr; SemaphoreHandle_t renderingMutex = nullptr; bool updateRequired = false; WebServerActivityState state = WebServerActivityState::WIFI_SELECTION; const std::function onGoBack; - // WiFi selection subactivity - std::unique_ptr wifiSelection; - // Web server - owned by this activity std::unique_ptr webServer; @@ -58,7 +56,7 @@ class CrossPointWebServerActivity final : public Activity { public: explicit CrossPointWebServerActivity(GfxRenderer& renderer, InputManager& inputManager, const std::function& onGoBack) - : Activity(renderer, inputManager), onGoBack(onGoBack) {} + : ActivityWithSubactivity("CrossPointWebServer", renderer, inputManager), onGoBack(onGoBack) {} void onEnter() override; void onExit() override; void loop() override; diff --git a/src/activities/network/WifiSelectionActivity.cpp b/src/activities/network/WifiSelectionActivity.cpp index d6c3b1e..7f202fe 100644 --- a/src/activities/network/WifiSelectionActivity.cpp +++ b/src/activities/network/WifiSelectionActivity.cpp @@ -14,6 +14,8 @@ void WifiSelectionActivity::taskTrampoline(void* param) { } void WifiSelectionActivity::onEnter() { + Activity::onEnter(); + renderingMutex = xSemaphoreCreateMutex(); // Load saved WiFi credentials @@ -47,7 +49,8 @@ void WifiSelectionActivity::onEnter() { } void WifiSelectionActivity::onExit() { - Serial.printf("[%lu] [WIFI] ========== WifiSelectionActivity onExit START ==========\n", millis()); + Activity::onExit(); + Serial.printf("[%lu] [WIFI] [MEM] Free heap at onExit start: %d bytes\n", millis(), ESP.getFreeHeap()); // Stop any ongoing WiFi scan @@ -78,7 +81,6 @@ void WifiSelectionActivity::onExit() { Serial.printf("[%lu] [WIFI] Mutex deleted\n", millis()); Serial.printf("[%lu] [WIFI] [MEM] Free heap at onExit end: %d bytes\n", millis(), ESP.getFreeHeap()); - Serial.printf("[%lu] [WIFI] ========== WifiSelectionActivity onExit COMPLETE ==========\n", millis()); } void WifiSelectionActivity::startWifiScan() { diff --git a/src/activities/network/WifiSelectionActivity.h b/src/activities/network/WifiSelectionActivity.h index e7b12ae..a009de1 100644 --- a/src/activities/network/WifiSelectionActivity.h +++ b/src/activities/network/WifiSelectionActivity.h @@ -98,7 +98,7 @@ class WifiSelectionActivity final : public Activity { public: explicit WifiSelectionActivity(GfxRenderer& renderer, InputManager& inputManager, const std::function& onComplete) - : Activity(renderer, inputManager), onComplete(onComplete) {} + : Activity("WifiSelection", renderer, inputManager), onComplete(onComplete) {} void onEnter() override; void onExit() override; void loop() override; diff --git a/src/activities/reader/EpubReaderActivity.cpp b/src/activities/reader/EpubReaderActivity.cpp index 9635952..84abc49 100644 --- a/src/activities/reader/EpubReaderActivity.cpp +++ b/src/activities/reader/EpubReaderActivity.cpp @@ -26,6 +26,8 @@ void EpubReaderActivity::taskTrampoline(void* param) { } void EpubReaderActivity::onEnter() { + ActivityWithSubactivity::onEnter(); + if (!epub) { return; } @@ -61,6 +63,8 @@ void EpubReaderActivity::onEnter() { } void EpubReaderActivity::onExit() { + ActivityWithSubactivity::onExit(); + // Wait until not rendering to delete task to avoid killing mid-instruction to EPD xSemaphoreTake(renderingMutex, portMAX_DELAY); if (displayTaskHandle) { @@ -75,8 +79,8 @@ void EpubReaderActivity::onExit() { void EpubReaderActivity::loop() { // Pass input responsibility to sub activity if exists - if (subAcitivity) { - subAcitivity->loop(); + if (subActivity) { + subActivity->loop(); return; } @@ -84,11 +88,11 @@ void EpubReaderActivity::loop() { if (inputManager.wasPressed(InputManager::BTN_CONFIRM)) { // Don't start activity transition while rendering xSemaphoreTake(renderingMutex, portMAX_DELAY); - subAcitivity.reset(new EpubReaderChapterSelectionActivity( + exitActivity(); + enterNewActivity(new EpubReaderChapterSelectionActivity( this->renderer, this->inputManager, epub, currentSpineIndex, [this] { - subAcitivity->onExit(); - subAcitivity.reset(); + exitActivity(); updateRequired = true; }, [this](const int newSpineIndex) { @@ -97,11 +101,9 @@ void EpubReaderActivity::loop() { nextPageNumber = 0; section.reset(); } - subAcitivity->onExit(); - subAcitivity.reset(); + exitActivity(); updateRequired = true; })); - subAcitivity->onEnter(); xSemaphoreGive(renderingMutex); } @@ -330,8 +332,8 @@ void EpubReaderActivity::renderStatusBar() const { constexpr auto textY = 776; // Calculate progress in book - float sectionChapterProg = static_cast(section->currentPage) / section->pageCount; - uint8_t bookProgress = epub->calculateProgress(currentSpineIndex, sectionChapterProg); + const float sectionChapterProg = static_cast(section->currentPage) / section->pageCount; + const uint8_t bookProgress = epub->calculateProgress(currentSpineIndex, sectionChapterProg); // Right aligned text for progress counter const std::string progress = std::to_string(section->currentPage + 1) + "/" + std::to_string(section->pageCount) + diff --git a/src/activities/reader/EpubReaderActivity.h b/src/activities/reader/EpubReaderActivity.h index 8eeddc1..4edbabc 100644 --- a/src/activities/reader/EpubReaderActivity.h +++ b/src/activities/reader/EpubReaderActivity.h @@ -5,14 +5,13 @@ #include #include -#include "../Activity.h" +#include "activities/ActivityWithSubactivity.h" -class EpubReaderActivity final : public Activity { +class EpubReaderActivity final : public ActivityWithSubactivity { std::shared_ptr epub; std::unique_ptr
section = nullptr; TaskHandle_t displayTaskHandle = nullptr; SemaphoreHandle_t renderingMutex = nullptr; - std::unique_ptr subAcitivity = nullptr; int currentSpineIndex = 0; int nextPageNumber = 0; int pagesUntilFullRefresh = 0; @@ -28,7 +27,7 @@ class EpubReaderActivity final : public Activity { public: explicit EpubReaderActivity(GfxRenderer& renderer, InputManager& inputManager, std::unique_ptr epub, const std::function& onGoBack) - : Activity(renderer, inputManager), epub(std::move(epub)), onGoBack(onGoBack) {} + : ActivityWithSubactivity("EpubReader", renderer, inputManager), epub(std::move(epub)), onGoBack(onGoBack) {} void onEnter() override; void onExit() override; void loop() override; diff --git a/src/activities/reader/EpubReaderChapterSelectionActivity.cpp b/src/activities/reader/EpubReaderChapterSelectionActivity.cpp index 9af556b..07fd456 100644 --- a/src/activities/reader/EpubReaderChapterSelectionActivity.cpp +++ b/src/activities/reader/EpubReaderChapterSelectionActivity.cpp @@ -16,6 +16,8 @@ void EpubReaderChapterSelectionActivity::taskTrampoline(void* param) { } void EpubReaderChapterSelectionActivity::onEnter() { + Activity::onEnter(); + if (!epub) { return; } @@ -34,6 +36,8 @@ void EpubReaderChapterSelectionActivity::onEnter() { } void EpubReaderChapterSelectionActivity::onExit() { + Activity::onExit(); + // Wait until not rendering to delete task to avoid killing mid-instruction to EPD xSemaphoreTake(renderingMutex, portMAX_DELAY); if (displayTaskHandle) { diff --git a/src/activities/reader/EpubReaderChapterSelectionActivity.h b/src/activities/reader/EpubReaderChapterSelectionActivity.h index b25ef6f..8c1adef 100644 --- a/src/activities/reader/EpubReaderChapterSelectionActivity.h +++ b/src/activities/reader/EpubReaderChapterSelectionActivity.h @@ -27,7 +27,7 @@ class EpubReaderChapterSelectionActivity final : public Activity { const std::shared_ptr& epub, const int currentSpineIndex, const std::function& onGoBack, const std::function& onSelectSpineIndex) - : Activity(renderer, inputManager), + : Activity("EpubReaderChapterSelection", renderer, inputManager), epub(epub), currentSpineIndex(currentSpineIndex), onGoBack(onGoBack), diff --git a/src/activities/reader/FileSelectionActivity.cpp b/src/activities/reader/FileSelectionActivity.cpp index d8aef3c..fc39a8c 100644 --- a/src/activities/reader/FileSelectionActivity.cpp +++ b/src/activities/reader/FileSelectionActivity.cpp @@ -48,6 +48,8 @@ void FileSelectionActivity::loadFiles() { } void FileSelectionActivity::onEnter() { + Activity::onEnter(); + renderingMutex = xSemaphoreCreateMutex(); basepath = "/"; @@ -66,6 +68,8 @@ void FileSelectionActivity::onEnter() { } void FileSelectionActivity::onExit() { + Activity::onExit(); + // Wait until not rendering to delete task to avoid killing mid-instruction to EPD xSemaphoreTake(renderingMutex, portMAX_DELAY); if (displayTaskHandle) { diff --git a/src/activities/reader/FileSelectionActivity.h b/src/activities/reader/FileSelectionActivity.h index ff1a922..2a8f8ae 100644 --- a/src/activities/reader/FileSelectionActivity.h +++ b/src/activities/reader/FileSelectionActivity.h @@ -28,7 +28,7 @@ class FileSelectionActivity final : public Activity { explicit FileSelectionActivity(GfxRenderer& renderer, InputManager& inputManager, const std::function& onSelect, const std::function& onGoHome) - : Activity(renderer, inputManager), onSelect(onSelect), onGoHome(onGoHome) {} + : Activity("FileSelection", renderer, inputManager), onSelect(onSelect), onGoHome(onGoHome) {} void onEnter() override; void onExit() override; void loop() override; diff --git a/src/activities/reader/ReaderActivity.cpp b/src/activities/reader/ReaderActivity.cpp index 93389fe..d888fb6 100644 --- a/src/activities/reader/ReaderActivity.cpp +++ b/src/activities/reader/ReaderActivity.cpp @@ -50,6 +50,8 @@ void ReaderActivity::onGoToEpubReader(std::unique_ptr epub) { } void ReaderActivity::onEnter() { + ActivityWithSubactivity::onEnter(); + if (initialEpubPath.empty()) { onGoToFileSelection(); return; diff --git a/src/activities/reader/ReaderActivity.h b/src/activities/reader/ReaderActivity.h index a68cd89..e566d6d 100644 --- a/src/activities/reader/ReaderActivity.h +++ b/src/activities/reader/ReaderActivity.h @@ -17,7 +17,7 @@ class ReaderActivity final : public ActivityWithSubactivity { public: explicit ReaderActivity(GfxRenderer& renderer, InputManager& inputManager, std::string initialEpubPath, const std::function& onGoBack) - : ActivityWithSubactivity(renderer, inputManager), + : ActivityWithSubactivity("Reader", renderer, inputManager), initialEpubPath(std::move(initialEpubPath)), onGoBack(onGoBack) {} void onEnter() override; diff --git a/src/activities/settings/SettingsActivity.cpp b/src/activities/settings/SettingsActivity.cpp index 29f6876..d38d85c 100644 --- a/src/activities/settings/SettingsActivity.cpp +++ b/src/activities/settings/SettingsActivity.cpp @@ -21,6 +21,8 @@ void SettingsActivity::taskTrampoline(void* param) { } void SettingsActivity::onEnter() { + Activity::onEnter(); + renderingMutex = xSemaphoreCreateMutex(); // Reset selection to first item @@ -38,6 +40,8 @@ void SettingsActivity::onEnter() { } void SettingsActivity::onExit() { + Activity::onExit(); + // Wait until not rendering to delete task to avoid killing mid-instruction to EPD xSemaphoreTake(renderingMutex, portMAX_DELAY); if (displayTaskHandle) { @@ -76,7 +80,7 @@ void SettingsActivity::loop() { } } -void SettingsActivity::toggleCurrentSetting() { +void SettingsActivity::toggleCurrentSetting() const { // Validate index if (selectedSettingIndex < 0 || selectedSettingIndex >= settingsCount) { return; diff --git a/src/activities/settings/SettingsActivity.h b/src/activities/settings/SettingsActivity.h index 333f467..6fe5db1 100644 --- a/src/activities/settings/SettingsActivity.h +++ b/src/activities/settings/SettingsActivity.h @@ -32,11 +32,11 @@ class SettingsActivity final : public Activity { static void taskTrampoline(void* param); [[noreturn]] void displayTaskLoop(); void render() const; - void toggleCurrentSetting(); + void toggleCurrentSetting() const; public: explicit SettingsActivity(GfxRenderer& renderer, InputManager& inputManager, const std::function& onGoHome) - : Activity(renderer, inputManager), onGoHome(onGoHome) {} + : Activity("Settings", renderer, inputManager), onGoHome(onGoHome) {} void onEnter() override; void onExit() override; void loop() override; diff --git a/src/activities/util/FullScreenMessageActivity.cpp b/src/activities/util/FullScreenMessageActivity.cpp index a56952f..cf84cc5 100644 --- a/src/activities/util/FullScreenMessageActivity.cpp +++ b/src/activities/util/FullScreenMessageActivity.cpp @@ -5,6 +5,8 @@ #include "config.h" void FullScreenMessageActivity::onEnter() { + Activity::onEnter(); + const auto height = renderer.getLineHeight(UI_FONT_ID); const auto top = (GfxRenderer::getScreenHeight() - height) / 2; diff --git a/src/activities/util/FullScreenMessageActivity.h b/src/activities/util/FullScreenMessageActivity.h index 3180ddb..8c6e30e 100644 --- a/src/activities/util/FullScreenMessageActivity.h +++ b/src/activities/util/FullScreenMessageActivity.h @@ -16,6 +16,9 @@ class FullScreenMessageActivity final : public Activity { explicit FullScreenMessageActivity(GfxRenderer& renderer, InputManager& inputManager, std::string text, const EpdFontStyle style = REGULAR, const EInkDisplay::RefreshMode refreshMode = EInkDisplay::FAST_REFRESH) - : Activity(renderer, inputManager), text(std::move(text)), style(style), refreshMode(refreshMode) {} + : Activity("FullScreenMessage", renderer, inputManager), + text(std::move(text)), + style(style), + refreshMode(refreshMode) {} void onEnter() override; }; diff --git a/src/activities/util/KeyboardEntryActivity.cpp b/src/activities/util/KeyboardEntryActivity.cpp index 68fc079..b4ed01c 100644 --- a/src/activities/util/KeyboardEntryActivity.cpp +++ b/src/activities/util/KeyboardEntryActivity.cpp @@ -12,11 +12,6 @@ const char* const KeyboardEntryActivity::keyboard[NUM_ROWS] = { const char* const KeyboardEntryActivity::keyboardShift[NUM_ROWS] = {"~!@#$%^&*()_+", "QWERTYUIOP{}|", "ASDFGHJKL:\"", "ZXCVBNM<>?", "^ _____ 0 && text.length() > maxLength) { @@ -37,15 +32,13 @@ void KeyboardEntryActivity::reset(const std::string& newTitle, const std::string } void KeyboardEntryActivity::onEnter() { + Activity::onEnter(); + // Reset state when entering the activity complete = false; cancelled = false; } -void KeyboardEntryActivity::onExit() { - // Clean up if needed -} - void KeyboardEntryActivity::loop() { handleInput(); render(10); diff --git a/src/activities/util/KeyboardEntryActivity.h b/src/activities/util/KeyboardEntryActivity.h index af6d9b4..3b5b806 100644 --- a/src/activities/util/KeyboardEntryActivity.h +++ b/src/activities/util/KeyboardEntryActivity.h @@ -34,7 +34,12 @@ class KeyboardEntryActivity : public Activity { * @param isPassword If true, display asterisks instead of actual characters */ KeyboardEntryActivity(GfxRenderer& renderer, InputManager& inputManager, const std::string& title = "Enter Text", - const std::string& initialText = "", size_t maxLength = 0, bool isPassword = false); + const std::string& initialText = "", const size_t maxLength = 0, const bool isPassword = false) + : Activity("KeyboardEntry", renderer, inputManager), + title(title), + text(initialText), + maxLength(maxLength), + isPassword(isPassword) {} /** * Handle button input. Call this in your main loop. @@ -85,7 +90,6 @@ class KeyboardEntryActivity : public Activity { // Activity overrides void onEnter() override; - void onExit() override; void loop() override; private: