import { ApiError, request, type Page } from './client'; export type ReadProgress = { user_id: string; manga_id: string; chapter_id: string | null; page: number; updated_at: string; }; export type ReadProgressSummary = { manga_id: string; manga_title: string; manga_cover_image_path: string | null; chapter_id: string | null; /** `null` if the chapter was deleted after the progress was written. */ chapter_number: number | null; page: number; updated_at: string; }; export type ReadProgressPage = { items: ReadProgressSummary[]; page: Page; }; export type UpsertReadProgress = { manga_id: string; chapter_id?: string | null; page?: number | null; }; export async function updateReadProgress( input: UpsertReadProgress ): Promise { return request('/v1/me/read-progress', { method: 'PUT', headers: { 'content-type': 'application/json' }, body: JSON.stringify(input) }); } export async function listMyReadProgress( opts: { limit?: number; offset?: number } = {} ): Promise { const params = new URLSearchParams(); if (opts.limit != null) params.set('limit', String(opts.limit)); if (opts.offset != null) params.set('offset', String(opts.offset)); const qs = params.toString(); return request( `/v1/me/read-progress${qs ? `?${qs}` : ''}` ); } export async function listMyReadProgressOrEmpty(): Promise { try { return await listMyReadProgress(); } catch (e) { if (e instanceof ApiError && e.status === 401) { return { items: [], page: { limit: 50, offset: 0, total: null } }; } throw e; } } /** * Single-manga response shape returned by GET /me/read-progress/:id. * Includes `chapter_number` so the "Continue reading" CTA can render * without resolving the chapter id against a paged chapters list. */ export type ReadProgressForManga = { manga_id: string; chapter_id: string | null; /** `null` if the chapter was deleted after the progress was written. */ chapter_number: number | null; page: number; updated_at: string; }; /** * Returns the user's progress for a specific manga, or `null` when * they've never opened it (or aren't signed in). Used by the manga * detail page's "Continue from Ch. N" CTA and by the reader to seed * its session-local high-water mark from the persisted value. */ export async function getMyReadProgressForManga( mangaId: string ): Promise { try { return await request( `/v1/me/read-progress/${encodeURIComponent(mangaId)}` ); } catch (e) { if (e instanceof ApiError && (e.status === 404 || e.status === 401)) { return null; } throw e; } } export async function clearReadProgress(mangaId: string): Promise { await request( `/v1/me/read-progress/${encodeURIComponent(mangaId)}`, { method: 'DELETE' } ); }