fix: resume epub progress from the fields the API returns
The load function read progress.epub_loc and progress.progress, neither of
which BookProgressRead carries, so resuming never worked and every open
started at page one. Read epub_cfi and percentage instead.
Fail loudly when the book cannot be fetched. The previous version caught
everything and returned {status, error} that nothing consumed, so a missing
book produced a reader sitting on its spinner forever. Check response.ok
before parsing too: fetch resolves on a 404, and arrayBuffer() happily
returns the error page, which only surfaced later as an opaque epub parse
error.
Give the reader a working sidebar, a theme that survives the book's own
CSS, and an error state with a retry. The theme is registered rather than
applied as bare overrides because most EPUBs ship their own body colours
and win otherwise, which is why the page stayed white against a dark UI.
This commit is contained in:
+16
-13
@@ -1,21 +1,24 @@
|
||||
<script>
|
||||
<script lang="ts">
|
||||
import { page } from '$app/state';
|
||||
import EpubReader from '$lib/components/reader/epub-reader.svelte';
|
||||
|
||||
let { data } = $props();
|
||||
|
||||
let fileId = page.params.fileId;
|
||||
let bookId = page.params.bookId;
|
||||
const fileId = page.params.fileId!;
|
||||
const bookId = page.params.bookId!;
|
||||
|
||||
// Make sure this endpoint returns the complete EPUB file
|
||||
let bookUrl = `/api/books/download/${bookId}/${fileId}`;
|
||||
// Streams the file through the proxy so the browser fetches it directly
|
||||
const bookUrl = `/api/books/download/${bookId}/${fileId}`;
|
||||
</script>
|
||||
|
||||
<div class="h-screen w-screen">
|
||||
<EpubReader
|
||||
{bookUrl}
|
||||
{bookId}
|
||||
initialProgress={data.bookProgress?.progress}
|
||||
initialEpubLoc={data.bookProgress?.epub_loc}
|
||||
/>
|
||||
</div>
|
||||
<svelte:head>
|
||||
<title>{data.title} — Chitai</title>
|
||||
</svelte:head>
|
||||
|
||||
<EpubReader
|
||||
{bookUrl}
|
||||
{bookId}
|
||||
title={data.title}
|
||||
initialProgress={data.initialProgress}
|
||||
initialEpubLoc={data.initialEpubLoc}
|
||||
/>
|
||||
|
||||
@@ -1,17 +1,29 @@
|
||||
export async function load({ fetch, params, parent }) {
|
||||
try {
|
||||
const response = await fetch(`/api/books/${params.bookId}`);
|
||||
const result = await response.json();
|
||||
let bookProgress = result.progress;
|
||||
import { error } from '@sveltejs/kit';
|
||||
|
||||
return {
|
||||
bookProgress
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Error fetching book: ', error);
|
||||
return {
|
||||
status: error.status || 500,
|
||||
error: error.message
|
||||
};
|
||||
export async function load({ fetch, params }) {
|
||||
// Fail loudly. The previous version caught everything and returned
|
||||
// {status, error}, which nothing consumed — so a missing book produced a
|
||||
// reader that sat on its spinner forever.
|
||||
const response = await fetch(`/api/books/${params.bookId}`);
|
||||
|
||||
if (!response.ok) {
|
||||
error(response.status, 'This book could not be loaded.');
|
||||
}
|
||||
|
||||
const book = await response.json();
|
||||
const file = book.files?.find((f: { id: number }) => String(f.id) === params.fileId);
|
||||
|
||||
if (!file) {
|
||||
error(404, 'That file is not part of this book.');
|
||||
}
|
||||
|
||||
return {
|
||||
title: book.title,
|
||||
filename: file.filename,
|
||||
// epub_cfi and percentage are what BookProgressRead actually carries;
|
||||
// this used to read progress.epub_loc and progress.progress, so resuming
|
||||
// never worked.
|
||||
initialEpubLoc: book.progress?.epub_cfi ?? null,
|
||||
initialProgress: book.progress?.percentage ?? 0
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user