mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Use a shared CADisplayLink whenever possible
This commit is contained in:
parent
654f61a06b
commit
b80eace071
@ -34,55 +34,6 @@ private let completionKey = "CAAnimationUtils_completion"
|
|||||||
public let kCAMediaTimingFunctionSpring = "CAAnimationUtilsSpringCurve"
|
public let kCAMediaTimingFunctionSpring = "CAAnimationUtilsSpringCurve"
|
||||||
public let kCAMediaTimingFunctionCustomSpringPrefix = "CAAnimationUtilsSpringCustomCurve"
|
public let kCAMediaTimingFunctionCustomSpringPrefix = "CAAnimationUtilsSpringCustomCurve"
|
||||||
|
|
||||||
private final class FrameRangeContext {
|
|
||||||
private var animationCount: Int = 0
|
|
||||||
private var displayLink: CADisplayLink?
|
|
||||||
|
|
||||||
init() {
|
|
||||||
}
|
|
||||||
|
|
||||||
func add() {
|
|
||||||
self.animationCount += 1
|
|
||||||
self.update()
|
|
||||||
}
|
|
||||||
|
|
||||||
func remove() {
|
|
||||||
self.animationCount -= 1
|
|
||||||
if self.animationCount < 0 {
|
|
||||||
self.animationCount = 0
|
|
||||||
assertionFailure()
|
|
||||||
}
|
|
||||||
self.update()
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc func displayEvent() {
|
|
||||||
}
|
|
||||||
|
|
||||||
private func update() {
|
|
||||||
if self.animationCount != 0 {
|
|
||||||
if self.displayLink == nil {
|
|
||||||
let displayLink = CADisplayLink(target: self, selector: #selector(self.displayEvent))
|
|
||||||
|
|
||||||
if #available(iOS 15.0, *) {
|
|
||||||
let maxFps = Float(UIScreen.main.maximumFramesPerSecond)
|
|
||||||
if maxFps > 61.0 {
|
|
||||||
displayLink.preferredFrameRateRange = CAFrameRateRange(minimum: 60.0, maximum: maxFps, preferred: maxFps)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.displayLink = displayLink
|
|
||||||
displayLink.add(to: .main, forMode: .common)
|
|
||||||
displayLink.isPaused = false
|
|
||||||
}
|
|
||||||
} else if let displayLink = self.displayLink {
|
|
||||||
self.displayLink = nil
|
|
||||||
displayLink.invalidate()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private let frameRangeContext = FrameRangeContext()
|
|
||||||
|
|
||||||
public extension CAAnimation {
|
public extension CAAnimation {
|
||||||
var completion: ((Bool) -> Void)? {
|
var completion: ((Bool) -> Void)? {
|
||||||
get {
|
get {
|
||||||
@ -103,18 +54,16 @@ public extension CAAnimation {
|
|||||||
|
|
||||||
private func adjustFrameRate(animation: CAAnimation) {
|
private func adjustFrameRate(animation: CAAnimation) {
|
||||||
if #available(iOS 15.0, *) {
|
if #available(iOS 15.0, *) {
|
||||||
if let animation = animation as? CABasicAnimation {
|
|
||||||
if animation.keyPath == "opacity" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let maxFps = Float(UIScreen.main.maximumFramesPerSecond)
|
let maxFps = Float(UIScreen.main.maximumFramesPerSecond)
|
||||||
if maxFps > 61.0 {
|
if maxFps > 61.0 {
|
||||||
#if DEBUG
|
var preferredFps: Float = maxFps
|
||||||
//let _ = frameRangeContext.add()
|
if let animation = animation as? CABasicAnimation {
|
||||||
#endif
|
if animation.keyPath == "opacity" {
|
||||||
|
preferredFps = 60.0
|
||||||
animation.preferredFrameRateRange = CAFrameRateRange(minimum: 30.0, maximum: maxFps, preferred: maxFps)
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
animation.preferredFrameRateRange = CAFrameRateRange(minimum: 30.0, maximum: preferredFps, preferred: maxFps)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,153 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
|
public final class SharedDisplayLinkDriver {
|
||||||
|
public static let shared = SharedDisplayLinkDriver()
|
||||||
|
|
||||||
|
public final class Link {
|
||||||
|
private let driver: SharedDisplayLinkDriver
|
||||||
|
public let needsHighestFramerate: Bool
|
||||||
|
let update: () -> Void
|
||||||
|
var isValid: Bool = true
|
||||||
|
public var isPaused: Bool = false {
|
||||||
|
didSet {
|
||||||
|
if self.isPaused != oldValue {
|
||||||
|
driver.requestUpdate()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init(driver: SharedDisplayLinkDriver, needsHighestFramerate: Bool, update: @escaping () -> Void) {
|
||||||
|
self.driver = driver
|
||||||
|
self.needsHighestFramerate = needsHighestFramerate
|
||||||
|
self.update = update
|
||||||
|
}
|
||||||
|
|
||||||
|
public func invalidate() {
|
||||||
|
self.isValid = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final class RequestContext {
|
||||||
|
weak var link: Link?
|
||||||
|
|
||||||
|
init(link: Link) {
|
||||||
|
self.link = link
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var displayLink: CADisplayLink?
|
||||||
|
private var hasRequestedHighestFramerate: Bool = false
|
||||||
|
private var requests: [RequestContext] = []
|
||||||
|
|
||||||
|
private var isInForeground: Bool = false
|
||||||
|
|
||||||
|
private init() {
|
||||||
|
let _ = NotificationCenter.default.addObserver(forName: UIApplication.willEnterForegroundNotification, object: nil, queue: nil, using: { [weak self] _ in
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.isInForeground = true
|
||||||
|
self.update()
|
||||||
|
})
|
||||||
|
let _ = NotificationCenter.default.addObserver(forName: UIApplication.didEnterBackgroundNotification, object: nil, queue: nil, using: { [weak self] _ in
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.isInForeground = false
|
||||||
|
self.update()
|
||||||
|
})
|
||||||
|
|
||||||
|
switch UIApplication.shared.applicationState {
|
||||||
|
case .active:
|
||||||
|
self.isInForeground = true
|
||||||
|
default:
|
||||||
|
self.isInForeground = false
|
||||||
|
}
|
||||||
|
|
||||||
|
self.update()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func requestUpdate() {
|
||||||
|
self.update()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func update() {
|
||||||
|
var hasActiveItems = false
|
||||||
|
var needHighestFramerate = false
|
||||||
|
for request in self.requests {
|
||||||
|
if let link = request.link {
|
||||||
|
needHighestFramerate = link.needsHighestFramerate
|
||||||
|
if link.isValid && !link.isPaused {
|
||||||
|
hasActiveItems = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.isInForeground && hasActiveItems {
|
||||||
|
let displayLink: CADisplayLink
|
||||||
|
if let current = self.displayLink {
|
||||||
|
displayLink = current
|
||||||
|
} else {
|
||||||
|
displayLink = CADisplayLink(target: self, selector: #selector(self.displayLinkEvent))
|
||||||
|
self.displayLink = displayLink
|
||||||
|
displayLink.add(to: .main, forMode: .common)
|
||||||
|
}
|
||||||
|
if #available(iOS 15.0, *) {
|
||||||
|
let frameRateRange: CAFrameRateRange
|
||||||
|
if needHighestFramerate {
|
||||||
|
frameRateRange = CAFrameRateRange(minimum: 30.0, maximum: 120.0, preferred: 120.0)
|
||||||
|
} else {
|
||||||
|
frameRateRange = .default
|
||||||
|
}
|
||||||
|
if displayLink.preferredFrameRateRange != frameRateRange {
|
||||||
|
displayLink.preferredFrameRateRange = frameRateRange
|
||||||
|
}
|
||||||
|
}
|
||||||
|
displayLink.isPaused = false
|
||||||
|
} else {
|
||||||
|
if let displayLink = self.displayLink {
|
||||||
|
self.displayLink = nil
|
||||||
|
displayLink.invalidate()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc private func displayLinkEvent() {
|
||||||
|
var removeIndices: [Int]?
|
||||||
|
for i in 0 ..< self.requests.count {
|
||||||
|
if let link = self.requests[i].link, link.isValid {
|
||||||
|
link.update()
|
||||||
|
} else {
|
||||||
|
if removeIndices == nil {
|
||||||
|
removeIndices = [i]
|
||||||
|
} else {
|
||||||
|
removeIndices?.append(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let removeIndices = removeIndices {
|
||||||
|
for index in removeIndices.reversed() {
|
||||||
|
self.requests.remove(at: index)
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.requests.isEmpty {
|
||||||
|
self.update()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func add(needsHighestFramerate: Bool = true, _ update: @escaping () -> Void) -> Link {
|
||||||
|
let link = Link(driver: self, needsHighestFramerate: needsHighestFramerate, update: update)
|
||||||
|
self.requests.append(RequestContext(link: link))
|
||||||
|
|
||||||
|
self.update()
|
||||||
|
|
||||||
|
return link
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public final class DisplayLinkTarget: NSObject {
|
public final class DisplayLinkTarget: NSObject {
|
||||||
private let f: () -> Void
|
private let f: () -> Void
|
||||||
|
|
||||||
@ -14,7 +161,7 @@ public final class DisplayLinkTarget: NSObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final class DisplayLinkAnimator {
|
public final class DisplayLinkAnimator {
|
||||||
private var displayLink: CADisplayLink!
|
private var displayLink: SharedDisplayLinkDriver.Link?
|
||||||
private let duration: Double
|
private let duration: Double
|
||||||
private let fromValue: CGFloat
|
private let fromValue: CGFloat
|
||||||
private let toValue: CGFloat
|
private let toValue: CGFloat
|
||||||
@ -32,21 +179,20 @@ public final class DisplayLinkAnimator {
|
|||||||
|
|
||||||
self.startTime = CACurrentMediaTime()
|
self.startTime = CACurrentMediaTime()
|
||||||
|
|
||||||
self.displayLink = CADisplayLink(target: DisplayLinkTarget({ [weak self] in
|
self.displayLink = SharedDisplayLinkDriver.shared.add { [weak self] in
|
||||||
self?.tick()
|
self?.tick()
|
||||||
}), selector: #selector(DisplayLinkTarget.event))
|
}
|
||||||
self.displayLink.isPaused = false
|
self.displayLink?.isPaused = false
|
||||||
self.displayLink.add(to: RunLoop.main, forMode: .common)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
self.displayLink.isPaused = true
|
self.displayLink?.isPaused = true
|
||||||
self.displayLink.invalidate()
|
self.displayLink?.invalidate()
|
||||||
}
|
}
|
||||||
|
|
||||||
public func invalidate() {
|
public func invalidate() {
|
||||||
self.displayLink.isPaused = true
|
self.displayLink?.isPaused = true
|
||||||
self.displayLink.invalidate()
|
self.displayLink?.invalidate()
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc private func tick() {
|
@objc private func tick() {
|
||||||
@ -60,14 +206,14 @@ public final class DisplayLinkAnimator {
|
|||||||
self.update(self.fromValue * CGFloat(1 - t) + self.toValue * CGFloat(t))
|
self.update(self.fromValue * CGFloat(1 - t) + self.toValue * CGFloat(t))
|
||||||
if abs(t - 1.0) < Double.ulpOfOne {
|
if abs(t - 1.0) < Double.ulpOfOne {
|
||||||
self.completed = true
|
self.completed = true
|
||||||
self.displayLink.isPaused = true
|
self.displayLink?.isPaused = true
|
||||||
self.completion()
|
self.completion()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class ConstantDisplayLinkAnimator {
|
public final class ConstantDisplayLinkAnimator {
|
||||||
private var displayLink: CADisplayLink?
|
private var displayLink: SharedDisplayLinkDriver.Link?
|
||||||
private let update: () -> Void
|
private let update: () -> Void
|
||||||
private var completed = false
|
private var completed = false
|
||||||
|
|
||||||
@ -81,26 +227,16 @@ public final class ConstantDisplayLinkAnimator {
|
|||||||
guard let displayLink = self.displayLink else {
|
guard let displayLink = self.displayLink else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if self.frameInterval == 1 {
|
let _ = displayLink
|
||||||
if #available(iOS 15.0, *) {
|
|
||||||
self.displayLink?.preferredFrameRateRange = CAFrameRateRange(minimum: 60.0, maximum: 120.0, preferred: 120.0)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
displayLink.preferredFramesPerSecond = 30
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public var isPaused: Bool = true {
|
public var isPaused: Bool = true {
|
||||||
didSet {
|
didSet {
|
||||||
if self.isPaused != oldValue {
|
if self.isPaused != oldValue {
|
||||||
if !self.isPaused && self.displayLink == nil {
|
if !self.isPaused && self.displayLink == nil {
|
||||||
let displayLink = CADisplayLink(target: DisplayLinkTarget({ [weak self] in
|
let displayLink = SharedDisplayLinkDriver.shared.add { [weak self] in
|
||||||
self?.tick()
|
self?.tick()
|
||||||
}), selector: #selector(DisplayLinkTarget.event))
|
}
|
||||||
/*if #available(iOS 15.0, *) {
|
|
||||||
self.displayLink?.preferredFrameRateRange = CAFrameRateRange(minimum: 60.0, maximum: 120.0, preferred: 120.0)
|
|
||||||
}*/
|
|
||||||
displayLink.add(to: RunLoop.main, forMode: .common)
|
|
||||||
self.displayLink = displayLink
|
self.displayLink = displayLink
|
||||||
self.updateDisplayLink()
|
self.updateDisplayLink()
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ import Foundation
|
|||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
public class DisplayLinkDispatcher: NSObject {
|
public class DisplayLinkDispatcher: NSObject {
|
||||||
private var displayLink: CADisplayLink!
|
|
||||||
private var blocksToDispatch: [() -> Void] = []
|
private var blocksToDispatch: [() -> Void] = []
|
||||||
private let limit: Int
|
private let limit: Int
|
||||||
|
|
||||||
@ -10,38 +9,13 @@ public class DisplayLinkDispatcher: NSObject {
|
|||||||
self.limit = limit
|
self.limit = limit
|
||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
if #available(iOS 10.0, *) {
|
|
||||||
//self.displayLink.preferredFramesPerSecond = 60
|
|
||||||
} else {
|
|
||||||
self.displayLink = CADisplayLink(target: self, selector: #selector(self.run))
|
|
||||||
self.displayLink.isPaused = true
|
|
||||||
self.displayLink.add(to: RunLoop.main, forMode: .common)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public func dispatch(f: @escaping () -> Void) {
|
public func dispatch(f: @escaping () -> Void) {
|
||||||
if self.displayLink == nil {
|
if Thread.isMainThread {
|
||||||
if Thread.isMainThread {
|
f()
|
||||||
f()
|
|
||||||
} else {
|
|
||||||
DispatchQueue.main.async(execute: f)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
self.blocksToDispatch.append(f)
|
DispatchQueue.main.async(execute: f)
|
||||||
self.displayLink.isPaused = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc func run() {
|
|
||||||
for _ in 0 ..< (self.limit == 0 ? 1000 : self.limit) {
|
|
||||||
if self.blocksToDispatch.count == 0 {
|
|
||||||
self.displayLink.isPaused = true
|
|
||||||
break
|
|
||||||
} else {
|
|
||||||
let f = self.blocksToDispatch.removeFirst()
|
|
||||||
f()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -814,12 +814,6 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
|
public func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
|
||||||
if #available(iOS 15.0, *) {
|
|
||||||
if let scrollDisplayLink = self.scroller.value(forKey: "_scrollHeartbeat") as? CADisplayLink {
|
|
||||||
let _ = scrollDisplayLink
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.isDragging = false
|
self.isDragging = false
|
||||||
if decelerate {
|
if decelerate {
|
||||||
self.lastContentOffsetTimestamp = CACurrentMediaTime()
|
self.lastContentOffsetTimestamp = CACurrentMediaTime()
|
||||||
|
@ -36,44 +36,6 @@ class DisplayLinkService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// private init() {
|
|
||||||
// displayLink.add(to: .main, forMode: .common)
|
|
||||||
// displayLink.preferredFramesPerSecond = 60
|
|
||||||
// displayLink.isPaused = true
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // MARK: - Display Link
|
|
||||||
// private lazy var displayLink: CADisplayLink! = { CADisplayLink(target: self, selector: #selector(displayLinkDidFire)) } ()
|
|
||||||
// private var previousTickTime = 0.0
|
|
||||||
//
|
|
||||||
// private func startDisplayLink() {
|
|
||||||
// guard displayLink.isPaused else {
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// previousTickTime = CACurrentMediaTime()
|
|
||||||
// displayLink.isPaused = false
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @objc private func displayLinkDidFire(_ displayLink: CADisplayLink) {
|
|
||||||
// let currentTime = CACurrentMediaTime()
|
|
||||||
// let delta = currentTime - previousTickTime
|
|
||||||
// previousTickTime = currentTime
|
|
||||||
// let allListners = listners.allObjects
|
|
||||||
// var hasListners = false
|
|
||||||
// for listner in allListners {
|
|
||||||
// (listner as! DisplayLinkListner).update(delta: delta)
|
|
||||||
// hasListners = true
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if !hasListners {
|
|
||||||
// stopDisplayLink()
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// private func stopDisplayLink() {
|
|
||||||
// displayLink.isPaused = true
|
|
||||||
// }
|
|
||||||
|
|
||||||
private init() {
|
private init() {
|
||||||
dispatchSourceTimer.schedule(deadline: .now() + 1.0 / 60, repeating: 1.0 / 60)
|
dispatchSourceTimer.schedule(deadline: .now() + 1.0 / 60, repeating: 1.0 / 60)
|
||||||
dispatchSourceTimer.setEventHandler {
|
dispatchSourceTimer.setEventHandler {
|
||||||
|
@ -145,7 +145,7 @@ open class ManagedAnimationNode: ASDisplayNode {
|
|||||||
public let intrinsicSize: CGSize
|
public let intrinsicSize: CGSize
|
||||||
|
|
||||||
private let imageNode: ASImageNode
|
private let imageNode: ASImageNode
|
||||||
private let displayLink: CADisplayLink
|
private let displayLink: SharedDisplayLinkDriver.Link
|
||||||
|
|
||||||
public var imageUpdated: ((UIImage) -> Void)?
|
public var imageUpdated: ((UIImage) -> Void)?
|
||||||
public var image: UIImage? {
|
public var image: UIImage? {
|
||||||
@ -179,19 +179,14 @@ open class ManagedAnimationNode: ASDisplayNode {
|
|||||||
self.imageNode.frame = CGRect(origin: CGPoint(), size: self.intrinsicSize)
|
self.imageNode.frame = CGRect(origin: CGPoint(), size: self.intrinsicSize)
|
||||||
|
|
||||||
var displayLinkUpdate: (() -> Void)?
|
var displayLinkUpdate: (() -> Void)?
|
||||||
self.displayLink = CADisplayLink(target: DisplayLinkTarget {
|
self.displayLink = SharedDisplayLinkDriver.shared.add {
|
||||||
displayLinkUpdate?()
|
displayLinkUpdate?()
|
||||||
}, selector: #selector(DisplayLinkTarget.event))
|
|
||||||
if #available(iOS 10.0, *) {
|
|
||||||
self.displayLink.preferredFramesPerSecond = 60
|
|
||||||
}
|
}
|
||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
self.addSubnode(self.imageNode)
|
self.addSubnode(self.imageNode)
|
||||||
|
|
||||||
self.displayLink.add(to: RunLoop.main, forMode: .common)
|
|
||||||
|
|
||||||
displayLinkUpdate = { [weak self] in
|
displayLinkUpdate = { [weak self] in
|
||||||
self?.updateAnimation()
|
self?.updateAnimation()
|
||||||
}
|
}
|
||||||
@ -199,6 +194,7 @@ open class ManagedAnimationNode: ASDisplayNode {
|
|||||||
|
|
||||||
open func advanceState() {
|
open func advanceState() {
|
||||||
guard !self.trackStack.isEmpty else {
|
guard !self.trackStack.isEmpty else {
|
||||||
|
self.displayLink.isPaused = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,6 +207,7 @@ open class ManagedAnimationNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.didTryAdvancingState = false
|
self.didTryAdvancingState = false
|
||||||
|
self.displayLink.isPaused = false
|
||||||
}
|
}
|
||||||
|
|
||||||
public func updateAnimation() {
|
public func updateAnimation() {
|
||||||
@ -219,6 +216,7 @@ open class ManagedAnimationNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
guard let state = self.state else {
|
guard let state = self.state else {
|
||||||
|
self.displayLink.isPaused = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,7 +300,7 @@ private final class MediaPlayerScrubbingBufferingNode: ASDisplayNode {
|
|||||||
public final class MediaPlayerScrubbingNode: ASDisplayNode {
|
public final class MediaPlayerScrubbingNode: ASDisplayNode {
|
||||||
private var contentNodes: MediaPlayerScrubbingNodeContentNodes
|
private var contentNodes: MediaPlayerScrubbingNodeContentNodes
|
||||||
|
|
||||||
private var displayLink: CADisplayLink?
|
private var displayLink: SharedDisplayLinkDriver.Link?
|
||||||
private var isInHierarchyValue: Bool = false
|
private var isInHierarchyValue: Bool = false
|
||||||
|
|
||||||
private var playbackStatusValue: MediaPlayerPlaybackStatus?
|
private var playbackStatusValue: MediaPlayerPlaybackStatus?
|
||||||
@ -798,20 +798,9 @@ public final class MediaPlayerScrubbingNode: ASDisplayNode {
|
|||||||
|
|
||||||
if needsAnimation {
|
if needsAnimation {
|
||||||
if self.displayLink == nil {
|
if self.displayLink == nil {
|
||||||
class DisplayLinkProxy: NSObject {
|
let displayLink = SharedDisplayLinkDriver.shared.add { [weak self] in
|
||||||
var f: () -> Void
|
|
||||||
init(_ f: @escaping () -> Void) {
|
|
||||||
self.f = f
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc func displayLinkEvent() {
|
|
||||||
self.f()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let displayLink = CADisplayLink(target: DisplayLinkProxy({ [weak self] in
|
|
||||||
self?.updateProgress()
|
self?.updateProgress()
|
||||||
}), selector: #selector(DisplayLinkProxy.displayLinkEvent))
|
}
|
||||||
displayLink.add(to: .main, forMode: RunLoop.Mode.common)
|
|
||||||
self.displayLink = displayLink
|
self.displayLink = displayLink
|
||||||
}
|
}
|
||||||
self.displayLink?.isPaused = false
|
self.displayLink?.isPaused = false
|
||||||
|
@ -209,64 +209,8 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class AnimationSupportContext {
|
|
||||||
private let window: UIWindow
|
|
||||||
private let testView: UIView
|
|
||||||
private var animationCount: Int = 0
|
|
||||||
private var displayLink: CADisplayLink?
|
|
||||||
|
|
||||||
init(window: UIWindow) {
|
|
||||||
self.window = window
|
|
||||||
self.testView = UIView()
|
|
||||||
window.addSubview(self.testView)
|
|
||||||
self.testView.frame = CGRect(origin: CGPoint(), size: CGSize(width: 10.0, height: 10.0))
|
|
||||||
self.testView.backgroundColor = .black
|
|
||||||
}
|
|
||||||
|
|
||||||
func add() {
|
|
||||||
self.animationCount += 1
|
|
||||||
self.update()
|
|
||||||
}
|
|
||||||
|
|
||||||
func remove() {
|
|
||||||
self.animationCount -= 1
|
|
||||||
if self.animationCount < 0 {
|
|
||||||
self.animationCount = 0
|
|
||||||
assertionFailure()
|
|
||||||
}
|
|
||||||
self.update()
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc func displayEvent() {
|
|
||||||
self.testView.frame = CGRect(origin: CGPoint(x: self.testView.frame.minX == 0.0 ? 1.0 : 0.0, y: 0.0), size: self.testView.bounds.size)
|
|
||||||
}
|
|
||||||
|
|
||||||
private func update() {
|
|
||||||
if self.animationCount != 0 {
|
|
||||||
if self.displayLink == nil {
|
|
||||||
let displayLink = CADisplayLink(target: self, selector: #selector(self.displayEvent))
|
|
||||||
|
|
||||||
if #available(iOS 15.0, *) {
|
|
||||||
let maxFps = Float(UIScreen.main.maximumFramesPerSecond)
|
|
||||||
if maxFps > 61.0 {
|
|
||||||
displayLink.preferredFrameRateRange = CAFrameRateRange(minimum: 60.0, maximum: maxFps, preferred: maxFps)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.displayLink = displayLink
|
|
||||||
displayLink.add(to: .main, forMode: .common)
|
|
||||||
displayLink.isPaused = false
|
|
||||||
}
|
|
||||||
} else if let displayLink = self.displayLink {
|
|
||||||
self.displayLink = nil
|
|
||||||
displayLink.invalidate()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc(AppDelegate) class AppDelegate: UIResponder, UIApplicationDelegate, PKPushRegistryDelegate, UNUserNotificationCenterDelegate {
|
@objc(AppDelegate) class AppDelegate: UIResponder, UIApplicationDelegate, PKPushRegistryDelegate, UNUserNotificationCenterDelegate {
|
||||||
@objc var window: UIWindow?
|
@objc var window: UIWindow?
|
||||||
private var animationSupportContext: AnimationSupportContext?
|
|
||||||
var nativeWindow: (UIWindow & WindowHost)?
|
var nativeWindow: (UIWindow & WindowHost)?
|
||||||
var mainWindow: Window1!
|
var mainWindow: Window1!
|
||||||
private var dataImportSplash: LegacyDataImportSplash?
|
private var dataImportSplash: LegacyDataImportSplash?
|
||||||
@ -362,9 +306,6 @@ private final class AnimationSupportContext {
|
|||||||
self.window = window
|
self.window = window
|
||||||
self.nativeWindow = window
|
self.nativeWindow = window
|
||||||
|
|
||||||
//self.animationSupportContext = AnimationSupportContext(window: window)
|
|
||||||
//self.animationSupportContext?.add()
|
|
||||||
|
|
||||||
let clearNotificationsManager = ClearNotificationsManager(getNotificationIds: { completion in
|
let clearNotificationsManager = ClearNotificationsManager(getNotificationIds: { completion in
|
||||||
if #available(iOS 10.0, *) {
|
if #available(iOS 10.0, *) {
|
||||||
UNUserNotificationCenter.current().getDeliveredNotifications(completionHandler: { notifications in
|
UNUserNotificationCenter.current().getDeliveredNotifications(completionHandler: { notifications in
|
||||||
|
@ -78,12 +78,6 @@ extension CALayer {
|
|||||||
let animation = CABasicAnimation(keyPath: property.caLayerKeypath)
|
let animation = CABasicAnimation(keyPath: property.caLayerKeypath)
|
||||||
animation.fromValue = keyframeValue
|
animation.fromValue = keyframeValue
|
||||||
animation.toValue = keyframeValue
|
animation.toValue = keyframeValue
|
||||||
if #available(iOS 15.0, *) {
|
|
||||||
let maxFps = Float(UIScreen.main.maximumFramesPerSecond)
|
|
||||||
if maxFps > 61.0 {
|
|
||||||
animation.preferredFrameRateRange = CAFrameRateRange(minimum: maxFps, maximum: maxFps, preferred: maxFps)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return animation
|
return animation
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,12 +135,6 @@ extension CALayer {
|
|||||||
let calculationMode = try self.calculationMode(for: keyframes, context: context)
|
let calculationMode = try self.calculationMode(for: keyframes, context: context)
|
||||||
|
|
||||||
let animation = CAKeyframeAnimation(keyPath: property.caLayerKeypath)
|
let animation = CAKeyframeAnimation(keyPath: property.caLayerKeypath)
|
||||||
if #available(iOS 15.0, *) {
|
|
||||||
let maxFps = Float(UIScreen.main.maximumFramesPerSecond)
|
|
||||||
if maxFps > 61.0 {
|
|
||||||
animation.preferredFrameRateRange = CAFrameRateRange(minimum: maxFps, maximum: maxFps, preferred: maxFps)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Position animations define a `CGPath` curve that should be followed,
|
// Position animations define a `CGPath` curve that should be followed,
|
||||||
// instead of animating directly between keyframe point values.
|
// instead of animating directly between keyframe point values.
|
||||||
|
@ -113,12 +113,6 @@ final class MainThreadAnimationLayer: CALayer, RootAnimationLayer {
|
|||||||
let animation = CABasicAnimation(keyPath: event)
|
let animation = CABasicAnimation(keyPath: event)
|
||||||
animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear)
|
animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear)
|
||||||
animation.fromValue = presentation()?.currentFrame
|
animation.fromValue = presentation()?.currentFrame
|
||||||
if #available(iOS 15.0, *) {
|
|
||||||
let maxFps = Float(UIScreen.main.maximumFramesPerSecond)
|
|
||||||
if maxFps > 61.0 {
|
|
||||||
animation.preferredFrameRateRange = CAFrameRateRange(minimum: maxFps, maximum: maxFps, preferred: maxFps)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return animation
|
return animation
|
||||||
}
|
}
|
||||||
return super.action(forKey: event)
|
return super.action(forKey: event)
|
||||||
|
@ -412,14 +412,14 @@ final public class AnimationView: AnimationViewBase {
|
|||||||
self.f()
|
self.f()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.workaroundDisplayLink = CADisplayLink(target: WorkaroundDisplayLinkTarget { [weak self] in
|
/*self.workaroundDisplayLink = CADisplayLink(target: WorkaroundDisplayLinkTarget { [weak self] in
|
||||||
let _ = self?.realtimeAnimationProgress
|
let _ = self?.realtimeAnimationProgress
|
||||||
}, selector: #selector(WorkaroundDisplayLinkTarget.update))
|
}, selector: #selector(WorkaroundDisplayLinkTarget.update))
|
||||||
if #available(iOS 15.0, *) {
|
if #available(iOS 15.0, *) {
|
||||||
let maxFps = Float(UIScreen.main.maximumFramesPerSecond)
|
let maxFps = Float(UIScreen.main.maximumFramesPerSecond)
|
||||||
self.workaroundDisplayLink?.preferredFrameRateRange = CAFrameRateRange(minimum: maxFps, maximum: maxFps, preferred: maxFps)
|
self.workaroundDisplayLink?.preferredFrameRateRange = CAFrameRateRange(minimum: maxFps, maximum: maxFps, preferred: maxFps)
|
||||||
}
|
}
|
||||||
self.workaroundDisplayLink?.add(to: .main, forMode: .common)
|
self.workaroundDisplayLink?.add(to: .main, forMode: .common)*/
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if let workaroundDisplayLink = self.workaroundDisplayLink {
|
if let workaroundDisplayLink = self.workaroundDisplayLink {
|
||||||
@ -1305,12 +1305,6 @@ final public class AnimationView: AnimationViewBase {
|
|||||||
layerAnimation.fillMode = CAMediaTimingFillMode.both
|
layerAnimation.fillMode = CAMediaTimingFillMode.both
|
||||||
layerAnimation.repeatCount = loopMode.caAnimationConfiguration.repeatCount
|
layerAnimation.repeatCount = loopMode.caAnimationConfiguration.repeatCount
|
||||||
layerAnimation.autoreverses = loopMode.caAnimationConfiguration.autoreverses
|
layerAnimation.autoreverses = loopMode.caAnimationConfiguration.autoreverses
|
||||||
if #available(iOS 15.0, *) {
|
|
||||||
let maxFps = Float(UIScreen.main.maximumFramesPerSecond)
|
|
||||||
if maxFps > 61.0 {
|
|
||||||
layerAnimation.preferredFrameRateRange = CAFrameRateRange(minimum: maxFps, maximum: maxFps, preferred: maxFps)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
layerAnimation.isRemovedOnCompletion = false
|
layerAnimation.isRemovedOnCompletion = false
|
||||||
if timeOffset != 0 {
|
if timeOffset != 0 {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user