fix: use effective bodyweight load for exercise display and 1RM (#684)#685
Conversation
…y and 1RM ExerciseDetailScreen was reading weightPerCableKg (configured/nominal load) for weight trend, history table, and session history row. For bodyweight exercises, this field contains the nominal cable value (e.g. 11.0 lb) instead of the bodyweight-derived effective load that was correctly persisted during the workout session. The 1RM helper (estimatedOneRepMaxPerCableOrNull) had the same issue, producing 1RM estimates from the nominal load rather than the effective load. Fix: switch all 4 display/read paths to use effectiveHeaviestKgPerCable(), which prefers the persisted heaviestLiftKg and falls back to weightPerCableKg for legacy sessions without that field. Closes #684
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: fcdc7bba9f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Address Codex P2 review: when heaviestLiftKg=0f (measured zero but summary metrics exist), effectiveHeaviestKgPerCable() returns 0 instead of falling back to weightPerCableKg. This mirrors the SQL selectExerciseWeightHistory behavior that treats nonpositive heaviestLiftKg as absent. Added test case covering heaviestLiftKg=0f edge case.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 49a31e32c8
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…Kg=0f Address Codex P2 review on ExerciseDetailScreen: added displayHeaviestKgPerCable() helper that falls back to weightPerCableKg when effectiveHeaviestKgPerCable() returns 0 (from heaviestLiftKg=0f). Applied to weight trend chart, history table weight column, and session history row — matching the SQL selectExerciseWeightHistory fallback.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 41f6d847c1
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Local extension function inside composable was unreachable from nested composable lambdas (Compose compiler transform). Moved to top-level private extension function at file bottom.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a5ada65f56
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 092d3cceba
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a27d32db4e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 766c25e1e9
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| suspend operator fun invoke( | ||
| exerciseId: String, | ||
| profileId: String, | ||
| isBodyweight: Boolean = false, |
There was a problem hiding this comment.
Pass bodyweight context from Profile insights
When the selected exercise is bodyweight, counterweight clamps a session's effective load to zero, and no velocity or assessment result exists, ProfileViewModel.loadInsights still invokes the resolver with only (exerciseId, profileId). This new default therefore supplies false, causing the session fallback to replace the legitimate zero with the configured load and show a nonzero current 1RM on the Profile screen. Fresh evidence after the earlier bodyweight-zero thread is the unchanged two-argument call at ProfileViewModel.kt:831; pass exercise.isBodyweight there rather than silently defaulting the new parameter.
Useful? React with 👍 / 👎.
Summary
Fixes the display-path bug where Exercise Detail / Personal Records shows the configured nominal cable weight instead of the bodyweight-derived effective load for bodyweight exercises (e.g. Decline Push Up).
Root Cause
ExerciseDetailScreen.ktandResolveCurrentOneRepMaxUseCase.ktreadsession.weightPerCableKg(the configured/nominal machine load) in 4 display paths. For bodyweight exercises, the correct effective load is persisted insession.heaviestLiftKgduring the workout, andeffectiveHeaviestKgPerCable()already provides the backward-compatible accessor (heaviestLiftKg ?: weightPerCableKg).Volume was already correct because it uses
effectiveTotalVolumeKg()— this fix aligns the weight and 1RM display paths with the same pattern.Changes
ExerciseDetailScreen.ktweightPerCableKg→effectiveHeaviestKgPerCable()ResolveCurrentOneRepMaxUseCase.ktestimatedOneRepMaxPerCableOrNull(): same switchResolveCurrentOneRepMaxUseCaseTest.ktWhat this does NOT change
BodyweightVolumeCalculator)heaviestLiftKg(they fall through toweightPerCableKgvia the existing accessor)Testing
session helper uses effectiveHeaviestKgPerCable for bodyweight sessionscovers:Fixes #684