diff --git a/tasks.org b/tasks.org index 3d448fa..e1933da 100644 --- a/tasks.org +++ b/tasks.org @@ -184,13 +184,20 @@ server/Dockerfile uses python:3.11-slim, installs deps, copies app/, exposes 876 - datetime: [2026-05-17 Sat 17:00] * milestone 2: android local capture -** TODO create android project +** DONE create android project *** acceptance - kotlin android app builds. - jetpack compose enabled. - min sdk is reasonable for current personal device. - app id is stable, e.g. `me.hgsky.phonecapture`. -** TODO build capture screen +*** notes +Gradle project in android/. AGP 8.7.3, Kotlin 2.0.21, Compose BOM 2024.10.01. minSdk=31, compileSdk=36. App ID is me.hgsky.synq. Open android/ in Android Studio and hit Sync — AS will download the Gradle wrapper (8.9) automatically. +*** evidence +- commit: 19b05a8 +- tests: Gradle sync in Android Studio (manual step) +- datetime: [2026-05-18 Sun 17:00] + +** DONE build capture screen *** acceptance - app opens to multiline text box. - keyboard opens automatically. @@ -198,22 +205,49 @@ server/Dockerfile uses python:3.11-slim, installs deps, copies app/, exposes 876 - tags field exists. - save button exists. - save and close affordance exists. -** TODO implement local room database +*** notes +CaptureScreen.kt uses LaunchedEffect(Unit) { focusRequester.requestFocus() } for auto-focus. note/todo Switch, tags OutlinedTextField, "save" OutlinedButton (stays), "save & close" Button (finishes activity). No network call on launch. +*** evidence +- commit: 19b05a8 +- tests: manual — build and run on device/emulator +- datetime: [2026-05-18 Sun 17:00] + +** DONE implement local room database *** acceptance - capture entity has id, created_at, kind, body, tags, device, status, synced_at, and last_error. - saving creates pending row. - pending captures survive app restart. -** TODO implement capture id generation +*** notes +CaptureEntity, CaptureDao, CaptureDatabase in data/db/. Tags stored as JSON string (kotlinx-serialization). DB name synq.db, singleton via companion object. Room persists across restarts by default. +*** evidence +- commit: 19b05a8 +- tests: manual — save a capture, force-close app, reopen and check history +- datetime: [2026-05-18 Sun 17:00] + +** DONE implement capture id generation *** acceptance - id format is stable and readable, e.g. `phone-yyyymmdd-hhmmss-rand`. - ids are generated client-side. - tests or simple assertions prevent blank/duplicate ids in normal flow. -** TODO implement basic history screen +*** notes +generateCaptureId() in data/CaptureId.kt. Format: phone-YYYYMMDD-HHmmss-xxxx (4 random [a-z0-9] chars). Called in CaptureViewModel.save() before Room insert. +*** evidence +- commit: 19b05a8 +- tests: manual — check id column in history; each save produces a unique phone-… id +- datetime: [2026-05-18 Sun 17:00] + +** DONE implement basic history screen *** acceptance - lists recent captures. - shows pending/synced/failed status. - failed row shows last error. - user can retry failed/pending sync. +*** notes +HistoryScreen.kt observes captureDao.observeAll() as Flow. Status colored green/red/grey. Retry button shown for pending/failed; calls updateStatus(id, "pending", null) so the sync worker picks it up in milestone 3. +*** evidence +- commit: 19b05a8 +- tests: manual — save captures, navigate to history, verify status labels and retry button +- datetime: [2026-05-18 Sun 17:00] * milestone 3: android sync ** TODO implement api client