mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
130 lines
4.7 KiB
Swift
130 lines
4.7 KiB
Swift
import Foundation
|
|
import UIKit
|
|
import AsyncDisplayKit
|
|
import Display
|
|
|
|
public enum ChatTitleActivityAnimationStyle {
|
|
case none
|
|
case crossfade
|
|
case slide
|
|
}
|
|
|
|
public enum ChatTitleActivityInfoType {
|
|
case online
|
|
case lastSeenTime
|
|
case generic
|
|
}
|
|
|
|
public enum ChatTitleActivityNodeState: Equatable {
|
|
case none
|
|
case info(NSAttributedString, ChatTitleActivityInfoType)
|
|
case typingText(NSAttributedString, UIColor)
|
|
case uploading(NSAttributedString, UIColor)
|
|
case recordingVoice(NSAttributedString, UIColor)
|
|
case recordingVideo(NSAttributedString, UIColor)
|
|
case playingGame(NSAttributedString, UIColor)
|
|
|
|
func contentNode() -> ChatTitleActivityContentNode? {
|
|
switch self {
|
|
case .none:
|
|
return nil
|
|
case let .info(text, _):
|
|
return ChatTitleActivityContentNode(text: text)
|
|
case let .typingText(text, color):
|
|
return ChatTypingActivityContentNode(text: text, color: color)
|
|
case let .uploading(text, color):
|
|
return ChatUploadingActivityContentNode(text: text, color: color)
|
|
case let .recordingVoice(text, color):
|
|
return ChatRecordingVoiceActivityContentNode(text: text, color: color)
|
|
case let .recordingVideo(text, color):
|
|
return ChatRecordingVideoActivityContentNode(text: text, color: color)
|
|
case let .playingGame(text, color):
|
|
return ChatPlayingActivityContentNode(text: text, color: color)
|
|
}
|
|
}
|
|
|
|
public var string: String? {
|
|
if case let .info(text, _) = self {
|
|
return text.string
|
|
}
|
|
return nil
|
|
}
|
|
}
|
|
|
|
public class ChatTitleActivityNode: ASDisplayNode {
|
|
public private(set) var state: ChatTitleActivityNodeState = .none
|
|
|
|
private var contentNode: ChatTitleActivityContentNode?
|
|
private var nextContentNode: ChatTitleActivityContentNode?
|
|
|
|
override public init() {
|
|
super.init()
|
|
}
|
|
|
|
public func makeCopy() -> ASDisplayNode {
|
|
let node = ASDisplayNode()
|
|
if let contentNode = self.contentNode {
|
|
node.addSubnode(contentNode.makeCopy())
|
|
}
|
|
node.frame = self.frame
|
|
return node
|
|
}
|
|
|
|
public func transitionToState(_ state: ChatTitleActivityNodeState, animation: ChatTitleActivityAnimationStyle = .crossfade, completion: @escaping () -> Void = {}) -> Bool {
|
|
if self.state != state {
|
|
let currentState = self.state
|
|
self.state = state
|
|
|
|
let contentNode = state.contentNode()
|
|
if contentNode !== self.contentNode {
|
|
self.transitionToContentNode(contentNode, state: state, fromState: currentState, animation: animation, completion: completion)
|
|
}
|
|
|
|
return true
|
|
} else {
|
|
completion()
|
|
return false
|
|
}
|
|
}
|
|
|
|
private func transitionToContentNode(_ node: ChatTitleActivityContentNode?, state: ChatTitleActivityNodeState, fromState: ChatTitleActivityNodeState, animation: ChatTitleActivityAnimationStyle = .crossfade, completion: @escaping () -> Void) {
|
|
if let previousContentNode = self.contentNode {
|
|
if case .none = animation {
|
|
previousContentNode.removeFromSupernode()
|
|
self.contentNode = node
|
|
if let contentNode = self.contentNode {
|
|
self.addSubnode(contentNode)
|
|
}
|
|
} else {
|
|
var animation = animation
|
|
if case let .info(_, fromType) = fromState, case let .info(_, toType) = state, fromType == toType {
|
|
animation = .none
|
|
}
|
|
if case .typingText = fromState, case .typingText = state {
|
|
animation = .none
|
|
}
|
|
|
|
self.contentNode = node
|
|
if let contentNode = self.contentNode {
|
|
self.addSubnode(contentNode)
|
|
if self.isNodeLoaded {
|
|
contentNode.animateIn(from: fromState, style: animation)
|
|
}
|
|
}
|
|
previousContentNode.animateOut(to: state, style: animation) {
|
|
previousContentNode.removeFromSupernode()
|
|
}
|
|
}
|
|
} else {
|
|
self.contentNode = node
|
|
if let contentNode = self.contentNode {
|
|
self.addSubnode(contentNode)
|
|
}
|
|
}
|
|
}
|
|
|
|
public func updateLayout(_ constrainedSize: CGSize, alignment: NSTextAlignment) -> CGSize {
|
|
return CGSize(width: 0.0, height: self.contentNode?.updateLayout(constrainedSize, alignment: alignment).height ?? 0.0)
|
|
}
|
|
}
|