#pragma once #include #include #include #include #include #include #include "../Activity.h" #include "BookListStore.h" #include "RecentBooksStore.h" // Cached thumbnail existence info for Recent tab struct ThumbExistsCache { std::string bookPath; // Book path this cache entry belongs to std::string thumbPath; // Path to micro-thumbnail (if exists) bool checked = false; // Whether we've checked for this book bool exists = false; // Whether thumbnail exists }; // Search result for the Search tab struct SearchResult { std::string path; std::string title; std::string author; int matchScore = 0; // Higher = better match }; // Book with bookmarks info for the Bookmarks tab struct BookmarkedBook { std::string path; std::string title; std::string author; int bookmarkCount = 0; }; class MyLibraryActivity final : public Activity { public: enum class Tab { Recent, Lists, Bookmarks, Search, Files }; enum class UIState { Normal, ActionMenu, Confirming, ListActionMenu, ListConfirmingDelete, ClearAllRecentsConfirming }; enum class ActionType { Archive, Delete, RemoveFromRecents, ClearAllRecents }; private: TaskHandle_t displayTaskHandle = nullptr; SemaphoreHandle_t renderingMutex = nullptr; Tab currentTab = Tab::Recent; int selectorIndex = 0; bool updateRequired = false; bool inTabBar = false; // true = focus on tab bar for switching tabs (all tabs) // Action menu state UIState uiState = UIState::Normal; ActionType selectedAction = ActionType::Archive; std::string actionTargetPath; std::string actionTargetName; int menuSelection = 0; // 0 = Archive, 1 = Delete bool ignoreNextConfirmRelease = false; // Prevents immediate selection after long-press opens menu // Recent tab state std::vector recentBooks; // Static thumbnail existence cache - persists across activity enter/exit static constexpr int MAX_THUMB_CACHE = 10; static ThumbExistsCache thumbExistsCache[MAX_THUMB_CACHE]; public: // Clear the thumbnail existence cache (call when disk cache is cleared) static void clearThumbExistsCache(); private: // Lists tab state std::vector lists; // List action menu state (for Lists tab) int listMenuSelection = 0; // 0 = Pin/Unpin, 1 = Delete std::string listActionTargetName; // Bookmarks tab state std::vector bookmarkedBooks; // Search tab state std::string searchQuery; std::vector searchResults; std::vector allBooks; // Cached index of all books std::vector searchCharacters; // Dynamic character set from library int searchCharIndex = 0; // Current position in character picker bool searchInResults = false; // true = navigating results, false = in character picker // Files tab state (from FileSelectionActivity) std::string basepath = "/"; std::vector files; // Callbacks const std::function onGoHome; const std::function onSelectBook; const std::function onSelectList; const std::function onSelectBookmarkedBook; // Number of items that fit on a page int getPageItems() const; int getCurrentItemCount() const; int getTotalPages() const; int getCurrentPage() const; // Data loading void loadRecentBooks(); void loadLists(); void loadBookmarkedBooks(); void loadAllBooks(); void updateSearchResults(); void loadFiles(); size_t findEntry(const std::string& name) const; // Rendering static void taskTrampoline(void* param); [[noreturn]] void displayTaskLoop(); void render() const; void renderRecentTab() const; void renderListsTab() const; void renderBookmarksTab() const; void renderSearchTab() const; void renderFilesTab() const; void renderActionMenu() const; void renderConfirmation() const; // Search character picker helpers void buildSearchCharacters(); void renderCharacterPicker(int y) const; // Action handling void openActionMenu(); void executeAction(); bool isSelectedItemAFile() const; // List pinning void togglePinForSelectedList(); // List action menu void openListActionMenu(); void executeListAction(); void renderListActionMenu() const; void renderListDeleteConfirmation() const; // Clear all recents confirmation void renderClearAllRecentsConfirmation() const; public: explicit MyLibraryActivity(GfxRenderer& renderer, MappedInputManager& mappedInput, const std::function& onGoHome, const std::function& onSelectBook, const std::function& onSelectList, const std::function& onSelectBookmarkedBook = nullptr, Tab initialTab = Tab::Recent, std::string initialPath = "/") : Activity("MyLibrary", renderer, mappedInput), currentTab(initialTab), basepath(initialPath.empty() ? "/" : std::move(initialPath)), onGoHome(onGoHome), onSelectBook(onSelectBook), onSelectList(onSelectList), onSelectBookmarkedBook(onSelectBookmarkedBook) {} void onEnter() override; void onExit() override; void loop() override; };