book-story/AGENTS.md
Atte149 f7307f4199 feat: paginated reader sync, search crash fix, audio cache + unified auth
- Sync pagination measurement with rendered layout (page geometry, spacing, images, chapter extras)
- Improve split algorithm with getLineForVerticalPosition and widow/orphan handling
- Fix search crash from duplicate LazyColumn keys on empty guids
- Switch BookCard cover to fixed-height vertical variant
- Add ExoPlayer SimpleCache + CacheDataSource for streaming audio
- Unify AuthorizationInterceptor for player via PlaybackAuthProvider
- Bump version to 1.9.11 (27) and update AGENTS.md
2026-06-21 19:45:08 +03:00

124 lines
6.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Book's Story — Bookshelf Fork
> Форк `Acclorite/book-story` под Bookshelf: audiobookshelf + bookshelf-api + TTS + offline.
## Stack
- **Язык:** Kotlin 100%
- **UI:** Jetpack Compose + Material3
- **DI:** Dagger Hilt
- **БД:** Room
- **Настройки:** DataStore
- **Сеть:** Retrofit + OkHttp + Kotlinx Serialization
- **Аудио:** ExoPlayer (Media3) + MediaSession
- **Фоновые задачи:** WorkManager
- **Читалка:** собственная Book's Story (jsoup, pdfbox, commonmark)
- **minSdk:** 31
- **compileSdk/targetSdk:** 36
## Goal
- Сохранить Material You reader Book's Story.
- Добавить поддержку bookshelf-api: библиотеки, поиск, TTS, подкасты, Яндекс/YouTube.
- Добавить аудиоплеер для аудиокниг из Audiobookshelf.
- Добавить offline-кэш и синхронизацию прогресса.
## Layout
- `app/src/main/java/org/dueattendant149/bookshelf/` — основной код
- `core/` — crash handler, typealias, commonmark parser
- `data/` — repository, Room, DataStore, mappers, parsers, DI
- `domain/` — models, use cases, repository interfaces
- `presentation/` — ViewModels, MVI screens, navigator
- `ui/` — Compose UI
- `bookshelf-api` backend находится в `~/bookshelf/bookshelf-api/` (отдельный проект)
- Lissen (который дорабатывается параллельно) — `~/bookshelf/lissen/`
## API endpoints
- **bookshelf-api:** `http://bookshelf-api:8073` (или `https://tts.dueattendant149.org` после DNS)
- `GET /api/v1/books/libraries`
- `GET /api/v1/books/{item_id}`
- `GET /api/v1/books/library/{id}/search?q=...`
- `POST /api/v1/search`
- `POST /api/v1/tts`, `GET /api/v1/tts/{job_id}`, `GET /api/v1/tts/{job_id}/download`
- `GET /api/v1/tts/engines`, `GET /api/v1/tts/voices`
- `POST /api/v1/download`, `GET /api/v1/download/list`
- `POST /api/v1/podcasts`, `POST /api/v1/sources/yandex`
- **Audiobookshelf (напрямую):** для аудио файлов и обложек
- `GET /api/items/{id}/file/{ino}`
- `GET /api/items/{id}/download`
- `GET /api/items/{id}/cover`
## Git
- **origin:** `https://git.dueattendant149.org/Atte149/book-story.git` (Forgejo)
- **upstream:** `https://github.com/Acclorite/book-story.git`
- **Лицензия:** GPL-3.0-only (как у оригинала)
## Build
```bash
./gradlew :app:assembleDebug
```
## Current Status
- Phase 1: fork + package rename completed.
- Phase 2: network layer (Retrofit, OkHttp, bookshelf-api + ABS clients) completed.
- Phase 3: data layer (remote Book fields, audio/ebook/cache tables, migration 16→17→18) completed.
- Phase 4: domain layer (ServerSettings, RemoteLibrary repository, use cases) completed.
- Phase 5a: UI scaffold (server settings screen, RemoteLibrary tab) completed.
- Phase 5b: UI/UX polish (icons, string resources, pull-to-refresh, empty/error states) completed.
- Phase 5c: server settings validation (health check, derive ABS URL, credential checks) completed.
- Phase 6: feature integration on `feature/ui-polish` completed:
- RemoteLibrary cache UI (offline-only filter, download/delete, progress indicator).
- Remote ebook opening in the existing reader.
- Audiobook player with ExoPlayer + MediaSession.
- TTS jobs screen via bookshelf-api.
- Reading and playback progress sync with periodic WorkManager worker.
- Current: `feature/ui-polish` builds and produces `app-debug.apk` (~58 MB). Debug APK uploaded as `KRait-debug-15.apk` to ownCloud + caddy download site.
- Polished: PlayerContent and TtsContent labels moved to `strings.xml`; TTS WorkManager observer leak fixed (`TtsModel` removes observer in `onCleared`).
- Raised `minSdk` from 26 to 31.
- Phase 7 (nav redesign): `MainActivity` tabs = Книги | Аудиокниги | Поиск | Настройки.
- `BooksModel` / `AudiobooksModel` extend `RemoteLibraryViewModel` with `mediaTypeFilter`.
- Library filter uses name fallback ("Books" / "Audiobooks") because ABS returns `mediaType: "book"` for both.
- `SearchModel` + `SearchContent` for global Librarr search (`/api/v1/search`).
- `ServerStatusMonitor` (singleton, pings `/health` every 30 s) → auto offline-only when down.
- `SettingsScreen` is a root tab — back button hidden when stack size ≤ 1.
- Phase 8 (RSVP speed reading): core tokenizer + engine + UI.
- `domain/model/rsvp/``RsvpToken`, `OrpTable`, `RsvpTokenizer`, `RsvpEngine`.
- `presentation/rsvp/``RsvpScreen`, `RsvpModel`, `RsvpState/Event/Effect`.
- `ui/rsvp/RsvpContent.kt` — word stage with prefix/pivot/suffix, focus guide ▲▼, controls bar.
- `ReaderTopBar` got a ⚡ button → `RsvpScreen(bookId)`.
- Persists reading progress on close via `UpdateBookUseCase`.
- Settings: `rsvpWpm` (100900), `rsvpFontSize` (2496 sp), `rsvpPauseOnParagraph`, `rsvpPauseOnChapter`, `rsvpPauseOnLongWords`, `rsvpShowFocusGuide`.
- Phase 9 (reader pagination + polish):
- Kindle-style paginated reading mode with `HorizontalPager`.
- Volume keys (Up/Down) mapped to page navigation via `VolumeKeyWindowCallback`.
- Pagination measurement/render synchronization: exact page geometry, real inter-item spacing, image sizing, chapter title extras.
- Algorithm improvements: `TextLayoutResult.getLineForVerticalPosition()` split point, better widow/orphan handling.
- Phase 10 (bugfixes):
- Fixed search crash caused by duplicate LazyColumn keys when search results have empty `guid`.
- Fixed `BookCard` intrinsic-measurement crash risk by switching cover to fixed-height vertical variant.
- Phase 11 (audio player hardening):
- ExoPlayer streaming cache via `SimpleCache` + `CacheDataSource` (512 MB external cache).
- Unified `AuthorizationInterceptor` for player, backed by `PlaybackAuthProvider` refreshed from `ServerSettings`.
- Current APK: `KRait-debug-27.apk` (1.9.11) on `books.dueattendant149.org/download`.
- Next: final APK rebuild after pushing to Forgejo.
## WARNs
- **Не пушить в `upstream` (Acclorite/book-story).** Только в `origin` (Forgejo).
- **Lissen остаётся живым проектом.** Book's Story fork — отдельная ветка развития.
- **Секреты** (ABS token, API keys) хранить только в `.env` / `credentials.json` / DataStore, никогда в коде.
- **Package:** `org.dueattendant149.bookshelf`. Все ссылки на `ua.acclorite.book_story` в коде заменены; README оставлен с оригинальными F-Droid ссылками.
## Typical tasks
- Добавить новый endpoint bookshelf-api
- Расширить `Book` / `BookEntity` для remote полей
- Добавить аудиоплеер экран
- Добавить TTS экран
- Поднять minSdk, добавить новые разрешения
- Обновить AGENTS.md при существенных изменениях архитектуры