#pragma once #include #include #include #include #include "EndOfBookOptions.h" #include "activities/Activity.h" class ReaderActivity : public Activity { protected: std::string bookPath; int pagesUntilFullRefresh = 0; bool forcedRefreshPending = false; std::unique_ptr endOfBookOptions; std::atomic endOfBookOptionsReady{false}; std::atomic pageRendered{false}; bool bookRemembered = false; void markPageRendered() { pageRendered.store(true, std::memory_order_release); } void rememberBookOnceRendered(); explicit ReaderActivity(const char* name, GfxRenderer& renderer, MappedInputManager& mappedInput, std::string bookPath, bool allowFastInitialRefresh); virtual bool loadBook() = 0; virtual std::string getBookTitle() const = 0; virtual std::string getBookAuthor() const { return ""; } virtual std::string getBookThumbBmpPath() const { return ""; } virtual bool handleFormatInput() { return false; } virtual bool pageTurn(bool isForward) = 0; virtual bool skipPages(int amount) { return pageTurn(amount > 0); } virtual bool isAtEndOfBook() const = 0; virtual void onReturnFromEndOfBook() {} virtual void renderBook() = 0; virtual void applyInitialOrientation(); virtual void onEndOfBookRendered() {} bool handleBackNavigation(); /** True while the end-of-book suggestion menu is on screen and owning input. */ bool endOfBookMenuActive() const; bool handleEndOfBookMenu(bool suppressConfirmRelease = false); bool handleEndOfBookPageTurn(bool prevTriggered, bool nextTriggered); void clearEndOfBookOptionsIfNeeded(); void disableFastInitialRefresh(); public: ~ReaderActivity() override = default; static std::unique_ptr create(GfxRenderer& renderer, MappedInputManager& mappedInput, std::string path, bool allowFastInitialRefresh); void onEnter() override; void onExit() override; void loop() override; void render(RenderLock&& lock) override; bool isReaderActivity() const final { return true; } bool handleForcedRefresh() final; };