11
22import CoreHaptics
3- import SwiftUI
43import Foundation
4+ import SwiftUI
55#if canImport(UIKit)
6- import UIKit
6+ import UIKit
77#endif
88
9- @MainActor
9+ @MainActor
1010@Observable
1111public final class FlareHapticManager {
12-
13- public static let shared = FlareHapticManager ( )
14-
12+ public static let shared = FlareHapticManager ( )
1513
16- public enum ImpactStyle : String , CaseIterable {
17- case light = " light "
18- case medium = " medium "
19- case heavy = " heavy "
20- case soft = " soft "
21- case rigid = " rigid "
14+ public enum ImpactStyle : String , CaseIterable {
15+ case light
16+ case medium
17+ case heavy
18+ case soft
19+ case rigid
2220
2321 public var displayName : String {
2422 switch self {
25- case . light: return " Light "
26- case . medium: return " Medium "
27- case . heavy: return " Heavy "
28- case . soft: return " Soft "
29- case . rigid: return " Rigid "
23+ case . light: " Light "
24+ case . medium: " Medium "
25+ case . heavy: " Heavy "
26+ case . soft: " Soft "
27+ case . rigid: " Rigid "
3028 }
3129 }
3230 }
3331
34- public enum NotificationStyle : String , CaseIterable {
35- case success = " success "
36- case warning = " warning "
37- case error = " error "
32+ public enum NotificationStyle : String , CaseIterable {
33+ case success
34+ case warning
35+ case error
3836
3937 public var displayName : String {
4038 switch self {
41- case . success: return " Success "
42- case . warning: return " Warning "
43- case . error: return " Error "
39+ case . success: " Success "
40+ case . warning: " Warning "
41+ case . error: " Error "
4442 }
4543 }
4644 }
4745
48- public enum HapticType {
46+ public enum HapticType {
4947 case impact( ImpactStyle )
5048 case selection
5149 case notification( NotificationStyle )
@@ -63,170 +61,159 @@ public final class FlareHapticManager {
6361 public static let warning = HapticType . notification ( . warning)
6462 public static let error = HapticType . notification ( . error)
6563 }
66-
6764
6865 #if !os(visionOS) && canImport(UIKit)
69- private var impactGenerators : [ UIImpactFeedbackGenerator . FeedbackStyle : UIImpactFeedbackGenerator ] = [ : ]
70- private let selectionGenerator = UISelectionFeedbackGenerator ( )
71- private let notificationGenerator = UINotificationFeedbackGenerator ( )
66+ private var impactGenerators : [ UIImpactFeedbackGenerator . FeedbackStyle : UIImpactFeedbackGenerator ] = [ : ]
67+ private let selectionGenerator = UISelectionFeedbackGenerator ( )
68+ private let notificationGenerator = UINotificationFeedbackGenerator ( )
7269 #endif
7370
74- private var appSettings : AppSettings {
75- return AppSettings ( )
71+ private var appSettings : AppSettings {
72+ AppSettings ( )
7673 }
77-
7874
7975 private init ( ) {
8076 #if !os(visionOS) && canImport(UIKit)
81- selectionGenerator. prepare ( )
82- notificationGenerator. prepare ( )
77+ selectionGenerator. prepare ( )
78+ notificationGenerator. prepare ( )
8379 #endif
8480 }
85-
8681
87-
88- public var supportsHaptics : Bool {
82+ public var supportsHaptics : Bool {
8983 #if os(visionOS)
90- return false
84+ return false
9185 #elseif canImport(UIKit)
92- return CHHapticEngine . capabilitiesForHardware ( ) . supportsHaptics
86+ return CHHapticEngine . capabilitiesForHardware ( ) . supportsHaptics
9387 #else
94- return false
88+ return false
9589 #endif
9690 }
9791
98- public func prepare( _ type: HapticType ) {
92+ public func prepare( _ type: HapticType ) {
9993 #if !os(visionOS) && canImport(UIKit)
100- guard supportsHaptics else { return }
101-
102- switch type {
103- case . impact( let style) :
104- impactGenerator ( for: uiImpactStyle ( from: style) ) . prepare ( )
105- case . selection, . tabSelection:
106- selectionGenerator. prepare ( )
107- case . notification, . buttonPress:
108- notificationGenerator. prepare ( )
109- case . dataRefresh:
110- impactGenerator ( for: . heavy) . prepare ( )
111- }
94+ guard supportsHaptics else { return }
95+
96+ switch type {
97+ case let . impact( style) :
98+ impactGenerator ( for: uiImpactStyle ( from: style) ) . prepare ( )
99+ case . selection, . tabSelection:
100+ selectionGenerator. prepare ( )
101+ case . notification, . buttonPress:
102+ notificationGenerator. prepare ( )
103+ case . dataRefresh:
104+ impactGenerator ( for: . heavy) . prepare ( )
105+ }
112106 #endif
113107 }
114-
115- public func generate( _ type: HapticType ) {
108+
109+ public func generate( _ type: HapticType ) {
116110 #if !os(visionOS) && canImport(UIKit)
117- guard supportsHaptics else { return }
111+ guard supportsHaptics else { return }
118112
119-
120- guard shouldGenerateHaptic ( for: type) else { return }
113+ guard shouldGenerateHaptic ( for: type) else { return }
121114
122- switch type {
123- case . impact( let style) :
124- impactGenerator ( for: uiImpactStyle ( from: style) ) . impactOccurred ( )
115+ switch type {
116+ case let . impact( style) :
117+ impactGenerator ( for: uiImpactStyle ( from: style) ) . impactOccurred ( )
125118
126- case . selection:
127- selectionGenerator. selectionChanged ( )
119+ case . selection:
120+ selectionGenerator. selectionChanged ( )
128121
129- case . notification( let style) :
130- notificationGenerator. notificationOccurred ( uiNotificationStyle ( from: style) )
122+ case let . notification( style) :
123+ notificationGenerator. notificationOccurred ( uiNotificationStyle ( from: style) )
131124
132- case . buttonPress:
133- let userIntensity = getUserIntensityStyle ( )
134- impactGenerator ( for: userIntensity) . impactOccurred ( )
125+ case . buttonPress:
126+ let userIntensity = getUserIntensityStyle ( )
127+ impactGenerator ( for: userIntensity) . impactOccurred ( )
135128
136- case . tabSelection:
137- selectionGenerator. selectionChanged ( )
129+ case . tabSelection:
130+ selectionGenerator. selectionChanged ( )
138131
139- case . dataRefresh( let intensity) :
140- let userIntensity = getUserIntensityStyle ( )
141- impactGenerator ( for: userIntensity) . impactOccurred ( intensity: intensity)
142- }
132+ case let . dataRefresh( intensity) :
133+ let userIntensity = getUserIntensityStyle ( )
134+ impactGenerator ( for: userIntensity) . impactOccurred ( intensity: intensity)
135+ }
143136 #endif
144137 }
145-
146138
147- public func buttonPress( ) {
139+ public func buttonPress( ) {
148140 generate ( . buttonPress)
149141 }
150142
151- public func tabSelection( ) {
143+ public func tabSelection( ) {
152144 generate ( . tabSelection)
153145 }
154146
155- public func selection( ) {
147+ public func selection( ) {
156148 generate ( . selection)
157149 }
158150
159- public func success( ) {
151+ public func success( ) {
160152 generate ( . success)
161153 }
162154
163- public func warning( ) {
155+ public func warning( ) {
164156 generate ( . warning)
165157 }
166158
167- public func error( ) {
159+ public func error( ) {
168160 generate ( . error)
169161 }
170162
171- public func dataRefresh( intensity: CGFloat = 1.0 ) {
163+ public func dataRefresh( intensity: CGFloat = 1.0 ) {
172164 generate ( . dataRefresh( intensity: intensity) )
173165 }
174166}
175167
176-
177168extension FlareHapticManager {
178-
179169 #if !os(visionOS) && canImport(UIKit)
180- private func impactGenerator( for style: UIImpactFeedbackGenerator . FeedbackStyle ) -> UIImpactFeedbackGenerator {
181- if let generator = impactGenerators [ style] {
182- return generator
183- } else {
184- let generator = UIImpactFeedbackGenerator ( style: style)
185- impactGenerators [ style] = generator
186- return generator
170+ private func impactGenerator( for style: UIImpactFeedbackGenerator . FeedbackStyle ) -> UIImpactFeedbackGenerator {
171+ if let generator = impactGenerators [ style] {
172+ return generator
173+ } else {
174+ let generator = UIImpactFeedbackGenerator ( style: style)
175+ impactGenerators [ style] = generator
176+ return generator
177+ }
187178 }
188- }
189179
190-
191- private func uiImpactStyle ( from style : ImpactStyle ) -> UIImpactFeedbackGenerator . FeedbackStyle {
192- switch style {
193- case . light : return . light
194- case . medium : return . medium
195- case . heavy : return . heavy
196- case . soft : return . soft
197- case . rigid : return . rigid
180+ private func uiImpactStyle ( from style : ImpactStyle ) -> UIImpactFeedbackGenerator . FeedbackStyle {
181+ switch style {
182+ case . light : . light
183+ case . medium : . medium
184+ case . heavy : . heavy
185+ case . soft : . soft
186+ case . rigid : . rigid
187+ }
198188 }
199- }
200189
201- private func uiNotificationStyle( from style: NotificationStyle ) -> UINotificationFeedbackGenerator . FeedbackType {
202- switch style {
203- case . success: return . success
204- case . warning: return . warning
205- case . error: return . error
190+ private func uiNotificationStyle( from style: NotificationStyle ) -> UINotificationFeedbackGenerator . FeedbackType {
191+ switch style {
192+ case . success: . success
193+ case . warning: . warning
194+ case . error: . error
195+ }
206196 }
207- }
208197 #endif
209198
210- private func shouldGenerateHaptic( for type : HapticType ) -> Bool {
211- return appSettings. appearanceSettings. hapticFeedback. isEnabled
199+ private func shouldGenerateHaptic( for _ : HapticType ) -> Bool {
200+ appSettings. appearanceSettings. hapticFeedback. isEnabled
212201 }
213202
214203 #if !os(visionOS) && canImport(UIKit)
215- private func getUserIntensityStyle( ) -> UIImpactFeedbackGenerator . FeedbackStyle {
216- let userIntensity = appSettings. appearanceSettings. hapticFeedback. intensity
217- switch userIntensity {
218- case . light: return . light
219- case . medium: return . medium
220- case . heavy: return . heavy
204+ private func getUserIntensityStyle( ) -> UIImpactFeedbackGenerator . FeedbackStyle {
205+ let userIntensity = appSettings. appearanceSettings. hapticFeedback. intensity
206+ switch userIntensity {
207+ case . light: return . light
208+ case . medium: return . medium
209+ case . heavy: return . heavy
210+ }
221211 }
222- }
223212 #endif
224213}
225214
226-
227- extension FlareHapticManager {
228-
229- public struct HapticFeedbackModifier : ViewModifier {
215+ public extension FlareHapticManager {
216+ struct HapticFeedbackModifier : ViewModifier {
230217 let hapticType : HapticType
231218
232219 public func body( content: Content ) -> some View {
@@ -238,17 +225,12 @@ extension FlareHapticManager {
238225 }
239226}
240227
241-
242- extension View {
243-
244-
245- public func hapticFeedback( _ type: FlareHapticManager . HapticType ) -> some View {
228+ public extension View {
229+ func hapticFeedback( _ type: FlareHapticManager . HapticType ) -> some View {
246230 modifier ( FlareHapticManager . HapticFeedbackModifier ( hapticType: type) )
247231 }
248232
249-
250- public func hapticButtonPress( ) -> some View {
233+ func hapticButtonPress( ) -> some View {
251234 hapticFeedback ( . buttonPress)
252235 }
253236}
254-
0 commit comments