archive-97f2350/SETUP.md 3.2 KB
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.