granular position tracking
This commit is contained in:
@@ -1,9 +1,11 @@
|
||||
#include "EpubReaderActivity.h"
|
||||
|
||||
#include <Epub/Page.h>
|
||||
#include <Epub/Section.h>
|
||||
#include <FsHelpers.h>
|
||||
#include <GfxRenderer.h>
|
||||
#include <SDCardManager.h>
|
||||
#include <Serialization.h>
|
||||
|
||||
#include "BookManager.h"
|
||||
#include "CrossPointSettings.h"
|
||||
@@ -22,6 +24,10 @@ namespace {
|
||||
constexpr unsigned long skipChapterMs = 700;
|
||||
constexpr unsigned long goHomeMs = 1000;
|
||||
constexpr int statusBarMargin = 19;
|
||||
|
||||
// Progress file version for content offset tracking
|
||||
// Version 1: Added content offset for position restoration after re-indexing
|
||||
constexpr uint8_t EPUB_PROGRESS_VERSION = 1;
|
||||
} // namespace
|
||||
|
||||
void EpubReaderActivity::taskTrampoline(void* param) {
|
||||
@@ -101,11 +107,47 @@ void EpubReaderActivity::onEnter() {
|
||||
|
||||
FsFile f;
|
||||
if (SdMan.openFileForRead("ERS", epub->getCachePath() + "/progress.bin", f)) {
|
||||
uint8_t data[4];
|
||||
if (f.read(data, 4) == 4) {
|
||||
currentSpineIndex = data[0] + (data[1] << 8);
|
||||
nextPageNumber = data[2] + (data[3] << 8);
|
||||
Serial.printf("[%lu] [ERS] Loaded cache: %d, %d\n", millis(), currentSpineIndex, nextPageNumber);
|
||||
const size_t fileSize = f.size();
|
||||
|
||||
if (fileSize >= 9) {
|
||||
// New format: version (1) + spineIndex (2) + pageNumber (2) + contentOffset (4) = 9 bytes
|
||||
uint8_t version;
|
||||
serialization::readPod(f, version);
|
||||
|
||||
if (version == EPUB_PROGRESS_VERSION) {
|
||||
uint16_t spineIndex, pageNumber;
|
||||
serialization::readPod(f, spineIndex);
|
||||
serialization::readPod(f, pageNumber);
|
||||
serialization::readPod(f, savedContentOffset);
|
||||
|
||||
currentSpineIndex = spineIndex;
|
||||
nextPageNumber = pageNumber;
|
||||
hasContentOffset = true;
|
||||
|
||||
Serial.printf("[%lu] [ERS] Loaded progress v1: spine %d, page %d, offset %u\n",
|
||||
millis(), currentSpineIndex, nextPageNumber, savedContentOffset);
|
||||
} else {
|
||||
// Unknown version, try legacy format
|
||||
f.seek(0);
|
||||
uint8_t data[4];
|
||||
if (f.read(data, 4) == 4) {
|
||||
currentSpineIndex = data[0] + (data[1] << 8);
|
||||
nextPageNumber = data[2] + (data[3] << 8);
|
||||
hasContentOffset = false;
|
||||
Serial.printf("[%lu] [ERS] Loaded legacy progress (unknown version %d): spine %d, page %d\n",
|
||||
millis(), version, currentSpineIndex, nextPageNumber);
|
||||
}
|
||||
}
|
||||
} else if (fileSize >= 4) {
|
||||
// Legacy format: just spineIndex (2) + pageNumber (2) = 4 bytes
|
||||
uint8_t data[4];
|
||||
if (f.read(data, 4) == 4) {
|
||||
currentSpineIndex = data[0] + (data[1] << 8);
|
||||
nextPageNumber = data[2] + (data[3] << 8);
|
||||
hasContentOffset = false;
|
||||
Serial.printf("[%lu] [ERS] Loaded legacy progress: spine %d, page %d\n",
|
||||
millis(), currentSpineIndex, nextPageNumber);
|
||||
}
|
||||
}
|
||||
f.close();
|
||||
}
|
||||
@@ -435,10 +477,13 @@ void EpubReaderActivity::renderScreen() {
|
||||
const uint16_t viewportWidth = renderer.getScreenWidth() - orientedMarginLeft - orientedMarginRight;
|
||||
const uint16_t viewportHeight = renderer.getScreenHeight() - orientedMarginTop - orientedMarginBottom;
|
||||
|
||||
bool sectionWasReIndexed = false;
|
||||
|
||||
if (!section->loadSectionFile(SETTINGS.getReaderFontId(), SETTINGS.getReaderLineCompression(),
|
||||
SETTINGS.extraParagraphSpacing, SETTINGS.paragraphAlignment, viewportWidth,
|
||||
viewportHeight, SETTINGS.hyphenationEnabled)) {
|
||||
Serial.printf("[%lu] [ERS] Cache not found, building...\n", millis());
|
||||
sectionWasReIndexed = true;
|
||||
|
||||
// Progress bar dimensions
|
||||
constexpr int barWidth = 200;
|
||||
@@ -491,9 +536,21 @@ void EpubReaderActivity::renderScreen() {
|
||||
Serial.printf("[%lu] [ERS] Cache found, skipping build...\n", millis());
|
||||
}
|
||||
|
||||
// Determine the correct page to display
|
||||
if (nextPageNumber == UINT16_MAX) {
|
||||
// Special case: go to last page
|
||||
section->currentPage = section->pageCount - 1;
|
||||
} else if (sectionWasReIndexed && hasContentOffset) {
|
||||
// Section was re-indexed (settings changed) and we have a content offset
|
||||
// Use the offset to find the correct page
|
||||
const int restoredPage = section->findPageForContentOffset(savedContentOffset);
|
||||
section->currentPage = restoredPage;
|
||||
Serial.printf("[%lu] [ERS] Restored position via offset: %u -> page %d (was page %d)\n",
|
||||
millis(), savedContentOffset, restoredPage, nextPageNumber);
|
||||
// Clear the offset flag since we've used it
|
||||
hasContentOffset = false;
|
||||
} else {
|
||||
// Normal case: use the saved page number
|
||||
section->currentPage = nextPageNumber;
|
||||
}
|
||||
}
|
||||
@@ -540,16 +597,21 @@ void EpubReaderActivity::renderScreen() {
|
||||
Serial.printf("[%lu] [ERS] Rendered page in %dms\n", millis(), millis() - start);
|
||||
}
|
||||
|
||||
// Save progress
|
||||
// Save progress with content offset for position restoration after re-indexing
|
||||
FsFile f;
|
||||
if (SdMan.openFileForWrite("ERS", epub->getCachePath() + "/progress.bin", f)) {
|
||||
uint8_t data[4];
|
||||
data[0] = currentSpineIndex & 0xFF;
|
||||
data[1] = (currentSpineIndex >> 8) & 0xFF;
|
||||
data[2] = section->currentPage & 0xFF;
|
||||
data[3] = (section->currentPage >> 8) & 0xFF;
|
||||
f.write(data, 4);
|
||||
// Get content offset for current page
|
||||
const uint32_t contentOffset = section->getContentOffsetForPage(section->currentPage);
|
||||
|
||||
// New format: version (1) + spineIndex (2) + pageNumber (2) + contentOffset (4) = 9 bytes
|
||||
serialization::writePod(f, EPUB_PROGRESS_VERSION);
|
||||
serialization::writePod(f, static_cast<uint16_t>(currentSpineIndex));
|
||||
serialization::writePod(f, static_cast<uint16_t>(section->currentPage));
|
||||
serialization::writePod(f, contentOffset);
|
||||
|
||||
f.close();
|
||||
Serial.printf("[%lu] [ERS] Saved progress: spine %d, page %d, offset %u\n",
|
||||
millis(), currentSpineIndex, section->currentPage, contentOffset);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user