mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-22 14:20:20 +00:00
Conference updates
This commit is contained in:
@@ -10,9 +10,12 @@ import ChatMessageBubbleContentNode
|
||||
import ChatMessageItemCommon
|
||||
import ChatMessageDateAndStatusNode
|
||||
import SwiftSignalKit
|
||||
import AnimatedAvatarSetNode
|
||||
import AvatarNode
|
||||
|
||||
private let titleFont: UIFont = Font.medium(16.0)
|
||||
private let labelFont: UIFont = Font.regular(13.0)
|
||||
private let avatarFont: UIFont = avatarPlaceholderFont(size: 8.0)
|
||||
|
||||
private let incomingGreenIcon = generateTintedImage(image: UIImage(bundleImageName: "Chat/Message/CallIncomingArrow"), color: UIColor(rgb: 0x36c033))
|
||||
private let incomingRedIcon = generateTintedImage(image: UIImage(bundleImageName: "Chat/Message/CallIncomingArrow"), color: UIColor(rgb: 0xff4747))
|
||||
@@ -23,6 +26,11 @@ private let outgoingRedIcon = generateTintedImage(image: UIImage(bundleImageName
|
||||
public class ChatMessageCallBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
private let titleNode: TextNode
|
||||
private let labelNode: TextNode
|
||||
|
||||
private var peopleAvatarsContext: AnimatedAvatarSetContext?
|
||||
private var peopleAvatarsNode: AnimatedAvatarSetNode?
|
||||
private var peopleTextNode: TextNode?
|
||||
|
||||
private let iconNode: ASImageNode
|
||||
private let buttonNode: HighlightableButtonNode
|
||||
|
||||
@@ -82,6 +90,7 @@ public class ChatMessageCallBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
override public func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize, _ avatarInset: CGFloat) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
||||
let makeTitleLayout = TextNode.asyncLayout(self.titleNode)
|
||||
let makeLabelLayout = TextNode.asyncLayout(self.labelNode)
|
||||
let makePeopleTextLayout = TextNode.asyncLayout(self.peopleTextNode)
|
||||
|
||||
return { item, layoutConstants, _, _, _, _ in
|
||||
let contentProperties = ChatMessageBubbleContentProperties(hidesSimpleAuthorHeader: false, headerSpacing: 0.0, hidesBackground: .never, forceFullCorners: false, forceAlignment: .none)
|
||||
@@ -90,8 +99,16 @@ public class ChatMessageCallBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
|
||||
let horizontalInset = layoutConstants.text.bubbleInsets.left + layoutConstants.text.bubbleInsets.right
|
||||
let textConstrainedSize = CGSize(width: constrainedSize.width - horizontalInset, height: constrainedSize.height)
|
||||
|
||||
let avatarsLeftInset: CGFloat = 5.0
|
||||
let avatarsRightInset: CGFloat = 5.0
|
||||
let peopleAvatarSize: CGFloat = 16.0
|
||||
let peopleAvatarSpacing: CGFloat = 10.0
|
||||
|
||||
let messageTheme = incoming ? item.presentationData.theme.theme.chat.message.incoming : item.presentationData.theme.theme.chat.message.outgoing
|
||||
|
||||
var peopleTextString: String?
|
||||
var peopleAvatars: [Peer] = []
|
||||
|
||||
var titleString: String?
|
||||
var callDuration: Int32?
|
||||
@@ -135,6 +152,20 @@ public class ChatMessageCallBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
} else if let action = media as? TelegramMediaAction, case let .conferenceCall(conferenceCall) = action.action {
|
||||
isVideo = conferenceCall.flags.contains(.isVideo)
|
||||
callDuration = conferenceCall.duration
|
||||
|
||||
if conferenceCall.otherParticipants.count > 0 {
|
||||
//TODO:localize
|
||||
peopleTextString = "\(conferenceCall.otherParticipants.count + 1) people"
|
||||
if let peer = item.message.author {
|
||||
peopleAvatars.append(peer)
|
||||
}
|
||||
for id in conferenceCall.otherParticipants {
|
||||
if let peer = item.message.peers[id] {
|
||||
peopleAvatars.append(peer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//TODO:localize
|
||||
let missedTimeout: Int32
|
||||
#if DEBUG
|
||||
@@ -217,17 +248,25 @@ public class ChatMessageCallBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
|
||||
let dateText = stringForMessageTimestampStatus(accountPeerId: item.context.account.peerId, message: item.message, dateTimeFormat: item.presentationData.dateTimeFormat, nameDisplayOrder: item.presentationData.nameDisplayOrder, strings: item.presentationData.strings, associatedData: item.associatedData)
|
||||
|
||||
let statusText: String
|
||||
var statusText: String
|
||||
if let callDuration = callDuration, callDuration > 1 {
|
||||
statusText = item.presentationData.strings.Notification_CallFormat(dateText, callDurationString(strings: item.presentationData.strings, value: callDuration)).string
|
||||
} else {
|
||||
statusText = dateText
|
||||
}
|
||||
if peopleTextString != nil || !peopleAvatars.isEmpty {
|
||||
statusText.append(",")
|
||||
}
|
||||
|
||||
let attributedLabel = NSAttributedString(string: statusText, font: labelFont, textColor: messageTheme.fileDurationColor)
|
||||
|
||||
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: attributedTitle, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: textConstrainedSize, alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
let (labelLayout, labelApply) = makeLabelLayout(TextNodeLayoutArguments(attributedString: attributedLabel, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: textConstrainedSize, alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
var peopleTextLayoutAndApply: (TextNodeLayout, () -> TextNode)?
|
||||
if let peopleTextString {
|
||||
peopleTextLayoutAndApply = makePeopleTextLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: peopleTextString, font: labelFont, textColor: messageTheme.fileDurationColor), backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: textConstrainedSize, alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
}
|
||||
|
||||
let titleSize = titleLayout.size
|
||||
let labelSize = labelLayout.size
|
||||
@@ -239,7 +278,21 @@ public class ChatMessageCallBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
labelFrame = labelFrame.offsetBy(dx: layoutConstants.text.bubbleInsets.left, dy: layoutConstants.text.bubbleInsets.top + titleSize.height + 4.0)
|
||||
|
||||
var boundingSize: CGSize
|
||||
boundingSize = CGSize(width: max(titleFrame.size.width, labelFrame.size.width + 14.0), height: 47.0)
|
||||
|
||||
var labelsWidth: CGFloat = labelFrame.size.width
|
||||
var avatarsWidth: CGFloat = 0.0
|
||||
if !peopleAvatars.isEmpty {
|
||||
avatarsWidth += avatarsLeftInset
|
||||
avatarsWidth += 1.0 * peopleAvatarSize + CGFloat(peopleAvatars.count - 1) * peopleAvatarSpacing
|
||||
avatarsWidth += avatarsRightInset
|
||||
labelsWidth += avatarsWidth
|
||||
}
|
||||
if let peopleTextLayoutAndApply {
|
||||
labelsWidth += peopleTextLayoutAndApply.0.size.width
|
||||
}
|
||||
|
||||
boundingSize = CGSize(width: max(titleFrame.size.width, labelsWidth + 14.0), height: 47.0)
|
||||
|
||||
boundingSize.width += layoutConstants.text.bubbleInsets.left + layoutConstants.text.bubbleInsets.right
|
||||
boundingSize.height += layoutConstants.text.bubbleInsets.top + layoutConstants.text.bubbleInsets.bottom
|
||||
|
||||
@@ -257,6 +310,44 @@ public class ChatMessageCallBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
|
||||
strongSelf.titleNode.frame = titleFrame
|
||||
strongSelf.labelNode.frame = labelFrame
|
||||
|
||||
if !peopleAvatars.isEmpty {
|
||||
let peopleAvatarsContext: AnimatedAvatarSetContext
|
||||
if let current = strongSelf.peopleAvatarsContext {
|
||||
peopleAvatarsContext = current
|
||||
} else {
|
||||
peopleAvatarsContext = AnimatedAvatarSetContext()
|
||||
strongSelf.peopleAvatarsContext = peopleAvatarsContext
|
||||
}
|
||||
let peopleAvatarsNode: AnimatedAvatarSetNode
|
||||
if let current = strongSelf.peopleAvatarsNode {
|
||||
peopleAvatarsNode = current
|
||||
} else {
|
||||
peopleAvatarsNode = AnimatedAvatarSetNode()
|
||||
strongSelf.peopleAvatarsNode = peopleAvatarsNode
|
||||
strongSelf.addSubnode(peopleAvatarsNode)
|
||||
}
|
||||
|
||||
let peopleAvatarsContent = peopleAvatarsContext.update(peers: peopleAvatars.map(EnginePeer.init), animated: false)
|
||||
let peopleAvatarsSize = peopleAvatarsNode.update(context: item.context, content: peopleAvatarsContent, itemSize: CGSize(width: peopleAvatarSize, height: peopleAvatarSize), customSpacing: peopleAvatarSize - peopleAvatarSpacing, font: avatarFont, animated: false, synchronousLoad: false)
|
||||
peopleAvatarsNode.frame = CGRect(origin: CGPoint(x: labelFrame.maxX + avatarsLeftInset, y: labelFrame.minY - 1.0), size: peopleAvatarsSize)
|
||||
} else {
|
||||
strongSelf.peopleAvatarsContext = nil
|
||||
if let peopleAvatarsNode = strongSelf.peopleAvatarsNode {
|
||||
strongSelf.peopleAvatarsNode = nil
|
||||
peopleAvatarsNode.removeFromSupernode()
|
||||
}
|
||||
}
|
||||
|
||||
if let peopleTextLayoutAndApply {
|
||||
let peopleTextNode = peopleTextLayoutAndApply.1()
|
||||
if strongSelf.peopleTextNode !== peopleTextNode {
|
||||
strongSelf.peopleTextNode?.removeFromSupernode()
|
||||
strongSelf.peopleTextNode = peopleTextNode
|
||||
strongSelf.addSubnode(peopleTextNode)
|
||||
}
|
||||
peopleTextNode.frame = CGRect(origin: CGPoint(x: labelFrame.maxX + avatarsWidth, y: labelFrame.minY), size: peopleTextLayoutAndApply.0.size)
|
||||
}
|
||||
|
||||
if let callIcon = callIcon {
|
||||
if strongSelf.iconNode.image != callIcon {
|
||||
|
||||
Reference in New Issue
Block a user