mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
241 lines
7.2 KiB
Swift
241 lines
7.2 KiB
Swift
import Foundation
|
|
import UIKit
|
|
import AudioToolbox
|
|
import CoreHaptics
|
|
|
|
public enum ImpactHapticFeedbackStyle: Hashable {
|
|
case light
|
|
case medium
|
|
case heavy
|
|
case soft
|
|
case rigid
|
|
case veryLight
|
|
case click05
|
|
case click06
|
|
}
|
|
|
|
@available(iOSApplicationExtension 10.0, iOS 10.0, *)
|
|
private final class HapticFeedbackImpl {
|
|
private lazy var impactGenerator: [ImpactHapticFeedbackStyle : UIImpactFeedbackGenerator] = {
|
|
if #available(iOSApplicationExtension 13.0, iOS 13.0, *) {
|
|
return [.light: UIImpactFeedbackGenerator(style: .light),
|
|
.medium: UIImpactFeedbackGenerator(style: .medium),
|
|
.heavy: UIImpactFeedbackGenerator(style: .heavy),
|
|
.soft: UIImpactFeedbackGenerator(style: .soft),
|
|
.rigid: UIImpactFeedbackGenerator(style: .rigid),
|
|
.veryLight: UIImpactFeedbackGenerator(),
|
|
.click05: UIImpactFeedbackGenerator(),
|
|
.click06: UIImpactFeedbackGenerator()]
|
|
} else {
|
|
return [.light: UIImpactFeedbackGenerator(style: .light),
|
|
.medium: UIImpactFeedbackGenerator(style: .medium),
|
|
.heavy: UIImpactFeedbackGenerator(style: .heavy)]
|
|
}
|
|
}()
|
|
|
|
private lazy var selectionGenerator: UISelectionFeedbackGenerator? = {
|
|
return UISelectionFeedbackGenerator()
|
|
}()
|
|
|
|
private lazy var notificationGenerator: UINotificationFeedbackGenerator? = {
|
|
return UINotificationFeedbackGenerator()
|
|
}()
|
|
|
|
func prepareTap() {
|
|
if let selectionGenerator = self.selectionGenerator {
|
|
selectionGenerator.prepare()
|
|
}
|
|
}
|
|
|
|
func tap() {
|
|
if let selectionGenerator = self.selectionGenerator {
|
|
selectionGenerator.selectionChanged()
|
|
}
|
|
}
|
|
|
|
func prepareImpact(_ style: ImpactHapticFeedbackStyle) {
|
|
if let impactGenerator = self.impactGenerator[style] {
|
|
impactGenerator.prepare()
|
|
}
|
|
}
|
|
|
|
func impact(_ style: ImpactHapticFeedbackStyle) {
|
|
if let impactGenerator = self.impactGenerator[style] {
|
|
if #available(iOSApplicationExtension 13.0, iOS 13.0, *) {
|
|
switch style {
|
|
case .click05:
|
|
impactGenerator.impactOccurred(intensity: 0.3)
|
|
case .click06:
|
|
impactGenerator.impactOccurred(intensity: 0.4)
|
|
case .veryLight:
|
|
impactGenerator.impactOccurred(intensity: 0.3)
|
|
default:
|
|
impactGenerator.impactOccurred()
|
|
}
|
|
} else {
|
|
impactGenerator.impactOccurred()
|
|
}
|
|
}
|
|
}
|
|
|
|
func success() {
|
|
if let notificationGenerator = self.notificationGenerator {
|
|
notificationGenerator.notificationOccurred(.success)
|
|
} else {
|
|
AudioServicesPlaySystemSound(1520)
|
|
}
|
|
}
|
|
|
|
func prepareError() {
|
|
if let notificationGenerator = self.notificationGenerator {
|
|
notificationGenerator.prepare()
|
|
}
|
|
}
|
|
|
|
func error() {
|
|
if let notificationGenerator = self.notificationGenerator {
|
|
notificationGenerator.notificationOccurred(.error)
|
|
} else {
|
|
AudioServicesPlaySystemSound(1521)
|
|
}
|
|
}
|
|
|
|
func warning() {
|
|
AudioServicesPlaySystemSound(1102)
|
|
// if let notificationGenerator = self.notificationGenerator {
|
|
// notificationGenerator.notificationOccurred(.warning)
|
|
// } else {
|
|
//
|
|
// }
|
|
}
|
|
|
|
@objc dynamic func f() {
|
|
}
|
|
}
|
|
|
|
public final class HapticFeedback {
|
|
private var impl: AnyObject?
|
|
|
|
public init() {
|
|
}
|
|
|
|
deinit {
|
|
let impl = self.impl
|
|
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1.0, execute: {
|
|
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
|
|
if let impl = impl as? HapticFeedbackImpl {
|
|
impl.f()
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
@available(iOSApplicationExtension 10.0, iOS 10.0, *)
|
|
private func withImpl(_ f: (HapticFeedbackImpl) -> Void) {
|
|
if self.impl == nil {
|
|
self.impl = HapticFeedbackImpl()
|
|
}
|
|
f(self.impl as! HapticFeedbackImpl)
|
|
}
|
|
|
|
public func prepareTap() {
|
|
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
|
|
self.withImpl { impl in
|
|
impl.prepareTap()
|
|
}
|
|
}
|
|
}
|
|
|
|
public func tap() {
|
|
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
|
|
self.withImpl { impl in
|
|
impl.tap()
|
|
}
|
|
}
|
|
}
|
|
|
|
public func prepareImpact(_ style: ImpactHapticFeedbackStyle = .medium) {
|
|
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
|
|
self.withImpl { impl in
|
|
impl.prepareImpact(style)
|
|
}
|
|
}
|
|
}
|
|
|
|
public func impact(_ style: ImpactHapticFeedbackStyle = .medium) {
|
|
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
|
|
self.withImpl { impl in
|
|
impl.impact(style)
|
|
}
|
|
}
|
|
}
|
|
|
|
public func success() {
|
|
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
|
|
self.withImpl { impl in
|
|
impl.success()
|
|
}
|
|
}
|
|
}
|
|
|
|
public func prepareError() {
|
|
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
|
|
self.withImpl { impl in
|
|
impl.prepareError()
|
|
}
|
|
}
|
|
}
|
|
|
|
public func error() {
|
|
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
|
|
self.withImpl { impl in
|
|
impl.error()
|
|
}
|
|
}
|
|
}
|
|
|
|
public func warning() {
|
|
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
|
|
self.withImpl { impl in
|
|
impl.warning()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@available(iOS 13.0, *)
|
|
public final class ContinuousHaptic {
|
|
private let engine: CHHapticEngine
|
|
private let player: CHHapticPatternPlayer
|
|
|
|
public init(duration: Double) throws {
|
|
self.engine = try CHHapticEngine()
|
|
|
|
var events: [CHHapticEvent] = []
|
|
for i in 0 ... 10 {
|
|
let t = CGFloat(i) / 10.0
|
|
|
|
let intensity = CHHapticEventParameter(parameterID: .hapticIntensity, value: Float((1.0 - t) * 0.1 + t * 1.0))
|
|
let sharpness = CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.3)
|
|
let eventDuration: Double
|
|
if i == 10 {
|
|
eventDuration = 100.0
|
|
} else {
|
|
eventDuration = duration
|
|
}
|
|
let event = CHHapticEvent(eventType: .hapticContinuous, parameters: [intensity, sharpness], relativeTime: Double(i) / 10.0 * duration, duration: eventDuration)
|
|
events.append(event)
|
|
}
|
|
|
|
let pattern = try CHHapticPattern(events: events, parameters: [])
|
|
self.player = try self.engine.makePlayer(with: pattern)
|
|
|
|
try self.engine.start()
|
|
try self.player.start(atTime: 0)
|
|
}
|
|
|
|
deinit {
|
|
self.engine.stop(completionHandler: nil)
|
|
}
|
|
}
|