# Listora
Listora — a beautiful, free audiobook player for the public-domain
[LibriVox](https://librivox.org) catalogue (served via the
[Internet Archive](https://archive.org)). Browse, stream, download for offline
listening, and pick up right where you left off — all free, forever.
## Screenshots
## Features
- **Browse** — most-downloaded and recently-added books from the LibriVox collection
- **Search** by title *or* author; tap any author to see all their readings
("More by …" rails + a full author page)
- **Immersive player** — full-screen now-playing with a cover-colour gradient,
scrubber, ±10s/30s, variable speed (persisted), and lock-screen / notification
controls
- **Resume** — playback position is bookmarked per book and restored automatically
- **Sleep timer** — 15/30/45/60 min or end-of-chapter
- **Offline** — download single chapters or a whole book; downloaded chapters
play from disk; per-chapter and per-book removal
- **Library** — Favourites, Continue listening, and Downloaded in one place
- **Favourites** — heart a book from its page or directly on any cover
- **Theming** — dark-first immersive UI (built on the
[popup_bits_design](https://github.com/lohanidamodar/popup-bits-design-system)
system) with light / dark / system modes
## Tech stack
- **Flutter 3.44** / Dart 3.12
- **State:** Riverpod 3 (hand-written providers, no codegen)
- **Audio:** `just_audio` + `just_audio_background`
- **Downloads:** `background_downloader`
- **Cache:** `sqflite` (catalogue) + `shared_preferences` (bookmarks, favourites, settings)
- **Theme:** `popup_bits_design` + `google_fonts` (Fraunces display)
- **Cover colours:** `palette_generator`
## Project layout
```
lib/
main.dart app entry, ProviderScope, theme
pages/ main_shell, home, library, book_details,
now_playing, settings
providers/ providers.dart (data/player/downloads/favourites),
settings_provider, sleep_timer_provider
resources/ repository + archive.org API, sqflite cache,
audio_helper, downloads_service, favorites_service,
playback_bookmarks
widgets/ book_cards, mini_player, seek_bar, immersive_scrubber
```
## Running
The app targets a real device/emulator (audio + downloads).
```sh
flutter pub get
flutter run
```
## Release signing
Release builds are signed from credentials in `android/key.properties`, which
is **gitignored** (this is a public repo — the keystore and passwords are never
committed). If the file is absent, release falls back to debug signing so the
project still builds for anyone who clones it.
To set it up, copy `android/key.properties.example` to `android/key.properties`,
generate an upload keystore, and point `storeFile` at it:
```sh
keytool -genkey -v -keystore ~/upload-keystore.jks \
-keyalg RSA -keysize 2048 -validity 10000 -alias upload
```
Keep the keystore and its passwords backed up somewhere safe and out of the
repo. Using **Google Play App Signing** is recommended (your committed key is
just an *upload* key, which can be reset if lost).
## Store assets
Ready-to-upload Play Store art lives in `playstore_screenshots/`: the listing
icon (`play_store_icon_512.png`), `feature_graphic.png`, raw phone screenshots,
and branded marketing frames under `marketing/`. The launcher icon is generated
with `flutter_launcher_icons` (`dart run flutter_launcher_icons`).
## License & content
App code is open source. All audiobook content is public domain, provided by
LibriVox volunteers via the Internet Archive.