mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Merge commit '28e2c78c8190dd57571ecf9ebacb48486ecc450f'
This commit is contained in:
commit
99103f5259
@ -119,6 +119,19 @@ public final class DeviceLocationManager: NSObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension CLHeading {
|
||||||
|
var effectiveHeading: Double? {
|
||||||
|
if self.headingAccuracy < 0.0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if self.trueHeading > 0.0 {
|
||||||
|
return self.trueHeading
|
||||||
|
} else {
|
||||||
|
return self.magneticHeading
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extension DeviceLocationManager: CLLocationManagerDelegate {
|
extension DeviceLocationManager: CLLocationManagerDelegate {
|
||||||
public func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
|
public func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
|
||||||
assert(self.queue.isCurrent())
|
assert(self.queue.isCurrent())
|
||||||
@ -127,7 +140,7 @@ extension DeviceLocationManager: CLLocationManagerDelegate {
|
|||||||
if self.currentTopMode != nil {
|
if self.currentTopMode != nil {
|
||||||
self.currentLocation = location
|
self.currentLocation = location
|
||||||
for subscriber in self.subscribers {
|
for subscriber in self.subscribers {
|
||||||
subscriber.update(location, self.currentHeading?.magneticHeading)
|
subscriber.update(location, self.currentHeading?.effectiveHeading)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -140,7 +153,7 @@ extension DeviceLocationManager: CLLocationManagerDelegate {
|
|||||||
self.currentHeading = newHeading
|
self.currentHeading = newHeading
|
||||||
if let currentLocation = self.currentLocation {
|
if let currentLocation = self.currentLocation {
|
||||||
for subscriber in self.subscribers {
|
for subscriber in self.subscribers {
|
||||||
subscriber.update(currentLocation, newHeading.magneticHeading)
|
subscriber.update(currentLocation, newHeading.effectiveHeading)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -544,7 +544,14 @@ final class LocationViewControllerNode: ViewControllerTracingNode, CLLocationMan
|
|||||||
}
|
}
|
||||||
|
|
||||||
func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) {
|
func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) {
|
||||||
self.headerNode.mapNode.userHeading = CGFloat(newHeading.magneticHeading)
|
if newHeading.headingAccuracy < 0.0 {
|
||||||
|
self.headerNode.mapNode.userHeading = nil
|
||||||
|
}
|
||||||
|
if newHeading.trueHeading > 0.0 {
|
||||||
|
self.headerNode.mapNode.userHeading = CGFloat(newHeading.trueHeading)
|
||||||
|
} else {
|
||||||
|
self.headerNode.mapNode.userHeading = CGFloat(newHeading.magneticHeading)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func updatePresentationData(_ presentationData: PresentationData) {
|
func updatePresentationData(_ presentationData: PresentationData) {
|
||||||
|
@ -176,6 +176,8 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
private var highlightedState: Bool = false
|
private var highlightedState: Bool = false
|
||||||
|
|
||||||
private var haptic: EmojiHaptic?
|
private var haptic: EmojiHaptic?
|
||||||
|
private var mediaPlayer: MediaPlayer?
|
||||||
|
private let mediaStatusDisposable = MetaDisposable()
|
||||||
|
|
||||||
private var currentSwipeToReplyTranslation: CGFloat = 0.0
|
private var currentSwipeToReplyTranslation: CGFloat = 0.0
|
||||||
|
|
||||||
@ -246,6 +248,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
self.disposable.dispose()
|
self.disposable.dispose()
|
||||||
|
self.mediaStatusDisposable.set(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
required init?(coder aDecoder: NSCoder) {
|
required init?(coder aDecoder: NSCoder) {
|
||||||
@ -1231,6 +1234,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
|
|
||||||
let beatingHearts: [UInt32] = [0x2764, 0x1F90E, 0x1F9E1, 0x1F499, 0x1F49A, 0x1F49C, 0x1F49B, 0x1F5A4, 0x1F90D]
|
let beatingHearts: [UInt32] = [0x2764, 0x1F90E, 0x1F9E1, 0x1F499, 0x1F49A, 0x1F49C, 0x1F49B, 0x1F5A4, 0x1F90D]
|
||||||
let peach = 0x1F351
|
let peach = 0x1F351
|
||||||
|
let coffin = 0x26B0
|
||||||
|
|
||||||
let appConfiguration = item.context.account.postbox.preferencesView(keys: [PreferencesKeys.appConfiguration])
|
let appConfiguration = item.context.account.postbox.preferencesView(keys: [PreferencesKeys.appConfiguration])
|
||||||
|> take(1)
|
|> take(1)
|
||||||
@ -1271,16 +1275,46 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
if shouldPlay {
|
if shouldPlay {
|
||||||
let _ = (appConfiguration
|
let _ = (appConfiguration
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] appConfiguration in
|
|> deliverOnMainQueue).start(next: { [weak self] appConfiguration in
|
||||||
|
guard let strongSelf = self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
let emojiSounds = AnimatedEmojiSoundsConfiguration.with(appConfiguration: appConfiguration, account: item.context.account)
|
let emojiSounds = AnimatedEmojiSoundsConfiguration.with(appConfiguration: appConfiguration, account: item.context.account)
|
||||||
for (emoji, file) in emojiSounds.sounds {
|
for (emoji, file) in emojiSounds.sounds {
|
||||||
if emoji.unicodeScalars.first == firstScalar {
|
if emoji.unicodeScalars.first == firstScalar {
|
||||||
let mediaManager = item.context.sharedContext.mediaManager
|
let mediaManager = item.context.sharedContext.mediaManager
|
||||||
let mediaPlayer = MediaPlayer(audioSessionManager: mediaManager.audioSession, postbox: item.context.account.postbox, resourceReference: .standalone(resource: file.resource), streamable: .none, video: false, preferSoftwareDecoding: false, enableSound: true, fetchAutomatically: true)
|
let mediaPlayer = MediaPlayer(audioSessionManager: mediaManager.audioSession, postbox: item.context.account.postbox, resourceReference: .standalone(resource: file.resource), streamable: .none, video: false, preferSoftwareDecoding: false, enableSound: true, fetchAutomatically: true)
|
||||||
mediaPlayer.togglePlayPause()
|
mediaPlayer.togglePlayPause()
|
||||||
self?.mediaPlayer = mediaPlayer
|
mediaPlayer.actionAtEnd = .action({ [weak self] in
|
||||||
|
self?.mediaPlayer = nil
|
||||||
animationNode.play()
|
})
|
||||||
|
strongSelf.mediaPlayer = mediaPlayer
|
||||||
|
|
||||||
|
strongSelf.mediaStatusDisposable.set((mediaPlayer.status
|
||||||
|
|> deliverOnMainQueue).start(next: { [weak self, weak animationNode] status in
|
||||||
|
if let strongSelf = self {
|
||||||
|
if firstScalar.value == coffin {
|
||||||
|
var haptic: EmojiHaptic
|
||||||
|
if let current = strongSelf.haptic {
|
||||||
|
haptic = current
|
||||||
|
} else {
|
||||||
|
haptic = CoffinHaptic()
|
||||||
|
haptic.enabled = true
|
||||||
|
strongSelf.haptic = haptic
|
||||||
|
}
|
||||||
|
if !haptic.active {
|
||||||
|
haptic.start(time: 0.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch status.status {
|
||||||
|
case .playing:
|
||||||
|
animationNode?.play()
|
||||||
|
strongSelf.mediaStatusDisposable.set(nil)
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}))
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1303,8 +1337,6 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
private var mediaPlayer: MediaPlayer?
|
|
||||||
|
|
||||||
@objc private func shareButtonPressed() {
|
@objc private func shareButtonPressed() {
|
||||||
if let item = self.item {
|
if let item = self.item {
|
||||||
if case .pinnedMessages = item.associatedData.subject {
|
if case .pinnedMessages = item.associatedData.subject {
|
||||||
|
74
submodules/TelegramUI/Sources/CoffinHaptic.swift
Normal file
74
submodules/TelegramUI/Sources/CoffinHaptic.swift
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
import Foundation
|
||||||
|
import Display
|
||||||
|
import SwiftSignalKit
|
||||||
|
|
||||||
|
private let firstImpactTime: Double = 0.4
|
||||||
|
private let secondImpactTime: Double = 0.6
|
||||||
|
|
||||||
|
final class CoffinHaptic: EmojiHaptic {
|
||||||
|
private var hapticFeedback = HapticFeedback()
|
||||||
|
private var timer: SwiftSignalKit.Timer?
|
||||||
|
private var time: Double = 0.0
|
||||||
|
var enabled: Bool = false {
|
||||||
|
didSet {
|
||||||
|
if !self.enabled {
|
||||||
|
self.reset()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var active: Bool {
|
||||||
|
return self.timer != nil
|
||||||
|
}
|
||||||
|
|
||||||
|
private func reset() {
|
||||||
|
if let timer = self.timer {
|
||||||
|
self.time = 0.0
|
||||||
|
timer.invalidate()
|
||||||
|
self.timer = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func beat(time: Double) {
|
||||||
|
let epsilon = 0.1
|
||||||
|
if fabs(firstImpactTime - time) < epsilon || fabs(secondImpactTime - time) < epsilon {
|
||||||
|
self.hapticFeedback.impact(.heavy)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func start(time: Double) {
|
||||||
|
self.hapticFeedback.prepareImpact()
|
||||||
|
|
||||||
|
if time > firstImpactTime {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let startTime: Double = 0.0
|
||||||
|
|
||||||
|
let block = { [weak self] in
|
||||||
|
guard let strongSelf = self, strongSelf.enabled else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
strongSelf.time = startTime
|
||||||
|
strongSelf.beat(time: startTime)
|
||||||
|
strongSelf.timer = SwiftSignalKit.Timer(timeout: 0.2, repeat: true, completion: { [weak self] in
|
||||||
|
guard let strongSelf = self, strongSelf.enabled else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
strongSelf.time += 0.2
|
||||||
|
strongSelf.beat(time: strongSelf.time)
|
||||||
|
|
||||||
|
if strongSelf.time > secondImpactTime {
|
||||||
|
strongSelf.reset()
|
||||||
|
strongSelf.time = 0.0
|
||||||
|
strongSelf.timer?.invalidate()
|
||||||
|
strongSelf.timer = nil
|
||||||
|
}
|
||||||
|
}, queue: Queue.mainQueue())
|
||||||
|
strongSelf.timer?.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
block()
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user