Skip to content

Commit 958a587

Browse files
committed
15.0.0
1 parent 6067fab commit 958a587

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+3491
-14
lines changed

CHANGELOG.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,21 @@
11
# Change Log
22

3+
## [15.0.0](https://github.com/relatedcode/ProgressHUD/releases/tag/15.0.0)
4+
5+
Released on 2025-11-28.
6+
7+
#### Changed
8+
9+
- Complete rewrite from UIKit to SwiftUI.
10+
- Minimum iOS requirement updated from iOS 13.0+ to iOS 17.0+.
11+
- Source path changed from `ProgressHUD/Sources` to `SwiftUI/Sources`.
12+
- All color, font, and image properties now use SwiftUI types (`Color`, `Font`, `Image`) instead of UIKit types.
13+
- Updated API to use SwiftUI's `@Observable` and modern Swift concurrency.
14+
15+
#### Note
16+
17+
- This version (15.0.0+) is built with SwiftUI. If you need the UIKit version, please use version 14.1.4.
18+
319
## [14.1.4](https://github.com/relatedcode/ProgressHUD/releases/tag/14.1.4)
420

521
Released on 2025-07-04.

Package.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ let package = Package(
66
name: "ProgressHUD",
77
defaultLocalization: "en",
88
platforms: [
9-
.iOS(.v13),
9+
.iOS(.v17),
1010
],
1111
products: [
1212
.library(
@@ -18,7 +18,7 @@ let package = Package(
1818
.target(
1919
name: "ProgressHUD",
2020
dependencies: [],
21-
path: "ProgressHUD/Sources",
21+
path: "SwiftUI/Sources",
2222
resources: [
2323
.process("PrivacyInfo.xcprivacy"),
2424
]

README.md

Lines changed: 63 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## Let's Build Together! ✨
2+
3+
I'd be happy to work with you! 🚀 Whether you need help integrating ProgressHUD, have questions, or want to collaborate on a project, feel free to [reach out](https://relatedcode.com/#contact-form).
4+
15
## WHAT'S NEW
26

37
For detailed changes, please refer to the [Change log](CHANGELOG.md).
@@ -6,11 +10,13 @@ For detailed changes, please refer to the [Change log](CHANGELOG.md).
610

711
**ProgressHUD** is a convenient and intuitive HUD tool designed specifically for iOS. It enables the seamless presentation of concise alerts or notifications to your app users in a simple and non-disruptive way.
812

13+
**Note:** This version (15.0.0+) is built with SwiftUI. If you need the UIKit version, please use version 14.1.4.
14+
915
## INSTALLATION
1016

1117
### Swift Package Manager
1218

13-
[Swift Package Manager](https://www.swift.org/documentation/package-manager) is a tool for managing Swift code distribution.
19+
[Swift Package Manager](https://docs.swift.org/swiftpm/documentation/packagemanagerdocs/) is a tool for managing Swift code distribution.
1420

1521
To add **ProgressHUD** as a dependency to your project, follow these steps:
1622

@@ -21,10 +27,30 @@ To add **ProgressHUD** as a dependency to your project, follow these steps:
2127

2228
### Manually
2329

24-
If you prefer not to use the dependency manager above, you can integrate **ProgressHUD** into your project manually. Simply copy all the `*.swift` files from the `ProgressHUD/Sources` folder into your Xcode project.
30+
If you prefer not to use the dependency manager above, you can integrate **ProgressHUD** into your project manually. Simply copy all the `*.swift` files from the `SwiftUI/Sources` folder into your Xcode project.
2531

2632
## QUICK START
2733

34+
### SwiftUI Setup
35+
36+
Add the `.progressHUD()` modifier to your root view:
37+
38+
```swift
39+
import SwiftUI
40+
41+
@main
42+
struct MyApp: App {
43+
var body: some Scene {
44+
WindowGroup {
45+
ContentView()
46+
.progressHUD()
47+
}
48+
}
49+
}
50+
```
51+
52+
### Usage Examples
53+
2854
```swift
2955
ProgressHUD.banner("Banner title", "Banner message to display.")
3056
```
@@ -81,6 +107,22 @@ ProgressHUD.symbol(name: "box.truck")
81107
ProgressHUD.symbol("Some text...", name: "sun.max")
82108
```
83109

110+
```swift
111+
ProgressHUD.success("Success message")
112+
```
113+
114+
```swift
115+
ProgressHUD.error("Error message")
116+
```
117+
118+
```swift
119+
ProgressHUD.added("Item added")
120+
```
121+
122+
```swift
123+
ProgressHUD.animate("Loading...", symbol: "star.fill")
124+
```
125+
84126
```swift
85127
ProgressHUD.dismiss()
86128
```
@@ -91,7 +133,7 @@ ProgressHUD.remove()
91133

92134
## REQUIREMENTS
93135

94-
- iOS 13.0+
136+
- iOS 17.0+
95137
- Xcode 15.0+
96138

97139
## CUSTOMIZATION
@@ -103,23 +145,23 @@ ProgressHUD.animationType = .circleStrokeSpin
103145
```
104146

105147
```swift
106-
ProgressHUD.colorHUD = .systemGray
148+
ProgressHUD.colorHUD = .gray.opacity(0.1)
107149
```
108150

109151
```swift
110-
ProgressHUD.colorBackground = .lightGray
152+
ProgressHUD.colorBackground = .gray.opacity(0.3)
111153
```
112154

113155
```swift
114-
ProgressHUD.colorAnimation = .systemBlue
156+
ProgressHUD.colorAnimation = .blue
115157
```
116158

117159
```swift
118-
ProgressHUD.colorProgress = .systemBlue
160+
ProgressHUD.colorProgress = .blue
119161
```
120162

121163
```swift
122-
ProgressHUD.colorStatus = .label
164+
ProgressHUD.colorStatus = .primary
123165
```
124166

125167
```swift
@@ -128,12 +170,22 @@ ProgressHUD.marginSize = 50
128170
```
129171

130172
```swift
131-
ProgressHUD.fontStatus = .boldSystemFont(ofSize: 24)
173+
ProgressHUD.fontStatus = .system(size: 24, weight: .bold)
174+
```
175+
176+
```swift
177+
ProgressHUD.imageSuccess = Image("success")
178+
ProgressHUD.imageError = Image("error")
132179
```
133180

181+
Banner customization:
182+
134183
```swift
135-
ProgressHUD.imageSuccess = UIImage(named: "success.png")
136-
ProgressHUD.imageError = UIImage(named: "error.png")
184+
ProgressHUD.colorBanner = .blue.opacity(0.1)
185+
ProgressHUD.colorBannerTitle = .primary
186+
ProgressHUD.colorBannerMessage = .secondary
187+
ProgressHUD.fontBannerTitle = .system(size: 16, weight: .semibold)
188+
ProgressHUD.fontBannerMessage = .system(size: 14)
137189
```
138190

139191
A comprehensive list of the predefined enums:
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//
2+
// Copyright (c) 2025 Related Code - https://relatedcode.com
3+
//
4+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
5+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
6+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
7+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
8+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
9+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
10+
// THE SOFTWARE.
11+
12+
import SwiftUI
13+
14+
// MARK: - ActivityIndicatorView
15+
struct ActivityIndicatorView: View {
16+
17+
// MARK: - Properties
18+
@State private var hud = ProgressHUD.shared
19+
20+
// MARK: - Body
21+
var body: some View {
22+
ProgressView()
23+
.controlSize(.large)
24+
.scaleEffect(1.35)
25+
.tint(hud.colorAnimation)
26+
}
27+
}
28+
29+
#Preview {
30+
ActivityIndicatorView()
31+
}
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
//
2+
// Copyright (c) 2025 Related Code - https://relatedcode.com
3+
//
4+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
5+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
6+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
7+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
8+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
9+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
10+
// THE SOFTWARE.
11+
12+
import SwiftUI
13+
14+
// MARK: - BallVerticalBounceView
15+
struct BallVerticalBounceView: View {
16+
17+
// MARK: - Properties
18+
@State private var hud = ProgressHUD.shared
19+
20+
// MARK: - Body
21+
var body: some View {
22+
GeometryReader { geometry in
23+
let size = geometry.size
24+
let width = size.width
25+
let height = size.height
26+
27+
let ballRadius = width * 0.12
28+
let lineWidth = width * 0.96
29+
let lineY = height * 0.75
30+
let topY = height * 0.15
31+
32+
let fallDistance = (lineY - ballRadius) - topY
33+
let maxBend = height * 0.2
34+
35+
let animationDuration: TimeInterval = 0.9
36+
37+
KeyframeAnimator(initialValue: AnimationPhase(t: 0), repeating: true) { phase in
38+
let t = phase.t
39+
let (yOffset, bend) = calculatePhysics(t: t, maxFall: fallDistance, maxBend: maxBend)
40+
41+
let rubberHeight = maxBend * 1.5
42+
43+
ZStack {
44+
RubberBand(bend: bend)
45+
.stroke(hud.colorAnimation, style: StrokeStyle(lineWidth: width * 0.08, lineCap: .round))
46+
.frame(width: lineWidth, height: rubberHeight)
47+
.position(x: width / 2, y: lineY + (rubberHeight / 2))
48+
49+
Circle()
50+
.fill(hud.colorAnimation)
51+
.frame(width: ballRadius * 2, height: ballRadius * 2)
52+
.position(
53+
x: width / 2,
54+
y: topY + yOffset
55+
)
56+
}
57+
} keyframes: { _ in
58+
KeyframeTrack(\.t) {
59+
LinearKeyframe(1.0, duration: animationDuration)
60+
}
61+
}
62+
}
63+
}
64+
65+
// MARK: - Private Methods
66+
private func calculatePhysics(t: Double, maxFall: CGFloat, maxBend: CGFloat) -> (CGFloat, CGFloat) {
67+
let fallEnd = 0.40
68+
let bendEnd = 0.60
69+
70+
var yOffset: CGFloat = 0
71+
var currentBend: CGFloat = 0
72+
73+
if t < fallEnd {
74+
let nt = t / fallEnd
75+
let progress = nt * nt
76+
yOffset = maxFall * CGFloat(progress)
77+
currentBend = 0
78+
79+
} else if t < bendEnd {
80+
let nt = (t - fallEnd) / (bendEnd - fallEnd)
81+
82+
let bendProgress = sin(nt * .pi)
83+
currentBend = maxBend * CGFloat(bendProgress)
84+
85+
yOffset = maxFall + currentBend
86+
87+
} else {
88+
let nt = (t - bendEnd) / (1.0 - bendEnd)
89+
90+
let risingT = 1.0 - nt
91+
let progress = risingT * risingT
92+
93+
yOffset = maxFall * CGFloat(progress)
94+
currentBend = 0
95+
}
96+
97+
return (yOffset, currentBend)
98+
}
99+
}
100+
101+
private struct AnimationPhase {
102+
var t: Double
103+
}
104+
105+
private struct RubberBand: Shape {
106+
var bend: CGFloat
107+
108+
var animatableData: CGFloat {
109+
get { bend }
110+
set { bend = newValue }
111+
}
112+
113+
func path(in rect: CGRect) -> Path {
114+
var path = Path()
115+
let start = CGPoint(x: 0, y: 0)
116+
let end = CGPoint(x: rect.width, y: 0)
117+
118+
let control = CGPoint(x: rect.width / 2, y: bend * 2)
119+
120+
path.move(to: start)
121+
path.addQuadCurve(to: end, control: control)
122+
123+
return path
124+
}
125+
}
126+
127+
#Preview {
128+
BallVerticalBounceView()
129+
.frame(width: 70, height: 70)
130+
}

0 commit comments

Comments
 (0)