Merge pull request #130 from jpirnay/fix-kosync-upload

fix: Reestablish 1.37 kosync upload behaviour
This commit is contained in:
jpirnay
2026-04-24 15:47:05 +02:00
committed by GitHub
2 changed files with 13 additions and 22 deletions
@@ -38,12 +38,16 @@ via a KOReader contributor mapping spine items to DocFragment numbers.
Implemented in `ProgressMapper::toKOReader`. Implemented in `ProgressMapper::toKOReader`.
1. Compute overall `percentage` from chapter/page. 1. Compute overall `percentage` from chapter/page.
2. If a paragraph index is available from the section cache LUT (`CrossPointPosition::hasParagraphIndex`), 2. Generate XPath via byte-offset estimation (`ChapterXPathIndexer::findXPathForProgress`),
generate an XPath directly: `/body/DocFragment[spineIndex + 1]/body/p[paragraphIndex]`. producing a `…/text()[K].M` anchor proportional to intra-spine progress.
3. Otherwise, attempt byte-offset estimation via `ChapterXPathIndexer::findXPathForProgress`. 3. If XPath extraction fails, fallback to synthetic chapter path:
4. If XPath extraction fails, fallback to synthetic chapter path:
- `/body/DocFragment[spineIndex + 1]/body` - `/body/DocFragment[spineIndex + 1]/body`
The paragraph LUT (see below) is intentionally **not** used for upload: snapping to the
start of `p[N]` when the user is mid-paragraph causes pulled positions to land at the
start of the paragraph (and at the start of the chapter when an opening paragraph spans
many pages). The LUT remains in use for the reverse direction.
### KOReader -> CrossPoint ### KOReader -> CrossPoint
Implemented in `ProgressMapper::toCrossPoint`. Implemented in `ProgressMapper::toCrossPoint`.
+5 -18
View File
@@ -57,24 +57,11 @@ KOReaderPosition ProgressMapper::toKOReader(const std::shared_ptr<Epub>& epub, c
// Calculate overall book progress (0.0-1.0) // Calculate overall book progress (0.0-1.0)
result.percentage = epub->calculateProgress(pos.spineIndex, intraSpineProgress); result.percentage = epub->calculateProgress(pos.spineIndex, intraSpineProgress);
// Generate XPath for the current position. // Generate XPath for the current position via byte-offset scan. Targeting the
// When we have a paragraph index from the section LUT, target that specific <p> element // paragraph LUT entry instead would snap to the start of the paragraph the user
// directly — this produces a structurally precise full-ancestry path even for chapters // is inside, which causes pulled positions to land at the start of the chapter
// where paragraphs are nested inside divs/sections. Fall back to the progress-based // when an opening paragraph spans many pages.
// scan (which works for any content) when no paragraph index is available. result.xpath = ChapterXPathIndexer::findXPathForProgress(epub, pos.spineIndex, intraSpineProgress);
if (pos.hasParagraphIndex && pos.paragraphIndex > 0) {
// When a seek hint is set, the LUT entry's paragraphIndex equals pos.paragraphIndex
// (both describe the same page). The byte offset now points at the body-child element
// that was current at the page break, so re-parsing from there will re-encounter that
// paragraph — seed startParagraphCount with paragraphIndex-1 to avoid double counting.
const uint16_t startCount =
pos.xhtmlSeekHint > 0 && pos.paragraphIndex > 0 ? static_cast<uint16_t>(pos.paragraphIndex - 1) : 0;
result.xpath = ChapterXPathIndexer::findXPathForParagraph(epub, pos.spineIndex, pos.paragraphIndex,
pos.xhtmlSeekHint, startCount);
}
if (result.xpath.empty()) {
result.xpath = ChapterXPathIndexer::findXPathForProgress(epub, pos.spineIndex, intraSpineProgress);
}
if (result.xpath.empty()) { if (result.xpath.empty()) {
result.xpath = generateXPath(pos.spineIndex); result.xpath = generateXPath(pos.spineIndex);
} }