Skip to content

Commit 03c1c5b

Browse files
2 parents 30e9c69 + fdf880f commit 03c1c5b

File tree

8 files changed

+110
-59
lines changed

8 files changed

+110
-59
lines changed

Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/CircularProgressPreview.swift

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,8 @@ import UIKit
44

55
struct CircularProgressPreview: View {
66
@State private var model = Self.initialModel
7-
@State private var currentValue: CGFloat = Self.initialValue
87

9-
private let circularProgress = UKCircularProgress(
10-
initialValue: Self.initialValue,
11-
model: Self.initialModel
12-
)
8+
private let circularProgress = UKCircularProgress(model: Self.initialModel)
139

1410
private let timer = Timer
1511
.publish(every: 0.5, on: .main, in: .common)
@@ -21,18 +17,14 @@ struct CircularProgressPreview: View {
2117
self.circularProgress
2218
.preview
2319
.onAppear {
24-
self.circularProgress.currentValue = Self.initialValue
2520
self.circularProgress.model = Self.initialModel
2621
}
2722
.onChange(of: model) { newModel in
2823
self.circularProgress.model = newModel
2924
}
30-
.onChange(of: self.currentValue) { newValue in
31-
self.circularProgress.currentValue = newValue
32-
}
3325
}
3426
PreviewWrapper(title: "SwiftUI") {
35-
SUCircularProgress(currentValue: self.currentValue, model: self.model)
27+
SUCircularProgress(model: self.model)
3628
}
3729
Form {
3830
ComponentColorPicker(selection: self.$model.color)
@@ -54,28 +46,25 @@ struct CircularProgressPreview: View {
5446
SizePicker(selection: self.$model.size)
5547
}
5648
.onReceive(self.timer) { _ in
57-
if self.currentValue < self.model.maxValue {
49+
if self.model.currentValue < self.model.maxValue {
5850
let step = (self.model.maxValue - self.model.minValue) / 100
59-
self.currentValue = min(
51+
self.model.currentValue = min(
6052
self.model.maxValue,
61-
self.currentValue + CGFloat(Int.random(in: 1...20)) * step
53+
self.model.currentValue + CGFloat(Int.random(in: 1...20)) * step
6254
)
6355
} else {
64-
self.currentValue = self.model.minValue
56+
self.model.currentValue = self.model.minValue
6557
}
66-
self.model.label = "\(Int(self.currentValue))%"
58+
self.model.label = "\(Int(self.model.currentValue))%"
6759
}
6860
}
6961
}
7062

7163
// MARK: - Helpers
7264

73-
private static var initialValue: Double {
74-
return 0.0
75-
}
76-
7765
private static var initialModel = CircularProgressVM {
7866
$0.label = "0%"
67+
$0.currentValue = 0.0
7968
}
8069
}
8170

Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/ProgressBarPreview.swift

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,9 @@ import UIKit
44

55
struct ProgressBarPreview: View {
66
@State private var model = Self.initialModel
7-
@State private var currentValue: CGFloat = Self.initialValue
8-
9-
private let progressBar = UKProgressBar(initialValue: Self.initialValue, model: Self.initialModel)
10-
7+
8+
private let progressBar = UKProgressBar(model: Self.initialModel)
9+
1110
private let timer = Timer
1211
.publish(every: 0.5, on: .main, in: .common)
1312
.autoconnect()
@@ -18,15 +17,14 @@ struct ProgressBarPreview: View {
1817
self.progressBar
1918
.preview
2019
.onAppear {
21-
self.progressBar.currentValue = self.currentValue
2220
self.progressBar.model = Self.initialModel
2321
}
2422
.onChange(of: self.model) { newValue in
2523
self.progressBar.model = newValue
2624
}
2725
}
2826
PreviewWrapper(title: "SwiftUI") {
29-
SUProgressBar(currentValue: self.currentValue, model: self.model)
27+
SUProgressBar(model: self.model)
3028
}
3129
Form {
3230
ComponentColorPicker(selection: self.$model.color)
@@ -42,25 +40,20 @@ struct ProgressBarPreview: View {
4240
}
4341
}
4442
.onReceive(self.timer) { _ in
45-
if self.currentValue < self.model.maxValue {
43+
if self.model.currentValue < self.model.maxValue {
4644
let step = (self.model.maxValue - self.model.minValue) / 100
47-
self.currentValue = min(
45+
self.model.currentValue = min(
4846
self.model.maxValue,
49-
self.currentValue + CGFloat(Int.random(in: 1...20)) * step
47+
self.model.currentValue + CGFloat(Int.random(in: 1...20)) * step
5048
)
5149
} else {
52-
self.currentValue = self.model.minValue
50+
self.model.currentValue = self.model.minValue
5351
}
54-
55-
self.progressBar.currentValue = self.currentValue
5652
}
5753
}
5854

5955
// MARK: - Helpers
6056

61-
private static var initialValue: Double {
62-
return 0.0
63-
}
6457
private static var initialModel: ProgressBarVM {
6558
return .init()
6659
}

Sources/ComponentsKit/Components/CircularProgress/Models/CircularProgressVM.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ public struct CircularProgressVM: ComponentVM {
77
/// Defaults to `.accent`.
88
public var color: ComponentColor = .accent
99

10+
/// The current value of the circular progress.
11+
///
12+
/// Defaults to `0`.
13+
public var currentValue: CGFloat = 0
14+
1015
/// The font used for the circular progress label text.
1116
public var font: UniversalFont?
1217

@@ -103,6 +108,13 @@ extension CircularProgressVM {
103108
}
104109

105110
extension CircularProgressVM {
111+
var progress: CGFloat {
112+
let range = self.maxValue - self.minValue
113+
guard range > 0 else { return 0 }
114+
let normalized = (self.currentValue - self.minValue) / range
115+
return max(0, min(1, normalized))
116+
}
117+
106118
func progress(for currentValue: CGFloat) -> CGFloat {
107119
let range = self.maxValue - self.minValue
108120
guard range > 0 else { return 0 }
@@ -123,6 +135,7 @@ extension CircularProgressVM {
123135
func shouldRecalculateProgress(_ oldModel: Self) -> Bool {
124136
return self.minValue != oldModel.minValue
125137
|| self.maxValue != oldModel.maxValue
138+
|| self.currentValue != oldModel.currentValue
126139
}
127140
func shouldUpdateShape(_ oldModel: Self) -> Bool {
128141
return self.shape != oldModel.shape

Sources/ComponentsKit/Components/CircularProgress/SUCircularProgress.swift

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ public struct SUCircularProgress: View {
88
public var model: CircularProgressVM
99

1010
/// The current progress value.
11-
public var currentValue: CGFloat
11+
public var currentValue: CGFloat?
1212

1313
private var progress: CGFloat {
14-
self.model.progress(for: self.currentValue)
14+
self.currentValue.map { self.model.progress(for: $0) } ?? self.model.progress
1515
}
1616

1717
// MARK: - Initializer
@@ -20,6 +20,7 @@ public struct SUCircularProgress: View {
2020
/// - Parameters:
2121
/// - currentValue: Current progress.
2222
/// - model: A model that defines the appearance properties.
23+
@available(*, deprecated, message: "Set `currentValue` in the model instead.")
2324
public init(
2425
currentValue: CGFloat = 0,
2526
model: CircularProgressVM = .init()
@@ -28,6 +29,13 @@ public struct SUCircularProgress: View {
2829
self.model = model
2930
}
3031

32+
/// Initializer.
33+
/// - Parameters:
34+
/// - model: A model that defines the appearance properties.
35+
public init(model: CircularProgressVM) {
36+
self.model = model
37+
}
38+
3139
// MARK: - Body
3240

3341
public var body: some View {

Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,16 @@ open class UKCircularProgress: UIView, UKComponent {
1313
}
1414

1515
/// The current progress value.
16-
public var currentValue: CGFloat {
16+
public var currentValue: CGFloat? {
1717
didSet {
1818
self.updateProgress()
1919
}
2020
}
2121

22+
private var progress: CGFloat {
23+
self.currentValue.map { self.model.progress(for: $0) } ?? self.model.progress
24+
}
25+
2226
// MARK: - Subviews
2327

2428
/// The shape layer responsible for rendering the background.
@@ -42,6 +46,7 @@ open class UKCircularProgress: UIView, UKComponent {
4246
/// - Parameters:
4347
/// - initialValue: The initial progress value. Defaults to `0`.
4448
/// - model: The model that defines the appearance properties.
49+
@available(*, deprecated, message: "Set `currentValue` in the model instead.")
4550
public init(
4651
initialValue: CGFloat = 0,
4752
model: CircularProgressVM = .init()
@@ -55,6 +60,18 @@ open class UKCircularProgress: UIView, UKComponent {
5560
self.layout()
5661
}
5762

63+
/// Initializer.
64+
/// - Parameters:
65+
/// - model: The model that defines the appearance properties.
66+
public init(model: CircularProgressVM) {
67+
self.model = model
68+
super.init(frame: .zero)
69+
70+
self.setup()
71+
self.style()
72+
self.layout()
73+
}
74+
5875
public required init?(coder: NSCoder) {
5976
fatalError("init(coder:) has not been implemented")
6077
}
@@ -72,7 +89,7 @@ open class UKCircularProgress: UIView, UKComponent {
7289
}
7390
}
7491

75-
self.progressLayer.strokeEnd = self.model.progress(for: self.currentValue)
92+
self.progressLayer.strokeEnd = self.progress
7693
self.label.text = self.model.label
7794
}
7895

@@ -132,7 +149,7 @@ open class UKCircularProgress: UIView, UKComponent {
132149
CATransaction.begin()
133150
CATransaction.setAnimationDuration(self.model.animationDuration)
134151
CATransaction.setAnimationTimingFunction(CAMediaTimingFunction(name: .linear))
135-
self.progressLayer.strokeEnd = self.model.progress(for: self.currentValue)
152+
self.progressLayer.strokeEnd = self.progress
136153
CATransaction.commit()
137154
}
138155

Sources/ComponentsKit/Components/ProgressBar/Models/ProgressBarVM.swift

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,26 +7,29 @@ public struct ProgressBarVM: ComponentVM {
77
/// Defaults to `.accent`.
88
public var color: ComponentColor = .accent
99

10-
/// The visual style of the progress bar component.
11-
///
12-
/// Defaults to `.striped`.
13-
public var style: Style = .striped
14-
15-
/// The size of the progress bar.
10+
/// The corner radius of the progress bar.
1611
///
1712
/// Defaults to `.medium`.
18-
public var size: ComponentSize = .medium
13+
public var cornerRadius: ComponentRadius = .medium
1914

20-
/// The minimum value of the progress bar.
21-
public var minValue: CGFloat = 0
15+
/// The current value of the progress bar.
16+
public var currentValue: CGFloat = 0
2217

2318
/// The maximum value of the progress bar.
2419
public var maxValue: CGFloat = 100
2520

26-
/// The corner radius of the progress bar.
21+
/// The minimum value of the progress bar.
22+
public var minValue: CGFloat = 0
23+
24+
/// The size of the progress bar.
2725
///
2826
/// Defaults to `.medium`.
29-
public var cornerRadius: ComponentRadius = .medium
27+
public var size: ComponentSize = .medium
28+
29+
/// The visual style of the progress bar component.
30+
///
31+
/// Defaults to `.striped`.
32+
public var style: Style = .striped
3033

3134
/// Initializes a new instance of `ProgressBarVM` with default values.
3235
public init() {}
@@ -139,6 +142,13 @@ extension ProgressBarVM {
139142
}
140143

141144
extension ProgressBarVM {
145+
var progress: CGFloat {
146+
let range = self.maxValue - self.minValue
147+
guard range > 0 else { return 0 }
148+
let normalized = (self.currentValue - self.minValue) / range
149+
return max(0, min(1, normalized))
150+
}
151+
142152
func progress(for currentValue: CGFloat) -> CGFloat {
143153
let range = self.maxValue - self.minValue
144154
guard range > 0 else { return 0 }

Sources/ComponentsKit/Components/ProgressBar/SUProgressBar.swift

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
import SwiftUI
22

3-
/// A SwiftUI component that displays a progress bar.
3+
/// A SwiftUI component that visually represents the progress of a task or process using a horizontal bar.
44
public struct SUProgressBar: View {
55
// MARK: - Properties
66

77
/// A model that defines the appearance properties.
88
public var model: ProgressBarVM
99
/// The current progress value.
10-
public var currentValue: CGFloat
10+
public var currentValue: CGFloat?
1111

1212
private var progress: CGFloat {
13-
self.model.progress(for: self.currentValue)
13+
self.currentValue.map { self.model.progress(for: $0) } ?? self.model.progress
1414
}
1515

1616
// MARK: - Initializer
@@ -19,6 +19,7 @@ public struct SUProgressBar: View {
1919
/// - Parameters:
2020
/// - currentValue: The current progress value.
2121
/// - model: A model that defines the appearance properties.
22+
@available(*, deprecated, message: "Set `currentValue` in the model instead.")
2223
public init(
2324
currentValue: CGFloat,
2425
model: ProgressBarVM = .init()
@@ -27,6 +28,13 @@ public struct SUProgressBar: View {
2728
self.model = model
2829
}
2930

31+
/// Initializer.
32+
/// - Parameters:
33+
/// - model: A model that defines the appearance properties.
34+
public init(model: ProgressBarVM) {
35+
self.model = model
36+
}
37+
3038
// MARK: - Body
3139

3240
public var body: some View {

0 commit comments

Comments
 (0)