- 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
6.9 KiB
6.9 KiB
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 parserdata/— repository, Room, DataStore, mappers, parsers, DIdomain/— models, use cases, repository interfacespresentation/— ViewModels, MVI screens, navigatorui/— Compose UI
bookshelf-apibackend находится в~/bookshelf/bookshelf-api/(отдельный проект)- Lissen (который дорабатывается параллельно) —
~/bookshelf/lissen/
API endpoints
- bookshelf-api:
http://bookshelf-api:8073(илиhttps://tts.dueattendant149.orgпосле DNS)GET /api/v1/books/librariesGET /api/v1/books/{item_id}GET /api/v1/books/library/{id}/search?q=...POST /api/v1/searchPOST /api/v1/tts,GET /api/v1/tts/{job_id},GET /api/v1/tts/{job_id}/downloadGET /api/v1/tts/engines,GET /api/v1/tts/voicesPOST /api/v1/download,GET /api/v1/download/listPOST /api/v1/podcasts,POST /api/v1/sources/yandex
- Audiobookshelf (напрямую): для аудио файлов и обложек
GET /api/items/{id}/file/{ino}GET /api/items/{id}/downloadGET /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-polishcompleted:- 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-polishbuilds and producesapp-debug.apk(~58 MB). Debug APK uploaded asKRait-debug-15.apkto ownCloud + caddy download site. - Polished: PlayerContent and TtsContent labels moved to
strings.xml; TTS WorkManager observer leak fixed (TtsModelremoves observer inonCleared). - Raised
minSdkfrom 26 to 31. - Phase 7 (nav redesign):
MainActivitytabs = Книги | Аудиокниги | Поиск | Настройки.BooksModel/AudiobooksModelextendRemoteLibraryViewModelwithmediaTypeFilter.- Library filter uses name fallback ("Books" / "Audiobooks") because ABS returns
mediaType: "book"for both. SearchModel+SearchContentfor global Librarr search (/api/v1/search).ServerStatusMonitor(singleton, pings/healthevery 30 s) → auto offline-only when down.SettingsScreenis 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.ReaderTopBargot a ⚡ button →RsvpScreen(bookId).- Persists reading progress on close via
UpdateBookUseCase. - Settings:
rsvpWpm(100–900),rsvpFontSize(24–96 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.
- Kindle-style paginated reading mode with
- Phase 10 (bugfixes):
- Fixed search crash caused by duplicate LazyColumn keys when search results have empty
guid. - Fixed
BookCardintrinsic-measurement crash risk by switching cover to fixed-height vertical variant.
- Fixed search crash caused by duplicate LazyColumn keys when search results have empty
- Phase 11 (audio player hardening):
- ExoPlayer streaming cache via
SimpleCache+CacheDataSource(512 MB external cache). - Unified
AuthorizationInterceptorfor player, backed byPlaybackAuthProviderrefreshed fromServerSettings.
- ExoPlayer streaming cache via
- Current APK:
KRait-debug-27.apk(1.9.11) onbooks.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 при существенных изменениях архитектуры