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

6.9 KiB
Raw Blame History

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

./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 при существенных изменениях архитектуры