Skip to content

Commit

Permalink
multiple: attempt to fix crashes related to CoreData, update weather …
Browse files Browse the repository at this point in the history
…icon cases, add device specification for health data
  • Loading branch information
liamcharger committed Jan 9, 2025
1 parent 6ed85ec commit 53c0aa3
Show file tree
Hide file tree
Showing 13 changed files with 118 additions and 111 deletions.
Binary file modified .DS_Store
Binary file not shown.
12 changes: 6 additions & 6 deletions InfiniLink/BLE/DeviceManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ class DeviceManager: ObservableObject {
// Get persisted settings, before settings.dat has loaded
func getSettings() {
guard let uuid = bleManager.pairedDeviceID else { return }
let device = self.fetchDevice(with: uuid)
guard let device = fetchDevice(with: uuid) else { return }

DispatchQueue.main.async {
self.settings = Settings(
Expand All @@ -86,7 +86,7 @@ class DeviceManager: ObservableObject {
}
}

func fetchDevice(with uuid: String? = nil) -> Device {
func fetchDevice(with uuid: String? = nil) -> Device? {
let id: String = uuid ?? bleManager.pairedDeviceID!

let fetchRequest: NSFetchRequest<Device> = Device.fetchRequest()
Expand All @@ -113,15 +113,15 @@ class DeviceManager: ObservableObject {
return newDevice
}
} catch {
fatalError("Error fetching or saving device: \(error)")
log("Error fetching or saving device: \(error)", caller: "DeviceManager")
return nil
}
}

// Get settings from settings file from watch and save it to keep device object up-to-date
func updateSettings(settings: Settings) {
guard let uuid = bleManager.pairedDevice?.uuid else { return }

let device = fetchDevice(with: uuid)
guard let device = fetchDevice(with: uuid) else { return }

device.brightLevel = Int16(settings.brightLevel.rawValue)
device.chimesOption = Int16(settings.chimesOption.rawValue)
Expand Down Expand Up @@ -153,8 +153,8 @@ class DeviceManager: ObservableObject {

func updateName(name: String, for device: Device) {
guard let uuid = device.uuid else { return }
guard let device = fetchDevice(with: uuid) else { return }

let device = fetchDevice(with: uuid)
device.name = name

save()
Expand Down
10 changes: 1 addition & 9 deletions InfiniLink/Core/Components/Charts/HeartChartView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,7 @@ struct HeartChartView: View {
var body: some View {
let chartStyle = LineChartStyle(infoBoxPlacement: .floating /* TODO: fork and set to infoBox */, infoBoxBackgroundColour: Color(.secondarySystemBackground), baseline: .minimumValue, topLine: .maximumValue)
let lineStyle = LineStyle(lineColour: ColourStyle(colours: [Color.red.opacity(0.8), Color.red.opacity(0.5)], startPoint: .top, endPoint: .bottom), lineType: .line, ignoreZero: true)
let data = LineChartData(dataSets: LineDataSet(dataPoints: {
let points = chartManager.convert(heartPoints)

if let point = points.first, points.count <= 1 {
return [point, point]
}

return points
}(), style: lineStyle), chartStyle: chartStyle)
let data = LineChartData(dataSets: LineDataSet(dataPoints: chartManager.convert(heartPoints), style: lineStyle), chartStyle: chartStyle)

FilledLineChart(chartData: data)
.floatingInfoBox(chartData: data)
Expand Down
17 changes: 10 additions & 7 deletions InfiniLink/Core/Exercise/Views/ExerciseDetailView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -98,14 +98,17 @@ struct ExerciseDetailView: View {
.frame(height: geo.size.width / 1.6)
}
.listRowBackground(Color.clear)
if let tracks = userExercise.playedTracks, tracks.count > 0 {
// TODO: add tracks to list
if let tracksSet = userExercise.playedTracks as? Set<PlayedTrack>, !tracksSet.isEmpty {
let tracks = Array(tracksSet).sorted(by: { $0.timestamp ?? Date() < $1.timestamp ?? Date() })

Section("Played Tracks") {
ForEach(1...7, id: \.self) { index in
VStack(alignment: .leading, spacing: 5) {
Text("Track \(index)")
.fontWeight(.bold)
Text("Artist Name")
ForEach(tracks) { track in
if let title = track.title, let artist = track.artist {
VStack(alignment: .leading, spacing: 5) {
Text(title)
.fontWeight(.bold)
Text(artist)
}
}
}
}
Expand Down
23 changes: 3 additions & 20 deletions InfiniLink/Core/HeartView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,7 @@ struct HeartView: View {
@FetchRequest(sortDescriptors: [SortDescriptor(\.timestamp)]) var heartDataPoints: FetchedResults<HeartDataPoint>

var heartPointValues: [Double] {
return heartPoints.compactMap({ $0.value })
}
var heartPoints: [HeartDataPoint] {
return heartDataPoints.filter({
guard let timestamp = $0.timestamp?.timeIntervalSinceNow else { return false }
let secondsFromNow = abs(timestamp)

switch dataSelection {
case 1:
return secondsFromNow <= (60 * 60 * 24) // Day
case 2:
return secondsFromNow <= (60 * 60 * 24 * 7) // Week
case 3:
return secondsFromNow <= (60 * 60 * 24 * 7 * 4) // TODO: dynamically calculate number of weeks
default:
return secondsFromNow <= (60 * 60) // Hour
}
})
return chartManager.heartPoints().compactMap({ $0.value })
}

func heartRate(for val: Double) -> String {
Expand Down Expand Up @@ -68,7 +51,7 @@ struct HeartView: View {
ScrollView {
VStack(spacing: 20) {
Section {
DetailHeaderView(Header(title: String(format: "%.0f", heartPointValues.last ?? 0), subtitle: timestamp(for: heartPoints.last), units: "BPM", icon: "heart.fill", accent: .red), width: geo.size.width, animate: true) {
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: true) {
HStack {
DetailHeaderSubItemView(
title: "Min",
Expand Down Expand Up @@ -106,7 +89,7 @@ struct HeartView: View {
.pickerStyle(.segmented)
}
Section {
HeartChartView(heartPoints: heartPoints)
HeartChartView(heartPoints: chartManager.heartPoints())
.frame(height: geo.size.width / 1.6)
.padding(.vertical)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Music control from InfiniTime is available when using the Apple Music app, but s
For more information on InfiniLink or InfiniTime, visit their GitHub repositories.
""")
Text("""
This new version of InfiniLink has not been localized yet, so if you can help translate, visit the InfiniLink GitHub repo to a pull request!
""")
}
Section {
Expand Down
8 changes: 3 additions & 5 deletions InfiniLink/Core/StepsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,11 @@ import SwiftUICharts
struct StepsView: View {
@ObservedObject var bleManager = BLEManager.shared
@ObservedObject var deviceManager = DeviceManager.shared
@ObservedObject var chartManager = ChartManager.shared
@ObservedObject var personalizationController = PersonalizationController.shared

@AppStorage("stepsChartDataSelection") private var dataSelection = 0

@FetchRequest(sortDescriptors: [NSSortDescriptor(keyPath: \StepCounts.timestamp, ascending: true)])
private var stepCounts: FetchedResults<StepCounts>

let exerciseCalculator = FitnessCalculator.shared

func getStepCounts(displayWeek: Date) -> [BarChartDataPoint] {
Expand All @@ -39,7 +37,7 @@ struct StepsView: View {
let color = ColourStyle(colour: .blue)
dataPoints.append(BarChartDataPoint(value: 0, xAxisLabel: shortFormatter.string(from: day), description: longFormatter.string(from: day), date: day, colour: color))

for i in stepCounts {
for i in chartManager.stepPoints() {
if calendar.isDate(i.timestamp!, inSameDayAs: day) {
dataPoints[weekDay] = BarChartDataPoint(value: Double(i.steps), xAxisLabel: shortFormatter.string(from: day), description: longFormatter.string(from: day), date: i.timestamp!, colour: color)
}
Expand All @@ -50,7 +48,7 @@ struct StepsView: View {
return dataPoints
}
func steps(for date: Date) -> String {
for stepCount in stepCounts {
for stepCount in chartManager.stepPoints() {
if Calendar.current.isDate(stepCount.timestamp!, inSameDayAs: date) {
let formattedSteps = NumberFormatter.localizedString(from: NSNumber(value: stepCount.steps), number: .decimal)
return formattedSteps
Expand Down
25 changes: 10 additions & 15 deletions InfiniLink/InfiniLink.xcdatamodeld/InfiniLink.xcdatamodel/contents
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="23605" systemVersion="24C5089c" minimumToolsVersion="Automatic" sourceLanguage="Swift" usedWithSwiftData="YES" userDefinedModelVersionIdentifier="">
<entity name="BatteryDataPoint" representedClassName="BatteryDataPoint" syncable="YES" codeGenerationType="class">
<attribute name="deviceId" optional="YES" attributeType="String"/>
<attribute name="id" optional="YES" attributeType="UUID" usesScalarValueType="NO"/>
<attribute name="timestamp" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="value" optional="YES" attributeType="Double" defaultValueString="0" usesScalarValueType="YES"/>
<relationship name="device" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Device" inverseName="batteryPoints" inverseEntity="Device"/>
<relationship name="device" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Device"/>
</entity>
<entity name="Device" representedClassName="Device" syncable="YES" codeGenerationType="class">
<attribute name="alwaysOnDisplay" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
Expand All @@ -28,17 +29,15 @@
<attribute name="uuid" attributeType="String"/>
<attribute name="watchface" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="weatherFormat" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/>
<relationship name="batteryPoints" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="BatteryDataPoint" inverseName="device" inverseEntity="BatteryDataPoint"/>
<relationship name="heartPoints" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="HeartDataPoint" inverseName="device" inverseEntity="HeartDataPoint"/>
<relationship name="pineTimeStyle" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="PineTimeStyleWatchface" inverseName="device" inverseEntity="PineTimeStyleWatchface"/>
<relationship name="stepCounts" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="StepCounts" inverseName="device" inverseEntity="StepCounts"/>
<relationship name="watchFaceInfineat" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="InfineatWatchface" inverseName="device" inverseEntity="InfineatWatchface"/>
</entity>
<entity name="HeartDataPoint" representedClassName="HeartDataPoint" syncable="YES" codeGenerationType="class">
<attribute name="deviceId" optional="YES" attributeType="String"/>
<attribute name="id" optional="YES" attributeType="UUID" usesScalarValueType="NO"/>
<attribute name="timestamp" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="value" attributeType="Double" defaultValueString="0" usesScalarValueType="YES"/>
<relationship name="device" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Device" inverseName="heartPoints" inverseEntity="Device"/>
<relationship name="device" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Device"/>
<relationship name="exercise" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="UserExercise" inverseName="heartPoints" inverseEntity="UserExercise"/>
</entity>
<entity name="InfineatWatchface" representedClassName="InfineatWatchface" syncable="YES" codeGenerationType="class">
Expand All @@ -57,25 +56,21 @@
<entity name="PlayedTrack" representedClassName="PlayedTrack" syncable="YES" codeGenerationType="class">
<attribute name="artist" optional="YES" attributeType="String"/>
<attribute name="id" optional="YES" attributeType="UUID" usesScalarValueType="NO"/>
<attribute name="timestamp" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="timestamp" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="title" attributeType="String"/>
<relationship name="exercise" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="UserExercise" inverseName="playedTracks" inverseEntity="UserExercise"/>
</entity>
<entity name="SleepDataPoint" representedClassName="SleepDataPoint" syncable="YES" codeGenerationType="class">
<attribute name="deviceId" optional="YES" attributeType="String"/>
<attribute name="id" attributeType="UUID" usesScalarValueType="NO"/>
<attribute name="minutes" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="timestamp" attributeType="Date" usesScalarValueType="NO"/>
</entity>
<entity name="StepCounts" representedClassName="StepCounts" syncable="YES" codeGenerationType="class">
<attribute name="deviceId" optional="YES" attributeType="String"/>
<attribute name="id" optional="YES" attributeType="UUID" usesScalarValueType="NO"/>
<attribute name="steps" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="timestamp" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
<relationship name="device" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Device" inverseName="stepCounts" inverseEntity="Device"/>
</entity>
<entity name="User" representedClassName="User" syncable="YES" codeGenerationType="class">
<attribute name="age" optional="YES" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="id" attributeType="UUID" usesScalarValueType="NO"/>
<attribute name="units" optional="YES" attributeType="String"/>
<attribute name="weight" optional="YES" attributeType="Integer 32" defaultValueString="0.0" usesScalarValueType="YES"/>
</entity>
<entity name="UserExercise" representedClassName="UserExercise" syncable="YES" codeGenerationType="class">
<attribute name="endDate" attributeType="Date" usesScalarValueType="NO"/>
Expand All @@ -84,6 +79,6 @@
<attribute name="startDate" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="steps" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<relationship name="heartPoints" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="HeartDataPoint" inverseName="exercise" inverseEntity="HeartDataPoint"/>
<relationship name="playedTracks" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="PlayedTrack" inverseName="exercise" inverseEntity="PlayedTrack"/>
<relationship name="playedTracks" toMany="YES" deletionRule="Nullify" destinationEntity="PlayedTrack" inverseName="exercise" inverseEntity="PlayedTrack"/>
</entity>
</model>
</model>
6 changes: 0 additions & 6 deletions InfiniLink/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -189,9 +189,6 @@
},
"Are you sure you want to unpair from %@?" : {

},
"Artist Name" : {

},
"Back" : {

Expand Down Expand Up @@ -660,9 +657,6 @@
},
"Total Tracks Played" : {

},
"Track %lld" : {

},
"Units" : {

Expand Down
Loading

0 comments on commit 53c0aa3

Please sign in to comment.