Skip to content

Heart rate chart redesign#159

Open
tituscmd wants to merge 8 commits intoInfiniTimeOrg:rebuildfrom
tituscmd:hrm_chart
Open

Heart rate chart redesign#159
tituscmd wants to merge 8 commits intoInfiniTimeOrg:rebuildfrom
tituscmd:hrm_chart

Conversation

@tituscmd
Copy link
Copy Markdown
Contributor

@tituscmd tituscmd commented May 5, 2026

Hey all!

This PR reworks the heart rate chart to more closely match the style of Apple Health.

Instead of the previous line/area chart, it now uses a range bar chart that groups readings by the hour, showing the min/max range as a darker bar and the average of that hour as a brighter dot overlaid on top. The header still shows the BPM range and date for the day you're currently viewing, and now fluidly updates when you navigate to a different day.

Since smooth horizontal scrolling requires iOS 17+, I went with a chevron-based day navigation approach instead to keep things compatible with iOS 16. The chart fetches up to a week of data, using the existing weekPredicate in ChartManager, instead of the previously used dayPredicate. Only the data from the current week is fetched, not the last 7 days, similar to how the step chart operates.

The Y axis scales dynamically to the visible data rather than being hardcoded, which I think makes it a lot more readable especially when readings are close together.

Hope you like it 🙂

image

@liamcharger liamcharger added enhancement New feature or request ui Improvements or changes to the user interface labels May 5, 2026
}

let heartColor = Color(red: 0.996, green: 0.212, blue: 0.369)
let darkHeartColor = Color(red: 0.369, green: 0.090, blue: 0.145)
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.

Are they any built in swiftui colors we can use without declaring our own?

Comment thread InfiniLink/Core/Components/Charts/Heart/HeartChartView.swift

return grouped.map { (bucket, samples) in
let values = samples.map { $0.value }
return HeartChartDataPoint(
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.

Hm we're doing a lot of computation here. I wonder if any of this can be avoided. For example, we already compute the min, max, and avg of the values in the header view

I'm just not a huge fan of how many computed properties we have in this view. However, I may just be being picky :)

@@ -79,16 +258,43 @@
.listRowBackground(Color.clear)
if points.count >= 3 {
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.

Same thing with the flatMap here :)

Come to think of it, it's probably best to remove this section entirely until we have more advanced stats. Right now it's just duplicating what the header says

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

That's what I was thinking too. In the future we'd want some stuff like "Sleep avg, workout avg" and so on, but right now it's just duplicate information. I'll remove it for now in the next commit

var body: some View {
Group {
Group {
if points.count <= 1 {
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.

A flat map should be used here to check the count of values of each point, not just the number of the points themselves. Otherwise, we'll see an empty chart view when we have one day of data saved, regardless of the points inside it

Suggested change
if points.flatMap({ $0.values }).count <= 1 {

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

Labels

enhancement New feature or request ui Improvements or changes to the user interface

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants