Phase 4- Full format support

This commit is contained in:
jpirnay
2026-05-20 00:25:06 +02:00
parent dddb3c1bcb
commit dcbe79aab2
3 changed files with 48 additions and 4 deletions
+15 -1
View File
@@ -16,10 +16,12 @@
#include "CrossPointSettings.h" #include "CrossPointSettings.h"
#include "CrossPointState.h" #include "CrossPointState.h"
#include "FinishedBookActivity.h" #include "FinishedBookActivity.h"
#include "KOReaderDocumentId.h"
#include "MappedInputManager.h" #include "MappedInputManager.h"
#include "MdReaderTocSelectionActivity.h" #include "MdReaderTocSelectionActivity.h"
#include "ReaderActivity.h" #include "ReaderActivity.h"
#include "ReaderUtils.h" #include "ReaderUtils.h"
#include "ReadingSessionTracker.h"
#include "RecentBooksStore.h" #include "RecentBooksStore.h"
#include "components/UITheme.h" #include "components/UITheme.h"
#include "fontIds.h" #include "fontIds.h"
@@ -60,6 +62,9 @@ void MdReaderActivity::onEnter() {
const std::string txtCover = txtSidecar.empty() ? txt->getThumbBmpPath() : txtSidecar; const std::string txtCover = txtSidecar.empty() ? txt->getThumbBmpPath() : txtSidecar;
RECENT_BOOKS.addBook(filePath, fileName, "", "", txtCover); RECENT_BOOKS.addBook(filePath, fileName, "", "", txtCover);
// Start the stats session.
globalReadingSessionTracker().begin(KOReaderDocumentId::calculateFromFilename(filePath), fileName, "");
requestUpdate(); requestUpdate();
} }
@@ -218,6 +223,9 @@ void MdReaderActivity::scanHeadings() {
void MdReaderActivity::onExit() { void MdReaderActivity::onExit() {
Activity::onExit(); Activity::onExit();
// Flush the stats session before tearing down the reader.
globalReadingSessionTracker().end();
renderer.setOrientation(GfxRenderer::Orientation::Portrait); renderer.setOrientation(GfxRenderer::Orientation::Portrait);
pageOffsets.clear(); pageOffsets.clear();
@@ -269,6 +277,7 @@ void MdReaderActivity::loop() {
if (currentPage > 0) { if (currentPage > 0) {
currentPage--; currentPage--;
currentHeadingIndex = getHeadingIndexForOffset(pageOffsets[currentPage]); currentHeadingIndex = getHeadingIndexForOffset(pageOffsets[currentPage]);
globalReadingSessionTracker().onPageTurn();
requestUpdate(); requestUpdate();
} }
return; return;
@@ -279,6 +288,7 @@ void MdReaderActivity::loop() {
if (currentPage < totalPages - 1) { if (currentPage < totalPages - 1) {
currentPage++; currentPage++;
currentHeadingIndex = getHeadingIndexForOffset(pageOffsets[currentPage]); currentHeadingIndex = getHeadingIndexForOffset(pageOffsets[currentPage]);
globalReadingSessionTracker().onPageTurn();
requestUpdate(); requestUpdate();
} else { } else {
saveProgress(); 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) // 7-byte format matching TxtReaderActivity: page(2 bytes LE) + file offset(4 bytes LE) + overallPercent(1 byte)
const size_t offset = const size_t offset =
(currentPage >= 0 && currentPage < static_cast<int>(pageOffsets.size())) ? pageOffsets[currentPage] : 0; (currentPage >= 0 && currentPage < static_cast<int>(pageOffsets.size())) ? pageOffsets[currentPage] : 0;
const uint8_t percent = ReaderUtils::pageProgressPercentByte(currentPage, totalPages);
uint8_t data[7]; uint8_t data[7];
data[0] = currentPage & 0xFF; data[0] = currentPage & 0xFF;
data[1] = (currentPage >> 8) & 0xFF; data[1] = (currentPage >> 8) & 0xFF;
@@ -921,9 +932,10 @@ void MdReaderActivity::saveProgress() const {
data[3] = (offset >> 8) & 0xFF; data[3] = (offset >> 8) & 0xFF;
data[4] = (offset >> 16) & 0xFF; data[4] = (offset >> 16) & 0xFF;
data[5] = (offset >> 24) & 0xFF; data[5] = (offset >> 24) & 0xFF;
data[6] = ReaderUtils::pageProgressPercentByte(currentPage, totalPages); data[6] = percent;
f.write(data, 7); f.write(data, 7);
f.close(); f.close();
globalReadingSessionTracker().updateProgress(percent);
} }
} }
@@ -1082,6 +1094,7 @@ void MdReaderActivity::onButtonAction(const CrossPointSettings::BUTTON_ACTION ac
if (currentPage < totalPages - 1) { if (currentPage < totalPages - 1) {
currentPage++; currentPage++;
currentHeadingIndex = pageOffsets.empty() ? -1 : getHeadingIndexForOffset(pageOffsets[currentPage]); currentHeadingIndex = pageOffsets.empty() ? -1 : getHeadingIndexForOffset(pageOffsets[currentPage]);
globalReadingSessionTracker().onPageTurn();
requestUpdate(); requestUpdate();
} }
break; break;
@@ -1089,6 +1102,7 @@ void MdReaderActivity::onButtonAction(const CrossPointSettings::BUTTON_ACTION ac
if (currentPage > 0) { if (currentPage > 0) {
currentPage--; currentPage--;
currentHeadingIndex = pageOffsets.empty() ? -1 : getHeadingIndexForOffset(pageOffsets[currentPage]); currentHeadingIndex = pageOffsets.empty() ? -1 : getHeadingIndexForOffset(pageOffsets[currentPage]);
globalReadingSessionTracker().onPageTurn();
requestUpdate(); requestUpdate();
} }
break; break;
+17 -1
View File
@@ -15,9 +15,11 @@
#include "CrossPointState.h" #include "CrossPointState.h"
#include "FinishedBookActivity.h" #include "FinishedBookActivity.h"
#include "GlobalBookmarkIndex.h" #include "GlobalBookmarkIndex.h"
#include "KOReaderDocumentId.h"
#include "MappedInputManager.h" #include "MappedInputManager.h"
#include "ReaderActivity.h" #include "ReaderActivity.h"
#include "ReaderUtils.h" #include "ReaderUtils.h"
#include "ReadingSessionTracker.h"
#include "RecentBooksStore.h" #include "RecentBooksStore.h"
#include "StarredPagesActivity.h" #include "StarredPagesActivity.h"
#include "components/UITheme.h" #include "components/UITheme.h"
@@ -124,6 +126,10 @@ void TxtReaderActivity::onEnter() {
const std::string txtCover = txtSidecar.empty() ? txt->getThumbBmpPath() : txtSidecar; const std::string txtCover = txtSidecar.empty() ? txt->getThumbBmpPath() : txtSidecar;
RECENT_BOOKS.addBook(filePath, fileName, "", "", txtCover); 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 // Trigger first update
requestUpdate(); requestUpdate();
} }
@@ -131,6 +137,10 @@ void TxtReaderActivity::onEnter() {
void TxtReaderActivity::onExit() { void TxtReaderActivity::onExit() {
Activity::onExit(); Activity::onExit();
// Flush the stats session before tearing down the txt — same pattern as
// EpubReaderActivity::onExit().
globalReadingSessionTracker().end();
// Save bookmarks before exit // Save bookmarks before exit
bookmarkStore.save(); bookmarkStore.save();
if (txt) { if (txt) {
@@ -195,6 +205,7 @@ void TxtReaderActivity::loop() {
ev.type == ButtonEventManager::PressType::Short) { ev.type == ButtonEventManager::PressType::Short) {
if (currentPage > 0) { if (currentPage > 0) {
currentPage--; currentPage--;
globalReadingSessionTracker().onPageTurn();
requestUpdate(); requestUpdate();
} }
return; return;
@@ -204,6 +215,7 @@ void TxtReaderActivity::loop() {
ev.type == ButtonEventManager::PressType::Short) { ev.type == ButtonEventManager::PressType::Short) {
if (currentPage < totalPages - 1) { if (currentPage < totalPages - 1) {
currentPage++; currentPage++;
globalReadingSessionTracker().onPageTurn();
requestUpdate(); requestUpdate();
} else { } else {
launchFinishedBookFlow(); launchFinishedBookFlow();
@@ -220,11 +232,13 @@ void TxtReaderActivity::loop() {
if (prevTriggered) { if (prevTriggered) {
if (currentPage > 0) { if (currentPage > 0) {
currentPage--; currentPage--;
globalReadingSessionTracker().onPageTurn();
requestUpdate(); requestUpdate();
} }
} else if (nextTriggered) { } else if (nextTriggered) {
if (currentPage < totalPages - 1) { if (currentPage < totalPages - 1) {
currentPage++; currentPage++;
globalReadingSessionTracker().onPageTurn();
requestUpdate(); requestUpdate();
} else { } else {
launchFinishedBookFlow(); launchFinishedBookFlow();
@@ -515,6 +529,7 @@ void TxtReaderActivity::saveProgress() const {
// 7-byte format: page(2 bytes LE) + file offset(4 bytes LE) + overallPercent(1 byte) // 7-byte format: page(2 bytes LE) + file offset(4 bytes LE) + overallPercent(1 byte)
// The offset lets drawCurrentPageToBuffer render without requiring index.bin. // The offset lets drawCurrentPageToBuffer render without requiring index.bin.
const size_t offset = (currentPage < static_cast<int>(pageOffsets.size())) ? pageOffsets[currentPage] : 0; const size_t offset = (currentPage < static_cast<int>(pageOffsets.size())) ? pageOffsets[currentPage] : 0;
const uint8_t percent = ReaderUtils::pageProgressPercentByte(currentPage, totalPages);
uint8_t data[7]; uint8_t data[7];
data[0] = currentPage & 0xFF; data[0] = currentPage & 0xFF;
data[1] = (currentPage >> 8) & 0xFF; data[1] = (currentPage >> 8) & 0xFF;
@@ -522,9 +537,10 @@ void TxtReaderActivity::saveProgress() const {
data[3] = (offset >> 8) & 0xFF; data[3] = (offset >> 8) & 0xFF;
data[4] = (offset >> 16) & 0xFF; data[4] = (offset >> 16) & 0xFF;
data[5] = (offset >> 24) & 0xFF; data[5] = (offset >> 24) & 0xFF;
data[6] = ReaderUtils::pageProgressPercentByte(currentPage, totalPages); data[6] = percent;
f.write(data, 7); f.write(data, 7);
f.close(); f.close();
globalReadingSessionTracker().updateProgress(percent);
} }
} }
+16 -2
View File
@@ -17,9 +17,11 @@
#include "CrossPointSettings.h" #include "CrossPointSettings.h"
#include "CrossPointState.h" #include "CrossPointState.h"
#include "FinishedBookActivity.h" #include "FinishedBookActivity.h"
#include "KOReaderDocumentId.h"
#include "MappedInputManager.h" #include "MappedInputManager.h"
#include "ReaderActivity.h" #include "ReaderActivity.h"
#include "ReaderUtils.h" #include "ReaderUtils.h"
#include "ReadingSessionTracker.h"
#include "RecentBooksStore.h" #include "RecentBooksStore.h"
#include "XtcReaderChapterSelectionActivity.h" #include "XtcReaderChapterSelectionActivity.h"
#include "components/UITheme.h" #include "components/UITheme.h"
@@ -48,6 +50,11 @@ void XtcReaderActivity::onEnter() {
const std::string xtcCover = xtcSidecar.empty() ? xtc->getThumbBmpPath() : xtcSidecar; const std::string xtcCover = xtcSidecar.empty() ? xtc->getThumbBmpPath() : xtcSidecar;
RECENT_BOOKS.addBook(xtc->getPath(), xtc->getTitle(), xtc->getAuthor(), "", xtcCover); 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 // Trigger first update
requestUpdate(); requestUpdate();
} }
@@ -55,6 +62,9 @@ void XtcReaderActivity::onEnter() {
void XtcReaderActivity::onExit() { void XtcReaderActivity::onExit() {
Activity::onExit(); Activity::onExit();
// Flush stats session before tearing down the XTC reader.
globalReadingSessionTracker().end();
APP_STATE.readerActivityLoadCount = 0; APP_STATE.readerActivityLoadCount = 0;
APP_STATE.saveToFile(); APP_STATE.saveToFile();
@@ -182,10 +192,12 @@ void XtcReaderActivity::loop() {
if (prevTriggered) { if (prevTriggered) {
if (currentPage > 0) { if (currentPage > 0) {
currentPage--; currentPage--;
globalReadingSessionTracker().onPageTurn();
requestUpdate(); requestUpdate();
} }
} else if (nextTriggered) { } else if (nextTriggered) {
currentPage++; currentPage++;
globalReadingSessionTracker().onPageTurn();
requestUpdate(); requestUpdate();
} }
} }
@@ -393,15 +405,17 @@ void XtcReaderActivity::renderPage() {
void XtcReaderActivity::saveProgress() const { void XtcReaderActivity::saveProgress() const {
FsFile f; FsFile f;
if (Storage.openFileForWrite("XTR", xtc->getCachePath() + "/progress.bin", f)) { if (Storage.openFileForWrite("XTR", xtc->getCachePath() + "/progress.bin", f)) {
const uint8_t percent =
ReaderUtils::pageProgressPercentByte(static_cast<int>(currentPage), static_cast<int>(xtc->getPageCount()));
uint8_t data[5]; uint8_t data[5];
data[0] = currentPage & 0xFF; data[0] = currentPage & 0xFF;
data[1] = (currentPage >> 8) & 0xFF; data[1] = (currentPage >> 8) & 0xFF;
data[2] = (currentPage >> 16) & 0xFF; data[2] = (currentPage >> 16) & 0xFF;
data[3] = (currentPage >> 24) & 0xFF; data[3] = (currentPage >> 24) & 0xFF;
data[4] = data[4] = percent;
ReaderUtils::pageProgressPercentByte(static_cast<int>(currentPage), static_cast<int>(xtc->getPageCount()));
f.write(data, 5); f.write(data, 5);
f.close(); f.close();
globalReadingSessionTracker().updateProgress(percent);
} }
} }