From ba0ada422f3f50e5b1f24274e3479f103f1c3f52 Mon Sep 17 00:00:00 2001 From: Jalil Date: Sat, 31 Aug 2024 15:53:55 -0300 Subject: [PATCH 1/2] Update ConfettiSwiftUI.swift --- Sources/ConfettiSwiftUI.swift | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/Sources/ConfettiSwiftUI.swift b/Sources/ConfettiSwiftUI.swift index 0a27ef7..56ecaad 100644 --- a/Sources/ConfettiSwiftUI.swift +++ b/Sources/ConfettiSwiftUI.swift @@ -72,6 +72,8 @@ public struct ConfettiCannon: View { /// - radius: explosion radius /// - repetitions: number of repetitions of the explosion /// - repetitionInterval: duration between the repetitions + /// - hapticFeedback: play haptic feedback on explosion + public init(counter:Binding, num:Int = 20, confettis:[ConfettiType] = ConfettiType.allCases, @@ -84,7 +86,8 @@ public struct ConfettiCannon: View { closingAngle:Angle = .degrees(120), radius:CGFloat = 300, repetitions:Int = 0, - repetitionInterval:Double = 1.0 + repetitionInterval:Double = 1.0, + hapticFeedback:Bool = true ) { self._counter = counter var shapes = [AnyView]() @@ -114,7 +117,8 @@ public struct ConfettiCannon: View { closingAngle: closingAngle, radius: radius, repetitions: repetitions, - repetitionInterval: repetitionInterval + repetitionInterval: repetitionInterval, + hapticFeedback: hapticFeedback )) } @@ -138,6 +142,11 @@ public struct ConfettiCannon: View { if(value > 0 && value < animate.count){ animate[value-1].toggle() } + + if confettiConfig.hapticFeedback { + let impactFeedback = UIImpactFeedbackGenerator(style: .heavy) + impactFeedback.impactOccurred() + } } } } @@ -274,7 +283,7 @@ struct ConfettiAnimationView: View { } class ConfettiConfig: ObservableObject { - internal init(num: Int, shapes: [AnyView], colors: [Color], confettiSize: CGFloat, rainHeight: CGFloat, fadesOut: Bool, opacity: Double, openingAngle:Angle, closingAngle:Angle, radius:CGFloat, repetitions:Int, repetitionInterval:Double) { + internal init(num: Int, shapes: [AnyView], colors: [Color], confettiSize: CGFloat, rainHeight: CGFloat, fadesOut: Bool, opacity: Double, openingAngle:Angle, closingAngle:Angle, radius:CGFloat, repetitions:Int, repetitionInterval:Double, hapticFeedback:Bool) { self.num = num self.shapes = shapes self.colors = colors @@ -289,6 +298,7 @@ class ConfettiConfig: ObservableObject { self.repetitionInterval = repetitionInterval self.explosionAnimationDuration = Double(radius / 1300) self.rainAnimationDuration = Double((rainHeight + radius) / 200) + self.hapticFeedback = hapticFeedback } @Published var num:Int @@ -305,6 +315,7 @@ class ConfettiConfig: ObservableObject { @Published var repetitionInterval:Double @Published var explosionAnimationDuration:Double @Published var rainAnimationDuration:Double + @Published var hapticFeedback:Bool var animationDuration:Double{ From 6786e7eba5a75324b0aaf7ff05fef7c3ecba5835 Mon Sep 17 00:00:00 2001 From: Jalil Date: Sat, 31 Aug 2024 16:03:57 -0300 Subject: [PATCH 2/2] Add generic trigger --- Sources/ConfettiSwiftUI.swift | 13 +++++-------- Sources/View+ConfettiCannon.swift | 10 +++++----- .../ConfettiSwiftUITests/ConfettiSwiftUITests.swift | 8 ++++---- 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/Sources/ConfettiSwiftUI.swift b/Sources/ConfettiSwiftUI.swift index 56ecaad..b50208c 100644 --- a/Sources/ConfettiSwiftUI.swift +++ b/Sources/ConfettiSwiftUI.swift @@ -49,8 +49,8 @@ public enum ConfettiType:CaseIterable, Hashable { } @available(iOS 14.0, macOS 11.0, watchOS 7, tvOS 14.0, *) -public struct ConfettiCannon: View { - @Binding var counter:Int +public struct ConfettiCannon: View { + @Binding var trigger: T @StateObject private var confettiConfig:ConfettiConfig @State var animate:[Bool] = [] @@ -74,7 +74,7 @@ public struct ConfettiCannon: View { /// - repetitionInterval: duration between the repetitions /// - hapticFeedback: play haptic feedback on explosion - public init(counter:Binding, + public init(trigger:Binding, num:Int = 20, confettis:[ConfettiType] = ConfettiType.allCases, colors:[Color] = [.blue, .red, .green, .yellow, .pink, .purple, .orange], @@ -89,7 +89,7 @@ public struct ConfettiCannon: View { repetitionInterval:Double = 1.0, hapticFeedback:Bool = true ) { - self._counter = counter + self._trigger = trigger var shapes = [AnyView]() for confetti in confettis{ @@ -134,14 +134,11 @@ public struct ConfettiCannon: View { .onAppear(){ firstAppear = true } - .onChange(of: counter){value in + .onChange(of: trigger){value in if firstAppear{ for i in 0...confettiConfig.repetitions{ DispatchQueue.main.asyncAfter(deadline: .now() + confettiConfig.repetitionInterval * Double(i)) { animate.append(false) - if(value > 0 && value < animate.count){ - animate[value-1].toggle() - } if confettiConfig.hapticFeedback { let impactFeedback = UIImpactFeedbackGenerator(style: .heavy) diff --git a/Sources/View+ConfettiCannon.swift b/Sources/View+ConfettiCannon.swift index 9dcfa0f..76c92da 100644 --- a/Sources/View+ConfettiCannon.swift +++ b/Sources/View+ConfettiCannon.swift @@ -9,7 +9,7 @@ import SwiftUI public extension View { - /// renders configurable confetti animaiton + /// renders configurable confetti animation /// /// - Usage: /// @@ -43,8 +43,8 @@ public extension View { /// - repetitions: number of repetitions of the explosion /// - repetitionInterval: duration between the repetitions /// - @ViewBuilder func confettiCannon( - counter: Binding, + @ViewBuilder func confettiCannon( + trigger: Binding, num: Int = 20, confettis: [ConfettiType] = ConfettiType.allCases, colors: [Color] = [.blue, .red, .green, .yellow, .pink, .purple, .orange], @@ -57,11 +57,11 @@ public extension View { radius: CGFloat = 300, repetitions: Int = 0, repetitionInterval: Double = 1.0 - ) -> some View { + ) -> some View where T: Equatable { ZStack { self ConfettiCannon( - counter: counter, + trigger: trigger, num: num, confettis: confettis, colors: colors, diff --git a/Tests/ConfettiSwiftUITests/ConfettiSwiftUITests.swift b/Tests/ConfettiSwiftUITests/ConfettiSwiftUITests.swift index 6bf1e97..cc4c80b 100644 --- a/Tests/ConfettiSwiftUITests/ConfettiSwiftUITests.swift +++ b/Tests/ConfettiSwiftUITests/ConfettiSwiftUITests.swift @@ -4,12 +4,12 @@ import XCTest import SwiftUI final class ConfettiSwiftUITests: XCTestCase { - @State var counter = 0 - + @State var trigger = false + func testExample() { - ConfettiSwiftUI.ConfettiCannon(counter:$counter) + ConfettiSwiftUI.ConfettiCannon(trigger: $trigger) Button("Animation"){ - self.counter += 1 + self.trigger.toggle() } }