fix(kosync): don't normalize xpointer for more accurate progress sync, closes #3672 and closes #3616 (#3733)
This commit is contained in:
@@ -178,6 +178,7 @@ describe('HardcoverClient', () => {
|
||||
|
||||
test('should handle rate limiting with retries', async () => {
|
||||
// request() does NOT call authenticate() so only 2 mock values are needed
|
||||
vi.spyOn(console, 'warn').mockImplementation(() => {});
|
||||
|
||||
// First request fails with 429 then succeeds
|
||||
fetchMock.mockResolvedValueOnce({
|
||||
|
||||
@@ -9,7 +9,7 @@ import { Book, BookProgress, FIXED_LAYOUT_FORMATS } from '@/types/book';
|
||||
import { BookDoc } from '@/libs/document';
|
||||
import { debounce } from '@/utils/debounce';
|
||||
import { eventDispatcher } from '@/utils/event';
|
||||
import { getCFIFromXPointer, normalizeProgressXPointer, XCFI } from '@/utils/xcfi';
|
||||
import { getCFIFromXPointer, XCFI } from '@/utils/xcfi';
|
||||
|
||||
type SyncState = 'idle' | 'checking' | 'conflict' | 'synced' | 'error';
|
||||
|
||||
@@ -74,7 +74,7 @@ export const useKOSync = (bookKey: string) => {
|
||||
const { doc, index: spineIndex } = content;
|
||||
const converter = new XCFI(doc, spineIndex || 0);
|
||||
const xpointerResult = converter.cfiToXPointer(cfi);
|
||||
koProgress = normalizeProgressXPointer(xpointerResult.xpointer);
|
||||
koProgress = xpointerResult.xpointer;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to convert CFI to XPointer', error);
|
||||
@@ -90,6 +90,9 @@ export const useKOSync = (bookKey: string) => {
|
||||
|
||||
const applyRemoteProgress = async (book: Book, bookDoc: BookDoc, remote: KoSyncProgress) => {
|
||||
const view = getView(bookKey);
|
||||
const bookData = getBookData(bookKey);
|
||||
if (!view || !bookData) return;
|
||||
|
||||
if (FIXED_LAYOUT_FORMATS.has(book.format)) {
|
||||
const pageToGo = parseInt(remote.progress!, 10);
|
||||
if (isNaN(pageToGo)) return;
|
||||
@@ -97,10 +100,10 @@ export const useKOSync = (bookKey: string) => {
|
||||
} else {
|
||||
if (!remote.progress?.startsWith('/body')) return;
|
||||
try {
|
||||
const apContents = view?.renderer.getContents() ?? [];
|
||||
const apPrimaryIdx = view?.renderer.primaryIndex;
|
||||
const content = apContents.find((x) => x.index === apPrimaryIdx) ?? apContents[0];
|
||||
const koProgress = normalizeProgressXPointer(remote.progress);
|
||||
const content = view?.renderer
|
||||
.getContents()
|
||||
.find((x) => x.index === view?.renderer.primaryIndex);
|
||||
const koProgress = remote.progress;
|
||||
const cfi = await getCFIFromXPointer(koProgress, content?.doc, content?.index, bookDoc);
|
||||
view?.goTo(cfi);
|
||||
} catch (error) {
|
||||
|
||||
@@ -11,7 +11,7 @@ import { CFI } from '@/libs/document';
|
||||
import { debounce } from '@/utils/debounce';
|
||||
import { eventDispatcher } from '@/utils/event';
|
||||
import { DEFAULT_BOOK_SEARCH_CONFIG, SYNC_PROGRESS_INTERVAL_SEC } from '@/services/constants';
|
||||
import { getCFIFromXPointer, getXPointerFromCFI, normalizeProgressXPointer } from '@/utils/xcfi';
|
||||
import { getCFIFromXPointer, getXPointerFromCFI } from '@/utils/xcfi';
|
||||
|
||||
export const useProgressSync = (bookKey: string) => {
|
||||
const _ = useTranslation();
|
||||
@@ -61,7 +61,7 @@ export const useProgressSync = (bookKey: string) => {
|
||||
if (content && !FIXED_LAYOUT_FORMATS.has(book.format)) {
|
||||
const { doc, index } = content;
|
||||
const xpointerResult = await getXPointerFromCFI(config.location!, doc, index || 0);
|
||||
config.xpointer = normalizeProgressXPointer(xpointerResult.xpointer);
|
||||
config.xpointer = xpointerResult.xpointer;
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Failed to convert CFI to XPointer', error);
|
||||
@@ -124,16 +124,15 @@ export const useProgressSync = (bookKey: string) => {
|
||||
if (syncedConfig) {
|
||||
const configCFI = config?.location;
|
||||
let remoteCFILocation = syncedConfig.location;
|
||||
const xPointer = syncedConfig.xpointer;
|
||||
const xpointer = syncedConfig.xpointer;
|
||||
const bookData = getBookData(bookKey);
|
||||
const view = getView(bookKey);
|
||||
if (xPointer && view && bookData && bookData.bookDoc) {
|
||||
if (xpointer && view && bookData && bookData.bookDoc) {
|
||||
const pContents = view.renderer.getContents();
|
||||
const pIdx = view.renderer.primaryIndex;
|
||||
const content = pContents.find((x) => x.index === pIdx) ?? pContents[0];
|
||||
const koProgress = normalizeProgressXPointer(xPointer);
|
||||
const candidateCFI = await getCFIFromXPointer(
|
||||
koProgress,
|
||||
xpointer,
|
||||
content?.doc,
|
||||
content?.index,
|
||||
bookData.bookDoc,
|
||||
|
||||
Reference in New Issue
Block a user