import CoreHaptics import UIKit @MainActor public class HapticManager { public static let shared: HapticManager = .init() #if os(visionOS) public enum FeedbackType: Int { case success, warning, error } #endif public enum HapticType { case buttonPress case dataRefresh(intensity: CGFloat) #if os(visionOS) case notification(_ type: FeedbackType) #else case notification(_ type: UINotificationFeedbackGenerator.FeedbackType) #endif case tabSelection case timeline } #if !os(visionOS) private let selectionGenerator = UISelectionFeedbackGenerator() private let impactGenerator = UIImpactFeedbackGenerator(style: .heavy) private let notificationGenerator = UINotificationFeedbackGenerator() #endif private let userPreferences = UserPreferences.shared private init() { #if !os(visionOS) selectionGenerator.prepare() impactGenerator.prepare() #endif } @MainActor public func fireHaptic(_ type: HapticType) { #if !os(visionOS) guard supportsHaptics else { return } switch type { case .buttonPress: if userPreferences.hapticButtonPressEnabled { impactGenerator.impactOccurred() } case let .dataRefresh(intensity): if userPreferences.hapticTimelineEnabled { impactGenerator.impactOccurred(intensity: intensity) } case let .notification(type): if userPreferences.hapticButtonPressEnabled { notificationGenerator.notificationOccurred(type) } case .tabSelection: if userPreferences.hapticTabSelectionEnabled { selectionGenerator.selectionChanged() } case .timeline: if userPreferences.hapticTimelineEnabled { selectionGenerator.selectionChanged() } } #endif } public var supportsHaptics: Bool { CHHapticEngine.capabilitiesForHardware().supportsHaptics } }