Skip to content

Commit d6afb89

Browse files
Merge pull request #14 from SimformSolutionsPvtLtd/develop
Develop
2 parents da6b5dc + 124ceb5 commit d6afb89

File tree

15 files changed

+601
-6
lines changed

15 files changed

+601
-6
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ playground.xcworkspace
5454
# you should judge for yourself, the pros and cons are mentioned at:
5555
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
5656
#
57-
# Pods/
57+
Pods/
5858
#
5959
# Add this line if you want to avoid checking in source code from the Xcode workspace
6060
# *.xcworkspace

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ SwiftUI animation library to bring your app to life. ✨
2828

2929
[**Code Link**](SSSwiftUIAnimations/Sources/ArrowLeftRightAnimation)
3030

31+
### Water Effect ProgressView 🌊
32+
![LRArrowView](SSSwiftUIAnimations/GIFs/WaterProgressView.gif)
33+
34+
[**Code Link**](SSSwiftUIAnimations/Sources/WaterProgressAnimation)
35+
3136
## Found these animations useful? :heart:
3237

3338
Support it by joining [stargazers] :star: for this repository.

SSSwiftUIAnimations.podspec

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
Pod::Spec.new do |s|
2+
s.name = 'SSSwiftUIAnimations'
3+
s.version = '1.0.0'
4+
s.summary = 'With this library, you can make your app more fun and engaging by adding smooth and eye-catching animations to your app.'
5+
s.readme = 'https://github.com/SimformSolutionsPvtLtd/SS-iOS-Animations/blob/master/README.md'
6+
7+
s.description = <<-DESC
8+
SS-iOS-Animations: Turn ordinary user interfaces into extraordinary experiences! With this library, you can make your app more fun and engaging by adding smooth and eye-catching animations to your app. Whether you're new to SwiftUI or a pro, our easy-to-use animations make it simple to add that extra wow factor to your app. Spice up your app with cool transitions, fun effects, and interactive touches, all thanks to SS-iOS-Animations. Try it out and take your SwiftUI apps to the next level!
9+
DESC
10+
11+
s.homepage = 'https://github.com/SimformSolutionsPvtLtd/SS-iOS-Animations.git'
12+
s.license = { :type => 'MIT', :file => 'LICENSE' }
13+
s.author = { 'Rahul Yadav' => '[email protected]' }
14+
s.source = { :git => 'https://github.com/SimformSolutionsPvtLtd/SS-iOS-Animations.git', :tag => s.version.to_s }
15+
16+
s.ios.deployment_target = '15.0'
17+
18+
s.source_files = 'SSSwiftUIAnimations/Sources/**/*'
19+
20+
s.subspec 'WaterProgressAnimation' do |waterprogressanimation|
21+
waterprogressanimation.source_files = 'SSSwiftUIAnimations/Sources/WaterProgressAnimation/**/*', 'SSSwiftUIAnimations/Sources/Utils/**/*'
22+
end
23+
24+
s.subspec 'ProgressAnimation' do |progressanimation|
25+
progressanimation.source_files = 'SSSwiftUIAnimations/Sources/ProgressAnimation/**/*',
26+
'SSSwiftUIAnimations/Sources/Utils/**/*'
27+
end
28+
29+
s.subspec 'ArrowLeftRightAnimation' do |arrowleftrightanimation|
30+
arrowleftrightanimation.source_files = 'SSSwiftUIAnimations/Sources/ArrowLeftRightAnimation/**/*', 'SSSwiftUIAnimations/Sources/Utils/**/*'
31+
end
32+
end

