feat(komga): add Komga read-status sync with reports and history

Adds Komga sync feature to import read status from a Komga server.
Books are matched by title (case-insensitive) with series+title primary
match and title-only fallback. Sync reports are persisted with matched,
newly marked, and unmatched book lists. UI shows check icon for newly
marked books, sorted to top. Credentials (URL+username) are saved
between sessions. Uses HashSet for O(1) lookups to handle large libraries.

Closes #2

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-16 22:04:19 +01:00
parent 1b9f2d3915
commit 127cd8a42c
11 changed files with 833 additions and 2 deletions

View File

@@ -539,3 +539,48 @@ export async function markSeriesRead(seriesName: string, status: "read" | "unrea
body: JSON.stringify({ series: seriesName, status }),
});
}
export type KomgaSyncRequest = {
url: string;
username: string;
password: string;
};
export type KomgaSyncResponse = {
id: string;
komga_url: string;
total_komga_read: number;
matched: number;
already_read: number;
newly_marked: number;
matched_books: string[];
newly_marked_books: string[];
unmatched: string[];
created_at: string;
};
export type KomgaSyncReportSummary = {
id: string;
komga_url: string;
total_komga_read: number;
matched: number;
already_read: number;
newly_marked: number;
unmatched_count: number;
created_at: string;
};
export async function syncKomga(req: KomgaSyncRequest) {
return apiFetch<KomgaSyncResponse>("/komga/sync", {
method: "POST",
body: JSON.stringify(req),
});
}
export async function listKomgaReports() {
return apiFetch<KomgaSyncReportSummary[]>("/komga/reports");
}
export async function getKomgaReport(id: string) {
return apiFetch<KomgaSyncResponse>(`/komga/reports/${id}`);
}