From 1ce02ca82049332f8cb62d7569453899ff1d3cff Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Sun, 25 Oct 2026 16:24:40 -0500 Subject: [PATCH] Show manual glucose entries as a larger red point on the watch Matches the phone charts (LoopKit/LoopKit#666): in the watch app's glucose chart and the complication chart, a user-entered sample that isn't display-only is drawn red and 1 pt larger than the CGM points. The watch already receives wasUserEntered with each sample. --- Common/Extensions/SampleValue.swift | 8 ++++++++ .../Managers/ComplicationChartManager.swift | 6 ++++-- WatchApp Extension/Scenes/GlucoseChartScene.swift | 4 ++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/Common/Extensions/SampleValue.swift b/Common/Extensions/SampleValue.swift index b85fec014..40d9faab4 100644 --- a/Common/Extensions/SampleValue.swift +++ b/Common/Extensions/SampleValue.swift @@ -8,6 +8,14 @@ import LoopKit import LoopAlgorithm +extension SampleValue { + /// A glucose value entered by hand, such as a fingerstick or calibration. + var isManualGlucose: Bool { + guard let sample = self as? GlucoseSampleValue else { return false } + return sample.wasUserEntered && !sample.isDisplayOnly + } +} + extension Collection where Element == SampleValue { /// O(n) var quantityRange: ClosedRange? { diff --git a/WatchApp Extension/Managers/ComplicationChartManager.swift b/WatchApp Extension/Managers/ComplicationChartManager.swift index 3d4268afa..4be94984f 100644 --- a/WatchApp Extension/Managers/ComplicationChartManager.swift +++ b/WatchApp Extension/Managers/ComplicationChartManager.swift @@ -16,6 +16,7 @@ private let textInsets = UIEdgeInsets(top: 2, left: 2, bottom: 2, right: 2) extension CGSize { fileprivate static let glucosePoint = CGSize(width: 2, height: 2) + fileprivate static let manualGlucosePoint = CGSize(width: 3, height: 3) } extension NSAttributedString { @@ -150,12 +151,13 @@ final class ComplicationChartManager { } private func drawHistoricalGlucose(in context: CGContext, using scaler: GlucoseChartScaler) { - context.setFillColor(UIColor.glucose.cgColor) data?.historicalGlucose?.lazy.filter { scaler.dates.contains($0.startDate) }.forEach { glucose in let origin = scaler.point(for: glucose, unit: unit) - let glucoseRect = CGRect(origin: origin, size: .glucosePoint).alignedToScreenScale(WKInterfaceDevice.current().screenScale) + let size: CGSize = glucose.isManualGlucose ? .manualGlucosePoint : .glucosePoint + let glucoseRect = CGRect(origin: origin, size: size).alignedToScreenScale(WKInterfaceDevice.current().screenScale) + context.setFillColor((glucose.isManualGlucose ? UIColor.red : UIColor.glucose).cgColor) context.fill(glucoseRect) } } diff --git a/WatchApp Extension/Scenes/GlucoseChartScene.swift b/WatchApp Extension/Scenes/GlucoseChartScene.swift index 0c7c6473a..c582d75b4 100644 --- a/WatchApp Extension/Scenes/GlucoseChartScene.swift +++ b/WatchApp Extension/Scenes/GlucoseChartScene.swift @@ -291,10 +291,10 @@ class GlucoseChartScene: SKScene { data.historicalGlucose?.filter { scaler.dates.contains($0.startDate) }.forEach { let center = scaler.point($0.startDate, $0.quantity.doubleValue(for: unit)) - let size = CGSize(width: 2, height: 2) + let size = $0.isManualGlucose ? CGSize(width: 3, height: 3) : CGSize(width: 2, height: 2) let origin = CGPoint(x: center.x - size.width / 2, y: center.y - size.height / 2) let (sprite, created) = getSprite(forHash: $0.chartHashValue) - sprite.color = .glucose + sprite.color = $0.isManualGlucose ? .red : .glucose sprite.zPosition = NodePlane.values.zPosition sprite.move(to: CGRect(origin: origin, size: size).alignedToScreenScale(WKInterfaceDevice.current().screenScale), animated: !created) inactiveNodes.removeValue(forKey: $0.chartHashValue)