file-share/plan.md

99 lines
No EOL
3.6 KiB
Markdown

# Android → PC File Drop
Minimal Kotlin Android app that picks files/images and uploads them to a folder on a PC over the local network.
## Architecture
Two pieces:
1. **PC receiver** — tiny HTTP server that accepts multipart uploads and writes files into a chosen folder.
2. **Android app** — one screen, one button: pick files → POST them to the PC.
No cloud, no accounts, no discovery protocol. You type (or QR-scan) the PC's LAN IP once and save it.
## PC Receiver
**Language:** Go (single binary). Go for "double-click and forget."
**Behavior:**
- Listen on `0.0.0.0:8787`.
- `POST /upload` accepts `multipart/form-data`, saves each part to `DROP_DIR` with its original filename.
- Collision policy: append ` (1)`, ` (2)`, etc.
- Optional shared-secret header (`X-Auth: <token>`) so randos on the same Wi-Fi can't dump files on you.
- `GET /` returns "ok" for a health check.
- Log each received file: name, size, source IP.
it is seen on the local panel so that user locally can download
**Config:**
- `DROP_DIR` — where files land (default `~/Drops`).
- `AUTH_TOKEN` — shared secret (generated on first run, printed + saved to config).
- `PORT` — default 8787.
**Firewall:** open the port on the PC's LAN profile only.
## Android App
**Stack:** Kotlin, Jetpack Compose, single Activity, minSdk 26.
**Screens:** one.
**UI:**
- Text field: PC address (e.g. `192.168.1.42:8787`), persisted in `DataStore`.
- Text field: auth token, persisted.
- Big button: "Pick files".
- Below: list of currently-selected files with progress bars during upload.
- Snackbar for success/failure per file.
**Flow:**
1. Tap button → `ActivityResultContracts.OpenMultipleDocuments()` (handles images, video, any file; no storage permission needed on modern Android).
2. For each returned `Uri`: stream it as a multipart part to `http://<address>/upload` with the auth header.
3. Show per-file progress; on 200, mark done; on error, show retry.
**Networking:** OkHttp with a `MultipartBody`, streaming from `contentResolver.openInputStream(uri)` so big videos don't OOM.
**Manifest:**
- `INTERNET` permission.
- `usesCleartextTraffic="true"` scoped to local IP ranges via `network_security_config.xml` (HTTP is fine on LAN; adding TLS is a stretch goal).
**Share target (stretch):** register as a share target so you can hit "Share → Drop to PC" from the Photos app.
## Protocol
```
POST /upload HTTP/1.1
Host: 192.168.1.42:8787
X-Auth: <token>
Content-Type: multipart/form-data; boundary=...
--boundary
Content-Disposition: form-data; name="file"; filename="IMG_1234.jpg"
Content-Type: image/jpeg
<bytes>
--boundary--
```
Response: `200 OK` with JSON `{"saved": "IMG_1234.jpg"}` or `4xx/5xx` with error text.
## Milestones
1. PC receiver in ~60 lines; test with `curl -F file=@foo.jpg http://localhost:8787/upload -H "X-Auth: ..."`.
2. Android app scaffold: Compose UI, DataStore for settings, file picker returning URIs.
3. Wire up OkHttp multipart upload from a URI stream.
4. Progress + error UI.
5. Package: PC receiver as a systemd user service (Linux) or Task Scheduler entry (Windows) so it autostarts. Android side sideload the APK.
## Stretch
- QR code on PC receiver's `GET /` page encoding `address + token` so first-time setup is scan-once.
- mDNS advertisement (`_filedrop._tcp.local`) so the app can discover the PC without typing IPs.
- TLS with a self-signed cert pinned in the app.
- Share-target intent filter.
- Resume interrupted uploads (`Content-Range`).
## Non-goals
- PC → Android direction (use MTP or a second app instance later).
- Internet / NAT traversal.
- Multiple PCs at once (one address at a time is fine).