SSSwiftUIAnimations.xcodeproj/project.pbxproj

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
2BC2D8FA28CF3A7000CAB302 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2BC2D8F928CF3A7000CAB302 /* Preview Assets.xcassets */; };
1414
4636F36E291E1BD600C8DB5B /* LeftArrow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4636F36D291E1BD600C8DB5B /* LeftArrow.swift */; };
1515
469963A5290FCE3600DC01AD /* SSLRArrowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 469963A4290FCE3600DC01AD /* SSLRArrowView.swift */; };
16+
8FE1727C2CAA8BF100F8AB45 /* ViewExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FE1727A2CAA8BF100F8AB45 /* ViewExtension.swift */; };
1617
B10677FE2BE8D0D400957B4E /* DownArrow.swift in Sources */ = {isa = PBXBuildFile; fileRef = B10677FD2BE8D0D400957B4E /* DownArrow.swift */; };
1718
B1098E7D2BD94ED900BC19DD /* WaveView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1098E7C2BD94ED900BC19DD /* WaveView.swift */; };
1819
B11B983A2BCE9C3F00D76016 /* CheckView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B11B98392BCE9C3F00D76016 /* CheckView.swift */; };
@@ -31,7 +32,15 @@
3132
B1DFCA512BF4FA3D00F01505 /* ProgressCircle.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1DFCA502BF4FA3D00F01505 /* ProgressCircle.swift */; };
3233
B1DFCA532BF4FC7900F01505 /* ArrowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1DFCA522BF4FC7900F01505 /* ArrowView.swift */; };
3334
B1EA09DE2C11A6B70024BC28 /* Banner.png in Resources */ = {isa = PBXBuildFile; fileRef = B1EA09DD2C11A6B70024BC28 /* Banner.png */; };
34-
B1FE861E2BFF6BC000FB111C /* ViewExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1FE861D2BFF6BC000FB111C /* ViewExtension.swift */; };
35+
B717EC9D2C45488100555F90 /* CheckmarkView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B717EC9C2C45488100555F90 /* CheckmarkView.swift */; };
36+
B741A1442C4A6D610083399B /* WaterProgressView.gif in Resources */ = {isa = PBXBuildFile; fileRef = B741A1432C4A6D610083399B /* WaterProgressView.gif */; };
37+
B741D9A62C46448200ABFCB4 /* WaterProgressTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B741D9A52C46448200ABFCB4 /* WaterProgressTextView.swift */; };
38+
B780A9182C3D063500342512 /* WaterProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B780A9172C3D063500342512 /* WaterProgressView.swift */; };
39+
B780A91A2C3D0BCB00342512 /* WaterProgressViewStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = B780A9192C3D0BCB00342512 /* WaterProgressViewStyle.swift */; };
40+
B780A9242C3D7A7C00342512 /* WaterCircleOutlineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B780A9232C3D7A7C00342512 /* WaterCircleOutlineView.swift */; };
41+
B780A9262C3D806300342512 /* ExampleWaterProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B780A9252C3D806300342512 /* ExampleWaterProgressView.swift */; };
42+
B780A9282C3D851700342512 /* WaterCircleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B780A9272C3D851700342512 /* WaterCircleView.swift */; };
43+
B7ECD58D2C452D8100B6A703 /* BubbleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7ECD58C2C452D8100B6A703 /* BubbleView.swift */; };
3544
/* End PBXBuildFile section */
3645

3746
/* Begin PBXFileReference section */
@@ -42,6 +51,7 @@
4251
2BC2D8F928CF3A7000CAB302 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
4352
4636F36D291E1BD600C8DB5B /* LeftArrow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LeftArrow.swift; sourceTree = "<group>"; };
4453
469963A4290FCE3600DC01AD /* SSLRArrowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SSLRArrowView.swift; sourceTree = "<group>"; };
54+
8FE1727A2CAA8BF100F8AB45 /* ViewExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewExtension.swift; sourceTree = "<group>"; };
4555
B10677FD2BE8D0D400957B4E /* DownArrow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownArrow.swift; sourceTree = "<group>"; };
4656
B1098E7C2BD94ED900BC19DD /* WaveView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaveView.swift; sourceTree = "<group>"; };
4757
B11B98392BCE9C3F00D76016 /* CheckView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckView.swift; sourceTree = "<group>"; };
@@ -60,7 +70,15 @@
6070
B1DFCA502BF4FA3D00F01505 /* ProgressCircle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressCircle.swift; sourceTree = "<group>"; };
6171
B1DFCA522BF4FC7900F01505 /* ArrowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArrowView.swift; sourceTree = "<group>"; };
6272
B1EA09DD2C11A6B70024BC28 /* Banner.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Banner.png; sourceTree = "<group>"; };
63-
B1FE861D2BFF6BC000FB111C /* ViewExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewExtension.swift; sourceTree = "<group>"; };
73+
B717EC9C2C45488100555F90 /* CheckmarkView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckmarkView.swift; sourceTree = "<group>"; };
74+
B741A1432C4A6D610083399B /* WaterProgressView.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = WaterProgressView.gif; sourceTree = "<group>"; };
75+
B741D9A52C46448200ABFCB4 /* WaterProgressTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaterProgressTextView.swift; sourceTree = "<group>"; };
76+
B780A9172C3D063500342512 /* WaterProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaterProgressView.swift; sourceTree = "<group>"; };
77+
B780A9192C3D0BCB00342512 /* WaterProgressViewStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaterProgressViewStyle.swift; sourceTree = "<group>"; };
78+
B780A9232C3D7A7C00342512 /* WaterCircleOutlineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaterCircleOutlineView.swift; sourceTree = "<group>"; };
79+
B780A9252C3D806300342512 /* ExampleWaterProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExampleWaterProgressView.swift; sourceTree = "<group>"; };
80+
B780A9272C3D851700342512 /* WaterCircleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaterCircleView.swift; sourceTree = "<group>"; };
81+
B7ECD58C2C452D8100B6A703 /* BubbleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BubbleView.swift; sourceTree = "<group>"; };
6482
/* End PBXFileReference section */
6583

