FitnessDroid
Android-klient (Android 12+) för gym-API:t — samma backend som gym-delen i brasse-pc.eu-v2. README:n täcker "få det att bygga"; här ligger arkitektur och designbeslut.
Arkitektur (M2)
MainActivity (Compose, edge-to-edge)
└── FitnessDroidApp — växlar på AuthState
├── LoginScreen
└── AppRoot — bottenrad (Hem/Pass/Statistik/Profil) + start-FAB + minispelare
├── HomeScreen — starta fritt pass, favoritpass/mallar, synk-chip
├── SessionScreen — passläget: HorizontalPager per övning, steppers,
│ vilotimer (helskärm/banner), synk-badge per set
├── ExercisePicker — sök + muskelgrupp/muskel-chips, favoriter först
├── HistoryScreen — avslutade pass (direkt mot API:t)
├── ProfileScreen — profil + Inställningar + logga ut
└── SettingsScreen — vilotimerstil, larmläge, standardvila
AppContainer (manuell DI)
├── TokenStore / SettingsStore (DataStore)
├── GraphQlClient (OkHttp; 5xx → IOException = nätfel, inte auth-fel)
├── AuthRepository — login/refresh/restore; loggar INTE ut vid nätfel
├── AppDatabase (Room) — LocalSession/-Exercise/-Set, PendingOp,
│ CachedExerciseType/MuscleGroup/Muscle/StartCard
├── SyncEngine — FIFO-op-kö, retry m. backoff, server-id-mappning
├── GymRepository — lokal-först-fasad som UI:t pratar med
└── RestTimerController — absolut sluttid, larm enligt inställning
Offline-modellen
Passet lever i Room. Varje åtgärd (starta pass, lägg övning, logga set,
avsluta) blir en rad i pending_op som SyncEngine kör i strikt ordning mot
GraphQL-API:t; server-id:n skrivs tillbaka på raderna. Ej synkade set får en
moln-upp-ikon, synkade en moln-check; hemskärmen visar global status
(Synkat / N osynkat / Offline / Synkfel). Uppdateras ett set som ännu inte
synkats bär den väntande ADD-opsen automatiskt de nya värdena (den läser
raden när den körs). Referensdata (övningar, muskler, favoritkort) cachas
och överlever offline; senaste prestation per övning cachas för förifyllnad.
Vilotimern
Startar automatiskt när ett set loggas. Längd: övningens
defaultRestSeconds från API:t, annars appens standard (inställning).
Presentation enligt inställning: helskärms-takeover eller banner längst ner.
Vid utgång: larmljud / vibration / bara visuellt / inget (inställning).
Räknar mot absolut sluttid så den överlever pausad app.
API-tillägg (2026-07-24)
MuscleGroup.iconKey— stabil ikonnyckel ("chest", "back", "legs", "shoulders", "arms", "core", "cardio", "fullbody"); null → namnheuristik i appen (MuscleIcons.kt)ExerciseType.defaultRestSeconds— förslagen vilotid; null → appens standard- Migration
20260724000000_AddIconKeyAndDefaultRestSeconds(körs automatiskt vid API-uppstart)
Designbeslut
- Handskrivna GraphQL-strängar (samma som webbens
gymTrackerApi.js) - Auth speglar webben: JWT 2h + roterande refresh-token 7d, auto-refresh 2 min före utgång bakom mutex; 5xx/nätfel loggar aldrig ut
- Tyst återinloggning (0.3.0): uppgifterna sparas AES/GCM-krypterade med
nyckel i Android Keystore (
CredentialStore); avvisar servern vår refresh-token provas ett nytt login innanforceLogout— användaren märker aldrig utloggningen. Manuell utloggning eller avstängd toggle rensar uppgifterna - Manuell DI, Material You (minSdk 31), versionCode = CI-byggnummer
- Favoritpass startas genom att kopiera övningslistan klient-side (fungerar offline); mallar ger även auto-progression via API:t
Signering & CI
Se README + infra-Doc:
nyckeln aldrig incheckad (Actions-secrets), CI bygger på Pi5/arm64 med
statisk arm64-aapt2 via android.aapt2FromMavenOverride.
Milstolpar
Se doc/plan.md. 1 (grund+login), 2 (aktivt pass, offline, vilotimer + polering: set- redigering, historikvyer, avsluta-överblick med tidsrättning/kcal/PB) och 3:s första del (statistik med KPI:er, volymtrend, kroppskarta i Canvas, PB-lista + tyst återinloggning + fler inställningar) är klara. M3 komplett: statistik (KPI:er, scrollbar volymtrend, kroppskarta, PB-lista, kroppsviktsgraf med trend), tyst återinloggning, in-app- uppdatering (version.json på släppsidan → hemskärmskort → nedladdning med sha256-koll → Androids installer), skivkalkylator (stång 20/0/egna), kroppsviktspårning (BodyMeasurement-API med uuid + datum + framtida muskel/fett/vatten-%; rätta/ta bort från profilen). Näst: mallredigering, övningsprogression-grafer, eget datumintervall i statistiken, loggsamlare, widget.