# Android Application ## 1. Purpose The Android application is a lightweight training-session recorder. Its design priority is low-friction data entry during a workout. It is not the canonical history or analytics application. ## 2. Session flow ```text Start session | v record started_at | v select/create exercise | v enter target + planned rest | v record actual sets | v optional body data / notes | v Finish session | v record ended_at | v validate + export Trainlog JSON ``` ## 3. Exercise catalog The Android application keeps a local exercise catalog so names are not retyped every session. Creating an exercise requires: - display name; - tracking mode: repetitions or duration. The application generates a stable `exercise_id`. A new exercise used in an exported session is included in the top-level session export metadata and is therefore importable by the TUI. The Android application must prevent accidental duplicate normalized names according to the Trainlog v1 contract. ## 4. Fast exercise form For a repetition exercise, the basic form is conceptually: ```text Exercise Presse à cuisses Load mode External Load 80 kg Sets 4 Repetitions 5 Rest 60 s ``` For a timed exercise: ```text Exercise Gainage ventral Load mode None Sets 3 Duration 45 s Rest 60 s ``` The application should remember practical defaults from the previous use of an exercise when that reduces typing, but remembered UI defaults are not part of the exchange-format contract. ## 5. Load modes The user chooses only when relevant: - none; - external; - assistance. `external` covers free weights and machine-displayed load. `assistance` stores a positive assistance value. The UI should label assistance explicitly so it cannot be confused with added resistance. ## 6. Actual work The application should pre-populate actual sets from the target. The user edits only what differs. Example target: ```text 5 / 5 / 5 / 5 ``` Actual: ```text 5 / 5 / 5 / 3 ``` The export preserves both target and actual values. Zero actual repetitions are valid for a real failed attempt. A planned exercise may also have zero actual sets if it was never started. ## 7. Rest `rest_seconds` is the planned rest duration for the exercise. v1 does not require a running rest timer and does not serialize measured per-set rest. A timer can be added later as UI behavior without changing the v1 format. ## 8. Timestamps `started_at` is recorded automatically when the session starts. `ended_at` is recorded automatically when the user finishes the session. An active/interrupted local session may exist without `ended_at`. The application must never invent an end timestamp merely to make export validation pass. ## 9. Body data Optional session-associated data: - body weight; - neck; - shoulders; - chest; - waist; - hips; - left/right arm; - left/right forearm; - left/right thigh; - left/right calf. The Android UI does not need to force these fields during every workout. ## 10. Notes Session and exercise notes are optional. The initial Android UI may omit note controls without violating v1, because the fields are optional. ## 11. Export Before export, Android must enforce both: - JSON structural validity; - Trainlog v1 semantic validity. A malformed or semantically inconsistent file must not be exported as a completed Trainlog document. ## 12. Non-goals Initial Android versions do not need: - analytics; - complex graphs; - cloud accounts; - remote databases; - social features; - muscle classification; - distance/cardio metrics; - per-set rest measurement. ## 13. Identifier generation When Android creates a new exercise, it generates: ```text ex_ ``` When Android creates a new session, it generates: ```text se_ ``` Display-name slugs must not be used as persistent identifiers. The visible exercise name remains independent from identity. ## 14. Catalog conflict behavior Android must prevent duplicate normalized names inside its own local catalog. A valid Android export can still conflict with an independently edited TUI catalog. The TUI owns final reconciliation. Android must not assume that a matching display name means two different IDs may be silently merged. ## 15. USB file-transfer transport The initial Android/Linux integration uses standard Android **file transfer (MTP)** mode. The Linux TUI/core accesses the device directly with `libudev` + `libmtp`. Trainlog does not require a mounted Android filesystem. Validated Linux-side capabilities: ```text USB_MTP_DETECTION=PASS MTP_STORAGE_ACCESS=PASS MTP_WRITE=PASS MTP_READ=PASS MTP_ROUNDTRIP=PASS ``` The transport foundation currently uses a root `Trainlog` folder for physical validation. The final JSON exchange subdirectory/naming convention is defined in the next slice before the Android recorder depends on it. The Android application itself will only need to produce a valid frozen Trainlog JSON v1 document and place it in the agreed exchange area. ## 16. Current Android implementation cursor The Linux transport and Sync TUI foundations are complete enough to begin the Android client. Initial Android development uses fictitious data. First Android slice: ```text 1. application scaffold 2. local exercise catalog 3. create/select exercise 4. session form 5. actual set entry 6. optional body measurements 7. fictitious completed session ``` Transport/export is added only after the local recorder workflow is comfortable. The Android client must preserve stable exercise IDs so a catalog snapshot from the PC can normalize exercise selection on both sides. ## Profile-aware Android forms Android uses the same exercise metadata as the TUI: ```text recording_mode tracking_mode data_fields ``` A continuous `Marche` configured with speed displays only: ```text Durée Vitesse ``` and no set count. Creating an exercise directly inside session entry must configure this metadata before adding it to the catalog/session. ## Android implementation cursor Android is the next implementation area. The application must share Trainlog's visual language with the TUI. Theme direction: ```text dark background cyan/teal Trainlog accent yellow active/focus role green success red error ``` Launcher icon: ```text T ``` Only the letter `T`, using Trainlog theme colors. Required recording sections: ```text Séance Exercice Mensurations ``` Session recording must allow creating a new exercise inline without leaving the session flow. Android forms are driven by the same profile metadata as desktop: ```text recording_mode tracking_mode data_fields ``` Examples: ```text SETS + REPS sets / reps / load / rest SETS + DURATION sets / duration / optional load / rest CONTINUOUS + DURATION + SPEED_KMH duration / speed ``` The app must never infer an input form from an exercise display name. Initial development uses fictitious records. Test/development data is removed before normal production use starts. ## Android scaffold implementation The Android project now lives in: ```text android/ ``` It is a native Kotlin + Jetpack Compose application with a custom Trainlog visual layer rather than default Material presentation. Implemented scaffold navigation: ```text Accueil ├── Enregistrer une séance │ ├── Ajouter depuis le catalogue │ └── Créer un nouvel exercice │ └── returns to session flow ├── Enregistrer un exercice └── Enregistrer des mensurations ``` The launcher icon is a minimal themed `T`. The UI reuses the Trainlog visual roles from the TUI: ```text background accent/cyan success/green warning/yellow error/red muted/blue graph/magenta ``` Android forms will be driven by: ```text recording_mode tracking_mode data_fields ``` The scaffold intentionally does not implement persistence or MTP yet. Next: ```text ANDROID_LOCAL_MODEL_AND_PERSISTENCE=NEXT ANDROID_SESSION_FORM=AFTER ANDROID_MTP_SYNC=AFTER_LOCAL_WORKFLOW ``` ## Android local catalog checkpoint The Android application now has a persistent local exercise catalog. Implemented: ```text Android SQLite exercise database profile-aware exercise model standalone exercise creation inline exercise creation from session flow catalog survives application restart session screen refreshes after inline creation ``` Android uses the same semantic axes as desktop: ```text recording_mode tracking_mode data_fields ``` Known supplemental fields remain: ```text SPEED_KMH DISTANCE_KM ``` Continuous creation forces duration tracking. Set-based creation keeps supplemental continuous fields disabled. The local Android schema is intentionally independent from the desktop SQLite schema. Synchronization later exchanges versioned domain data rather than copying SQLite database files. Next: ```text ANDROID_SESSION_RECORDING=NEXT ANDROID_BODY_PERSISTENCE=AFTER MTP_SYNC=AFTER_LOCAL_WORKFLOWS ``` ## Android session recording checkpoint Android can now build and persist real local sessions. Flow: ```text Session → choose catalog exercise → profile-aware entry form → add exercise to session draft → repeat for additional exercises → save session ``` Profile-aware forms: ```text SETS + REPS set count repetitions per set SETS + DURATION set count duration per set CONTINUOUS + DURATION duration minutes configured speed/distance fields ``` Persistence mirrors the domain split: ```text sessions session_exercises performed_sets continuous_activity ``` Continuous exercises do not create fake performed sets. The Android local database version is now 2. Next: ```text ANDROID_SESSION_HISTORY=NEXT ANDROID_BODY_PERSISTENCE=AFTER MTP_SYNC=AFTER_LOCAL_WORKFLOWS ``` ## Android session history checkpoint Android now exposes persisted local sessions through: ```text Accueil → Consultation → Historique des séances → Détail séance ``` Detail rendering remains profile-aware: ```text SETS + REPS one line per performed set with reps SETS + DURATION one line per performed set with duration CONTINUOUS duration configured speed configured distance ``` The history reader uses the persisted session snapshot metadata rather than inferring behavior from exercise names. Next: ```text ANDROID_BODY_PERSISTENCE=NEXT ANDROID_LOCAL_WORKFLOWS_THEN_MTP ``` ## Android body measurement checkpoint The Android body workflow is now persistent and uses the same measurement set as the TUI. Fields: ```text weight neck shoulders chest waist hips left/right arm left/right forearm left/right thigh left/right calf ``` Rules: ```text empty field = measurement not taken at least one positive metric required comma or dot accepted for decimal entry ``` Android SQLite schema version: ```text 3 ``` The body screen also shows the five most recent observations. At this point the three primary Android recording workflows are locally functional: ```text session recording exercise creation body measurement recording ``` Next: ```text ANDROID_LOCAL_POLISH_AND_VALIDATION=NEXT MTP_SYNC=AFTER_LOCAL_CHECKPOINT ``` ## Local Android workflows — validated ```text ANDROID_SCAFFOLD=PASS ANDROID_THEME_PARITY=PASS ANDROID_EXERCISE_CREATE=PASS ANDROID_INLINE_EXERCISE_CREATE=PASS ANDROID_SESSION_RECORDING=PASS ANDROID_SESSION_HISTORY=PASS ANDROID_BODY_RECORDING=PASS ANDROID_LOCAL_WORKFLOWS=PASS ``` The application is now locally usable for its three primary recording flows: ```text session exercise body measurements ``` Session and history rendering are profile-aware. The Android-local SQLite database is not a synchronization format. Next: ```text ANDROID_MTP_SYNC=NEXT ```