feat(books): support reviews, rating removal, and plugin enhancements

Add support for user-scoped personal notes (reviews) and allow clearing book ratings to null,
providing full sync capabilities for these actions in the KOReader plugin. Modularize the
KOReader plugin codebase into dedicated mixin files to improve maintainability and expand
the catalog detail view with related sections (series, author, similar books).

Closes #552
This commit is contained in:
neon
2026-07-07 04:26:23 +00:00
parent db5f17f8de
commit bf4102e8df
72 changed files with 31771 additions and 2447 deletions
+2
View File
@@ -134,6 +134,8 @@ export type BookDetail = {
seriesIndex: number | null;
seriesMemberships?: BookSeriesMembership[];
rating: number | null;
personalNote: string | null;
personalNoteUpdatedAt: string | null;
communityRatings: BookCommunityRating[];
coverSource: "extracted" | "custom" | null;
hardcoverEditionId: string | null;
+25
View File
@@ -203,6 +203,27 @@ export interface KoreaderCatalogBookListItem {
updatedAt: string;
}
export type KoreaderCatalogRelatedSectionId = "series" | "author" | "similar";
export interface KoreaderCatalogRelatedBook {
id: number;
title: string | null;
authors: string[];
seriesIndex: number | null;
hasCover: boolean;
thumbnailUrl: string | null;
detailUrl: string;
updatedAt: string | null;
isAudiobook?: boolean;
isComic?: boolean;
}
export interface KoreaderCatalogRelatedSection {
id: KoreaderCatalogRelatedSectionId;
title: string;
books: KoreaderCatalogRelatedBook[];
}
export interface KoreaderCatalogBookDetail extends KoreaderCatalogBookListItem {
subtitle: string | null;
description: string | null;
@@ -220,6 +241,7 @@ export interface KoreaderCatalogBookDetail extends KoreaderCatalogBookListItem {
tags: string[];
progress: KoreaderCatalogProgress | null;
files: KoreaderCatalogFile[];
relatedSections: KoreaderCatalogRelatedSection[];
}
export interface KoreaderCatalogPage<T> {
@@ -250,6 +272,9 @@ export interface KoreaderCatalogSectionResponse {
export interface KoreaderCatalogDashboardResponse {
generatedAt: string;
username: string;
displayName: string;
totalBooks: number;
sections: KoreaderCatalogEntry[];
continueReading: KoreaderCatalogBookListItem[];
discover: KoreaderCatalogBookListItem[];