feat: Integrate PR #857 dictionary intelligence and sub-activity refactor
Pull in the full feature update from PR #857 while preserving fork advantages (HTML parsing, custom drawHints, PageForward/PageBack, cache management, stardictCmp, /.dictionary/ paths). - Add morphological stemming (getStemVariants), Levenshtein edit distance, and fuzzy matching (findSimilar) to Dictionary - Create DictionarySuggestionsActivity for "Did you mean?" flow - Add onDone callback to DictionaryDefinitionActivity for direct exit-to-reader via "Done" button - Refactor DictionaryWordSelectActivity to ActivityWithSubactivity with cascading lookup (exact → stems → suggestions → not found), en-dash/em-dash splitting, and cross-page hyphenation - Refactor LookedUpWordsActivity with reverse-chronological order, inline cascading lookup, UITheme-aware rendering, and sub-activities - Simplify EpubReaderActivity LOOKUP/LOOKED_UP_WORDS handlers Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -19,7 +19,6 @@
|
||||
#include "fontIds.h"
|
||||
#include "util/BookmarkStore.h"
|
||||
#include "util/Dictionary.h"
|
||||
#include "util/LookupHistory.h"
|
||||
|
||||
namespace {
|
||||
// pagesPerRefresh now comes from SETTINGS.getRefreshFrequency()
|
||||
@@ -665,24 +664,27 @@ void EpubReaderActivity::onReaderMenuConfirm(EpubReaderMenuActivity::MenuAction
|
||||
const std::string bookCachePath = epub->getCachePath();
|
||||
const uint8_t currentOrientation = SETTINGS.orientation;
|
||||
|
||||
// Get first word of next page for cross-page hyphenation
|
||||
std::string nextPageFirstWord;
|
||||
if (section && section->currentPage < section->pageCount - 1) {
|
||||
int savedPage = section->currentPage;
|
||||
section->currentPage = savedPage + 1;
|
||||
auto nextPage = section->loadPageFromSectionFile();
|
||||
section->currentPage = savedPage;
|
||||
if (nextPage && !nextPage->elements.empty()) {
|
||||
const auto* firstLine = static_cast<const PageLine*>(nextPage->elements[0].get());
|
||||
if (firstLine->getBlock() && !firstLine->getBlock()->getWords().empty()) {
|
||||
nextPageFirstWord = firstLine->getBlock()->getWords().front();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exitActivity();
|
||||
|
||||
if (pageForLookup) {
|
||||
enterNewActivity(new DictionaryWordSelectActivity(
|
||||
renderer, mappedInput, std::move(pageForLookup), readerFontId, orientedMarginLeft, orientedMarginTop,
|
||||
bookCachePath, currentOrientation,
|
||||
[this]() {
|
||||
// On back from word select
|
||||
pendingSubactivityExit = true;
|
||||
},
|
||||
[this, bookCachePath, readerFontId, currentOrientation](const std::string& headword,
|
||||
const std::string& definition) {
|
||||
// On successful lookup - show definition
|
||||
exitActivity();
|
||||
enterNewActivity(new DictionaryDefinitionActivity(renderer, mappedInput, headword, definition,
|
||||
readerFontId, currentOrientation,
|
||||
[this]() { pendingSubactivityExit = true; }));
|
||||
}));
|
||||
bookCachePath, currentOrientation, [this]() { pendingSubactivityExit = true; }, nextPageFirstWord));
|
||||
}
|
||||
|
||||
xSemaphoreGive(renderingMutex);
|
||||
@@ -690,36 +692,11 @@ void EpubReaderActivity::onReaderMenuConfirm(EpubReaderMenuActivity::MenuAction
|
||||
}
|
||||
case EpubReaderMenuActivity::MenuAction::LOOKED_UP_WORDS: {
|
||||
xSemaphoreTake(renderingMutex, portMAX_DELAY);
|
||||
const std::string bookCachePath = epub->getCachePath();
|
||||
const int readerFontId = SETTINGS.getReaderFontId();
|
||||
const uint8_t currentOrientation = SETTINGS.orientation;
|
||||
|
||||
exitActivity();
|
||||
enterNewActivity(new LookedUpWordsActivity(
|
||||
renderer, mappedInput, bookCachePath,
|
||||
[this]() {
|
||||
// On back from looked up words
|
||||
pendingSubactivityExit = true;
|
||||
},
|
||||
[this, bookCachePath, readerFontId, currentOrientation](const std::string& headword) {
|
||||
// Look up the word and show definition with progress bar
|
||||
Rect popupLayout = GUI.drawPopup(renderer, "Looking up...");
|
||||
|
||||
std::string definition = Dictionary::lookup(
|
||||
headword, [this, &popupLayout](int percent) { GUI.fillPopupProgress(renderer, popupLayout, percent); });
|
||||
|
||||
if (definition.empty()) {
|
||||
GUI.drawPopup(renderer, "Not found");
|
||||
renderer.displayBuffer(HalDisplay::FAST_REFRESH);
|
||||
vTaskDelay(1500 / portTICK_PERIOD_MS);
|
||||
return;
|
||||
}
|
||||
|
||||
exitActivity();
|
||||
enterNewActivity(new DictionaryDefinitionActivity(renderer, mappedInput, headword, definition, readerFontId,
|
||||
currentOrientation,
|
||||
[this]() { pendingSubactivityExit = true; }));
|
||||
}));
|
||||
renderer, mappedInput, epub->getCachePath(), SETTINGS.getReaderFontId(), SETTINGS.orientation,
|
||||
[this]() { pendingSubactivityExit = true; }, [this]() { pendingSubactivityExit = true; }));
|
||||
xSemaphoreGive(renderingMutex);
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user