Commit Graph

679 Commits

Author SHA1 Message Date
0263a18c5f fix: preserve GPS data when saving session edits
All checks were successful
CI / update (push) Successful in 2m18s
The PUT endpoint overwrote the exercises array with client data that
doesn't include gpsTrack/gpsPreview/totalDistance. Now merges existing
GPS data back into incoming exercises before saving.
2026-03-25 07:24:20 +01:00
1e0dd27fa3 fix: shorten dashboard labels to "Burned" and "Covered"
All checks were successful
CI / update (push) Successful in 2m22s
Values already include units (kcal, km), so verbose labels were redundant.
Remove unused distance_covered i18n key.
2026-03-25 07:18:57 +01:00
9caa0fbc24 fix: preserve GPS data when recalculating workout sessions
Replace .save() with $set updateOne so only computed fields (totalVolume,
totalDistance, prs, gpsPreview) are written. Previously the full document
re-serialization could strip gpsTrack arrays.
2026-03-25 07:18:52 +01:00
f3a89d2590 feat: add cardio PRs for longest distance and fastest pace by range
All checks were successful
CI / update (push) Successful in 2m14s
Track longestDistance and fastestPace PRs for cardio exercises with
activity-specific distance ranges: running (0-3, 3-7, 7-21.1, 21.1-42.2,
42.2+ km), swimming (0-0.4, 0.4-1.5, 1.5-5, 5-10, 10+ km), cycling
(0-15, 15-40, 40-100, 100-200, 200+ km), hiking (0-5, 5-15, 15-30,
30-50, 50+ km), rowing (0-2, 2-5, 5-10, 10-21.1, 21.1+ km).

Shared detection logic in cardioPrRanges.ts used by both session save
and recalculate endpoints. Display support in history detail and workout
completion summary.
2026-03-24 20:41:23 +01:00
81bb3a2428 fix: persist and display Volume PRs in workout history
All checks were successful
CI / update (push) Successful in 2m13s
Volume PRs were calculated client-side in the workout summary but never
saved to the database, so they didn't appear in history detail pages.
Add bestSetVolume PR detection to both session save and recalculate
endpoints, and render the new type in the history detail view.
2026-03-24 20:31:18 +01:00
f9f8761c7b remove Android CI workflow and Dockerfile
All checks were successful
CI / update (push) Successful in 2m18s
APK build and deploy is now handled by a local post-commit hook
using scripts/android-build-deploy.sh + rsync.
2026-03-24 20:25:17 +01:00
10233a3804 fix: track Gradle wrapper in git so Docker build finds gradlew
Some checks failed
CI / update (push) Successful in 3m22s
Android APK / build (push) Failing after 18m10s
The Gradle wrapper (gradlew, gradlew.bat, gradle/wrapper/) was
gitignored, causing the Docker APK build to fail with
"`gradlew` not found" since COPY doesn't include ignored files.
2026-03-24 19:06:08 +01:00
d1fbb1c826 fix: use rust:slim-trixie for JDK 21 and latest Rust, trim CI paths
Some checks failed
Android APK / build (push) Failing after 14m16s
CI / update (push) Successful in 2m23s
- Switch to Debian Trixie base for native JDK 21 and latest Rust
- Remove Adoptium APT repo workaround
- Only trigger Android CI on src-tauri/ and build config changes
2026-03-24 18:48:08 +01:00
e9de9a35c8 fix: use Adoptium APT repo for JDK 21 in Android Dockerfile
Some checks failed
Android APK / build (push) Failing after 8m26s
CI / update (push) Has been cancelled
Bookworm only ships JDK 17. Add Adoptium's official APT repository
to install Temurin 21 via package manager.
2026-03-24 18:37:48 +01:00
6685e5731c fix: stop GPS tracking on workout cancellation
Some checks failed
Android APK / build (push) Failing after 4m48s
CI / update (push) Has been cancelled
The cancel button didn't stop the GPS foreground service, leaving it
running after the workout was dismissed.
2026-03-24 18:30:58 +01:00
fe49c5b997 add Android app to README, CI workflow for APK builds
- README: add Fitness section with APK download link
- Dockerfile.android: containerized build with Rust, Android SDK/NDK,
  Java 21, Node 22, pnpm — builds and signs the APK
