diff --git a/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.h b/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.h index 1802ac76..9eacfb19 100644 --- a/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.h +++ b/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.h @@ -84,6 +84,14 @@ class ChapterHtmlSlimParser { int xpathBodyDepth = -1; // depth of the element (-1 = not yet seen) std::vector paragraphIndexPerPage; //

index at each page completion + // Paragraph index tracking for XPath-to-page lookup table. + // Counts

sibling indices (1-based, matching XPath convention) during page building. + // Stored per page in the section cache so that XPath p[N] can be resolved to a page + // without reparsing, and current page can generate an XPath without reparsing. + uint16_t xpathParagraphIndex = 0; // current

sibling index (1-based) + int xpathBodyDepth = -1; // depth of the element (-1 = not yet seen) + std::vector paragraphIndexPerPage; //

index at each page completion + // Footnote link tracking bool insideFootnoteLink = false; int footnoteLinkDepth = -1; diff --git a/lib/hal/HalStorage.cpp b/lib/hal/HalStorage.cpp index 82b6e03c..9a6d1c9e 100644 --- a/lib/hal/HalStorage.cpp +++ b/lib/hal/HalStorage.cpp @@ -176,5 +176,8 @@ HalFile HalFile::openNextFile() { assert(impl != nullptr); return HalFile(std::make_unique(impl->file.openNextFile())); } +bool HalFile::getModifyDateTime(uint16_t* pdate, uint16_t* ptime) { + HAL_FILE_WRAPPED_CALL(getModifyDateTime, pdate, ptime); +} bool HalFile::isOpen() const { return impl != nullptr && impl->file.isOpen(); } // already thread-safe, no need to wrap HalFile::operator bool() const { return isOpen(); } diff --git a/lib/hal/HalStorage.h b/lib/hal/HalStorage.h index d9bee706..79b92178 100644 --- a/lib/hal/HalStorage.h +++ b/lib/hal/HalStorage.h @@ -95,6 +95,7 @@ class HalFile : public Print { void rewindDirectory(); bool close(); HalFile openNextFile(); + bool getModifyDateTime(uint16_t* pdate, uint16_t* ptime); bool isOpen() const; operator bool() const; }; diff --git a/src/activities/reader/KOReaderSyncActivity.cpp b/src/activities/reader/KOReaderSyncActivity.cpp index 74192b2a..ae9aa525 100644 --- a/src/activities/reader/KOReaderSyncActivity.cpp +++ b/src/activities/reader/KOReaderSyncActivity.cpp @@ -201,6 +201,7 @@ void KOReaderSyncActivity::performUpload() { { RenderLock lock(*this); state = UPLOAD_COMPLETE; + uploadCompleteTime = millis(); } requestUpdate(true); } @@ -351,6 +352,13 @@ void KOReaderSyncActivity::render(RenderLock&&) { void KOReaderSyncActivity::loop() { if (state == NO_CREDENTIALS || state == SYNC_FAILED || state == UPLOAD_COMPLETE) { + if (state == UPLOAD_COMPLETE && millis() - uploadCompleteTime >= 3000) { + ActivityResult result; + result.isCancelled = true; + setResult(std::move(result)); + finish(); + return; + } if (mappedInput.wasReleased(MappedInputManager::Button::Back)) { ActivityResult result; result.isCancelled = true; diff --git a/src/activities/reader/KOReaderSyncActivity.h b/src/activities/reader/KOReaderSyncActivity.h index 1cdd8477..d0276444 100644 --- a/src/activities/reader/KOReaderSyncActivity.h +++ b/src/activities/reader/KOReaderSyncActivity.h @@ -78,6 +78,9 @@ class KOReaderSyncActivity final : public Activity { // Selection in result screen (0=Apply, 1=Upload) int selectedOption = 0; + // Timestamp when UPLOAD_COMPLETE state was entered (for auto-close) + unsigned long uploadCompleteTime = 0; + void onWifiSelectionComplete(bool success); void performSync(); void performUpload();