6684
/* Begin PBXFrameworksBuildPhase section */
@@ -125,10 +143,19 @@
125143
path = ArrowLeftRightAnimation;
126144
sourceTree = "<group>";
127145
};
146+
8FE1727B2CAA8BF100F8AB45 /* Utils */ = {
147+
isa = PBXGroup;
148+
children = (
149+
8FE1727A2CAA8BF100F8AB45 /* ViewExtension.swift */,
150+
);
151+
path = Utils;
152+
sourceTree = "<group>";
153+
};
128154
B1343F702C06064B009ACE90 /* GIFs */ = {
129155
isa = PBXGroup;
130156
children = (
131157
B1343F712C060680009ACE90 /* ProgressView.gif */,
158+
B741A1432C4A6D610083399B /* WaterProgressView.gif */,
132159
B1343F732C060686009ACE90 /* LRArrowView.gif */,
133160
);
134161
path = GIFs;
@@ -144,7 +171,6 @@
144171
B1098E7C2BD94ED900BC19DD /* WaveView.swift */,
145172
B11B98392BCE9C3F00D76016 /* CheckView.swift */,
146173
B177713E2BF39A60001723EC /* ModelClass.swift */,
147-
B1FE861D2BFF6BC000FB111C /* ViewExtension.swift */,
148174
);
149175
path = ProgressAnimation;
150176
sourceTree = "<group>";
@@ -154,6 +180,7 @@
154180
children = (
155181
B19E0B652BF7498700E65974 /* ExampleProgressView.swift */,
156182
B153FD142BFB7A7900AEFE83 /* ExampleLRArrowView.swift */,
183+
B780A9252C3D806300342512 /* ExampleWaterProgressView.swift */,
157184
B1F9ED332BFCD85000189871 /* ExamplesList */,
158185
);
159186
path = Examples;
@@ -162,6 +189,8 @@
162189
B1DE99D72C060E1A006995FB /* Sources */ = {
163190
isa = PBXGroup;
164191
children = (
192+
8FE1727B2CAA8BF100F8AB45 /* Utils */,
193+
B780A9162C3D05CD00342512 /* WaterProgressAnimation */,
165194
B14AB36A2BC40286004B09C4 /* ProgressAnimation */,
166195
469963A3290FCE1900DC01AD /* ArrowLeftRightAnimation */,
167196
);
@@ -186,6 +215,20 @@
186215
path = ExamplesList;
187216
sourceTree = "<group>";
188217
};
218+
B780A9162C3D05CD00342512 /* WaterProgressAnimation */ = {
219+
isa = PBXGroup;
220+
children = (
221+
B780A9172C3D063500342512 /* WaterProgressView.swift */,
222+
B780A9192C3D0BCB00342512 /* WaterProgressViewStyle.swift */,
223+
B780A9232C3D7A7C00342512 /* WaterCircleOutlineView.swift */,
224+
B780A9272C3D851700342512 /* WaterCircleView.swift */,
225+
B7ECD58C2C452D8100B6A703 /* BubbleView.swift */,
226+
B717EC9C2C45488100555F90 /* CheckmarkView.swift */,
227+
B741D9A52C46448200ABFCB4 /* WaterProgressTextView.swift */,
228+
);
229+
path = WaterProgressAnimation;
230+
sourceTree = "<group>";
231+
};
189232
/* End PBXGroup section */
190233

