feat(api,web): support CBZ — scan, métadonnées, lecteur d'albums

- api: cbz utilitaire commun, scanner/métadonnées (+ tests), books, schéma et migrations
- web: CbzReader, ReaderPage/locators (+ tests), types et client API
- shared: types formats

Refs: #16
This commit is contained in:
Git Agent
2026-08-23 11:52:40 +02:00
parent 4b7d4d45ce
commit e5513d81eb
18 changed files with 366 additions and 15 deletions

View File

@ -13,7 +13,7 @@ import type {
UserDto
} from "@readabook/shared";
import { mockBooks, mockContinue, mockJobs, mockLibraries, mockProgress, mockUser } from "./mockData";
import type { ContinueItem, Session } from "./types";
import type { CbzPagesDto, ContinueItem, Session } from "./types";
const API_BASE = import.meta.env.VITE_API_BASE_URL ?? "";
@ -135,6 +135,12 @@ export const api = {
bookCoverUrl(id: number): string {
return `${API_BASE}/books/${id}/cover`;
},
async cbzPages(id: number): Promise<CbzPagesDto> {
return request<CbzPagesDto>(`/books/${id}/pages`);
},
cbzPageUrl(id: number, page: number): string {
return `${API_BASE}/books/${id}/pages/${page}`;
},
async progress(bookId: number): Promise<ProgressDto | null> {
try {
return await request<ProgressDto>(`/progress/${bookId}`, {

View File

@ -52,12 +52,31 @@ export const mockBooks: BookDto[] = [
fileMtime: now,
createdAt: now,
updatedAt: now
},
{
id: 3,
libraryId: 2,
title: "Les vitrines de verre",
author: "A. Muze",
description: "Un recit graphique indexe comme archive CBZ.",
isbn: null,
language: "fr",
publisher: "ReadaBook",
publishedDate: "1934",
format: "cbz",
filePath: "/library/cbz/vitrines.cbz",
coverPath: null,
fileSize: 12600000,
fileMtime: now,
createdAt: now,
updatedAt: now
}
];
export const mockProgress: ProgressDto[] = [
{ bookId: 1, locator: "mock:chapter-3", percent: 42, updatedAt: now },
{ bookId: 2, locator: "mock:page-12", percent: 18, updatedAt: now }
{ bookId: 2, locator: "pdf:page:12", percent: 18, updatedAt: now },
{ bookId: 3, locator: "cbz:page:4", percent: 40, updatedAt: now }
];
export const mockContinue: ContinueItem[] = mockProgress.map((progress) => ({

View File

@ -21,3 +21,9 @@ export type DashboardData = {
libraries: LibraryDto[];
jobs: JobDto[];
};
export type CbzPagesDto = {
bookId: number;
pageCount: number;
pages: Array<{ page: number; name: string }>;
};