mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-22 22:25:57 +00:00
Refactor SettingsUI and related modules
This commit is contained in:
134
submodules/SettingsUI/Sources/BlurredImageNode.swift
Normal file
134
submodules/SettingsUI/Sources/BlurredImageNode.swift
Normal file
@@ -0,0 +1,134 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
import SwiftSignalKit
|
||||
import AsyncDisplayKit
|
||||
import Accelerate
|
||||
import ImageBlur
|
||||
|
||||
private class BlurLayer: CALayer {
|
||||
private static let blurRadiusKey = "blurRadius"
|
||||
@NSManaged var blurRadius: CGFloat
|
||||
|
||||
private var fromBlurRadius: CGFloat?
|
||||
var presentationRadius: CGFloat {
|
||||
if let radius = self.fromBlurRadius {
|
||||
if let layer = presentation() {
|
||||
return layer.blurRadius
|
||||
} else {
|
||||
return radius
|
||||
}
|
||||
} else {
|
||||
return self.blurRadius
|
||||
}
|
||||
}
|
||||
|
||||
override class func needsDisplay(forKey key: String) -> Bool {
|
||||
if key == blurRadiusKey {
|
||||
return true
|
||||
}
|
||||
return super.needsDisplay(forKey: key)
|
||||
}
|
||||
|
||||
open override func action(forKey event: String) -> CAAction? {
|
||||
if event == BlurLayer.blurRadiusKey {
|
||||
self.fromBlurRadius = nil
|
||||
|
||||
if let action = super.action(forKey: "opacity") as? CABasicAnimation {
|
||||
self.fromBlurRadius = (presentation() ?? self).blurRadius
|
||||
|
||||
action.keyPath = event
|
||||
action.fromValue = self.fromBlurRadius
|
||||
return action
|
||||
}
|
||||
}
|
||||
|
||||
return super.action(forKey: event)
|
||||
}
|
||||
|
||||
func draw(_ image: UIImage) {
|
||||
self.contents = image.cgImage
|
||||
self.contentsScale = image.scale
|
||||
self.contentsGravity = .resizeAspectFill
|
||||
}
|
||||
|
||||
func render(in context: CGContext, for layer: CALayer) {
|
||||
layer.render(in: context)
|
||||
}
|
||||
}
|
||||
|
||||
class BlurView: UIView {
|
||||
override class var layerClass : AnyClass {
|
||||
return BlurLayer.self
|
||||
}
|
||||
|
||||
private var blurLayer: BlurLayer {
|
||||
return self.layer as! BlurLayer
|
||||
}
|
||||
|
||||
var image: UIImage?
|
||||
|
||||
private let queue: Queue = {
|
||||
return Queue(name: nil, qos: .userInteractive)
|
||||
}()
|
||||
|
||||
open var blurRadius: CGFloat {
|
||||
set { self.blurLayer.blurRadius = newValue }
|
||||
get { return self.blurLayer.blurRadius }
|
||||
}
|
||||
|
||||
public override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
self.isUserInteractionEnabled = false
|
||||
}
|
||||
|
||||
public required init?(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)
|
||||
self.isUserInteractionEnabled = false
|
||||
}
|
||||
|
||||
private func async(on queue: DispatchQueue, actions: @escaping () -> Void) {
|
||||
queue.async(execute: actions)
|
||||
}
|
||||
|
||||
private func sync(on queue: DispatchQueue, actions: () -> Void) {
|
||||
queue.sync(execute: actions)
|
||||
}
|
||||
|
||||
private func draw(_ image: UIImage, blurRadius: CGFloat) {
|
||||
self.queue.async { [weak self] in
|
||||
if let strongSelf = self, let blurredImage = blurredImage(image, radius: blurRadius) {
|
||||
Queue.mainQueue().sync {
|
||||
strongSelf.blurLayer.draw(blurredImage)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override func display(_ layer: CALayer) {
|
||||
let blurRadius = self.blurLayer.presentationRadius
|
||||
if let image = self.image {
|
||||
self.draw(image, blurRadius: blurRadius)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final class BlurredImageNode: ASDisplayNode {
|
||||
var image: UIImage? {
|
||||
didSet {
|
||||
self.blurView.image = self.image
|
||||
self.blurView.layer.setNeedsDisplay()
|
||||
}
|
||||
}
|
||||
|
||||
var blurView: BlurView {
|
||||
return (self.view as? BlurView)!
|
||||
}
|
||||
|
||||
override init() {
|
||||
super.init()
|
||||
|
||||
self.setViewBlock({
|
||||
return BlurView()
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user