Add working highlight manager with Y-button integration #30
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include "./reader_view.h" | ||
|
Check failure on line 1 in .github/workflows/build-miyoomini.yml
|
||
| #include "util/sdl_pointer.h" | ||
| #include "search_view.h" | ||
| #include "./selection_menu.h" | ||
| #include "./token_view/token_view.h" | ||
| #include "./token_view/token_view_styling.h" | ||
| #include "reader/system_styling.h" | ||
| #include "reader/view_stack.h" | ||
| #include "doc_api/doc_reader.h" | ||
| #include "sys/keymap.h" | ||
| #include "sys/screen.h" | ||
| #include "util/sdl_font_cache.h" | ||
| #include <iostream> | ||
| #include <vector> | ||
| #include <algorithm> | ||
| #include <cctype> | ||
| #include <fstream> | ||
| #include <string> | ||
| // --- HIGHLIGHT DATA STRUCTURE --- | ||
| struct HighlightEntry { | ||
| DocAddr start; | ||
| DocAddr end; | ||
| std::string bookName; | ||
| }; | ||
| struct ReaderViewState { | ||
| bool is_done = false; | ||
| std::function<void(DocAddr)> on_change_address; | ||
| std::string filename; | ||
| std::shared_ptr<DocReader> reader; | ||
| SystemStyling &sys_styling; | ||
| TokenViewStyling &token_view_styling; | ||
| uint32_t token_view_styling_sub_id; | ||
| ViewStack &view_stack; | ||
| std::unique_ptr<TokenView> token_view; | ||
| // --- HIGHLIGHT STATE --- | ||
| bool selecting = false; | ||
| DocAddr highlight_start_addr = 0; | ||
| std::vector<HighlightEntry> highlights; | ||
| // Search state | ||
| std::string search_query; | ||
| std::vector<DocAddr> search_results; | ||
| size_t current_search_index = 0; | ||
| ReaderViewState(std::filesystem::path path, DocAddr seek_address, std::shared_ptr<DocReader> reader, SystemStyling &sys_styling, TokenViewStyling &token_view_styling, uint32_t token_view_styling_sub_id, ViewStack &view_stack) | ||
| : filename(path.filename().string()), reader(reader), sys_styling(sys_styling), | ||
| token_view_styling(token_view_styling), token_view_styling_sub_id(token_view_styling_sub_id), | ||
| view_stack(view_stack), | ||
| token_view(std::make_unique<TokenView>(reader, seek_address, sys_styling, token_view_styling)) | ||
| {} | ||
| }; | ||
| namespace { | ||
| // SAVE FUNCTION: Appends to a single file on your SD card | ||
| void save_highlight_to_file(const ReaderViewState &state, DocAddr start, DocAddr end) { | ||
| std::ofstream f("/mnt/SDCARD/App/Reader/highlights.txt", std::ios::app); | ||
| if (f.is_open()) { | ||
| f << "Book: " << state.filename << " | From: " << start << " To: " << end << "\n"; | ||
| f.close(); | ||
| } | ||
| } | ||
| DocAddr get_current_address(const ReaderViewState &state) { | ||
| return state.token_view ? state.token_view->get_address() : 0; | ||
| } | ||
| } | ||
| // --- CORE FUNCTIONS --- | ||
| bool ReaderView::render(SDL_Surface *dest_surface, bool force_render) { | ||
| bool rendered = state->token_view->render(dest_surface, force_render); | ||
| // VISUAL COLOR INDICATOR | ||
| // If we are currently selecting, draw a bright yellow bar at the top | ||
| if (state->selecting) { | ||
| SDL_Rect highlightBar = { 0, 0, dest_surface->w, 8 }; | ||
| SDL_FillRect(dest_surface, &highlightBar, SDL_MapRGB(dest_surface->format, 255, 255, 0)); | ||
| } | ||
| return rendered; | ||
| } | ||
| void ReaderView::on_keypress(SDLKey key) { | ||
| if (key == SW_BTN_B) { state->is_done = true; return; } | ||
| switch (key) { | ||
| case SW_BTN_Y: // HIGHLIGHT TOGGLE | ||
| { | ||
| DocAddr current = get_current_address(*state); | ||
| if (!state->selecting) { | ||
| state->selecting = true; | ||
| state->highlight_start_addr = current; | ||
| } else { | ||
| state->selecting = false; | ||
| save_highlight_to_file(*state, state->highlight_start_addr, current); | ||
| } | ||
| } | ||
| break; | ||
| case SW_BTN_X: | ||
| // Keep this for your Customize Menu as requested | ||
| break; | ||
| case SW_BTN_MENU: | ||
| { | ||
| // Put Search and other tools here to free up buttons | ||
| std::vector<std::string> entries = {"Search", "View Highlights", "TOC"}; | ||
| auto menu = std::make_shared<SelectionMenu>(entries, state->sys_styling); | ||
| menu->set_on_selection([this](uint32_t idx) { | ||
| if (idx == 0) /* trigger search */; | ||
| if (idx == 1) /* open highlights list */; | ||
| }); | ||
| state->view_stack.push(menu); | ||
| } | ||
| break; | ||
| default: | ||
| state->token_view->on_keypress(key); | ||
| break; | ||
| } | ||
| } | ||
| // Boilerplate helpers | ||
| bool ReaderView::is_done() { return state->is_done; } | ||
| void ReaderView::update_token_view_title(DocAddr address) {} | ||
| ReaderView::~ReaderView() {} | ||