fix(koreader): keep manual links to a different copy matched and suggest links

Report a linked copy whose bytes differ from the library file as positionIncompatible instead of
unmatched, so the plugin keeps the match, skips highlights without a failure and still syncs progress.
Treat a position-less place within a page as the same place and jump to the nearest page.
Suggest library books with the same title and authors for books to review, with bulk linking.
See docs/KOREADER_HASH_MATCHING.md.

Closes #1872
Closes #1919
This commit is contained in:
neon
2026-10-26 15:06:04 +00:00
parent 834da8c954
commit 1c27e5dd05
36 changed files with 1634 additions and 63 deletions
+25
View File
@@ -120,10 +120,35 @@ export interface KoreaderManualHashLink {
koreaderTitle: string | null;
koreaderAuthors: string | null;
koreaderLastOpen: number | null;
/**
* False when the device copy's bytes differ from the linked library file: reading status, rating, reading time
* and progress (as a percentage) sync; highlights, bookmarks and exact positions do not.
*/
positionCompatible: boolean;
createdAt: string;
updatedAt: string;
}
/** A library book whose title and authors equal an unmatched KOReader book's, offered for the user to confirm. */
export interface KoreaderLinkSuggestionCandidate {
bookId: number;
title: string | null;
subtitle: string | null;
authors: string[];
/** Format of the book's primary file, which is what a link targets. */
format: string | null;
language: string | null;
publishedYear: number | null;
libraryName: string | null;
}
export interface KoreaderUnmatchedBookSuggestion {
hash: string;
candidates: KoreaderLinkSuggestionCandidate[];
/** More library books share the title than were checked, so none of the candidates may be presented as the only match. */
moreCandidates: boolean;
}
export interface LinkKoreaderUnmatchedBookPayload {
bookId: number;
}