Session count alone says nothing about consistency, which is what makes pelvic floor training work. Record every completion timestamp and derive streaks from local calendar days: current streak (survives until a full day is missed), best streak, and a 14-day dot strip on the home screen. The done screen now shows the streak so finishing is rewarded. - src/lib/streak.ts: pure day-key / streak logic, covered by node --test - store: new `sessions` array, defaulted for pre-existing installs - home: StreakCard, screen now scrolls for smaller phones - tsconfig: TS 6 no longer auto-includes @types, so declare node types Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
46 lines
1.7 KiB
Markdown
46 lines
1.7 KiB
Markdown
# Kegel
|
||
|
||
Pelvic floor trainer for sexual performance — a free, local-only take on what
|
||
Stamina was before it went paid. Expo / React Native, Android + iOS.
|
||
|
||
## How it works
|
||
|
||
A session is four guided blocks driven by a step timer with haptic cues:
|
||
|
||
1. **Holds** — 8 × squeeze-and-hold. This is the progressive-overload driver:
|
||
holds start at 5s and grow **+1s every 3 completed sessions** (capped at
|
||
30s). Manual ±1s adjustment in Settings.
|
||
2. **Pushes** — 5 × reverse kegel (gently bear down). Scales at half the rate
|
||
of holds, capped at 12s.
|
||
3. **Quick squeezes** — 10 × 1s burst contractions with 1s release.
|
||
4. **Quick pushes** — 10 × 1s burst pushes with 1s release.
|
||
|
||
Progress (session count, difficulty adjustment, completion history) lives in
|
||
AsyncStorage — no server, no account. The home screen shows your **day streak**
|
||
(alive until a full day is missed), best streak, and a two-week activity strip.
|
||
|
||
## Layout
|
||
|
||
- `src/app/` — expo-router screens: `index` (home), `session` (timer), `settings`
|
||
- `src/lib/workout.ts` — pure session-plan + progression logic
|
||
- `src/lib/streak.ts` — pure streak / calendar-day logic (tested)
|
||
- `src/lib/store.ts` — tiny local store persisted to AsyncStorage
|
||
- `android/` — committed prebuild output; CI builds it directly
|
||
|
||
## Development
|
||
|
||
```sh
|
||
npm install
|
||
npm start # Expo dev server
|
||
npm run typecheck
|
||
npm test # node --test over src/lib/*.test.ts
|
||
```
|
||
|
||
## Release
|
||
|
||
Push to `main` → Gitea Actions on the desktop runner (`runs-on: desktop`,
|
||
never the VPS) builds a signed APK and publishes a Gitea release — install via
|
||
Obtainium. Keystore: `~/.android-keys/kegel-release.jks` (repo secrets
|
||
`KEYSTORE_B64`, `KEYSTORE_PASSWORD`; alias `kegel`). iOS runs via
|
||
`npx expo run:ios` from a Mac.
|