fix: Fix kosync repositioning issue (#783)

## Summary

* Original implementation had inconsistent positioning logic:
- When XPath parsing succeeded: incorrectly set pageNumber = 0 (always
beginning of chapter)
- When XPath parsing failed: used percentage for positioning (worked
correctly)
- Result: Positions restored to wrong locations depending on XPath
parsing success
  - Mentioned in Issue #581 
* Solution
- Unified ProgressMapper::toCrossPoint() to use percentage-based
positioning exclusively for both spine identification and intra-chapter
page calculation, eliminating unreliable XPath parsing entirely.

## Additional Context

* ProgressMapper.cpp: Simplified toCrossPoint() to always use percentage
for positioning, removed parseDocFragmentIndex() function
* ProgressMapper.h: Updated comments and removed unused function
declaration
* Tests confirmed appropriate positioning
* __Notabene: the syncing to another device will (most probably) end up
at the current chapter of crosspoints reading position. There is not
much we can do about it, as KOReader needs to have the correct XPath
information - we can only provide an apporximate position (plus
percentage) - the percentage information is not used in KOReaders
current implementation__
---

### AI Usage

While CrossPoint doesn't have restrictions on AI tools in contributing,
please be transparent about their usage as it
helps set the right context for reviewers.

Did you use AI tools to help write this code? YES
This commit is contained in:
jpirnay
2026-02-19 11:38:46 +01:00
committed by cottongin
parent ef52af1a52
commit c8ddb6b61d
3 changed files with 69 additions and 66 deletions

View File

@@ -50,23 +50,18 @@ class ProgressMapper {
*
* @param epub The EPUB book
* @param koPos KOReader position
* @param totalPagesInSpine Total pages in the target spine item (for page estimation)
* @param currentSpineIndex Index of the currently open spine item (for density estimation)
* @param totalPagesInCurrentSpine Total pages in the current spine item (for density estimation)
* @return CrossPoint position
*/
static CrossPointPosition toCrossPoint(const std::shared_ptr<Epub>& epub, const KOReaderPosition& koPos,
int totalPagesInSpine = 0);
int currentSpineIndex = -1, int totalPagesInCurrentSpine = 0);
private:
/**
* Generate XPath for KOReader compatibility.
* Format: /body/DocFragment[spineIndex+1]/body/p[estimatedParagraph]
* Paragraph is estimated based on page position within the chapter.
* Format: /body/DocFragment[spineIndex+1]/body
* Since CrossPoint doesn't preserve HTML structure, we rely on percentage for positioning.
*/
static std::string generateXPath(int spineIndex, int pageNumber, int totalPages);
/**
* Parse DocFragment index from XPath string.
* Returns -1 if not found.
*/
static int parseDocFragmentIndex(const std::string& xpath);
};