191234
/* Begin PBXNativeTarget section */
@@ -245,6 +288,7 @@
245288
buildActionMask = 2147483647;
246289
files = (
247290
2BC2D8FA28CF3A7000CAB302 /* Preview Assets.xcassets in Resources */,
291+
B741A1442C4A6D610083399B /* WaterProgressView.gif in Resources */,
248292
B1343F722C060680009ACE90 /* ProgressView.gif in Resources */,
249293
B1EA09DE2C11A6B70024BC28 /* Banner.png in Resources */,
250294
2BC2D8F728CF3A7000CAB302 /* Assets.xcassets in Resources */,
@@ -273,13 +317,21 @@
273317
B15FD7992C04785700752CEA /* CustomToolBar.swift in Sources */,
274318
469963A5290FCE3600DC01AD /* SSLRArrowView.swift in Sources */,
275319
B153FD0C2BFB3C1800AEFE83 /* LRArrowAnimStyle.swift in Sources */,
320+
B717EC9D2C45488100555F90 /* CheckmarkView.swift in Sources */,
321+
B780A9282C3D851700342512 /* WaterCircleView.swift in Sources */,
276322
B153FD132BFB71F500AEFE83 /* FilledStrokeCircle.swift in Sources */,
277323
2BC2D8F328CF3A6F00CAB302 /* SSSwiftUIAnimationsApp.swift in Sources */,
324+
B741D9A62C46448200ABFCB4 /* WaterProgressTextView.swift in Sources */,
325+
B780A9242C3D7A7C00342512 /* WaterCircleOutlineView.swift in Sources */,
278326
B1DFCA532BF4FC7900F01505 /* ArrowView.swift in Sources */,
327+
B780A9182C3D063500342512 /* WaterProgressView.swift in Sources */,
279328
B11B983A2BCE9C3F00D76016 /* CheckView.swift in Sources */,
329+
B7ECD58D2C452D8100B6A703 /* BubbleView.swift in Sources */,
330+
8FE1727C2CAA8BF100F8AB45 /* ViewExtension.swift in Sources */,
331+
B780A9262C3D806300342512 /* ExampleWaterProgressView.swift in Sources */,
332+
B780A91A2C3D0BCB00342512 /* WaterProgressViewStyle.swift in Sources */,
280333
B1DFCA512BF4FA3D00F01505 /* ProgressCircle.swift in Sources */,
281334
B14AB36C2BC41B05004B09C4 /* ProgressView.swift in Sources */,
282-
B1FE861E2BFF6BC000FB111C /* ViewExtension.swift in Sources */,
283335
);
284336
runOnlyForDeploymentPostprocessing = 0;
285337
};
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//
2+
// ExampleWaterProgressView.swift
3+
// SSSwiftUIAnimations
4+
//
5+
// Created by Rahul Yadav on 09/07/24.
6+
//
7+
8+
import SwiftUI
9+
10+
struct ExampleWaterProgressView: View {
11+
12+
// MARK: - Variables
13+
@State private var progress: Double = 0.0
14+
15+
var body: some View {
16+
VStack {
17+
SSWaterProgressView(progress: $progress,
18+
showPercent: true,
19+
style: SSWaterProgressViewStyle(
20+
circleSize: 200,
21+
circleStrokeWidth: 10,
22+
progressFont: .system(size: 16, weight: .bold),
23+
progressTextColor: .black,
24+
emptyStrokeColor: .cyan.opacity(0.2),
25+
fillStrokeColor: .cyan,
26+
waterColor: .mint,
27+
showBubbles: true,
28+
bubbleColor: .white,
29+
checkMarkImg: "checkmark",
30+
checkMarkImgColor: .white
31+
),
32+
onProgressCompletion: { print("Progress Completed") })
33+
Spacer()
34+
.frame(height: 40)
35+
Slider(value: $progress) {
36+
Text("Slide to manage progress")
37+
}
38+
.frame(width: 150, alignment: .bottom)
39+
}
40+
.customToolbar(title: "Water ProgressView Example", fontSize: 17)
41+
}
42+
}
43+
44+
#Preview {
45+
ExampleWaterProgressView()
46+
}

