Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
fa1269e
new hrm graph
tituscmd May 4, 2026
7febcaf
change scrollable to switchable because of ios 16
tituscmd May 5, 2026
0abf19f
Revert local build dependency changes
tituscmd May 5, 2026
52849db
fix button behavior and ios 16 compatibility issues
tituscmd May 5, 2026
ddbd2f6
revert local files... again
tituscmd May 5, 2026
8f050d1
fix padding cropping out left and right most bar
tituscmd May 5, 2026
016305d
add native scrollable chart for iOS 17+ users, fallback to chevron st…
tituscmd May 6, 2026
e9aea7f
fix: correct heart chart Y scale and scroll position on appear and ne…
tituscmd May 8, 2026
74e86e8
feat: improve heart chart header to show date range with hour (rounde…
tituscmd May 8, 2026
7175691
missed one more tiny UX fix
tituscmd May 8, 2026
9b4eabf
chart now snaps to full days on bigger swipes
tituscmd May 11, 2026
882d22c
Update InfiniLink/Core/Components/Charts/Heart/HeartChartView.swift
tituscmd May 13, 2026
8724246
range bars are selectable and show detailed info in header
tituscmd May 12, 2026
8fd9068
feat: add tiny vibration on swiping through bars with slider
tituscmd May 13, 2026
b0ec58c
finalize slider for scrollable graph
tituscmd May 13, 2026
311d7f8
finalize slider to work on both charts and make it prettier
tituscmd May 13, 2026
74b1f5c
remove some redundant computations and banner above heart rate graph …
tituscmd May 13, 2026
d3379f8
remove now outdated line from readme
tituscmd May 13, 2026
f599c58
Clean up
liamcharger May 14, 2026
68d383c
Merge branch 'rebuild' into hrm_chart
tituscmd May 14, 2026
718ffb6
fix some stuff broken by cleanup commit
tituscmd May 14, 2026
81dcd93
apply review changes and tweak colors
tituscmd May 14, 2026
17302ce
First iteration of dynamic fetch
liamcharger May 14, 2026
4008158
Merge branch 'rebuild' into hrm_chart
tituscmd May 14, 2026
35b4cbd
Next iteration of improved data fetch
liamcharger May 15, 2026
4e43916
Fix INL-44 and INL-26
liamcharger May 15, 2026
7464ac8
bugfix: phone low battery notifs delivering more than once
liamcharger May 17, 2026
9c40e98
Fix occasional dropped dfu updates
liamcharger May 17, 2026
5ff5a86
Add force ancs toggle flag
liamcharger May 17, 2026
d5db991
Merge branch 'rebuild' into hrm_chart
tituscmd May 17, 2026
620db0c
Merge branch 'rebuild' into hrm_chart
liamcharger May 19, 2026
82de20a
Merge branch 'rebuild' into hrm_chart
liamcharger May 19, 2026
8a08201
Clean up
liamcharger May 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 1 addition & 19 deletions InfiniLink/Core/Components/Charts/EmptyChartView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,27 +20,9 @@ struct Line: Shape {
}

struct EmptyChartView: View {
@AppStorage("heartRateChartDataSelection") private var dataSelection = 0

let chartType: ChartType

private let backgroundColor = Color.primary.opacity(0.35)
private var detailString: String {
var base = "There isn't any \(chartType.rawValue) data to show "

switch dataSelection {
case 1:
base += "for today"
case 2:
base += "for the week"
case 3:
base += "for the month"
default:
base += "for the current hour"
}

return base
}

init(_ chartType: ChartType) {
self.chartType = chartType
Expand All @@ -64,7 +46,7 @@ struct EmptyChartView: View {
VStack {
Text("Nothing to see here")
.font(.title2.weight(.bold))
Text(detailString)
Text("There isn't any \(chartType.rawValue) data to show")
.foregroundStyle(.gray)
}
}
Expand Down
314 changes: 265 additions & 49 deletions InfiniLink/Core/Components/Charts/Heart/HeartChartView.swift

Large diffs are not rendered by default.

18 changes: 0 additions & 18 deletions InfiniLink/Core/HeartView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,24 +45,6 @@ struct HeartView: View {
List {
Section {
DetailHeaderView(Header(title: String(format: "%.0f", heartPointValues.last ?? 0), subtitle: timestamp(for: chartManager.heartPoints().last), units: "BPM", icon: "heart.fill", accent: .red), width: geo.size.width, animate: (chartManager.heartPoints().last?.timestamp?.timeIntervalSinceNow ?? 60) < 60) {
HStack {
DetailHeaderSubItemView(
title: "Min",
value: heartRate(for: heartPointValues.min() ?? 0)
)
DetailHeaderSubItemView(
title: "Avg",
value: heartRate(for: {
let ints = heartPointValues.compactMap { Int($0) }
guard ints.count > 0 else { return 0.0 }
return Double(ints.reduce(0, +)) / Double(ints.count)
}())
)
DetailHeaderSubItemView(
title: "Max",
value: heartRate(for: heartPointValues.max() ?? 0)
)
}
}
}
.listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
Expand Down
8 changes: 8 additions & 0 deletions InfiniLink/Core/Settings/HeartSettingsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import SwiftUI
struct HeartSettingsView: View {
@AppStorage("backgroundHRMMeasurements") var backgroundHRMMeasurements = false
@AppStorage("filterHeartRateData") var filterHeartRateData = true
@AppStorage("heartPointMarkMode") var heartPointMarkMode = "average"

@FetchRequest(sortDescriptors: [SortDescriptor(\.timestamp)]) var heartPoints: FetchedResults<HeartDataPoint>

Expand Down Expand Up @@ -60,6 +61,13 @@ struct HeartSettingsView: View {
Section(footer: Text("Filter inconsistent data from your heart rate measurements.")) {
Toggle("Filter Values", isOn: $filterHeartRateData)
}
Section(footer: Text("Choose how the point mark on the heart rate chart is calculated.")) {
Picker("Point Mark", selection: $heartPointMarkMode) {
Text("Average").tag("average")
Text("Median").tag("median")
}
.pickerStyle(.menu)
}
Button {
exportCSV(generateCSV(from: Array(heartPoints)))
} label: {
Expand Down
53 changes: 35 additions & 18 deletions InfiniLink/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -97,12 +97,12 @@
}
}
},
"%@-%@" : {
"%@, %@–%@ · %lld %@%@" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "%1$@-%2$@"
"value" : "%1$@, %2$@–%3$@ · %4$lld %5$@%6$@"
}
}
}
Expand Down Expand Up @@ -175,12 +175,15 @@
}
}
},
"%lld-%lld " : {
"%lld-day" : {

},
"%lld–%lld " : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "%1$lld-%2$lld "
"value" : "%1$lld%2$lld "
}
}
}
Expand Down Expand Up @@ -272,6 +275,9 @@
}
}
}
},
"avg" : {

},
"Back" : {

Expand Down Expand Up @@ -311,6 +317,9 @@
},
"Checking for updates..." : {

},
"Choose how the point mark on the heart rate chart is calculated." : {

},
"Clear All Exercises" : {

Expand Down Expand Up @@ -822,6 +831,9 @@
}
}
}
},
"Max" : {

},
"Maximum" : {
"localizations" : {
Expand All @@ -832,9 +844,18 @@
}
}
}
},
"mdn" : {

},
"Median" : {

},
"Metric" : {

},
"Min" : {

},
"Minimum" : {

Expand Down Expand Up @@ -872,9 +893,6 @@
},
"No" : {

},
"No Data" : {

},
"No Logs" : {

Expand Down Expand Up @@ -936,6 +954,9 @@
},
"Pinned" : {

},
"Point Mark" : {

},
"Poor" : {

Expand Down Expand Up @@ -990,6 +1011,9 @@
},
"Selected" : {

},
"Selected Hour" : {

},
"Send" : {

Expand Down Expand Up @@ -1166,6 +1190,9 @@
},
"There aren't any available releases." : {

},
"There isn't any %@ data to show" : {

},
"There wasn't any heart rate data recorded for this exercise." : {

Expand Down Expand Up @@ -1206,16 +1233,6 @@
},
"To start a route, you need to enable \"Always Allow\" location permissions for InfiniLink in Settings." : {

},
"Today your heart rate reached a high of %lld, and dropped to a low of %lld BPM." : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "Today your heart rate reached a high of %1$lld, and dropped to a low of %2$lld BPM."
}
}
}
},
"Total" : {

Expand Down Expand Up @@ -1456,4 +1473,4 @@
}
},
"version" : "1.1"
}
}
2 changes: 1 addition & 1 deletion InfiniLink/Model/ChartType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ enum ChartType: String {
case .heart:
return "heart.fill"
case .battery:
return "battery.20.fill"
return "battery.50percent.fill"
case .sleep:
return "moon.fill"
}
Expand Down
3 changes: 0 additions & 3 deletions InfiniLink/Utils/ChartManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@ import SwiftUI
import CoreData

class ChartManager: ObservableObject {
@AppStorage("heartRateChartDataSelection") var heartRateChartDataSelection = 0
@AppStorage("stepChartDataSelection") var stepChartDataSelection = 0

static let shared = ChartManager()

let persistenceController = PersistenceController.shared
Expand Down
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
- Download and install InfiniTime firmware updates from releases and GitHub Actions using the GitHub API (local file updates are supported)

### Partially implemented features:
- Apple Charts with date range selection
- System-wide notifications—implemented in [#2217](https://github.com/InfiniTimeOrg/InfiniTime/pull/2217), but not available in the main branch yet.

### Currently non-functional features:
Expand Down