app: Scaffold Android TV PeerTube client (MVP)
Start the SmartTube-inspired PeerTube TV client as a Kotlin + Compose for TV app. It targets any PeerTube instance (v1 API), with JTube as the default, and covers login 0, local/own video listings 1-2, search 3, subscriptions 4, server-backed history 5 and HLS/progressive playback with watching reports 6. Password is only used for the OAuth password grant and never stored; tokens are kept in EncryptedSharedPreferences. Building needs JDK 17+ (see README); the Gradle wrapper is checked in so no local Gradle is required.
This commit is contained in:
commit
59029438ad
40 changed files with 2605 additions and 0 deletions
69
README.md
Normal file
69
README.md
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
# 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).
|
||||
|
||||
## Features (v0.1)
|
||||
|
||||
- **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.
|
||||
|
||||
Out of scope for now (see `BACKLOG.md`): uploading, editing, subscribing/unsubscribing,
|
||||
deleting, creating anything other than history entries.
|
||||
|
||||
## 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).
|
||||
|
||||
```bash
|
||||
./gradlew :app:assembleDebug
|
||||
```
|
||||
|
||||
Install on a TV device:
|
||||
|
||||
```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 overview
|
||||
|
||||
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.
|
||||
|
||||
## License
|
||||
|
||||
Not decided yet — TBD before first public release.
|
||||
Loading…
Add table
Add a link
Reference in a new issue