Dead imports and locals removed, each blocks keyed, `any` narrowed to unknown.
Two context setters kept their calls and lost only the unused binding; the
settings redirect no longer awaits a parent whose data it discards. A leading
underscore now marks a binding that only holds a position.
no-unused-expressions is off for Svelte files: a bare `book;` in an $effect
declares a dependency. The URL and Set instances it flagged are local
temporaries, marked individually. The one real finding was visibleApiKeys,
genuine reactive state cloned on every mutation to force an update; it is a
SvelteSet now.
The RequestHandler import sat commented out while all four handlers were
annotated with it, so every destructured parameter was an implicit any --
24 of the 30 svelte-check errors. deleteFn returned `{}`, which void is not
assignable to.
Applies ruff format, ruff check --fix and prettier, so CI can gate on all three.
The surviving unused imports were all re-exports in __init__.py, now covered by a
per-file ignore; the pdf.js viewer and the generated openapi types join the
vendored code that eslint and prettier already skip.
Reads metadata.db and copies the books into a library — from a zip uploaded on
the library settings page, or from a path with `litestar calibre-import`. The
source is never touched, and re-running only picks up what is new.
Also names the formats mimetypes does not know: a Calibre library is full of
MOBI and AZW3, and a null content type used to fail the book endpoint.
A workbench with the folded records in a rail, the survivor's fields live and
editable beside them, and per-field actions chosen by what kind of field it is.
Fields the records agree on stay out of the way. Reachable from a duplicate
group and from the selection toolbar, which is the only way to merge a pair the
detector never proposed.
Adds the per-library review screen, a muted note in the upload tray for a book
that may already be held, and the remote functions behind them. The tray note
is deliberately weaker than the file-level one, which means something stronger.
One request per book instead of one for everything, queued in state above the
dialog so closing it no longer cancels the import. A docked tray reports each
book and offers a retry; it clears itself after a clean run, stays put if
anything failed, and holds while hovered.
Also fixes the dialog overflowing on long filenames — Dialog.Content is a grid
and its body needed min-w-0 to shrink below the content's intrinsic width.
Drops epub.js's 1600-location pre-pass and its localStorage cache: foliate
hands back a CFI and an overall fraction on every relocate, so first open no
longer freezes.
Also fixes resuming (pre-resolves the stored CFI, falling back to the stored
percentage rather than silently resetting to page one), progress saving
(missing Content-Type, and no flush on the way out), and arrow keys inside
the book iframe.
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.
The PDF reader pointed an iframe at the vendored pdf.js viewer and had no
way to report a failure: the viewer renders its own errors inside the
frame, so a missing or unreadable file showed an empty grey panel. Probe
the file with a request first and render an error card with a retry when
that fails, matching the chrome the EPUB reader uses.
Add the missing +page.ts for the PDF route so the tab gets the book title
rather than a bare "Reader".
Drop chapter-sidebar.svelte and its import. It rendered a list of chapters
whose buttons had no click handler, and read/+layout@.svelte imported it
without ever rendering it. The reader's own sidebar replaces it.
The reader and login pages use +layout@ breakouts to escape the (root)
shell, so anything mounted in (root)/+layout.svelte never reaches them.
ModeWatcher was mounted there and duplicated in login/+layout@.svelte,
which left the reader's theme toggle inert: it flipped the store but
nothing wrote .dark onto <html>.
Mount both once at the top-level +layout.svelte instead, which every
route inherits regardless of breakouts.
Updated book progress model in anticipation of the KOReader sync
feature.
Renamed properties:
- renamed "progress" to "percentage"
- renamed "pdf_loc" to "pdf_page"
- renamed "epub_loc" to "epub_cfi"
New properties:
- "epub_xpointer", marks the location of an epub in KOReader
- "device", the device type that updated the progress
- "device_id", the id of the device that updated the progress