From 8e5f30ade366c1aba305eaf2729e6324aa43a6a4 Mon Sep 17 00:00:00 2001 From: Sam Watts Date: Thu, 6 Jun 2024 20:33:01 +0100 Subject: [PATCH 1/4] Added rate line --- .../Goals/GoalDetail/Chart/GoalChartView.swift | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Packages/Sources/Features/Goals/GoalDetail/Chart/GoalChartView.swift b/Packages/Sources/Features/Goals/GoalDetail/Chart/GoalChartView.swift index 050bf52..a2d5eb5 100644 --- a/Packages/Sources/Features/Goals/GoalDetail/Chart/GoalChartView.swift +++ b/Packages/Sources/Features/Goals/GoalDetail/Chart/GoalChartView.swift @@ -86,6 +86,7 @@ struct GoalChartView: View { y: .value("distance", goal.converted(to: .primaryUnit()).value), series: .value("goal", "b") ) + .lineStyle(StrokeStyle(lineWidth: 1, dash: [1])) .foregroundStyle(tint) LineMark( @@ -93,6 +94,23 @@ struct GoalChartView: View { y: .value("distance", goal.converted(to: .primaryUnit()).value), series: .value("goal", "b") ) + .lineStyle(StrokeStyle(lineWidth: 1, dash: [1])) + .foregroundStyle(tint) + + LineMark( + x: .value("index", start), + y: .value("distance", 0), + series: .value("rate", goal.converted(to: .primaryUnit()).value) + ) + .lineStyle(StrokeStyle(lineWidth: 1, dash: [1])) + .foregroundStyle(tint) + + LineMark( + x: .value("index", end), + y: .value("distance", goal.converted(to: .primaryUnit()).value), + series: .value("rate", goal.converted(to: .primaryUnit()).value) + ) + .lineStyle(StrokeStyle(lineWidth: 1, dash: [1])) .foregroundStyle(tint) } } From 9c0cb4bf733509f15704af2146f432614b4ca47c Mon Sep 17 00:00:00 2001 From: Sam Watts Date: Thu, 6 Jun 2024 20:33:12 +0100 Subject: [PATCH 2/4] TCA version updates --- .../project.xcworkspace/xcshareddata/swiftpm/Package.resolved | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Running.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Running.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 387261e..a0cfbd1 100644 --- a/Running.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Running.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -41,8 +41,8 @@ "kind" : "remoteSourceControl", "location" : "git@github.com:pointfreeco/swift-composable-architecture.git", "state" : { - "revision" : "e6c0959044cbe2c934ac0ce9c3c4ead86350f44f", - "version" : "1.10.2" + "revision" : "433a23118f739078644ebeb4009e23d307af694a", + "version" : "1.10.4" } }, { From 8e0dc1b98427943d5da1be8cf36f472d832ab0b3 Mon Sep 17 00:00:00 2001 From: Sam Watts Date: Thu, 6 Jun 2024 20:38:19 +0100 Subject: [PATCH 3/4] separate state management for showing rate and target --- .../GoalDetail/Chart/GoalChartView.swift | 68 +++++++++++-------- .../Goals/GoalDetail/GoalDetailFeature.swift | 5 +- 2 files changed, 43 insertions(+), 30 deletions(-) diff --git a/Packages/Sources/Features/Goals/GoalDetail/Chart/GoalChartView.swift b/Packages/Sources/Features/Goals/GoalDetail/Chart/GoalChartView.swift index a2d5eb5..ea26be3 100644 --- a/Packages/Sources/Features/Goals/GoalDetail/Chart/GoalChartView.swift +++ b/Packages/Sources/Features/Goals/GoalDetail/Chart/GoalChartView.swift @@ -80,38 +80,42 @@ struct GoalChartView: View { } } - if let goal = store.goal.target, store.showTarget, let start = columns.first?.index, let end = columns.last?.index { - LineMark( - x: .value("index", start), - y: .value("distance", goal.converted(to: .primaryUnit()).value), - series: .value("goal", "b") - ) - .lineStyle(StrokeStyle(lineWidth: 1, dash: [1])) - .foregroundStyle(tint) + if let goal = store.goal.target, let start = columns.first?.index, let end = columns.last?.index { + if store.showTarget { + LineMark( + x: .value("index", start), + y: .value("distance", goal.converted(to: .primaryUnit()).value), + series: .value("goal", "b") + ) + .lineStyle(StrokeStyle(lineWidth: 1, dash: [1])) + .foregroundStyle(tint) - LineMark( - x: .value("index", end), - y: .value("distance", goal.converted(to: .primaryUnit()).value), - series: .value("goal", "b") - ) - .lineStyle(StrokeStyle(lineWidth: 1, dash: [1])) - .foregroundStyle(tint) + LineMark( + x: .value("index", end), + y: .value("distance", goal.converted(to: .primaryUnit()).value), + series: .value("goal", "b") + ) + .lineStyle(StrokeStyle(lineWidth: 1, dash: [1])) + .foregroundStyle(tint) + } - LineMark( - x: .value("index", start), - y: .value("distance", 0), - series: .value("rate", goal.converted(to: .primaryUnit()).value) - ) - .lineStyle(StrokeStyle(lineWidth: 1, dash: [1])) - .foregroundStyle(tint) + if store.showRate { + LineMark( + x: .value("index", start), + y: .value("distance", 0), + series: .value("rate", goal.converted(to: .primaryUnit()).value) + ) + .lineStyle(StrokeStyle(lineWidth: 1, dash: [1])) + .foregroundStyle(tint) - LineMark( - x: .value("index", end), - y: .value("distance", goal.converted(to: .primaryUnit()).value), - series: .value("rate", goal.converted(to: .primaryUnit()).value) - ) - .lineStyle(StrokeStyle(lineWidth: 1, dash: [1])) - .foregroundStyle(tint) + LineMark( + x: .value("index", end), + y: .value("distance", goal.converted(to: .primaryUnit()).value), + series: .value("rate", goal.converted(to: .primaryUnit()).value) + ) + .lineStyle(StrokeStyle(lineWidth: 1, dash: [1])) + .foregroundStyle(tint) + } } } .chartScrollableAxes([.horizontal]) @@ -142,6 +146,12 @@ struct GoalChartView: View { if store.goal.target != nil { HStack { Spacer() + ChartButton( + title: "Rate", + symbol: "chart.line.uptrend.xyaxis", + selected: $store.showRate.animation() + ) + ChartButton( title: L10n.Goals.Detail.Chart.targetButton, symbol: "target", diff --git a/Packages/Sources/Features/Goals/GoalDetail/GoalDetailFeature.swift b/Packages/Sources/Features/Goals/GoalDetail/GoalDetailFeature.swift index a0caa1c..b052559 100644 --- a/Packages/Sources/Features/Goals/GoalDetail/GoalDetailFeature.swift +++ b/Packages/Sources/Features/Goals/GoalDetail/GoalDetailFeature.swift @@ -12,13 +12,15 @@ public struct GoalDetailFeature: Reducer { var emptyStateRuns: [Run] @Shared var showTarget: Bool + @Shared var showRate: Bool public init( goal: Goal, intervalDate: Date? = nil, runs: [Run]? = nil, emptyStateRuns: [Run] = [], - showTarget: Bool = false + showTarget: Bool = false, + showRate: Bool = false ) { self.goal = goal self.intervalDate = intervalDate @@ -26,6 +28,7 @@ public struct GoalDetailFeature: Reducer { self.emptyStateRuns = emptyStateRuns _showTarget = .init(wrappedValue: showTarget, .appStorage("show_target_\(goal.period.rawValue)")) + _showRate = .init(wrappedValue: showRate, .appStorage("show_rate_\(goal.period.rawValue)")) } var title: String { From e53813757e9882917aabd88c853859172ef316f7 Mon Sep 17 00:00:00 2001 From: Sam Watts Date: Thu, 6 Jun 2024 20:38:33 +0100 Subject: [PATCH 4/4] make sure full rate is shown --- .../Features/Goals/GoalDetail/Chart/GoalChartView.swift | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Packages/Sources/Features/Goals/GoalDetail/Chart/GoalChartView.swift b/Packages/Sources/Features/Goals/GoalDetail/Chart/GoalChartView.swift index ea26be3..25b2646 100644 --- a/Packages/Sources/Features/Goals/GoalDetail/Chart/GoalChartView.swift +++ b/Packages/Sources/Features/Goals/GoalDetail/Chart/GoalChartView.swift @@ -168,10 +168,10 @@ struct GoalChartView: View { let min = 0 let maxValue: Int let goalValue: Int - if store.showTarget, let goal = store.goal.target?.converted(to: .primaryUnit()) { + if showFullRange, let goal = store.goal.target?.converted(to: .primaryUnit()) { goalValue = Int(ceil(goal.value)) } else { - goalValue = store.showTarget ? 0 : 20 + goalValue = showFullRange ? 0 : 20 } if let cumulativeDistance = columns.last?.cumulativeDistance { @@ -181,6 +181,10 @@ struct GoalChartView: View { } return min ... (maxValue + 10) } + + var showFullRange: Bool { + store.showTarget || store.showRate + } } #Preview("Weekly") {