SSSwiftUIAnimations/Examples/ExamplesList/ExampleListModel.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,5 @@ class ExampleListModel: Identifiable {
2121
}
2222

2323
// data for example row list
24-
static let exampleList = [ExampleListModel(rowTitle: "ProgressView", destinationView: AnyView(ExampleProgressView())), ExampleListModel(rowTitle: "Arrow Left Right View", destinationView: AnyView(ExampleLRArrowView()))]
24+
static let exampleList = [ExampleListModel(rowTitle: "ProgressView", destinationView: AnyView(ExampleProgressView())), ExampleListModel(rowTitle: "Arrow Left Right View", destinationView: AnyView(ExampleLRArrowView())), ExampleListModel(rowTitle: "Water Progress View", destinationView: AnyView(ExampleWaterProgressView()))]
2525
}
737 KB
Loading

SSSwiftUIAnimations/Sources/ProgressAnimation/ViewExtension.swift renamed to SSSwiftUIAnimations/Sources/Utils/ViewExtension.swift

File renamed without changes.
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
//
2+
// BubbleView.swift
3+
// SSSwiftUIAnimations
4+
//
5+
// Created by Rahul Yadav on 15/07/24.
6+
//
7+
8+
import SwiftUI
9+
10+
/// Create a view with Bubbles used in animation
11+
struct BubbleView: View {
12+
13+
// MARK: Variables
14+
15+
/// Used for styling the view
16+
@State var style: SSWaterProgressViewStyle = SSWaterProgressViewStyle()
17+
18+
/// Initial Bubble Scale
19+
@State private var scale : CGFloat = 1
20+
21+
var body: some View {
22+
if style.showBubbles {
23+
ZStack {
24+
// Number of bubbles
25+
ForEach (1...10, id:\.self) { _ in
26+
Circle()
27+
.foregroundColor(style.bubbleColor.opacity(Double.random(in: 0.15...0.25)))
28+
.scaleEffect(self.scale * .random(in: 0.5...1))
29+
.frame(width: .random(in: 1...25),
30+
height: CGFloat.random (in: 20...25),
31+
alignment: .center)
32+
.position(
33+
CGPoint(
34+
x: .random(in: style.circleSize/4...style.circleSize/1.3),
35+
y: .random (in: style.circleSize/5...style.circleSize/1.2)
36+
)
37+
)
38+
}
39+
}
40+
.task {
41+
withAnimation(
42+
.spring (dampingFraction: 0.5)
43+
.repeatForever()
44+
.speed(.random(in: 0.1...0.15))
45+
.delay(.random(in: 0.01...0.1))
46+
) {
47+
self.scale = 1.2 // default circle scale
48+
}
49+
}
50+
}
51+
}
52+
}
53+
54+
#Preview {
55+
BubbleView()
56+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//
2+
// CheckmarkView.swift
3+
// SSSwiftUIAnimations
4+
//
5+
// Created by Rahul Yadav on 15/07/24.
6+
//
7+
8+
import SwiftUI
9+
10+
struct CheckmarkView: View {
11+
12+
// MARK: Variables
13+
14+
/// Decide weather to make checkmark visible or not
15+
@State var displayCheckmark: Bool = false
16+
17+
/// Initial Zoom of Checkmark
18+
@State private var zoom = 0.1
19+
20+
/// Style for SSWaterProgress View
21+
var style: SSWaterProgressViewStyle
22+
23+
var body: some View {
24+
checkMarkImg
25+
}
26+
27+
private var checkMarkImg: some View {
28+
Image(systemName: style.checkMarkImg)
29+
.resizable()
30+
.frame(width: style.circleSize/3, height: style.circleSize/3)
31+
.opacity(displayCheckmark ? 1 : 0)
32+
.foregroundStyle(style.checkMarkImgColor)
33+
.scaleEffect(zoom, anchor: .center)
34+
.foregroundColor(.white)
35+
.animation(.spring(dampingFraction: 0.4), value: displayCheckmark)
36+
.onAppear() {
37+
displayCheckmark.toggle()
38+
zoom = 1.0
39+
}
40+
}
41+
}

0 commit comments

Comments
 (0)