- CI workflow: builds APK in container on push, deploys to
  bocken.org/static/Bocken.apk via SCP
2026-03-24 18:29:38 +01:00
8fff5f14b5 android: rich GPS notification with pace, request POST_NOTIFICATIONS
- Notification title: "Bocken — Tracking GPS for active Workout"
- Live updates with elapsed time, distance, and pace (min/km)
- Request POST_NOTIFICATIONS permission at runtime (Android 13+)
- Page titles: "- Fitness" → "- Bocken" (missed in prior commit)
2026-03-24 18:29:38 +01:00
28b2494a08 rebrand app from Bocken Fitness to Bocken, track Android project
- Manifest: name/short_name → "Bocken", start_url → "/"
- Tauri: productName → "Bocken", identifier → org.bocken.app, url → "/"
- Cargo: package → bocken, lib → bocken_lib
- Page titles: "- Fitness" → "- Bocken" across all fitness routes
- Build script: auto-regenerate android project on identifier change
- Regenerate app icon from website favicon
- Track Android project source in git (ignore only build output/caches)
- Add native GPS foreground service and AndroidBridge for background
  location tracking (LocationForegroundService, AndroidBridge.kt)
- Add ACCESS_BACKGROUND_LOCATION permission for screen-off GPS
2026-03-24 18:29:38 +01:00
1ea0899bee fix: precache __data.json for offline client-side navigation
All checks were successful
CI / update (push) Successful in 2m2s
The fitness pages were only precaching HTML shells, but SvelteKit
client-side navigation fetches __data.json instead. Without these
cached, navigating to workout/training while offline would fail.
2026-03-23 22:28:39 +01:00
9245f3e17f fix: sync rest timer exercise/set indices across sessions
All checks were successful
CI / update (push) Successful in 2m2s
restExerciseIdx and restSetIdx were sent by the client but never
persisted server-side, so other sessions couldn't display which
exercise/set the rest timer belonged to.
2026-03-23 22:22:32 +01:00
785341bf0b fitness: match WorkoutFab rest timer style to active page RestTimer
All checks were successful
CI / update (push) Successful in 2m1s
2026-03-23 22:18:22 +01:00
0f79170f02 fitness: add offline support with session queue and shell caching
All checks were successful
CI / update (push) Successful in 2m3s
Cache fitness page shells and data routes in the service worker so
pages load offline. Queue finished workouts in IndexedDB when the
POST fails and auto-flush them on reconnect. Show an offline banner
on the completion screen so the user knows their workout will sync.
2026-03-23 22:15:42 +01:00
621aa46cda homepage: move docs to its previous place
All checks were successful
CI / update (push) Successful in 2m2s
2026-03-23 21:27:10 +01:00
2f31f3cc19 faith: fix typos in confiteor
All checks were successful
CI / update (push) Successful in 2m4s
2026-03-23 19:55:39 +01:00
831e6d158b homepage: move fitness page up on the page
All checks were successful
CI / update (push) Successful in 2m6s
2026-03-23 19:52:57 +01:00
069d524d3e fix: resolve Svelte a11y and reactivity build warnings
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 17:45:27 +01:00
3e2ba107e3 android: enable offline sync and hide theme toggle in Tauri app
All checks were successful
CI / update (push) Successful in 2m2s
Detect Tauri via __TAURI__ in pwaStore so the offline recipe sync,
image caching, and auto-sync activate in the Android shell.
2026-03-23 17:38:29 +01:00
92578a0419 app: follow system theme, remove toggle
Some checks failed
CI / update (push) Has been cancelled
2026-03-23 17:37:04 +01:00
5e48dc6f08 android: use bocken.org for production builds instead of local IP
All checks were successful
CI / update (push) Successful in 2m2s
2026-03-23 17:28:07 +01:00
b9c68b48c3 android: fix duplicate plus icon and button contrast in dark mode
Remove Plus icon from Add Exercise button (translation already includes +).
Use --primary-contrast instead of hardcoded white for button text so it's
legible in dark mode (nord0 on dark, white on light).
2026-03-23 17:13:49 +01:00
4ba3960607 android: native GPS tracking with foreground service for screen-off support
Move GPS collection from WebView JS (watchPosition) to native Android
LocationForegroundService, which survives screen-off. JS polls native
side for accumulated points. Also: auto-enable GPS for cardio exercises,
filter saved track to workout duration only, fix live map batch updates,
notification tap opens active workout, and fix build script for pnpm.
2026-03-23 17:05:15 +01:00
748537dc74 android: add Tauri v2 shell with GPS tracking for cardio workouts
Wraps the web app in a Tauri Android shell that provides native GPS
via the geolocation plugin. Includes foreground service for background
tracking, live map display, GPS data storage in workout sessions,
and route visualization in workout history.
2026-03-23 17:03:14 +01:00
08bd016404 fitness: add speed-based MET tables for swimming and rowing kcal estimation
All checks were successful
CI / update (push) Successful in 2m9s
Add SWIMMING_METS and ROWING_METS lookup tables from Ainsworth
Compendium for speed-based calorie estimation when distance+duration
are available. Add per-exercise flat-rate fallbacks (FLAT_RATE map)
instead of hardcoded if/else chains.
2026-03-23 12:37:06 +01:00
1f83b451de fitness: improve workouts chart with goal line, max bar width, and full 10-week range
Some checks failed
CI / update (push) Has been cancelled
Add weekly goal as a solid horizontal line on the bar chart via a
custom Chart.js plugin. Cap bar width at 40px. Always show all 10
weeks including empty ones instead of trimming leading zeros.
2026-03-23 12:35:50 +01:00
3ef61c900f fitness: add cardio kcal estimation with Minetti/Ainsworth models
Add cardioKcalEstimate.ts implementing tiered calorie estimation for
cardio exercises: Minetti gradient-dependent polynomials for GPS
run/walk/hike, cycling physics model, MET-based fallbacks from
Ainsworth Compendium, and flat-rate estimates. Wire cardio kcal into
SessionCard, workout completion screen, history detail, and stats
overview API alongside existing strength kcal (Lytle). Move citation
info from stats overview to clickable DOI links on workout detail
kcal pill.
2026-03-23 12:26:19 +01:00
0ba22b103b fitness: add streak aura with fire and lightning effects on stats page
Separate streak counter from stat tiles into its own component with
animated aura effects: glow (1w), particles (2w), fire (3w), and
fire + lightning bolts (6/12/24w). Fire animations tuned for energetic
workout feel with faster durations and upward-anchored scaling.
On desktop, streak sits beside the workouts chart; on mobile, above it.
2026-03-23 12:25:51 +01:00
9f45a1525b fitness: add kcal estimation based on Lytle et al. (2019) regression model
Estimate strength workout energy expenditure using the Lytle et al. multiple
linear regression model. Maps all 77 exercises to 7 studied categories with
confidence levels. Shows kcal on stats page (cumulative), session cards,
workout detail, and workout completion screen. Supports sex/height demographics
via profile section on measure page. Includes info tooltip with DOI reference.
2026-03-23 10:23:06 +01:00
fd580ecfe7 replace ß with ss for Swiss High German throughout codebase
All checks were successful
CI / update (push) Successful in 2m5s
2026-03-23 07:46:42 +01:00
9a27e50495 fitness: add German translations for all 77 exercises
Add per-exercise de property with translated name and instructions.
Add shared term translation map for bodyPart, equipment, target, and
muscle names. Add localizeExercise() and translateTerm() helpers.
Update all display components to use localized fields (localName,
localBodyPart, localEquipment, etc.) and pass lang to search/lookup.
2026-03-23 07:44:35 +01:00
69b3ac2aa4 fitness: add weekly workout goal with streak counter on stats page
All checks were successful
CI / update (push) Successful in 2m3s
Store a per-user weekly workout target (1-14) in a new FitnessGoal model.
Compute consecutive-week streak from WorkoutSession history via a new
/api/fitness/goal endpoint. Display streak as a 4th lifetime card on the
stats page with an inline goal editor modal.
2026-03-22 21:56:54 +01:00
f5420badc1 fitness: add bilingual EN/DE support for all fitness routes and components
All checks were successful
CI / update (push) Successful in 2m4s
Use SvelteKit param matchers for bilingual URL routing (e.g. /fitness/stats
and /fitness/statistik). Add centralized i18n module with translation
dictionary, language detection from URL, and path conversion utilities.
Translate all UI text across pages, components, and navigation.
2026-03-22 21:25:03 +01:00
f83bc7fa1e fitness: add page titles to all fitness routes
All checks were successful
CI / update (push) Successful in 2m4s
2026-03-22 21:00:04 +01:00
852cb978fc fitness: restart rest timer when completing a new set while one is running
All checks were successful
CI / update (push) Successful in 2m4s
2026-03-22 19:54:02 +01:00
f4e8b5fe85 fitness: add RPE input to template editor 2026-03-22 19:48:48 +01:00
6eb8c305be fitness: move workout controls to FAB, track rest timer position in store
All checks were successful
CI / update (push) Successful in 2m5s
2026-03-22 19:44:25 +01:00
b8f2a1e098 fitness: rest timer dark styling, wider weight input, hide spinners, shorten PREV header
All checks were successful
CI / update (push) Successful in 2m7s
2026-03-22 19:37:19 +01:00
2ad93b5ad1 fitness: more space for map-preview 2026-03-22 15:54:03 +01:00
c5bfba5440 fitness: add exercise reorder buttons in template editor and active workout
All checks were successful
CI / update (push) Successful in 2m6s
2026-03-21 16:46:42 +01:00
56bb606740 fitness: move add-template to header, remove FAB, fix dark mode contrast
All checks were successful
CI / update (push) Successful in 2m3s
- Replace floating action button with a subdued + icon in the templates
  header row next to the Schedule button
