Files
FitnessDroid/README.md
claude 213f635d93
All checks were successful
release / build-release (push) Successful in 4m22s
Statistik: PB-listan laddade inte — init-ordning i StatsViewModel + fallback mot äldre gym-API
- StatsViewModel: pbMode/pbs deklarerades efter init { load() } → refreshPbs()
  körde på null vid första öppningen (NPE som runCatching svalde). Listan kom
  först när man bytte läge/period. Deklarationerna flyttade före init.
- personalBestsDetailed: känner igen schemafel ("does not exist") från ett
  äldre API och faller tillbaka på den gamla personalBests-frågan +
  favoriteExercises; PbList.legacyApi styr UI:t (lägen/sök/ark avstängda,
  notis om att gym-API:t behöver uppdateras).
- Fel vid PB-hämtning visas under rubriken i stället för tom lista;
  LiftStatusSheet/PbSearchCard visar serverns fel i stället för "offline?".
- README: API-krav för rekordstatus, fallback, Waydroid-testflöde.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NGT3xpdm51McmSrJcHnrzq
2026-09-10 00:24:49 +02:00

135 lines
6.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# FitnessDroid
Android-klient för gym-API:t på `https://gymapi.brasse-pc.eu/graphql` — samma
backend som gym-delen i [brasse-pc.eu-v2](https://gitea.brasse-pc.eu/brasse/brasse-pc.eu-v2).
- **Kräver Android 12 eller nyare** (minSdk 31)
- Kotlin + Jetpack Compose + Material 3 (Material You-dynamiska färger)
- GraphQL över OkHttp, tokenlagring i DataStore
## Installera appen på telefonen
Ladda ner `FitnessDroid.apk` från [släppsidan](https://gitea.brasse-pc.eu/brasse/FitnessDroid/releases)
(`latest` byggs om vid varje push till `main`), öppna filen på telefonen och
tillåt installation från okänd källa. Uppdateringar installeras ovanpå — samma
signeringsnyckel används av CI och lokala byggen.
## Bygga själv
### Förutsättningar (Arch/Garuda)
```bash
sudo pacman -S jdk17-openjdk android-tools
```
Android SDK behövs också (platform 35 laddas ner automatiskt av bygget om
licensen är accepterad). Peka ut din SDK i `local.properties` i repo-roten:
```properties
sdk.dir=/home/<du>/Android/Sdk
```
### Bygg
```bash
git clone https://gitea.brasse-pc.eu/brasse/FitnessDroid.git && cd FitnessDroid
./gradlew :app:assembleRelease # signerad release-APK
# APK: app/build/outputs/apk/release/app-release.apk
```
I VS Code: kör build-tasken (`Ctrl+Skift+B`) — den lägger APK:n i
`build/FitnessDroid.apk`. Tasken `installera på telefon (adb)` installerar den
direkt på en ansluten telefon med USB-felsökning på.
### Testa lokalt i Waydroid
Waydroid (x86_64, Android 13) fungerar som emulator på brasse-linux01. Sessionen startas
med `waydroid session start` + `waydroid show-full-ui`, sedan
`adb connect 192.168.240.112:5555` (IP:n från `waydroid status`) — första gången måste
*Allow USB debugging* godkännas i Waydroid-fönstret. Installera med
`adb install -r app/build/outputs/apk/debug/app-debug.apk`; skärmdumpar via
`adb exec-out screencap -p > fil.png`, UI-koordinater via `uiautomator dump`.
Saknar Android nät bortom värden är det Dockers FORWARD-spärr — se infra-Doc
`hosts/brasse-linux01.md` (Waydroid-avsnittet). Testkonto: `bb01`.
### Testa mot API:t
Logga in med ditt vanliga gym-konto (LDAP). API-url:en går att ändra under
"Avancerat" på inloggningsskärmen (standard: `https://gymapi.brasse-pc.eu/graphql`).
## Rekordstatus: träning / tävling / räknas ej
Under **Statistik → Personbästa** finns växeln *Alla giltiga · Tävling · Träning*. Tryck på
ett rekord så öppnas ett ark med vikt, est. 1RM, datum, pass och anteckning, där lyftet kan
märkas som **Träning**, **Tävling** eller **Räknas ej** (fusk, felregistrerat, ej godkänt)
med en kommentar. Under arket visas topplistan för samma övning × reps ("näst i tur"),
så ett bortplockat lyft kan väljas och återställas. Samma ark öppnas när man trycker på
ett set i passhistoriken. Kortet **Sök i rekorden** överst i Personbästa svarar på "hur många reps på X kg?" eller
"hur tungt på N reps?" exakt träff eller närmast under/över, plus en uppskattning via
bästa est. 1RM. Stjärnan på ett PB-kort gör övningen till **favorit** (samma
favoriter som övningsväljaren) så att den ligger överst i PB-listan i både app och webb. "Räknas ej" tas ur rekord, 1RM och PB-höjdpunkter på servern
(kod: `ui/common/LiftStatusSheet.kt`, API: `setLiftStatus`/`setSessionSetStatus`).
**Kräver gym-API:t från 2026-09-06 eller senare** (`personalBests(mode)`, `pbLookup`,
`pbCandidates`, `liftDetail`, `setLiftStatus`). Mot ett äldre API faller appen tillbaka på
den gamla PB-frågan: rekorden visas fortfarande (favoriter hämtas via `favoriteExercises`),
men lägesväxeln, sökkortet och detaljarket är avstängda och en notis säger att servern
behöver uppdateras. Fel vid hämtningen visas under rubriken i stället för att listan tyst
blir tom. Schemafel känns igen på HotChocolates "does not exist" (`GraphQlException.isSchemaMismatch()`
i `data/GraphQlClient.kt`).
## Signeringsnyckeln
Nyckeln är **inte** incheckad (repot är publikt). Lokalt ligger den i
`signing/fitnessdroid.jks` + `signing/keystore.properties` (gitignorerade);
CI får samma nyckel via Actions-secrets `KEYSTORE_B64` och
`KEYSTORE_PASSWORD`. Finns ingen nyckel signeras release-bygget med
debug-nyckeln så att en färsk klon ändå kan bygga — men den APK:n kan inte
uppdatera en installation från släppsidan (annan signatur).
Skapa en ny nyckel (om `signing/` saknas):
```bash
keytool -genkeypair -keystore signing/fitnessdroid.jks -alias fitnessdroid \
-keyalg RSA -keysize 2048 -validity 10950 -dname "CN=FitnessDroid, O=brasse-pc.eu"
# och skriv motsvarande signing/keystore.properties (storeFile/storePassword/keyAlias/keyPassword)
```
## CI
`.gitea/workflows/release.yaml` bygger en signerad APK vid varje push till
`main` och lägger den på den rullande `latest`-releasen. Bygget körs på
runnern `brasse-linux01-runner` (x86_64, label `linux-amd64`) — Pi5:n orkar
inte APK-bygget. Workflowen är ändå arkitekturvillkorad: på arm64 används en
statiskt byggd aapt2 via `android.aapt2FromMavenOverride`.
## Aktiviteter, kcal-mätare & mål
Utöver gympass loggar appen **aktiviteter** (promenad, löpning, vandring,
fäktning/HEMA m.fl. — ~64 typer ur MET-kompendiet) med GPS-livespårning
(osmdroid/OSM-karta, fartgrind mot GPS-hopp, accelerometer-rörelsevakt),
RPE-slider för tidsbaserade aktiviteter och offline-kö. Hemskärmen visar
**dagens kalorier** (aktivt loggat / telefonens steg via Health Connect /
passiv BMR) och **mål** med progress (kcal, pass, steg, aktiviteter, km —
per dag/vecka/månad). Statistiken har en konditionssektion ❤️.
Plan & detaljer: [`doc/activities-plan.md`](doc/activities-plan.md).
## Bluetooth-våg
Appen kan hämta vägningar (vikt + muskel/fett/vatten-%) direkt från en
BLE-personvåg med [openScale](https://github.com/oliexdev/openScale)s
drivrutiner (vendrade under `app/src/main/java/com/health/openscale/`).
Koppla vågen under *Inställningar → Bluetooth-våg* och väg dig från profilen.
Först ut: Biltema 84-1002 (PT-727), som är en Exingtech Y1 ("VScale").
Detaljer: [`doc/openscale-integration.md`](doc/openscale-integration.md).
## Licens
GPL-3.0 (se [`LICENSE`](LICENSE)). Relicensierad från och med BT-vågstödet —
openScales drivrutiner är GPL-3.0, vilket kräver att hela appen är det.
BLE-biblioteket [Blessed-Kotlin](https://github.com/weliem/blessed-kotlin)
är MIT.
Mer om arkitektur och planer: [`doc/plan.md`](doc/plan.md) och
[wikin](https://gitea.brasse-pc.eu/brasse/FitnessDroid/wiki).