archive-97f2350/SETUP.md
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# Sianel — Android client setup
Compose app for orllewin.uk/video. Lets you enter your password, pick a video via the system file chooser, upload it, list existing uploads, and delete them.
## Open in Android Studio
This folder is a Gradle project but doesn't include the Gradle wrapper jar. Two options:
**Option A — generate the wrapper locally (fastest):**
```bash
cd android
gradle wrapper --gradle-version=8.7
./gradlew assembleDebug
```
Then in Android Studio: `File > Open` → select the `android/` folder.
**Option B — let Android Studio do it:**
In Android Studio: `File > New > Import Project` → select the `android/` folder. It will prompt to download Gradle and generate the wrapper.
## Run
Connect a device or start an emulator (API 26+), then:
```bash
./gradlew installDebug
```
…or hit Run in Android Studio.
## How it works
- **Password** is stored in `EncryptedSharedPreferences` (AES-256-GCM, key managed by Android Keystore). Cleared via the "Forget" button.
- **File chooser** is the system picker, launched with MIME filter `video/*` via `ActivityResultContracts.GetContent`.
- **Upload** streams via OkHttp multipart with a custom `ForwardingSink` that reports byte-level progress to the UI. The picked content URI is copied into the app's cacheDir first (since OkHttp needs a `File`), then deleted after the request completes.
- **List / delete** call `/video/api/list` and `/video/api/delete` with the same `Authorization: Bearer <password>` header.
## File map
```
android/
├── settings.gradle.kts
├── build.gradle.kts project-level
├── gradle.properties
└── app/
├── build.gradle.kts app-level deps
├── proguard-rules.pro
└── src/main/
├── AndroidManifest.xml
└── java/uk/orllewin/sianel/
├── MainActivity.kt entry point + Material3 theme
├── data/
│ ├── VideoClient.kt OkHttp wrapper around the API
│ └── Prefs.kt encrypted password store
└── ui/
├── MainViewModel.kt state + coroutines
└── VideoApp.kt Compose UI
```
## What's included
- **Persistent upload via `WorkManager`** — uploads survive backgrounding and process death. The ViewModel reattaches to any in-flight worker on resume (tagged `video-upload`).
- **Optional video compression with Media3 Transformer** — hardware-accelerated, no ffmpeg. A "Compression" dropdown on the main screen offers Original / 720p ~2.5 Mbps / 480p ~1 Mbps. Skipped automatically when the source is already shorter than the target on its long edge. Compress and upload happen in the same `UploadWorker`, so both survive backgrounding.
- **Tap a row to open the playback URL** — uses `CustomTabsIntent` with a fallback to `ACTION_VIEW`.
- **Delete confirmation dialog** — Material 3 `AlertDialog`, shows the hash.
- **Adaptive launcher icon** — filmstrip + play triangle, defined as a vector drawable (no PNGs to maintain).
## Still to polish
- Pull-to-refresh on the list.
- Share-intent target (open another app's "Share" sheet and pick this one).
- Cancel button on an in-progress upload.