diff --git a/src/activities/reader/MdReaderActivity.cpp b/src/activities/reader/MdReaderActivity.cpp index 4cf07319..330f8958 100644 --- a/src/activities/reader/MdReaderActivity.cpp +++ b/src/activities/reader/MdReaderActivity.cpp @@ -16,10 +16,12 @@ #include "CrossPointSettings.h" #include "CrossPointState.h" #include "FinishedBookActivity.h" +#include "KOReaderDocumentId.h" #include "MappedInputManager.h" #include "MdReaderTocSelectionActivity.h" #include "ReaderActivity.h" #include "ReaderUtils.h" +#include "ReadingSessionTracker.h" #include "RecentBooksStore.h" #include "components/UITheme.h" #include "fontIds.h" @@ -60,6 +62,9 @@ void MdReaderActivity::onEnter() { const std::string txtCover = txtSidecar.empty() ? txt->getThumbBmpPath() : txtSidecar; RECENT_BOOKS.addBook(filePath, fileName, "", "", txtCover); + // Start the stats session. + globalReadingSessionTracker().begin(KOReaderDocumentId::calculateFromFilename(filePath), fileName, ""); + requestUpdate(); } @@ -218,6 +223,9 @@ void MdReaderActivity::scanHeadings() { void MdReaderActivity::onExit() { Activity::onExit(); + // Flush the stats session before tearing down the reader. + globalReadingSessionTracker().end(); + renderer.setOrientation(GfxRenderer::Orientation::Portrait); pageOffsets.clear(); @@ -269,6 +277,7 @@ void MdReaderActivity::loop() { if (currentPage > 0) { currentPage--; currentHeadingIndex = getHeadingIndexForOffset(pageOffsets[currentPage]); + globalReadingSessionTracker().onPageTurn(); requestUpdate(); } return; @@ -279,6 +288,7 @@ void MdReaderActivity::loop() { if (currentPage < totalPages - 1) { currentPage++; currentHeadingIndex = getHeadingIndexForOffset(pageOffsets[currentPage]); + globalReadingSessionTracker().onPageTurn(); requestUpdate(); } else { saveProgress(); @@ -914,6 +924,7 @@ void MdReaderActivity::saveProgress() const { // 7-byte format matching TxtReaderActivity: page(2 bytes LE) + file offset(4 bytes LE) + overallPercent(1 byte) const size_t offset = (currentPage >= 0 && currentPage < static_cast(pageOffsets.size())) ? pageOffsets[currentPage] : 0; + const uint8_t percent = ReaderUtils::pageProgressPercentByte(currentPage, totalPages); uint8_t data[7]; data[0] = currentPage & 0xFF; data[1] = (currentPage >> 8) & 0xFF; @@ -921,9 +932,10 @@ void MdReaderActivity::saveProgress() const { data[3] = (offset >> 8) & 0xFF; data[4] = (offset >> 16) & 0xFF; data[5] = (offset >> 24) & 0xFF; - data[6] = ReaderUtils::pageProgressPercentByte(currentPage, totalPages); + data[6] = percent; f.write(data, 7); f.close(); + globalReadingSessionTracker().updateProgress(percent); } } @@ -1082,6 +1094,7 @@ void MdReaderActivity::onButtonAction(const CrossPointSettings::BUTTON_ACTION ac if (currentPage < totalPages - 1) { currentPage++; currentHeadingIndex = pageOffsets.empty() ? -1 : getHeadingIndexForOffset(pageOffsets[currentPage]); + globalReadingSessionTracker().onPageTurn(); requestUpdate(); } break; @@ -1089,6 +1102,7 @@ void MdReaderActivity::onButtonAction(const CrossPointSettings::BUTTON_ACTION ac if (currentPage > 0) { currentPage--; currentHeadingIndex = pageOffsets.empty() ? -1 : getHeadingIndexForOffset(pageOffsets[currentPage]); + globalReadingSessionTracker().onPageTurn(); requestUpdate(); } break; diff --git a/src/activities/reader/TxtReaderActivity.cpp b/src/activities/reader/TxtReaderActivity.cpp index 30c038fc..08fcc502 100644 --- a/src/activities/reader/TxtReaderActivity.cpp +++ b/src/activities/reader/TxtReaderActivity.cpp @@ -15,9 +15,11 @@ #include "CrossPointState.h" #include "FinishedBookActivity.h" #include "GlobalBookmarkIndex.h" +#include "KOReaderDocumentId.h" #include "MappedInputManager.h" #include "ReaderActivity.h" #include "ReaderUtils.h" +#include "ReadingSessionTracker.h" #include "RecentBooksStore.h" #include "StarredPagesActivity.h" #include "components/UITheme.h" @@ -124,6 +126,10 @@ void TxtReaderActivity::onEnter() { const std::string txtCover = txtSidecar.empty() ? txt->getThumbBmpPath() : txtSidecar; RECENT_BOOKS.addBook(filePath, fileName, "", "", txtCover); + // Start reading-stats session. Same filename-hash policy as EPUB so renamed + // files start fresh; author is unknown for plain TXT. + globalReadingSessionTracker().begin(KOReaderDocumentId::calculateFromFilename(filePath), fileName, ""); + // Trigger first update requestUpdate(); } @@ -131,6 +137,10 @@ void TxtReaderActivity::onEnter() { void TxtReaderActivity::onExit() { Activity::onExit(); + // Flush the stats session before tearing down the txt — same pattern as + // EpubReaderActivity::onExit(). + globalReadingSessionTracker().end(); + // Save bookmarks before exit bookmarkStore.save(); if (txt) { @@ -195,6 +205,7 @@ void TxtReaderActivity::loop() { ev.type == ButtonEventManager::PressType::Short) { if (currentPage > 0) { currentPage--; + globalReadingSessionTracker().onPageTurn(); requestUpdate(); } return; @@ -204,6 +215,7 @@ void TxtReaderActivity::loop() { ev.type == ButtonEventManager::PressType::Short) { if (currentPage < totalPages - 1) { currentPage++; + globalReadingSessionTracker().onPageTurn(); requestUpdate(); } else { launchFinishedBookFlow(); @@ -220,11 +232,13 @@ void TxtReaderActivity::loop() { if (prevTriggered) { if (currentPage > 0) { currentPage--; + globalReadingSessionTracker().onPageTurn(); requestUpdate(); } } else if (nextTriggered) { if (currentPage < totalPages - 1) { currentPage++; + globalReadingSessionTracker().onPageTurn(); requestUpdate(); } else { launchFinishedBookFlow(); @@ -515,6 +529,7 @@ void TxtReaderActivity::saveProgress() const { // 7-byte format: page(2 bytes LE) + file offset(4 bytes LE) + overallPercent(1 byte) // The offset lets drawCurrentPageToBuffer render without requiring index.bin. const size_t offset = (currentPage < static_cast(pageOffsets.size())) ? pageOffsets[currentPage] : 0; + const uint8_t percent = ReaderUtils::pageProgressPercentByte(currentPage, totalPages); uint8_t data[7]; data[0] = currentPage & 0xFF; data[1] = (currentPage >> 8) & 0xFF; @@ -522,9 +537,10 @@ void TxtReaderActivity::saveProgress() const { data[3] = (offset >> 8) & 0xFF; data[4] = (offset >> 16) & 0xFF; data[5] = (offset >> 24) & 0xFF; - data[6] = ReaderUtils::pageProgressPercentByte(currentPage, totalPages); + data[6] = percent; f.write(data, 7); f.close(); + globalReadingSessionTracker().updateProgress(percent); } } diff --git a/src/activities/reader/XtcReaderActivity.cpp b/src/activities/reader/XtcReaderActivity.cpp index 224596dc..a27840b4 100644 --- a/src/activities/reader/XtcReaderActivity.cpp +++ b/src/activities/reader/XtcReaderActivity.cpp @@ -17,9 +17,11 @@ #include "CrossPointSettings.h" #include "CrossPointState.h" #include "FinishedBookActivity.h" +#include "KOReaderDocumentId.h" #include "MappedInputManager.h" #include "ReaderActivity.h" #include "ReaderUtils.h" +#include "ReadingSessionTracker.h" #include "RecentBooksStore.h" #include "XtcReaderChapterSelectionActivity.h" #include "components/UITheme.h" @@ -48,6 +50,11 @@ void XtcReaderActivity::onEnter() { const std::string xtcCover = xtcSidecar.empty() ? xtc->getThumbBmpPath() : xtcSidecar; RECENT_BOOKS.addBook(xtc->getPath(), xtc->getTitle(), xtc->getAuthor(), "", xtcCover); + // Start the reading-stats session. XTC has real title/author from the + // file header so the per-book screen will look nicer than TXT/MD. + globalReadingSessionTracker().begin(KOReaderDocumentId::calculateFromFilename(xtc->getPath()), xtc->getTitle(), + xtc->getAuthor()); + // Trigger first update requestUpdate(); } @@ -55,6 +62,9 @@ void XtcReaderActivity::onEnter() { void XtcReaderActivity::onExit() { Activity::onExit(); + // Flush stats session before tearing down the XTC reader. + globalReadingSessionTracker().end(); + APP_STATE.readerActivityLoadCount = 0; APP_STATE.saveToFile(); @@ -182,10 +192,12 @@ void XtcReaderActivity::loop() { if (prevTriggered) { if (currentPage > 0) { currentPage--; + globalReadingSessionTracker().onPageTurn(); requestUpdate(); } } else if (nextTriggered) { currentPage++; + globalReadingSessionTracker().onPageTurn(); requestUpdate(); } } @@ -393,15 +405,17 @@ void XtcReaderActivity::renderPage() { void XtcReaderActivity::saveProgress() const { FsFile f; if (Storage.openFileForWrite("XTR", xtc->getCachePath() + "/progress.bin", f)) { + const uint8_t percent = + ReaderUtils::pageProgressPercentByte(static_cast(currentPage), static_cast(xtc->getPageCount())); uint8_t data[5]; data[0] = currentPage & 0xFF; data[1] = (currentPage >> 8) & 0xFF; data[2] = (currentPage >> 16) & 0xFF; data[3] = (currentPage >> 24) & 0xFF; - data[4] = - ReaderUtils::pageProgressPercentByte(static_cast(currentPage), static_cast(xtc->getPageCount())); + data[4] = percent; f.write(data, 5); f.close(); + globalReadingSessionTracker().updateProgress(percent); } }