mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
187 lines
5.8 KiB
Swift
187 lines
5.8 KiB
Swift
import Foundation
|
|
import UIKit
|
|
import AsyncDisplayKit
|
|
import SwiftSignalKit
|
|
|
|
public let displayLinkDispatcher = DisplayLinkDispatcher()
|
|
private let dispatcher = displayLinkDispatcher
|
|
|
|
public enum ImageCorner: Equatable {
|
|
case Corner(CGFloat)
|
|
case Tail(CGFloat, UIImage)
|
|
|
|
public var extendedInsets: CGSize {
|
|
switch self {
|
|
case .Tail:
|
|
return CGSize(width: 4.0, height: 0.0)
|
|
default:
|
|
return CGSize()
|
|
}
|
|
}
|
|
|
|
public var withoutTail: ImageCorner {
|
|
switch self {
|
|
case .Corner:
|
|
return self
|
|
case let .Tail(radius, _):
|
|
return .Corner(radius)
|
|
}
|
|
}
|
|
|
|
public var radius: CGFloat {
|
|
switch self {
|
|
case let .Corner(radius):
|
|
return radius
|
|
case let .Tail(radius, _):
|
|
return radius
|
|
}
|
|
}
|
|
}
|
|
|
|
public func ==(lhs: ImageCorner, rhs: ImageCorner) -> Bool {
|
|
switch lhs {
|
|
case let .Corner(lhsRadius):
|
|
switch rhs {
|
|
case let .Corner(rhsRadius) where abs(lhsRadius - rhsRadius) < CGFloat.ulpOfOne:
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
case let .Tail(lhsRadius, lhsImage):
|
|
if case let .Tail(rhsRadius, rhsImage) = rhs, lhsRadius.isEqual(to: rhsRadius), lhsImage === rhsImage {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
|
|
public func isRoundEqualCorners(_ corners: ImageCorners) -> Bool {
|
|
if case .Corner = corners.topLeft, case .Corner = corners.topRight, case .Corner = corners.bottomLeft, case .Corner = corners.bottomRight {
|
|
if corners.topLeft.radius == corners.topRight.radius && corners.topRight.radius == corners.bottomLeft.radius && corners.bottomLeft.radius == corners.bottomRight.radius {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
public struct ImageCorners: Equatable {
|
|
public let topLeft: ImageCorner
|
|
public let topRight: ImageCorner
|
|
public let bottomLeft: ImageCorner
|
|
public let bottomRight: ImageCorner
|
|
|
|
public var isEmpty: Bool {
|
|
if self.topLeft != .Corner(0.0) {
|
|
return false
|
|
}
|
|
if self.topRight != .Corner(0.0) {
|
|
return false
|
|
}
|
|
if self.bottomLeft != .Corner(0.0) {
|
|
return false
|
|
}
|
|
if self.bottomRight != .Corner(0.0) {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
public init(radius: CGFloat) {
|
|
self.topLeft = .Corner(radius)
|
|
self.topRight = .Corner(radius)
|
|
self.bottomLeft = .Corner(radius)
|
|
self.bottomRight = .Corner(radius)
|
|
}
|
|
|
|
public init(topLeft: ImageCorner, topRight: ImageCorner, bottomLeft: ImageCorner, bottomRight: ImageCorner) {
|
|
self.topLeft = topLeft
|
|
self.topRight = topRight
|
|
self.bottomLeft = bottomLeft
|
|
self.bottomRight = bottomRight
|
|
}
|
|
|
|
public init() {
|
|
self.init(topLeft: .Corner(0.0), topRight: .Corner(0.0), bottomLeft: .Corner(0.0), bottomRight: .Corner(0.0))
|
|
}
|
|
|
|
public var extendedEdges: UIEdgeInsets {
|
|
let left = self.bottomLeft.extendedInsets.width
|
|
let right = self.bottomRight.extendedInsets.width
|
|
|
|
return UIEdgeInsets(top: 0.0, left: left, bottom: 0.0, right: right)
|
|
}
|
|
|
|
public func withRemovedTails() -> ImageCorners {
|
|
return ImageCorners(topLeft: self.topLeft.withoutTail, topRight: self.topRight.withoutTail, bottomLeft: self.bottomLeft.withoutTail, bottomRight: self.bottomRight.withoutTail)
|
|
}
|
|
}
|
|
|
|
public func ==(lhs: ImageCorners, rhs: ImageCorners) -> Bool {
|
|
return lhs.topLeft == rhs.topLeft && lhs.topRight == rhs.topRight && lhs.bottomLeft == rhs.bottomLeft && lhs.bottomRight == rhs.bottomRight
|
|
}
|
|
|
|
public class ImageNode: ASDisplayNode {
|
|
private var disposable = MetaDisposable()
|
|
private let hasImage: ValuePromise<Bool>?
|
|
private var first = true
|
|
private let enableEmpty: Bool
|
|
|
|
public var ready: Signal<Bool, NoError> {
|
|
if let hasImage = self.hasImage {
|
|
return hasImage.get()
|
|
} else {
|
|
return .single(true)
|
|
}
|
|
}
|
|
|
|
public init(enableHasImage: Bool = false, enableEmpty: Bool = false) {
|
|
if enableHasImage {
|
|
self.hasImage = ValuePromise(false, ignoreRepeated: true)
|
|
} else {
|
|
self.hasImage = nil
|
|
}
|
|
self.enableEmpty = enableEmpty
|
|
super.init()
|
|
}
|
|
|
|
deinit {
|
|
self.disposable.dispose()
|
|
}
|
|
|
|
public func setSignal(_ signal: Signal<UIImage?, NoError>) {
|
|
var reportedHasImage = false
|
|
self.disposable.set((signal |> deliverOnMainQueue).start(next: {[weak self] next in
|
|
dispatcher.dispatch {
|
|
if let strongSelf = self {
|
|
if let image = next?.cgImage {
|
|
strongSelf.contents = image
|
|
} else if strongSelf.enableEmpty {
|
|
strongSelf.contents = nil
|
|
}
|
|
if strongSelf.first && next != nil {
|
|
strongSelf.first = false
|
|
if strongSelf.isNodeLoaded {
|
|
strongSelf.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.18)
|
|
}
|
|
}
|
|
if !reportedHasImage {
|
|
if let hasImage = strongSelf.hasImage {
|
|
reportedHasImage = true
|
|
hasImage.set(true)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}))
|
|
}
|
|
|
|
public override func clearContents() {
|
|
super.clearContents()
|
|
|
|
self.contents = nil
|
|
self.disposable.set(nil)
|
|
}
|
|
}
|
|
|