diff --git a/lib/Epub/Epub/Section.cpp b/lib/Epub/Epub/Section.cpp index 9365df20..bae3f9bf 100644 --- a/lib/Epub/Epub/Section.cpp +++ b/lib/Epub/Epub/Section.cpp @@ -135,7 +135,7 @@ bool Section::clearCache() const { bool Section::createSectionFile(const int fontId, const float lineCompression, const bool extraParagraphSpacing, const uint8_t paragraphAlignment, const uint16_t viewportWidth, const uint16_t viewportHeight, const bool hyphenationEnabled, const bool embeddedStyle, - const uint8_t imageRendering, const std::function& popupFn) { + const uint8_t imageRendering, const std::function& progressFn) { const auto localPath = epub->getSpineItem(spineIndex).href; const auto tmpHtmlPath = epub->getCachePath() + "/.tmp_" + std::to_string(spineIndex) + ".html"; @@ -207,7 +207,7 @@ bool Section::createSectionFile(const int fontId, const float lineCompression, c epub, tmpHtmlPath, renderer, fontId, lineCompression, extraParagraphSpacing, paragraphAlignment, viewportWidth, viewportHeight, hyphenationEnabled, [this, &lut](std::unique_ptr page) { lut.emplace_back(this->onPageComplete(std::move(page))); }, - embeddedStyle, contentBase, imageBasePath, imageRendering, popupFn, cssParser); + embeddedStyle, contentBase, imageBasePath, imageRendering, progressFn, cssParser); Hyphenator::setPreferredLanguage(epub->getLanguage()); success = visitor.parseAndBuildPages(); diff --git a/lib/Epub/Epub/Section.h b/lib/Epub/Epub/Section.h index 6f002c44..2c733ea8 100644 --- a/lib/Epub/Epub/Section.h +++ b/lib/Epub/Epub/Section.h @@ -37,7 +37,7 @@ class Section { bool clearCache() const; bool createSectionFile(int fontId, float lineCompression, bool extraParagraphSpacing, uint8_t paragraphAlignment, uint16_t viewportWidth, uint16_t viewportHeight, bool hyphenationEnabled, bool embeddedStyle, - uint8_t imageRendering, const std::function& popupFn = nullptr); + uint8_t imageRendering, const std::function& progressFn = nullptr); std::unique_ptr loadPageFromSectionFile(); // Look up the page number for an anchor id from the section cache file. diff --git a/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp b/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp index 8e014c07..6cdd9140 100644 --- a/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp +++ b/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp @@ -971,9 +971,13 @@ bool ChapterHtmlSlimParser::parseAndBuildPages() { return false; } - // Get file size to decide whether to show indexing popup. - if (popupFn && file.size() >= MIN_SIZE_FOR_POPUP) { - popupFn(); + const size_t totalFileSize = file.size(); + size_t bytesRead = 0; + int lastReportedProgress = -1; + + // Show initial progress popup for files above threshold. + if (progressFn && totalFileSize >= MIN_SIZE_FOR_POPUP) { + progressFn(0); } XML_SetUserData(parser, this); @@ -995,6 +999,16 @@ bool ChapterHtmlSlimParser::parseAndBuildPages() { } const size_t len = file.read(buf, PARSE_BUFFER_SIZE); + bytesRead += len; + + // Report progress in 5% increments to limit e-ink refreshes. + if (progressFn && totalFileSize >= MIN_SIZE_FOR_POPUP) { + const int progress = static_cast(bytesRead * 100 / totalFileSize); + if (progress / 5 > lastReportedProgress / 5) { + lastReportedProgress = progress; + progressFn(progress); + } + } if (len == 0 && file.available() > 0) { LOG_ERR("EHP", "File read error"); diff --git a/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.h b/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.h index 1cc0ea39..9b8d6b9c 100644 --- a/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.h +++ b/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.h @@ -26,7 +26,7 @@ class ChapterHtmlSlimParser { const std::string& filepath; GfxRenderer& renderer; std::function)> completePageFn; - std::function popupFn; // Popup callback + std::function progressFn; // Progress callback (0-100) int depth = 0; int skipUntilDepth = INT_MAX; int boldUntilDepth = INT_MAX; @@ -102,7 +102,8 @@ class ChapterHtmlSlimParser { const std::function)>& completePageFn, const bool embeddedStyle, const std::string& contentBase, const std::string& imageBasePath, const uint8_t imageRendering = 0, - const std::function& popupFn = nullptr, const CssParser* cssParser = nullptr) + const std::function& progressFn = nullptr, + const CssParser* cssParser = nullptr) : epub(epub), filepath(filepath), @@ -115,7 +116,7 @@ class ChapterHtmlSlimParser { viewportHeight(viewportHeight), hyphenationEnabled(hyphenationEnabled), completePageFn(completePageFn), - popupFn(popupFn), + progressFn(progressFn), cssParser(cssParser), embeddedStyle(embeddedStyle), imageRendering(imageRendering), diff --git a/src/activities/reader/EpubReaderActivity.cpp b/src/activities/reader/EpubReaderActivity.cpp index 0ce1c5b1..78187386 100644 --- a/src/activities/reader/EpubReaderActivity.cpp +++ b/src/activities/reader/EpubReaderActivity.cpp @@ -544,12 +544,18 @@ void EpubReaderActivity::render(RenderLock&& lock) { SETTINGS.imageRendering)) { LOG_DBG("ERS", "Cache not found, building..."); - const auto popupFn = [this]() { GUI.drawPopup(renderer, tr(STR_INDEXING)); }; + Rect popupRect{}; + const auto progressFn = [this, &popupRect](int progress) { + if (popupRect.width == 0) { + popupRect = GUI.drawPopup(renderer, tr(STR_INDEXING)); + } + GUI.fillPopupProgress(renderer, popupRect, progress); + }; if (!section->createSectionFile(SETTINGS.getReaderFontId(), SETTINGS.getReaderLineCompression(), SETTINGS.extraParagraphSpacing, SETTINGS.paragraphAlignment, viewportWidth, viewportHeight, SETTINGS.hyphenationEnabled, SETTINGS.embeddedStyle, - SETTINGS.imageRendering, popupFn)) { + SETTINGS.imageRendering, progressFn)) { LOG_ERR("ERS", "Failed to persist page data to SD"); section.reset(); return;