feat: Implement bookmark functionality for epub reader
Replace bookmark stubs with full add/remove/navigate implementation: - BookmarkStore: per-book binary persistence on SD card with v2 format supporting text snippets (backward-compatible with v1) - Visual bookmark ribbon indicator drawn on bookmarked pages via fillPolygon - Reader menu dynamically shows Add/Remove Bookmark based on current page state - Bookmark selection activity with chapter name, first sentence snippet, and page number display; long-press to delete with confirmation - Go to Bookmark falls back to Table of Contents when no bookmarks exist - Smart snippet extraction: skips partial sentences (lowercase first word) to capture the first full sentence on the page - Label truncation reserves space for page suffix so it's never cut off - Half refresh forced on menu exit to clear popup/menu artifacts Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
60
src/activities/reader/EpubReaderBookmarkSelectionActivity.h
Normal file
60
src/activities/reader/EpubReaderBookmarkSelectionActivity.h
Normal file
@@ -0,0 +1,60 @@
|
||||
#pragma once
|
||||
#include <Epub.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/semphr.h>
|
||||
#include <freertos/task.h>
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "../ActivityWithSubactivity.h"
|
||||
#include "util/BookmarkStore.h"
|
||||
#include "util/ButtonNavigator.h"
|
||||
|
||||
class EpubReaderBookmarkSelectionActivity final : public ActivityWithSubactivity {
|
||||
std::shared_ptr<Epub> epub;
|
||||
std::vector<Bookmark> bookmarks;
|
||||
std::string cachePath;
|
||||
TaskHandle_t displayTaskHandle = nullptr;
|
||||
SemaphoreHandle_t renderingMutex = nullptr;
|
||||
ButtonNavigator buttonNavigator;
|
||||
int selectorIndex = 0;
|
||||
bool updateRequired = false;
|
||||
bool deleteConfirmMode = false;
|
||||
bool ignoreNextConfirmRelease = false;
|
||||
int pendingDeleteIndex = 0;
|
||||
const std::function<void()> onGoBack;
|
||||
const std::function<void(int newSpineIndex, int newPage)> onSelectBookmark;
|
||||
|
||||
// Number of items that fit on a page, derived from logical screen height.
|
||||
int getPageItems() const;
|
||||
|
||||
int getTotalItems() const;
|
||||
|
||||
// Build the prefix portion of a bookmark label (chapter + snippet, without page suffix)
|
||||
std::string getBookmarkPrefix(const Bookmark& bookmark) const;
|
||||
|
||||
// Build the page suffix (e.g. " - Page 5")
|
||||
static std::string getPageSuffix(const Bookmark& bookmark);
|
||||
|
||||
static void taskTrampoline(void* param);
|
||||
[[noreturn]] void displayTaskLoop();
|
||||
void renderScreen();
|
||||
|
||||
public:
|
||||
explicit EpubReaderBookmarkSelectionActivity(GfxRenderer& renderer, MappedInputManager& mappedInput,
|
||||
const std::shared_ptr<Epub>& epub,
|
||||
std::vector<Bookmark> bookmarks,
|
||||
const std::string& cachePath,
|
||||
const std::function<void()>& onGoBack,
|
||||
const std::function<void(int newSpineIndex, int newPage)>& onSelectBookmark)
|
||||
: ActivityWithSubactivity("EpubReaderBookmarkSelection", renderer, mappedInput),
|
||||
epub(epub),
|
||||
bookmarks(std::move(bookmarks)),
|
||||
cachePath(cachePath),
|
||||
onGoBack(onGoBack),
|
||||
onSelectBookmark(onSelectBookmark) {}
|
||||
void onEnter() override;
|
||||
void onExit() override;
|
||||
void loop() override;
|
||||
};
|
||||
Reference in New Issue
Block a user