#pragma once #include #include #include "CrossPointSettings.h" #include "ReaderUtils.h" #include "activities/Activity.h" class TxtReaderActivity final : public Activity { std::unique_ptr txt; int currentPage = 0; int totalPages = 1; int pagesUntilFullRefresh = 0; ReaderUtils::InputDrainGuard inputDrainGuard; // Streaming text reader - stores file offsets for each page std::vector pageOffsets; // File offset for start of each page std::vector currentPageLines; int linesPerPage = 0; int viewportWidth = 0; bool initialized = false; // Cached settings for cache validation (different fonts/margins require re-indexing) int cachedFontId = 0; uint8_t cachedScreenMargin = 0; uint8_t cachedParagraphAlignment = CrossPointSettings::LEFT_ALIGN; int cachedOrientedMarginTop = 0; int cachedOrientedMarginRight = 0; int cachedOrientedMarginBottom = 0; int cachedOrientedMarginLeft = 0; void renderPage(); void renderStatusBar() const; void initializeReader(); bool loadPageAtOffset(size_t offset, std::vector& outLines, size_t& nextOffset); void buildPageIndex(); bool loadPageIndexCache(); void savePageIndexCache() const; void saveProgress() const; void loadProgress(); public: explicit TxtReaderActivity(GfxRenderer& renderer, MappedInputManager& mappedInput, std::unique_ptr txt) : Activity("TxtReader", renderer, mappedInput), txt(std::move(txt)) {} void onEnter() override; void onExit() override; void loop() override; void render(RenderLock&&) override; bool isReaderActivity() const override { return true; } // Renders the last saved page to the frame buffer without flushing to display. // Used by SleepActivity to prepare the background for the overlay sleep mode. // Returns false if the page cannot be loaded (missing cache / file error). static bool drawCurrentPageToBuffer(const std::string& filePath, GfxRenderer& renderer); };