Skip to content

demographics changes; prompted actions rework#167

Open
lukaskollmer wants to merge 34 commits into
mainfrom
lukas/demographics-improvements
Open

demographics changes; prompted actions rework#167
lukaskollmer wants to merge 34 commits into
mainfrom
lukas/demographics-improvements

Conversation

@lukaskollmer

@lukaskollmer lukaskollmer commented Jun 14, 2026

Copy link
Copy Markdown
Collaborator

demographics changes; prompted actions rework

♻️ Current situation & Problem

  • we currently require all demographics fields always be filled out
  • the promped actions UI was ok, but only really as long as you had a single action being prompted, and also it kinda was not ok.

⚙️ Release Notes

  • demographics:
    • added support for optional/required fields
    • added support for conditional fields based on trial opt in
    • some fields are now enabled/disabled based on whether the user has opted in to the trial
    • some fields are now optional (also based on trial opt in).
      • optional fields are not required to be filled out in order to complete the demographics
      • the user will be prompted to fill out these optional fields anyway (see below)
  • prompted actions:
    • idea: display a list of app (not study!) actions we want the user to perform (eg: enabling SensorKit, completing the demographics, etc)
    • new: prompted actions uses a new UI; instead of always putting buttons for all actios directly into the HomeTab, we now show a digest/summary section thing which, when tapped, brings up a small bottom sheet with a list of actions (and a button for each)
    • if all actions have been completed (or hidden/dismissed by the user), the digest button disappears
    • new: we also show the same digest in the AccountSheet, except that it always is present there, and turns green if all things have been completed, and tapping it brings up the same sheet except that it's not the same bc it also lists all pending/hidden/completed actions (i.e., everything))
    • new: we have several additional prompted actions:
      • Clinical Records flow (moved here from onboarding)
      • Email Address Verification
      • Demographics Completion
  • other:
    • fixed a bug where demographics fields would sometimes not properly get pre-populated when logging back in to an existing account for which the fields had already been filled out previously

📚 Documentation

no

✅ Testing

no

Code of Conduct & Contributing Guidelines

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

Summary by CodeRabbit

  • New Features
    • Added a prompted-actions digest and checklist sheet on the Home screen.
    • Expanded demographics with a full Postcode (UK) field, referral-source selection, and improved trial opt-in handling.
  • Bug Fixes
    • Improved onboarding and prompted-action readiness: SensorKit/Clinical Records suggestions now reflect current access/eligibility more accurately.
    • Refined UI behavior for SensorKit, including updated enable/manage wording based on authorization state.
  • Tests
    • Added UI test coverage for prompted home actions.

@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 for all the work here @lukaskollmer 🚀

We would need to also resolve the CI issues (UI tests + Package tests) and should test the general PR workflow in this organization including codecov and others.