- Use --primary-contrast (white/nord0) instead of hardcoded white for
  text on primary-colored backgrounds so dark mode has proper contrast
- Respect data-theme="light"/"dark" attrs in addition to prefers-color-scheme
2026-03-21 10:59:49 +01:00
6103bb75a0 fitness: add workout schedule rotation with next-workout suggestion
All checks were successful
CI / update (push) Successful in 2m2s
Users can define a custom order of templates (e.g., Push → Pull → Legs).
Based on the last completed session, the next workout in rotation is
recommended via a prominent banner and the floating action button.

- New WorkoutSchedule MongoDB model (per-user template order)
- GET/PUT /api/fitness/schedule API endpoints
- Schedule editor modal with reorder and add/remove
- Action button starts next scheduled workout when schedule exists
2026-03-21 10:53:44 +01:00
2bede967c2 fitness: rename to "Fitness" on homepage
All checks were successful
CI / update (push) Successful in 2m3s
2026-03-21 10:40:32 +01:00
17c7cd2cce fitness: offer to update template with new weights/reps on workout completion
All checks were successful
CI / update (push) Successful in 2m4s
When finishing a template-based workout, compares completed sets against
the source template. If weights, reps, or set counts differ, shows a
visual diff with old→new values and a button to update the template,
letting templates grow with the user's strength progression.
2026-03-21 09:44:44 +01:00
529d004516 fitness: fix template edit validation and allow empty sets
All checks were successful
CI / update (push) Successful in 2m6s
- Validate exerciseId instead of name (templates use exerciseId, not name)
- Remove mandatory reps minimum from template sets
- Allow exercises with empty sets in schema and API validation
2026-03-21 09:39:32 +01:00
81711f1f09 fix: cache auth session on locals to prevent cookies.set after response
All checks were successful
CI / update (push) Successful in 2m19s
The authorization hook already calls locals.auth() which can set cookies.
Layout server loads calling auth() again caused a race where cookies.set()
fired after the response started streaming. Now the hook stashes the session
on locals.session and all layouts reuse it.
2026-03-20 16:28:31 +01:00
82c4c39462 fitness: fix workout name input losing characters during sync
All checks were successful
CI / update (push) Successful in 2m12s
Decouple name input from live sync by using a local variable that only
commits to workout state on blur/Enter. Remote name updates are applied
only when the input is not focused, preventing the sync layer from
overwriting in-progress edits.
2026-03-20 16:21:08 +01:00