Various improvements

This commit is contained in:
Ilya Laktyushin
2022-10-04 17:20:21 +03:00
parent 533085c77a
commit 308bc5ad6a
14 changed files with 1080 additions and 131 deletions

View File

@@ -12,6 +12,8 @@ import TelegramStringFormatting
import AccountContext
import ChatPresentationInterfaceState
import WallpaperBackgroundNode
import ComponentFlow
import EmojiStatusComponent
private protocol ChatEmptyNodeContent {
func updateLayout(interfaceState: ChatPresentationInterfaceState, size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize
@@ -775,13 +777,128 @@ private final class ChatEmptyNodeCloudChatContent: ASDisplayNode, ChatEmptyNodeC
}
}
private enum ChatEmptyNodeContentType {
final class ChatEmptyNodeTopicChatContent: ASDisplayNode, ChatEmptyNodeContent, UIGestureRecognizerDelegate {
private let context: AccountContext
private let fileId: Int64?
private let titleNode: ImmediateTextNode
private let textNode: ImmediateTextNode
private var currentTheme: PresentationTheme?
private var currentStrings: PresentationStrings?
private let iconView: ComponentView<Empty>
init(context: AccountContext, fileId: Int64?) {
self.context = context
self.fileId = fileId
self.titleNode = ImmediateTextNode()
self.titleNode.maximumNumberOfLines = 0
self.titleNode.lineSpacing = 0.15
self.titleNode.textAlignment = .center
self.titleNode.isUserInteractionEnabled = false
self.titleNode.displaysAsynchronously = false
self.textNode = ImmediateTextNode()
self.textNode.maximumNumberOfLines = 0
self.textNode.lineSpacing = 0.15
self.textNode.textAlignment = .center
self.textNode.isUserInteractionEnabled = false
self.textNode.displaysAsynchronously = false
self.iconView = ComponentView<Empty>()
super.init()
self.addSubnode(self.titleNode)
self.addSubnode(self.textNode)
}
func updateLayout(interfaceState: ChatPresentationInterfaceState, size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize {
let serviceColor = serviceMessageColorComponents(theme: interfaceState.theme, wallpaper: interfaceState.chatWallpaper)
if self.currentTheme !== interfaceState.theme || self.currentStrings !== interfaceState.strings {
self.currentTheme = interfaceState.theme
self.currentStrings = interfaceState.strings
self.titleNode.attributedText = NSAttributedString(string: "Almost done!", font: titleFont, textColor: serviceColor.primaryText)
self.textNode.attributedText = NSAttributedString(string: "Send first message to\nstart this topic.", font: messageFont, textColor: serviceColor.primaryText)
}
let inset: CGFloat
if size.width == 320.0 {
inset = 8.0
} else {
inset = 15.0
}
let title = ""
let iconContent: EmojiStatusComponent.Content
if let fileId = self.fileId {
iconContent = .animation(content: .customEmoji(fileId: fileId), size: CGSize(width: 32.0, height: 32.0), placeholderColor: .clear, themeColor: serviceColor.primaryText, loopMode: .count(2))
} else {
iconContent = .topic(title: String(title.prefix(1)))
}
let insets = UIEdgeInsets(top: inset, left: inset, bottom: inset, right: inset)
let titleSpacing: CGFloat = 6.0
let iconSpacing: CGFloat = 9.0
let iconSize = self.iconView.update(
transition: .easeInOut(duration: 0.2),
component: AnyComponent(EmojiStatusComponent(
context: self.context,
animationCache: self.context.animationCache,
animationRenderer: self.context.animationRenderer,
content: iconContent,
isVisibleForAnimations: true,
action: nil
)),
environment: {},
containerSize: CGSize(width: 54.0, height: 54.0)
)
var contentWidth: CGFloat = 196.0
var contentHeight: CGFloat = 0.0
let titleSize = self.titleNode.updateLayout(CGSize(width: contentWidth, height: CGFloat.greatestFiniteMagnitude))
let textSize = self.textNode.updateLayout(CGSize(width: contentWidth, height: CGFloat.greatestFiniteMagnitude))
contentWidth = max(contentWidth, max(titleSize.width, textSize.width))
contentHeight += titleSize.height + titleSpacing + textSize.height + iconSpacing + iconSize.height
let contentRect = CGRect(origin: CGPoint(x: insets.left, y: insets.top), size: CGSize(width: contentWidth, height: contentHeight))
let iconFrame = CGRect(origin: CGPoint(x: contentRect.minX + floor((contentRect.width - iconSize.width) / 2.0), y: contentRect.minY), size: iconSize)
if let iconComponentView = self.iconView.view {
if iconComponentView.superview == nil {
self.view.addSubview(iconComponentView)
}
transition.updateFrame(view: iconComponentView, frame: iconFrame)
}
let titleFrame = CGRect(origin: CGPoint(x: contentRect.minX + floor((contentRect.width - titleSize.width) / 2.0), y: iconFrame.maxY + iconSpacing), size: titleSize)
transition.updateFrame(node: self.titleNode, frame: titleFrame)
let textFrame = CGRect(origin: CGPoint(x: contentRect.minX + floor((contentRect.width - textSize.width) / 2.0), y: titleFrame.maxY + titleSpacing), size: textSize)
transition.updateFrame(node: self.textNode, frame: textFrame)
return contentRect.insetBy(dx: -insets.left, dy: -insets.top).size
}
}
private enum ChatEmptyNodeContentType: Equatable {
case regular
case secret
case group
case cloud
case peerNearby
case greeting
case topic(Int64?)
}
final class ChatEmptyNode: ASDisplayNode {
@@ -857,9 +974,13 @@ final class ChatEmptyNode: ASDisplayNode {
let contentType: ChatEmptyNodeContentType
if case .replyThread = interfaceState.chatLocation {
contentType = .regular
if case .topic = emptyType {
contentType = .topic(nil)
} else {
contentType = .regular
}
} else if let peer = interfaceState.renderedPeer?.peer, !isScheduledMessages {
if peer.id == self.context.account.peerId {
if peer.id == self.context.account.peerId {
contentType = .cloud
} else if let _ = peer as? TelegramSecretChat {
contentType = .secret
@@ -890,7 +1011,7 @@ final class ChatEmptyNode: ASDisplayNode {
var animateContentIn = false
if let node = self.content?.1 {
node.removeFromSupernode()
if self.content?.0 != nil && contentType == .greeting && transition.isAnimated {
if self.content?.0 != nil, case .greeting = contentType, transition.isAnimated {
animateContentIn = true
}
}
@@ -909,6 +1030,8 @@ final class ChatEmptyNode: ASDisplayNode {
case .greeting:
node = ChatEmptyNodeGreetingChatContent(context: self.context, interaction: self.interaction)
updateGreetingSticker = true
case .topic:
node = ChatEmptyNodeTopicChatContent(context: self.context, fileId: nil)
}
self.content = (contentType, node)
self.addSubnode(node)