Skip to content

Settings: move HRV tuning to Advanced, add a shared info-popover#518

Open
digitalerdude wants to merge 6 commits into
ryanbr:mainfrom
digitalerdude:fix/settings-declutter-advanced
Open

Settings: move HRV tuning to Advanced, add a shared info-popover#518
digitalerdude wants to merge 6 commits into
ryanbr:mainfrom
digitalerdude:fix/settings-declutter-advanced

Conversation

@digitalerdude

Copy link
Copy Markdown

Summary

  • Strap and Features stayed always-visible and mixed everyday connection controls with power-user tuning (Continuous HRV capture, HRV window) and a long explanatory paragraph under every toggle — overwhelming for a first-time user.
  • Continuous HRV capture + HRV window move into a new "HRV" card under the already-collapsed Advanced disclosure group (same @AppStorage bindings, same BLE/re-score wiring — no behavior change, just relocated). Advanced's subtitle now mentions "HRV tuning" so anyone who goes looking finds it.
  • The long "nice to know" captions across Strap/Features/HRV become a tap-to-reveal (i) popover via a new shared InfoButton in StrandDesign (modeled on SleepView's existing nap-row popover idiom). Any sentence describing a safety or battery-impact consequence stays inline as visible text — only background/context prose moves behind the (i).
  • The strap-log Copy/Save row, strap name control and Live Activity toggle stay in the Strap card as-is (deliberately placed there per Keep Android Stress marker values readable #507/Localize the Android 9.0.1 changelog title #509 for bug-report discoverability — not touched).
  • SettingsSection/FormRow gained an optional trailing accessory slot (generic Accessory: View + Accessory == EmptyView extension, same pattern as StatTile in Components.swift), so every existing call site keeps compiling unchanged.

Pure SwiftUI/macOS+iOS change — no server/analytics/migration/stored-value crossing the .noopbak boundary, so no Android parity change is required in this PR (Android's Settings has no popover equivalent yet; porting the pattern there is a separate design decision, not a mechanical port).

Test plan

  • xcodebuild -scheme Strand -destination 'platform=macOS' CODE_SIGNING_ALLOWED=NO build — succeeds
  • xcodebuild -scheme NOOPiOS -destination 'platform=iOS Simulator,name=iPhone 17' build — succeeds
  • xcodebuild -scheme NOOPWatch -destination 'generic/platform=watchOS Simulator' build — succeeds (confirms the #if !os(watchOS) guard on InfoButton is correct, not a silent skip)
  • cd Packages/StrandDesign && swift build && swift test — succeeds, 0 failures
  • Manual: open Settings on macOS and iPhone, confirm Strap/Features are visibly shorter, Advanced still opens collapsed, HRV card appears inside it with both controls still functional, every new (i) opens/dismisses its popover

Strap and Features stayed always-visible and mixed everyday connection
controls with power-user tuning (Continuous HRV capture, HRV window) and
long paragraph captions under every toggle — overwhelming for a first-time
user. Continuous HRV capture + HRV window move into a new "HRV" card under
the already-collapsed Advanced disclosure (same bindings, no behavior
change); the long "nice to know" captions across Strap/Features become a
tap-to-reveal (i) popover via a new shared InfoButton (StrandDesign), while
any safety/battery-impact sentence stays inline. The strap-log button and
strap name/Live Activity controls stay in Strap as-is (ryanbr#507/ryanbr#509).

Verified: xcodebuild for Strand (macOS), NOOPiOS (iOS Simulator) and
NOOPWatch (watchOS Simulator) all build clean; swift build/test passes for
StrandDesign.
…age gate)

The Strap/HRV/Features caption split in the prior commit introduced new
literal Text(...) strings (shorter inline sentences, split off the original
paragraphs) that aren't in the catalog yet, so the i18n-coverage gate flags
them as un-extracted. Add de/es/fr entries for the 6 new literals, lifted
from the existing translations of the original combined paragraphs they
were split from (the wording overlaps almost verbatim in most cases).

i18n_audit.py --ci origin/main: OK, no un-extracted literals.
@digitalerdude
digitalerdude marked this pull request as ready for review July 17, 2026 05:29
…ter-advanced

# Conflicts:
#	Strand/Resources/Localizable.xcstrings
#	Strand/Screens/SettingsView.swift
…ter-advanced

# Conflicts:
#	Strand/Resources/Localizable.xcstrings
…ter-advanced

# Conflicts:
#	Strand/Resources/Localizable.xcstrings
…ter-advanced

# Conflicts:
#	Strand/Resources/Localizable.xcstrings
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant