Skip to content

"Update Health Conditions" button; Vo2Max#179

Open
lukaskollmer wants to merge 9 commits into
mainfrom
lukas/vo2max
Open

"Update Health Conditions" button; Vo2Max#179
lukaskollmer wants to merge 9 commits into
mainfrom
lukas/vo2max

Conversation

@lukaskollmer

@lukaskollmer lukaskollmer commented Jul 15, 2026

Copy link
Copy Markdown
Collaborator

♻️ Current situation & Problem

  • we currently only allow the participant to enter their preexisting conditions / comoirbidities / health conditions once, a the start when they first enroll into the study (in the onboarding), and we don't allow them to update or modify them afterwards
  • we don't surface VO2Max for timed walk/run tests

⚙️ Release Notes

  • added an "Update Health Conditions" button to the account sheet
  • added VO2Max estimation to 12MWT
  • todo updated Glucose/A1c tile in dashboard

📚 Documentation

n/a

✅ Testing

yes

Code of Conduct & Contributing Guidelines

By creating and submitting this pull request, you agree to follow our Code of Conduct and Contributing Guidelines:

@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 9f8cf575-1cef-4000-b759-eb105fe40b05

📥 Commits

Reviewing files that changed from the base of the PR and between ce240ff and 851473e.

📒 Files selected for processing (1)
  • MyHeartCounts/Account/UpdateComorbiditiesButton.swift
🚧 Files skipped from review as they are similar to previous changes (1)
  • MyHeartCounts/Account/UpdateComorbiditiesButton.swift

📝 Walkthrough

Walkthrough

The PR adds account controls for editing and persisting comorbidities. Timed walk and run results now use a shared view with a running-specific VO₂ max estimate and custom measurement unit. UI tests cover timed walk workflows, scheduled tasks, permission prompts, recovery after relaunch, and comorbidity persistence. Spezi is pinned to version 0.1.6, while accessibility, localization, onboarding setup, and consent test timing are updated.

Sequence Diagram(s)

sequenceDiagram
  participant AccountSheet
  participant UpdateComorbiditiesButton
  participant DemographicsData
  participant ComorbiditiesPicker
  AccountSheet->>UpdateComorbiditiesButton: display update control
  UpdateComorbiditiesButton->>DemographicsData: populateIfEmpty(from: account)
  UpdateComorbiditiesButton->>ComorbiditiesPicker: present picker
  ComorbiditiesPicker->>DemographicsData: update comorbidities
  UpdateComorbiditiesButton->>DemographicsData: flush changes
Loading
sequenceDiagram
  participant TimedWalkTestTests
  participant MyHeartCountsApp
  participant MotionFitnessAlert
  participant TimedWalkingTestView
  TimedWalkTestTests->>MyHeartCountsApp: launch and start test
  MyHeartCountsApp->>MotionFitnessAlert: request permission
  TimedWalkTestTests->>MotionFitnessAlert: allow access
  TimedWalkTestTests->>TimedWalkingTestView: complete test
  TimedWalkingTestView->>TimedWalkTestTests: return result fields
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title matches the main changes: an update health conditions button and VO2 max support.
Description check ✅ Passed The description is clearly related to the added health-conditions update flow and VO2 max estimation.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@lukaskollmer
lukaskollmer marked this pull request as ready for review July 15, 2026 17:08

@PaulGoldschmidt PaulGoldschmidt left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

l-g-t-mmmmmmmh

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
MyHeartCountsUITests/TimedWalkTestTests.swift (1)

84-84: 🔒 Security & Privacy | 🔵 Trivial | 💤 Low value

Use substitution variables to construct the NSPredicate.

Using dynamic string interpolation inside NSPredicate formats is considered bad practice because it can lead to predicate injection, and it triggers static analysis warnings. It is safer to use substitution variables (%@) instead.

