Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,34 @@ layer, playback service).
the typed field alone for dual-format books.
- The `continue-*` endpoints return nothing for admins; Continue rows are
built from the filtered list endpoint (see `BooksRepository`).
- **EPUB reader (`ui/reader/EpubReaderScreen.kt` + `assets/reader/`)**:
epub.js runs inside a `WebView` hosted in a Compose `AndroidView`; Kotlin
and the page talk over a `window.Android` JS bridge (`ReaderBridge`).
**Never trust the page's own `window.innerWidth`/`innerHeight` or the DOM
`resize` event to size the rendition** -- on-device testing found the
WebView reporting a real width but an exact zero height on first layout,
and the `resize` event never fires at all even on a genuine on-screen
size change (a rotation). `reader.open()`/`reader.resize()` instead take
explicit CSS-px width/height that Kotlin measures itself via
`Modifier.onSizeChanged` on the `AndroidView`; Compose's own layout is
the only sizing signal trusted for this component. Diagnosing anything
else in here: `reader.js`'s `open()` reports any thrown error through
the bridge to `Log.e("EpubReader", ...)`, `onConsoleMessage` pipes the
page's own console to the same tag, and `WebView.setWebContentsDebuggingEnabled`
is on in debug builds so `chrome://inspect` can attach live DevTools.
- **`Surface`'s automatic content-color inference is not reliable once its
`color` doesn't exactly equal a theme role color** (e.g. one with a
modified alpha, as `ReaderBar` in `ui/reader/ReaderChrome.kt` uses) --
the inference silently fails and falls back to whatever text color was
ambient outside the `Surface`, which can belong to an entirely different
theme once a caller nests its own `MaterialTheme(colorScheme = ...)`
override inside it. Always pass an explicit `contentColor` in that case.
- **Never `catch (e: Exception)` around a suspend call that can be
legitimately cancelled** (a debounced background save, for one) without
rethrowing `CancellationException` first -- otherwise leaving a screen
mid-save reports a normal cancellation as a real error to the user (seen
as a "StandaloneCoroutine was cancelled" Snackbar). See
`DebouncedSaver`/`PageProgressSaver` for the pattern.

## Building locally

Expand Down
23 changes: 15 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ digital library server. Kotlin and Jetpack Compose.

## What works today

- Connect to any Grimmory server, sign in with username and password
- Connect to any Grimmory server, sign in with username and password or
through your identity provider's SSO
- Home with the server's own rows, plus Up next in series and Recently
finished (each switchable off in Settings)
- Browse by series, author or shelf, and search across the whole library
- Libraries with status and format filter pills and sorting
- Book detail with progress and mark finished
- Audiobook playback: single-file and folder-based books, resume from the
Expand All @@ -29,11 +31,13 @@ digital library server. Kotlin and Jetpack Compose.
- Every file type the server stores has a path: FB2 is converted on the
device and opens in the EPUB reader; MOBI, AZW3 and supplementary files
can be handed to another app; a book's files are listed on its page
- EPUB reader: chapters, bookmarks, light, sepia and dark pages, text size,
font choice and line spacing,
swipe or tap to turn, progress saved as the same CFI and percentage the
web reader uses so both open at the same place
- Comic (CBX) and PDF readers: pinch to zoom, double-tap, page slider,
- EPUB reader: chapters, bookmarks, five reading themes (light, sepia,
dark, black and forest), text size, font choice and line spacing, swipe
or tap the edges to turn a page, tap the middle to hide every control
for distraction-free reading, progress saved as the same CFI and
percentage the web reader uses so both open at the same place
- Comic (CBX) and PDF readers: pinch to zoom, double-tap, tap the edges to
turn a page and the middle to hide the controls, page slider,
right-to-left reading for manga, night mode for PDFs, progress saved to
the server so the web reader opens on the same page
- Download any book for offline use: audiobooks play, EPUB, FB2 and PDF
Expand All @@ -56,11 +60,14 @@ digital library server. Kotlin and Jetpack Compose.
- Tablets and landscape: libraries as two panes, wider Home tiles, Settings
and stats at a readable width, two-column EPUB pages once the screen is
wide enough
- Checks for a newer release on GitHub, with an in-app banner and one-tap
install

## Coming next

In rough order: SSO sign-in, dashboard rows from the server's layout,
series, authors and shelves, search, bookmarks and in-app updates. Each has an issue in the tracker.
Nothing on a public roadmap right now; [open an
issue](https://github.com/schmitzkr/grimreader/issues) for anything
missing or broken.

## Building

Expand Down
Loading