#pragma once #include #include #include #include #include #include "DictionaryWordSelectActivity.h" #include "EpubReaderMenuActivity.h" #include "LookedUpWordsActivity.h" #include "activities/ActivityWithSubactivity.h" class EpubReaderActivity final : public ActivityWithSubactivity { std::shared_ptr epub; std::unique_ptr
section = nullptr; TaskHandle_t displayTaskHandle = nullptr; SemaphoreHandle_t renderingMutex = nullptr; int currentSpineIndex = 0; int nextPageNumber = 0; int pagesUntilFullRefresh = 0; int cachedSpineIndex = 0; int cachedChapterTotalPageCount = 0; // Signals that the next render should reposition within the newly loaded section // based on a cross-book percentage jump. bool pendingPercentJump = false; // Normalized 0.0-1.0 progress within the target spine item, computed from book percentage. float pendingSpineProgress = 0.0f; bool updateRequired = false; bool pendingSubactivityExit = false; // Defer subactivity exit to avoid use-after-free bool pendingGoHome = false; // Defer go home to avoid race condition with display task bool skipNextButtonCheck = false; // Skip button processing for one frame after subactivity exit volatile bool loadingSection = false; // True during the entire !section block (read from main loop) const std::function onGoBack; const std::function onGoHome; static void taskTrampoline(void* param); [[noreturn]] void displayTaskLoop(); void renderScreen(); void renderContents(std::unique_ptr page, int orientedMarginTop, int orientedMarginRight, int orientedMarginBottom, int orientedMarginLeft); void renderStatusBar(int orientedMarginRight, int orientedMarginBottom, int orientedMarginLeft) const; void saveProgress(int spineIndex, int currentPage, int pageCount); // Jump to a percentage of the book (0-100), mapping it to spine and page. void jumpToPercent(int percent); void onReaderMenuBack(uint8_t orientation); void onReaderMenuConfirm(EpubReaderMenuActivity::MenuAction action); void applyOrientation(uint8_t orientation); public: explicit EpubReaderActivity(GfxRenderer& renderer, MappedInputManager& mappedInput, std::unique_ptr epub, const std::function& onGoBack, const std::function& onGoHome) : ActivityWithSubactivity("EpubReader", renderer, mappedInput), epub(std::move(epub)), onGoBack(onGoBack), onGoHome(onGoHome) {} void onEnter() override; void onExit() override; void loop() override; // Defer low-power mode and auto-sleep while a section is loading/building. // !section covers the period before the Section object is created (including // cover prerendering in onEnter). loadingSection covers the full !section block // in renderScreen (including createSectionFile), during which section is non-null // but the section file is still being built. bool preventAutoSleep() override { return !section || loadingSection; } };