♻️ Proposed refactor
-        let testCellPred = NSPredicate(format: "label LIKE '\(kind.rawValue), *'")
+        let testCellPred = NSPredicate(format: "label LIKE %@", "\(kind.rawValue), *")
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@MyHeartCountsUITests/TimedWalkTestTests.swift` at line 84, Update the
testCellPred NSPredicate construction to use a %@ substitution placeholder and
pass kind.rawValue as the predicate argument, preserving the existing label
matching behavior without interpolating dynamic values into the format string.

Source: Linters/SAST tools

MyHeartCounts/Heart Health Dashboard/PastTimedWalkTestResultInfo.swift (1)

25-28: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Use EmptyView() for idiomatic SwiftUI.

Instead of declaring an empty tuple and disabling SwiftLint, you can return an EmptyView() in the .walking case. This is the idiomatic way to handle intentional "no-op" cases inside a @ViewBuilder.

♻️ Proposed refactor
         switch result.test.kind {
         case .walking:
-            let _ = () // swiftlint:disable:this redundant_discardable_let
+            EmptyView()
         case .running:
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@MyHeartCounts/Heart` Health Dashboard/PastTimedWalkTestResultInfo.swift
around lines 25 - 28, In the switch over result.test.kind, replace the discarded
empty tuple in the .walking case with an EmptyView() view. Remove the redundant
SwiftLint suppression while preserving the existing .running behavior and
`@ViewBuilder` output.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@MyHeartCounts/Account/UpdateComorbiditiesButton.swift`:
- Around line 50-61: Update closeSheetButton to remove the iOS availability
check and invalid ButtonRole.confirm usage. Replace both branches with a single
standard SwiftUI Button that closes the sheet, preserving the existing
confirmationAction toolbar placement and “Done” label behavior.

---

Nitpick comments:
In `@MyHeartCounts/Heart` Health Dashboard/PastTimedWalkTestResultInfo.swift:
- Around line 25-28: In the switch over result.test.kind, replace the discarded
empty tuple in the .walking case with an EmptyView() view. Remove the redundant
SwiftLint suppression while preserving the existing .running behavior and
`@ViewBuilder` output.

In `@MyHeartCountsUITests/TimedWalkTestTests.swift`:
- Line 84: Update the testCellPred NSPredicate construction to use a %@
substitution placeholder and pass kind.rawValue as the predicate argument,
preserving the existing label matching behavior without interpolating dynamic
values into the format string.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b8742753-f686-4b6e-9028-f4ebbb49feb0

📥 Commits

Reviewing files that changed from the base of the PR and between 319a333 and 81bd29b.

📒 Files selected for processing (17)
  • MyHeartCounts.xcodeproj/project.pbxproj
  • MyHeartCounts/Account/AccountSheet.swift
  • MyHeartCounts/Account/Demographics/DemographicsData.swift
  • MyHeartCounts/Account/UpdateComorbiditiesButton.swift
  • MyHeartCounts/Heart Health Dashboard/PastTimedWalkTestResultInfo.swift
  • MyHeartCounts/Heart Health Dashboard/PastTimedWalkTestResults.swift
  • MyHeartCounts/Modules/SetupTestEnvironment.swift
  • MyHeartCounts/Resources/Localizable.xcstrings
  • MyHeartCounts/Task Handling/Active Tasks/Timed Walk Test/TimedWalkingTestView.swift
  • MyHeartCounts/Utils/DisclosureIndicator.swift
  • MyHeartCounts/Utils/UnitOxygenConsumption.swift
  • MyHeartCountsShared/Package.swift
  • MyHeartCountsUITests/MHCTestCase.swift
  • MyHeartCountsUITests/OnboardingNavigator.swift
  • MyHeartCountsUITests/OtherTests.swift
  • MyHeartCountsUITests/TaskHandlingTests.swift
  • MyHeartCountsUITests/TimedWalkTestTests.swift
💤 Files with no reviewable changes (2)
  • MyHeartCountsUITests/OnboardingNavigator.swift
  • MyHeartCountsUITests/TaskHandlingTests.swift

Comment on lines +50 to +61
@ViewBuilder private var closeSheetButton: some View {
// look into using an AsyncButton here
if #available(iOS 26, *) {
Button(role: .confirm) {
closeSheet()
}
} else {
Button("Done") {
closeSheet()
}
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Fix the impossible version check and invalid button role.

The #available(iOS 26, *) check contains a typo and will evaluate to false for the next decade. Additionally, standard SwiftUI ButtonRole does not have a .confirm member, so this code will likely fail to compile when that hypothetical version is reached.

Because the parent ToolbarItem(placement: .confirmationAction) (Line 42) already applies the correct semantic styling (such as bolding the text) for a confirmation button, you can safely remove the version check entirely and use a standard button.

♻️ Proposed fix
-    `@ViewBuilder` private var closeSheetButton: some View {
-        // look into using an AsyncButton here
-        if `#available`(iOS 26, *) {
-            Button(role: .confirm) {
-                closeSheet()
-            }
-        } else {
-            Button("Done") {
-                closeSheet()
-            }
-        }
-    }
+    private var closeSheetButton: some View {
+        // look into using an AsyncButton here
+        Button("Done") {
+            closeSheet()
+        }
+    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@ViewBuilder private var closeSheetButton: some View {
// look into using an AsyncButton here
if #available(iOS 26, *) {
Button(role: .confirm) {
closeSheet()
}
} else {
Button("Done") {
closeSheet()
}
}
}
private var closeSheetButton: some View {
// look into using an AsyncButton here
Button("Done") {
closeSheet()
}
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@MyHeartCounts/Account/UpdateComorbiditiesButton.swift` around lines 50 - 61,
Update closeSheetButton to remove the iOS availability check and invalid
ButtonRole.confirm usage. Replace both branches with a single standard SwiftUI
Button that closes the sheet, preserving the existing confirmationAction toolbar
placement and “Done” label behavior.

@codecov

codecov Bot commented Jul 16, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 91.30435% with 2 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...eartCounts/Account/UpdateComorbiditiesButton.swift 94.45% 1 Missing ⚠️
MyHeartCounts/Utils/UnitOxygenConsumption.swift 0.00% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@PSchmiedmayer PSchmiedmayer left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @lukaskollmer 🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

Development

Successfully merging this pull request may close these issues.

3 participants