docs: README for humans, with logo and screenshots
Rewrite the README around what a user sees: what the app is for, how the screens look and what to press. Add the logo, five screenshots taken against a local mock PeerTube instance with placeholder content (no private media), and a debug-only manifest that allows plain HTTP so those mock instances work.
This commit is contained in:
parent
669c4af359
commit
116b6926e4
9 changed files with 210 additions and 46 deletions
125
README.md
125
README.md
|
|
@ -1,70 +1,103 @@
|
|||
# JTube TV
|
||||
|
||||
An Android TV client for [PeerTube](https://joinpeertube.org/) instances, inspired by
|
||||
how SmartTube works for YouTube. It talks to **any PeerTube instance**
|
||||
(the default is [JTube](https://tube.jeena.net) — my own instance) over the
|
||||
[PeerTube REST API](https://docs.joinpeertube.org/api-rest-reference.html).
|
||||
<p align="center">
|
||||
<img src="docs/jtube-logo.svg" width="150" alt="The JTube TV logo, a little orange TV" />
|
||||
</p>
|
||||
|
||||
## Features (v0.1)
|
||||
JTube TV is an Android TV app for [PeerTube](https://joinpeertube.org/). It puts
|
||||
a PeerTube instance on the big screen the way SmartTube puts YouTube there:
|
||||
browse from the couch, play with the remote, nothing else in the way.
|
||||
|
||||
- **Setup flow** — enter instance URL, username and password once; the app exchanges
|
||||
them for OAuth tokens via `POST /api/v1/users/token` and stores
|
||||
**only the tokens** (never the password), encrypted with the Android Keystore
|
||||
(EncryptedSharedPreferences).
|
||||
- **Local videos** — list public videos of the instance (`GET /api/v1/videos?isLocal=true`).
|
||||
- **My videos** — all of the logged-in user's own videos, every privacy level included
|
||||
(private, internal, unlisted — `GET /api/v1/users/me/videos`). Non-public entries
|
||||
carry a privacy badge.
|
||||
- **Channels** — list channels local to the instance
|
||||
(`GET /api/v1/video-channels?search=…&searchTarget=local`) and browse each channel's videos.
|
||||
- **Search** — search local videos by title.
|
||||
- **Subscriptions** — the videos in the user's subscription feed
|
||||
(`GET /api/v1/users/me/subscriptions/videos`).
|
||||
- **History** — the user's watch history as tracked by the server
|
||||
(`GET /api/v1/users/me/history/videos`).
|
||||
- **Playback** — HLS (or progressive MP4 fallback) playback with ExoPlayer/Media3.
|
||||
Viewing is reported to the server (`POST /api/v1/videos/{shortUuid}/watching`) so it
|
||||
shows up in server-side history. Private/internal media is streamed with the OAuth
|
||||
token attached to every playlist/segment request.
|
||||
It talks to any PeerTube instance over the
|
||||
[REST API](https://docs.joinpeertube.org/api-rest-reference.html). The default
|
||||
is [tube.jeena.net](https://tube.jeena.net), my own instance, where most videos
|
||||
are private family uploads. Signing in matters because "My videos" shows them
|
||||
all, privacy levels included.
|
||||
|
||||
Out of scope for now (see `BACKLOG.md`): uploading, editing, subscribing/unsubscribing,
|
||||
deleting, creating anything other than history entries.
|
||||
## What it looks like
|
||||
|
||||
Screenshots were taken against a demo instance with placeholder content, on an
|
||||
emulator. The app itself is on a dark theme, made for a 10-foot couch view.
|
||||
|
||||
The home screen. Continue watching picks up at the position the server saved,
|
||||
new videos first, page after page.
|
||||
|
||||
<p align="center">
|
||||
<img src="docs/screenshots/home.png" width="800" alt="Home screen with Continue watching and New videos rows" />
|
||||
</p>
|
||||
|
||||
A slide-in drawer opens with the left D-pad button. My videos shows your own
|
||||
uploads, every privacy level included, with a badge on anything not public.
|
||||
|
||||
<p align="center">
|
||||
<img src="docs/screenshots/drawer.png" width="800" alt="Menu drawer with the destinations" />
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<img src="docs/screenshots/myvideos.png" width="800" alt="My videos grid with Private and Internal badges" />
|
||||
</p>
|
||||
|
||||
Channels, one row per owner, with video and play counts on every card.
|
||||
|
||||
<p align="center">
|
||||
<img src="docs/screenshots/channels.png" width="800" alt="Channels screen with channel cards" />
|
||||
</p>
|
||||
|
||||
The player speaks remote: play and pause, seek back and forward, a seek bar
|
||||
with position and duration. Watching is reported to the server every 20
|
||||
seconds, so where you left off survives the app.
|
||||
|
||||
<p align="center">
|
||||
<img src="docs/screenshots/player.png" width="800" alt="Player with controls, seek bar and title" />
|
||||
</p>
|
||||
|
||||
## What it does in v0.1
|
||||
|
||||
- Sign in once. The app exchanges your username and password for OAuth tokens
|
||||
and stores only those, encrypted with the Android Keystore. The password
|
||||
itself is never kept.
|
||||
- Home with Continue watching and New videos.
|
||||
- Browse the instance's public videos, and search them by title.
|
||||
- My videos: every video you own, private, internal and unlisted included.
|
||||
- Channels: local channels with their videos, plus your subscriptions and your
|
||||
server-side watch history.
|
||||
- Player: HLS, with a progressive MP4 fallback, resume from the saved
|
||||
position, and watching reports.
|
||||
|
||||
What it deliberately does not do (yet, or ever): uploading, editing,
|
||||
deleting, managing subscriptions. That's tracked in
|
||||
[BACKLOG.md](BACKLOG.md).
|
||||
|
||||
## Build
|
||||
|
||||
Requirements: JDK 17+ (JDK 21 recommended), Android SDK platform 35.
|
||||
`local.properties` with `sdk.dir=…` is picked up automatically if present
|
||||
(standard Android Gradle Plugin behavior).
|
||||
Requirements: JDK 17 or newer (21 recommended) and an Android SDK with
|
||||
platform 35. The Gradle wrapper is checked in, so no local Gradle install is
|
||||
needed.
|
||||
|
||||
```bash
|
||||
./gradlew :app:assembleDebug
|
||||
```
|
||||
|
||||
Install on a TV device:
|
||||
Then put it on the TV:
|
||||
|
||||
```bash
|
||||
adb connect <tv-ip>:<port>
|
||||
adb install -r app/build/outputs/apk/debug/app-debug.apk
|
||||
```
|
||||
|
||||
> Building requires a JDK; the Gradle wrapper is checked in, so no local Gradle
|
||||
> installation is needed.
|
||||
## Architecture
|
||||
|
||||
## Architecture overview
|
||||
A single-module app, deliberately small:
|
||||
|
||||
Single-module Android TV app (`app/`):
|
||||
|
||||
- `data/api` — Retrofit interface + kotlinx-serialization DTOs for the PeerTube API.
|
||||
- `data/auth` — `TokenStore` (EncryptedSharedPreferences), token acquisition/refresh.
|
||||
- `data/network` — OkHttp/Retrofit wiring: dynamic base-URL interceptor, bearer-token
|
||||
interceptor, single-flight token refresh authenticator.
|
||||
- `data/PeerTubeRepository.kt` — one suspend-call surface used by all view models.
|
||||
- `ui/` — Compose for TV screens: Setup, Home (sidebar + list content),
|
||||
VideoList (local / my videos / subscriptions / history / search / channel),
|
||||
Channels, Player. `MainActivity` is the only activity.
|
||||
- `JTubeApp.kt` — tiny service locator (`AppGraph`); no DI framework on purpose.
|
||||
- `data/api` — Retrofit interface and kotlinx-serialization DTOs for the
|
||||
PeerTube API.
|
||||
- `data/auth` — TokenStore, the encrypted preference storage for tokens.
|
||||
- `data/network` — OkHttp/Retrofit wiring: dynamic base URL, bearer token
|
||||
interceptor, single-flight token refresh.
|
||||
- `data/PeerTubeRepository.kt` — one suspend-call surface for the whole UI.
|
||||
- `ui/` — Compose for TV screens, one for each of the destinations above.
|
||||
- No DI framework, no database. The service locator is `AppGraph`.
|
||||
|
||||
## License
|
||||
|
||||
JTube TV is free software: [GPL-3.0-or-later](LICENSE) — see the
|
||||
[fsf.org license page](https://www.gnu.org/licenses/) for details.
|
||||
JTube TV is free software under [GPL-3.0-or-later](LICENSE).
|
||||
Loading…
Add table
Add a link
Reference in a new issue