.padding(.top, 4)
.padding(.bottom, -8)
if let timeRange = score.timeRange, score.scoreAvailable {
// - For e.g. Sleep, we might prefer this saying "Today, 7:00" instead of just "7:00" which it would show currently

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.

Transform this into an GitHub issue?

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.

Nice setup here with the additional prompts!

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.

Good to auto-translate the keys to Spanish as well.

 into lukas/demographics-improvements

# Conflicts:
#	MyHeartCounts/Heart Health Dashboard/HeartHealthDashboard.swift
#	MyHeartCounts/Home Tab/Prompted Actions/PromptedAction.swift
@coderabbitai

coderabbitai Bot commented Jun 25, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The PR updates demographics consent and field handling, adds prompted-action digest and state filtering UI, introduces SensorKit authorization observation, and replaces color-scheme-derived foreground styling with semantic text-label styles.

Changes

Onboarding and demographics data flow

Layer / File(s) Summary
Consent, demographics, and form flow
MyHeartCounts/Onboarding/Consent+MHC.swift, MyHeartCounts/Onboarding/Consent.swift, MyHeartCounts/Onboarding/Screening/ScreeningDataCollection.swift, MyHeartCounts/Onboarding/FinalEnrollmentStep.swift, MyHeartCounts/Onboarding/HealthRecordPermissions.swift, MyHeartCounts/Onboarding/OnboardingFlow.swift, MyHeartCounts/Account/Demographics/DemographicsAccountKeys.swift, MyHeartCounts/Account/Demographics/ReferralSource.swift, MyHeartCounts/Account/Demographics/DemographicsData.swift, MyHeartCounts/Account/Demographics/NHSNumber.swift, MyHeartCounts/Account/Demographics/DemographicsLayout.swift, MyHeartCounts/Account/Demographics/DemographicsSingleSelectionValue.swift, MyHeartCounts/Account/Demographics/EducationStatus.swift, MyHeartCounts/Account/Demographics/HouseholdIncome.swift, MyHeartCounts/Account/Demographics/LatinoStatus.swift, MyHeartCounts/Account/Demographics/ComorbiditiesPicker.swift, MyHeartCounts/Account/Demographics/DemographicsButton.swift, MyHeartCounts/Account/Demographics/DemographicsForm.swift
Consent and onboarding now use typed consent keys and trial opt-in state; account details add ukPostcode and referralSource; demographics data persists referralSource; the demographics layout uses requiredness-aware completion states; single-selection pickers accept optional “prefer not to state”; and the demographics sheet passes trial opt-in through the form.

Prompted actions and SensorKit

Layer / File(s) Summary
Action model and filtering
MyHeartCounts/Home Tab/Prompted Actions/PromptedAction.swift, MyHeartCounts/Home Tab/Prompted Actions/PromptedActionsQuery.swift, MyHeartCounts/Home Tab/Prompted Actions/MHCPromptedActions.swift, MyHeartCounts/Home Tab/HomeTab.swift, MyHeartCounts/Account/AccountSheet.swift, MyHeartCounts/Resources/Localizable.xcstrings, MyHeartCountsUITests/PromptedActionsTests.swift
PromptedAction becomes a state-driven observable model, PromptedActions filters by computed state, four prompted actions are defined, HomeTab switches to PromptedActionsDigest, and the prompted-actions UI text and UI test coverage are added.
Digest and row UI
MyHeartCounts/Home Tab/Prompted Actions/PromptedActionsDigest.swift
The digest card, checklist sheet, row UI, rejection flow, dismissal handling, and localized text resources are added.
Sensor authorization observation
MyHeartCounts/SensorKit/SensorAccessPermissions.swift, MyHeartCounts/SensorKit/SensorKitButton.swift, MyHeartCounts/Account/AccountSheet.swift
SensorAccessPermissions observes per-sensor authorization state, SensorKitButton renders enable/manage flows from observed states, and AccountSheet gates the SensorKit button on permission state.
Supporting tests and setup
MyHeartCountsUITests/MHCTestCase.swift, MyHeartCountsUITests/OtherTests.swift, MyHeartCounts/Modules/SetupTestEnvironment.swift, MyHeartCountsShared/Sources/MyHeartCountsShared/Prompted Actions/PromptedAction+IDs.swift, MyHeartCountsShared/Sources/MyHeartCountsShared/Prompted Actions/PromptedActionsFilter.swift, MyHeartCountsShared/Package.swift, MyHeartCounts.xcodeproj/project.pbxproj, MyHeartCounts.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
Launch-option filtering, shared prompted-action IDs, test environment reset behavior, and dependency pinning are updated to support the new prompted-actions flow.

Semantic text-label styling

Layer / File(s) Summary
Shared text-label styling and view cleanup
MyHeartCounts/Utils/SwiftUI/TextLabelForegroundColor.swift, MyHeartCounts/Utils/SwiftUI/LabeledButton.swift, MyHeartCounts/Utils/SwiftUI/ListSelectionSheet.swift, MyHeartCounts/Utils/SwiftUI/NavigationLink.swift, MyHeartCounts/Utils/MenuIndicator.swift, MyHeartCounts/Utils/Debug Stuff/DebugForm.swift, MyHeartCounts/Heart Health Dashboard/DetailedHealthStatsView.swift, MyHeartCounts/Heart Health Dashboard/HeartHealthDashboard.swift, MyHeartCounts/Heart Health Dashboard/Health Dashboard/HealthDashboard+SleepAnalysis.swift, MyHeartCounts/News Tab/NewsTab.swift, MyHeartCounts/Account/AccountSheet.swift, MyHeartCounts/Account/Demographics/RaceEthnicityPicker.swift, MyHeartCounts/Account/Demographics/StageOfChangePicker.swift, MyHeartCounts/Onboarding/Screening/Components/IsFromRegion.swift, MyHeartCounts/Onboarding/Screening/SingleChoiceScreeningComponent.swift, MyHeartCounts/Onboarding/USRegionPicker.swift
TextLabelForegroundColor is introduced as a semantic ShapeStyle; shared utility views, dashboard screens, news tab, account sheet, and onboarding pickers remove @Environment(\.colorScheme) and adopt .textLabel; MenuIndicator is added.

Maintenance

Layer / File(s) Summary
Package, config, and test updates
MyHeartCounts/Modules/DeferredConfigLoading.swift, MyHeartCounts/Modules/SetupTestEnvironment.swift, MyHeartCountsShared/Package.swift, MyHeartCounts.xcodeproj/project.pbxproj, MyHeartCounts.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved, MyHeartCountsUITests/BasicAppUsage.swift, MyHeartCountsUITests/PromptedActionsTests.swift
The Spezi dependency is bumped, Firebase UK postcode mapping changes to ukPostcode, test environment reset updates onboarding state, and prompted-actions UI tests are added.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

Suggested labels: bug

Suggested reviewers: PSchmiedmayer

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.28% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title is related to the PR, but it is too broad and vague to clearly convey the main changes. Use a more specific title, such as one mentioning the demographics flow update and prompted actions UI rework.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch lukas/demographics-improvements

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.

@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: 8

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
MyHeartCounts/Account/Demographics/DemographicsButton.swift (1)

25-46: 🩺 Stability & Availability | 🟡 Minor

Add a Close/Cancel action when drag dismissal is disabled.

DemographicsButton(allowDragToDismiss: false) in MyHeartCounts/Utils/Debug Stuff/DebugForm.swift:44 can leave the sheet with no exit path: drag-to-dismiss is blocked, and the only toolbar action stays disabled until isComplete becomes true. Add an always-available Close/Cancel button, or don’t disable confirm when dismissal is already blocked.

🤖 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/Demographics/DemographicsButton.swift` around lines 25
- 46, The sheet in DemographicsButton currently has no escape path when
allowDragToDismiss is false because the toolbar dismissal action stays disabled
until isComplete is true; update the sheet content in DemographicsButton so
there is always an available Close/Cancel action, or adjust the existing primary
toolbar button logic so dismissal is not blocked when drag-to-dismiss is
disabled. Use the existing sheet setup, isPresentingSheet state, and the toolbar
Button inside NavigationStack to locate and fix the behavior.
🧹 Nitpick comments (2)
MyHeartCounts/Account/Demographics/DemographicsData.swift (1)

264-326: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove the commented-out Field2 implementation.

This ~60-line commented-out alternative property-wrapper is dead code and adds noise. If it's kept intentionally for a future migration, a short TODO referencing a tracking issue would be clearer than retaining the full block.

🤖 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/Demographics/DemographicsData.swift` around lines 264 -
326, Remove the commented-out Field2 property-wrapper block from the
DemographicsData extension, since it is dead code and clutters the file. Update
the DemographicsData extension to keep only the active implementation, and if
this is meant to be revisited later, replace the full commented block with a
brief TODO comment that references the relevant tracking item.
MyHeartCounts/Account/Demographics/DemographicsLayout.swift (1)

172-176: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Comorbidities label color won't reflect the completion state.

This row still uses the isEmpty:-based NavigationLinkLabel initializer, which only produces .red/.secondary. Since \.comorbidities is now conditionally required (isRequired: didOptInToTrial), an incomplete-but-optional state here will render red rather than the .orange used elsewhere via completionState. Consider passing completionState for visual consistency.

🤖 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/Demographics/DemographicsLayout.swift` around lines 172
- 176, The Comorbidities row in DemographicsLayout still uses the
`NavigationLinkLabel(_:isEmpty:value:)` path, so it only maps to red/secondary
and ignores the new required-vs-optional completion styling. Update the
Comorbidities label to use `completionState` instead of `isEmpty`, matching the
pattern used by other fields so `\.comorbidities` reflects `.orange` when
incomplete but optional and the correct state when `didOptInToTrial` makes it
required. Use the `NavigationLinkLabel` initializer and the surrounding
completion-state logic in `DemographicsLayout` to locate the change.
🤖 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/AccountSheet.swift`:
- Around line 74-82: The account digest is rendered unconditionally in
accountSheetExtraContent, which can show a misleading “all set” state before
enrollment is ready. Move PromptedActionsDigest(context: .viewAll) inside the
existing enrollment check in accountSheetExtraContent so it only appears when
enrollments.first exists, alongside the Study Participation and data processing
sections.

In `@MyHeartCounts/Account/Demographics/DemographicsAccountKeys.swift`:
- Around line 149-156: The ukPostcode account key is changing its persisted id,
which would orphan existing saved data. Update DemographicsAccountKeys so the
ukPostcode property keeps the old account key identifier as a compatibility
alias, or add a migration/backfill path that maps existing ukPostcodePrefix
values to the new ukPostcode field before switching names.

In `@MyHeartCounts/Home` Tab/Prompted Actions/MHCPromptedActions.swift:
- Around line 44-50: The prompted action state logic in MHCPromptedActions
should not keep SensorKit requests pending after the user has already responded.
Update the status decision in the prompted actions path so that once no sensor
authorization is .notDetermined, the action returns .completed instead of
remaining .pending, and leave any denied-specific handling to SensorKitButton;
use the sensorAuthStates check in the relevant returned branch to locate the
change.
- Around line 133-135: The prompted action currently calls
UIApplication.shared.open with a String literal, which is not the expected type.
Update the open call in MHCPromptedActions (the closure that handles the message
action) to construct a URL from "message://" first and pass that URL to
UIApplication.shared.open, keeping the existing behavior but using the correct
API signature.

In `@MyHeartCounts/Home` Tab/Prompted Actions/PromptedActionsDigest.swift:
- Around line 232-239: The sheet dismissal logic in PromptedActionsDigest’s
onChange handler is watching actions.isEmpty, but actions is backed by .all so
it won’t reflect when the rendered pending list becomes empty. Update the change
observation to use the pending/rendered list source instead of actions, and keep
the dismissal Task/dismiss() flow the same so the sheet closes as soon as the
last visible pending action is gone.

In `@MyHeartCounts/SensorKit/SensorAccessPermissions.swift`:
- Around line 81-83: The authStatus mutation in SensorAuthStatusObserver’s
sensorReader(_:didChange:) callback should be dispatched onto the MainActor
before assignment, since it is SwiftUI-observed state and the callback has no
main-thread guarantee. Update the implementation so the authStatus property is
only set from the main actor, using the sensorReader(_:didChange:) method as the
entry point for the fix.

In `@MyHeartCounts/SensorKit/SensorKitButton.swift`:
- Around line 28-35: Scope the authorization checks in SensorKitButton to the
sensors this UI actually manages instead of relying on the default
SensorAccessPermissions set; update the use of sensorAccessPermissions in the
AsyncButton action and any AccountSheet-related gating to reference the same
explicit SensorKit.mhcSensors scope. Ensure isFullyUndetermined and
numAuthorized are evaluated against the managed sensor set so the button and
sheet state stay aligned with the sensors this row labels and enables.
- Around line 45-48: The management sheet is not wired to the new observable
permissions model, so rows that depend on authorization status won’t refresh
while the sheet stays open. Update the sheet content in SensorKitButton’s
NavigationStack to pass or create SensorAccessPermissions and thread it into
SensorKitSheet and its row-building path in makeRow(for:), replacing any direct
downstream reads of authorization state so permission changes update the visible
rows immediately.

---

Outside diff comments:
In `@MyHeartCounts/Account/Demographics/DemographicsButton.swift`:
- Around line 25-46: The sheet in DemographicsButton currently has no escape
path when allowDragToDismiss is false because the toolbar dismissal action stays
disabled until isComplete is true; update the sheet content in
DemographicsButton so there is always an available Close/Cancel action, or
adjust the existing primary toolbar button logic so dismissal is not blocked
when drag-to-dismiss is disabled. Use the existing sheet setup,
isPresentingSheet state, and the toolbar Button inside NavigationStack to locate
and fix the behavior.

---

Nitpick comments:
In `@MyHeartCounts/Account/Demographics/DemographicsData.swift`:
- Around line 264-326: Remove the commented-out Field2 property-wrapper block
from the DemographicsData extension, since it is dead code and clutters the
file. Update the DemographicsData extension to keep only the active
implementation, and if this is meant to be revisited later, replace the full
commented block with a brief TODO comment that references the relevant tracking
item.

In `@MyHeartCounts/Account/Demographics/DemographicsLayout.swift`:
- Around line 172-176: The Comorbidities row in DemographicsLayout still uses
the `NavigationLinkLabel(_:isEmpty:value:)` path, so it only maps to
red/secondary and ignores the new required-vs-optional completion styling.
Update the Comorbidities label to use `completionState` instead of `isEmpty`,
matching the pattern used by other fields so `\.comorbidities` reflects
`.orange` when incomplete but optional and the correct state when
`didOptInToTrial` makes it required. Use the `NavigationLinkLabel` initializer
and the surrounding completion-state logic in `DemographicsLayout` to locate the
change.
🪄 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: ee7a7d5f-415f-4654-8718-e3ccf06e815c

📥 Commits

Reviewing files that changed from the base of the PR and between 844e761 and 86f42b8.

📒 Files selected for processing (38)
  • MyHeartCounts/Account/AccountSheet.swift
  • MyHeartCounts/Account/Demographics/ComorbiditiesPicker.swift
  • MyHeartCounts/Account/Demographics/DemographicsAccountKeys.swift
  • MyHeartCounts/Account/Demographics/DemographicsButton.swift
  • MyHeartCounts/Account/Demographics/DemographicsData.swift
  • MyHeartCounts/Account/Demographics/DemographicsForm.swift
  • MyHeartCounts/Account/Demographics/DemographicsLayout.swift
  • MyHeartCounts/Account/Demographics/DemographicsSingleSelectionValuePicker.swift
  • MyHeartCounts/Account/Demographics/NHSNumber.swift
  • MyHeartCounts/Account/Demographics/RaceEthnicityPicker.swift
  • MyHeartCounts/Account/Demographics/StageOfChangePicker.swift
  • MyHeartCounts/Heart Health Dashboard/DetailedHealthStatsView.swift
  • MyHeartCounts/Heart Health Dashboard/HeartHealthDashboard.swift
  • MyHeartCounts/Home Tab/HomeTab.swift
  • MyHeartCounts/Home Tab/Prompted Actions/MHCPromptedActions.swift
  • MyHeartCounts/Home Tab/Prompted Actions/PromptedAction.swift
  • MyHeartCounts/Home Tab/Prompted Actions/PromptedActionButton.swift
  • MyHeartCounts/Home Tab/Prompted Actions/PromptedActionsDigest.swift
  • MyHeartCounts/Home Tab/Prompted Actions/PromptedActionsQuery.swift
  • MyHeartCounts/Modules/DeferredConfigLoading.swift
  • MyHeartCounts/News Tab/NewsTab.swift
  • MyHeartCounts/Onboarding/Consent+MHC.swift
  • MyHeartCounts/Onboarding/Consent.swift
  • MyHeartCounts/Onboarding/FinalEnrollmentStep.swift
  • MyHeartCounts/Onboarding/HealthRecordPermissions.swift
  • MyHeartCounts/Onboarding/OnboardingFlow.swift
  • MyHeartCounts/Onboarding/Screening/Components/IsFromRegion.swift
  • MyHeartCounts/Onboarding/Screening/ScreeningDataCollection.swift
  • MyHeartCounts/Onboarding/Screening/SingleChoiceScreeningComponent.swift
  • MyHeartCounts/Onboarding/USRegionPicker.swift
  • MyHeartCounts/Resources/Localizable.xcstrings
  • MyHeartCounts/SensorKit/SensorAccessPermissions.swift
  • MyHeartCounts/SensorKit/SensorKitButton.swift
  • MyHeartCounts/Utils/Debug Stuff/DebugForm.swift
  • MyHeartCounts/Utils/SwiftUI/LabeledButton.swift
  • MyHeartCounts/Utils/SwiftUI/ListSelectionSheet.swift
  • MyHeartCounts/Utils/SwiftUI/NavigationLink.swift
  • MyHeartCounts/Utils/SwiftUI/TextLabelForegroundColor.swift
💤 Files with no reviewable changes (1)
  • MyHeartCounts/Home Tab/Prompted Actions/PromptedActionButton.swift

Comment thread MyHeartCounts/Account/AccountSheet.swift
Comment thread MyHeartCounts/Account/Demographics/DemographicsAccountKeys.swift
Comment thread MyHeartCounts/Home Tab/Prompted Actions/MHCPromptedActions.swift Outdated
Comment thread MyHeartCounts/Home Tab/Prompted Actions/MHCPromptedActions.swift
Comment thread MyHeartCounts/Home Tab/Prompted Actions/PromptedActionsDigest.swift
Comment thread MyHeartCounts/SensorKit/SensorAccessPermissions.swift
Comment thread MyHeartCounts/SensorKit/SensorKitButton.swift Outdated
Comment thread MyHeartCounts/SensorKit/SensorKitButton.swift

@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

🤖 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/Demographics/DemographicsSingleSelectionValue.swift`:
- Around line 59-87: The header section in
DemographicsSingleSelectionPicker.body should not be gated by checking `header
is EmptyView`, because a conditional `@ViewBuilder` can still produce a
non-EmptyView type while rendering nothing. Update the picker to decide header
presence explicitly in `init(selection:header:)` or by storing an optional/flag
for the header, and then only emit the header `Section` when that explicit state
says a header exists. Keep the rendering logic in `body` and `makeRow(for:)`
unchanged aside from replacing the type check with this explicit condition.
🪄 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: b8716190-d9a4-411b-8f1a-2877261f7cb7

📥 Commits

Reviewing files that changed from the base of the PR and between 86f42b8 and d080ef5.

📒 Files selected for processing (11)
  • MyHeartCounts/Account/Demographics/DemographicsAccountKeys.swift
  • MyHeartCounts/Account/Demographics/DemographicsData.swift
  • MyHeartCounts/Account/Demographics/DemographicsLayout.swift
  • MyHeartCounts/Account/Demographics/DemographicsSingleSelectionValue.swift
  • MyHeartCounts/Account/Demographics/EducationStatus.swift
  • MyHeartCounts/Account/Demographics/HouseholdIncome.swift
  • MyHeartCounts/Account/Demographics/LatinoStatus.swift
  • MyHeartCounts/Account/Demographics/ReferralOption.swift
  • MyHeartCounts/Resources/Localizable.xcstrings
  • MyHeartCounts/Utils/Debug Stuff/DebugForm.swift
  • MyHeartCounts/Utils/MenuIndicator.swift
✅ Files skipped from review due to trivial changes (1)
  • MyHeartCounts/Utils/MenuIndicator.swift
🚧 Files skipped from review as they are similar to previous changes (4)
  • MyHeartCounts/Utils/Debug Stuff/DebugForm.swift
  • MyHeartCounts/Account/Demographics/DemographicsAccountKeys.swift
  • MyHeartCounts/Account/Demographics/DemographicsData.swift
  • MyHeartCounts/Account/Demographics/DemographicsLayout.swift

Comment thread MyHeartCounts/Account/Demographics/DemographicsSingleSelectionValue.swift Outdated

@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.

Looks solid; good to also see the referral source in place 🚀

Comment thread MyHeartCounts/Account/Demographics/DemographicsData.swift Outdated

@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.

🧹 Nitpick comments (1)
MyHeartCountsShared/Package.swift (1)

15-16: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Avoid tracking an unreleased fork branch for the Spezi dependency before merge. Pinning Spezi to the lukas/local-preferences-reset branch on the SchmiedmayerLab fork makes builds non-reproducible (the branch HEAD can move or be deleted/force-pushed) and ties this PR to unreleased upstream work. Resolve to a tagged release or commit-pinned .revision(...) before merging, and confirm the LocalPreferencesStore APIs used in SetupTestEnvironment.swift are available in that pin.

  • MyHeartCountsShared/Package.swift#L15-L16: replace the branch: requirement with a released version range or a .revision("…") pin once the upstream change lands.
  • MyHeartCounts.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved#L233-L234: regenerate the pin so it reflects the tagged/commit-pinned state rather than a moving branch.
🤖 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 `@MyHeartCountsShared/Package.swift` around lines 15 - 16, Replace the moving
Spezi branch dependency with a reproducible pin: update
MyHeartCountsShared/Package.swift at the anchor site to use a released version
range or a commit-pinned .revision(...) instead of branch:
"lukas/local-preferences-reset", and then regenerate
MyHeartCounts.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
so it records the same tagged/commit-pinned Spezi state; also verify the
LocalPreferencesStore APIs referenced from SetupTestEnvironment.swift are
available in that chosen pin.
🤖 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.

Nitpick comments:
In `@MyHeartCountsShared/Package.swift`:
- Around line 15-16: Replace the moving Spezi branch dependency with a
reproducible pin: update MyHeartCountsShared/Package.swift at the anchor site to
use a released version range or a commit-pinned .revision(...) instead of
branch: "lukas/local-preferences-reset", and then regenerate
MyHeartCounts.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
so it records the same tagged/commit-pinned Spezi state; also verify the
LocalPreferencesStore APIs referenced from SetupTestEnvironment.swift are
available in that chosen pin.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: aeae501a-7acb-4e80-a301-6823e2e39ca1

📥 Commits

Reviewing files that changed from the base of the PR and between 1247b26 and 26f9993.

📒 Files selected for processing (10)
  • MyHeartCounts.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
  • MyHeartCounts/Heart Health Dashboard/Health Dashboard/HealthDashboard+SleepAnalysis.swift
  • MyHeartCounts/Heart Health Dashboard/HeartHealthDashboard.swift
  • MyHeartCounts/Home Tab/Prompted Actions/MHCPromptedActions.swift
  • MyHeartCounts/Home Tab/Prompted Actions/PromptedAction.swift
  • MyHeartCounts/Home Tab/Prompted Actions/PromptedActionsDigest.swift
  • MyHeartCounts/Modules/SetupTestEnvironment.swift
  • MyHeartCountsShared/Package.swift
  • MyHeartCountsUITests/BasicAppUsage.swift
  • MyHeartCountsUITests/PromptedActionsTests.swift
💤 Files with no reviewable changes (1)
  • MyHeartCountsUITests/BasicAppUsage.swift
🚧 Files skipped from review as they are similar to previous changes (4)
  • MyHeartCounts/Heart Health Dashboard/HeartHealthDashboard.swift
  • MyHeartCounts/Home Tab/Prompted Actions/MHCPromptedActions.swift
  • MyHeartCounts/Home Tab/Prompted Actions/PromptedActionsDigest.swift
  • MyHeartCounts/Home Tab/Prompted Actions/PromptedAction.swift

@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown

Caution

Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted.

Error details
{}

@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: 3

🧹 Nitpick comments (1)
MyHeartCounts/Home Tab/Prompted Actions/MHCPromptedActions.swift (1)

61-70: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Consider reusing a shared HKHealthStore instance.

HKHealthStore() is instantiated fresh every time this action's state is recomputed. Given this is now a state-driven observable model likely re-evaluated on re-renders, reusing a single store instance (e.g. via the existing HealthKit module/dependency) avoids repeated store initialization overhead.

🤖 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/Home` Tab/Prompted Actions/MHCPromptedActions.swift around
lines 61 - 70, The clinical-records prompted action is creating a new
HKHealthStore inside the enableClinicalRecords state closure on every
recomputation, which is unnecessary work in a frequently re-evaluated observable
model. Update MHCPromptedActions so this closure reuses a shared HKHealthStore
instance from the existing HealthKit dependency/module instead of instantiating
HKHealthStore() inline, while keeping the supportsHealthRecords() check in the
same state evaluation path.
🤖 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/Modules/SetupTestEnvironment.swift`:
- Around line 140-147: The dependency checks in SetupTestEnvironment set-up are
swallowing failures by logging and returning, which lets setUp() finish
successfully even when login/enrollment never happened. Update the guards in the
setup flow to throw an error instead of returning so failure propagates through
setup and configure() cannot report .done incorrectly; use the existing
accountService/account and studyManager checks in SetupTestEnvironment to locate
the fix.

In `@MyHeartCountsShared/Sources/MyHeartCountsShared/Prompted`
Actions/PromptedAction+IDs.swift:
- Around line 42-45: The public constants in PromptedAction+IDs are missing
documentation, causing SwiftLint’s missing_docs check to fail. Add brief doc
comments to each public static let in PromptedAction+IDs (sensorKit,
clinicalRecords, verifyAccountEmail, and completeDemographics) so the
identifiers remain unchanged but CI passes.
- Around line 22-38: The Codable path for PromptedAction.ID is crashing on
malformed input because init(from:) delegates to the precondition-based String
initializer. Update PromptedAction.ID’s decoding logic so it validates the
decoded String against Self.pattern and throws a DecodingError (for example in
init(from decoder:)) instead of calling the precondition initializer; keep the
existing init<S: StringProtocol> for trusted construction, but make decoding
fail gracefully for invalid persisted values.

---

Nitpick comments:
In `@MyHeartCounts/Home` Tab/Prompted Actions/MHCPromptedActions.swift:
- Around line 61-70: The clinical-records prompted action is creating a new
HKHealthStore inside the enableClinicalRecords state closure on every
recomputation, which is unnecessary work in a frequently re-evaluated observable
model. Update MHCPromptedActions so this closure reuses a shared HKHealthStore
instance from the existing HealthKit dependency/module instead of instantiating
HKHealthStore() inline, while keeping the supportsHealthRecords() check in the
same state evaluation path.
🪄 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: 5c2baaae-a7ae-4e94-92ed-01db5b8009fd

📥 Commits

Reviewing files that changed from the base of the PR and between 26f9993 and 58e6051.

📒 Files selected for processing (15)
  • .github/workflows/build-and-test.yml
  • .github/workflows/static-analysis.yml
  • MyHeartCounts/Account/AccountSheet.swift
  • MyHeartCounts/Account/Demographics/DemographicsForm.swift
  • MyHeartCounts/Home Tab/Prompted Actions/MHCPromptedActions.swift
  • MyHeartCounts/Home Tab/Prompted Actions/PromptedAction.swift
  • MyHeartCounts/Home Tab/Prompted Actions/PromptedActionsDigest.swift
  • MyHeartCounts/Home Tab/Prompted Actions/PromptedActionsQuery.swift
  • MyHeartCounts/Modules/SetupTestEnvironment.swift
  • MyHeartCountsShared/Package.swift
  • MyHeartCountsShared/Sources/MyHeartCountsShared/Prompted Actions/PromptedAction+IDs.swift
  • MyHeartCountsShared/Sources/MyHeartCountsShared/Prompted Actions/PromptedActionsFilter.swift
  • MyHeartCountsUITests/MHCTestCase.swift
  • MyHeartCountsUITests/OtherTests.swift
  • MyHeartCountsUITests/PromptedActionsTests.swift
🚧 Files skipped from review as they are similar to previous changes (6)
  • MyHeartCountsUITests/PromptedActionsTests.swift
  • MyHeartCounts/Account/Demographics/DemographicsForm.swift
  • MyHeartCounts/Home Tab/Prompted Actions/PromptedActionsQuery.swift
  • MyHeartCounts/Home Tab/Prompted Actions/PromptedAction.swift
  • MyHeartCounts/Home Tab/Prompted Actions/PromptedActionsDigest.swift
  • MyHeartCounts/Account/AccountSheet.swift

Comment thread MyHeartCounts/Modules/SetupTestEnvironment.swift

@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.

Thanks for all the work here 🚀

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.

2 participants