mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-24 07:05:35 +00:00
Various improvements
This commit is contained in:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user