mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-24 07:05:35 +00:00
Statistics improvements
This commit is contained in:
@@ -2,6 +2,7 @@ import Foundation
|
||||
import UIKit
|
||||
import Display
|
||||
import AsyncDisplayKit
|
||||
import ComponentFlow
|
||||
import SwiftSignalKit
|
||||
import Postbox
|
||||
import TelegramCore
|
||||
@@ -11,23 +12,28 @@ import TelegramStringFormatting
|
||||
import ItemListUI
|
||||
import PresentationDataUtils
|
||||
import PhotoResources
|
||||
import AvatarStoryIndicatorComponent
|
||||
|
||||
public class StatsMessageItem: ListViewItem, ItemListItem {
|
||||
let context: AccountContext
|
||||
let presentationData: ItemListPresentationData
|
||||
let message: Message
|
||||
let peer: Peer
|
||||
let item: StatsPostItem
|
||||
let views: Int32
|
||||
let reactions: Int32
|
||||
let forwards: Int32
|
||||
public let sectionId: ItemListSectionId
|
||||
let style: ItemListStyle
|
||||
let action: (() -> Void)?
|
||||
let contextAction: ((ASDisplayNode, ContextGesture?) -> Void)?
|
||||
|
||||
init(context: AccountContext, presentationData: ItemListPresentationData, message: Message, views: Int32, forwards: Int32, sectionId: ItemListSectionId, style: ItemListStyle, action: (() -> Void)?, contextAction: ((ASDisplayNode, ContextGesture?) -> Void)?) {
|
||||
init(context: AccountContext, presentationData: ItemListPresentationData, peer: Peer, item: StatsPostItem, views: Int32, reactions: Int32, forwards: Int32, sectionId: ItemListSectionId, style: ItemListStyle, action: (() -> Void)?, contextAction: ((ASDisplayNode, ContextGesture?) -> Void)?) {
|
||||
self.context = context
|
||||
self.presentationData = presentationData
|
||||
self.message = message
|
||||
self.peer = peer
|
||||
self.item = item
|
||||
self.views = views
|
||||
self.reactions = reactions
|
||||
self.forwards = forwards
|
||||
self.sectionId = sectionId
|
||||
self.style = style
|
||||
@@ -79,7 +85,7 @@ public class StatsMessageItem: ListViewItem, ItemListItem {
|
||||
|
||||
private let badgeFont = Font.regular(15.0)
|
||||
|
||||
public class StatsMessageItemNode: ListViewItemNode, ItemListItemNode {
|
||||
final class StatsMessageItemNode: ListViewItemNode, ItemListItemNode {
|
||||
private let backgroundNode: ASDisplayNode
|
||||
private let topStripeNode: ASDisplayNode
|
||||
private let bottomStripeNode: ASDisplayNode
|
||||
@@ -96,9 +102,14 @@ public class StatsMessageItemNode: ListViewItemNode, ItemListItemNode {
|
||||
private var nonExtractedRect: CGRect?
|
||||
|
||||
let contentImageNode: TransformImageNode
|
||||
var storyIndicator: ComponentView<Empty>?
|
||||
let titleNode: TextNode
|
||||
let labelNode: TextNode
|
||||
let viewsNode: TextNode
|
||||
|
||||
let reactionsIconNode: ASImageNode
|
||||
let reactionsNode: TextNode
|
||||
let forwardsIconNode: ASImageNode
|
||||
let forwardsNode: TextNode
|
||||
|
||||
private let activateArea: AccessibilityAreaNode
|
||||
@@ -152,6 +163,15 @@ public class StatsMessageItemNode: ListViewItemNode, ItemListItemNode {
|
||||
self.forwardsNode = TextNode()
|
||||
self.forwardsNode.isUserInteractionEnabled = false
|
||||
|
||||
self.forwardsIconNode = ASImageNode()
|
||||
self.forwardsIconNode.displaysAsynchronously = false
|
||||
|
||||
self.reactionsNode = TextNode()
|
||||
self.reactionsNode.isUserInteractionEnabled = false
|
||||
|
||||
self.reactionsIconNode = ASImageNode()
|
||||
self.reactionsIconNode.displaysAsynchronously = false
|
||||
|
||||
self.highlightedBackgroundNode = ASDisplayNode()
|
||||
self.highlightedBackgroundNode.isLayerBacked = true
|
||||
|
||||
@@ -172,6 +192,9 @@ public class StatsMessageItemNode: ListViewItemNode, ItemListItemNode {
|
||||
self.offsetContainerNode.addSubnode(self.labelNode)
|
||||
self.countersContainerNode.addSubnode(self.viewsNode)
|
||||
self.countersContainerNode.addSubnode(self.forwardsNode)
|
||||
self.countersContainerNode.addSubnode(self.forwardsIconNode)
|
||||
self.countersContainerNode.addSubnode(self.reactionsNode)
|
||||
self.countersContainerNode.addSubnode(self.reactionsIconNode)
|
||||
self.containerNode.targetNodeForActivationProgress = self.contextSourceNode.contentNode
|
||||
|
||||
self.addSubnode(self.activateArea)
|
||||
@@ -200,8 +223,8 @@ public class StatsMessageItemNode: ListViewItemNode, ItemListItemNode {
|
||||
|
||||
transition.updateAlpha(node: strongSelf.countersContainerNode, alpha: isExtracted ? 0.0 : 1.0)
|
||||
|
||||
transition.updateSublayerTransformOffset(layer: strongSelf.countersContainerNode.layer, offset: CGPoint(x: isExtracted ? -24.0 : 0.0, y: 0.0))
|
||||
transition.updateSublayerTransformOffset(layer: strongSelf.offsetContainerNode.layer, offset: CGPoint(x: isExtracted ? 12.0 : 0.0, y: 0.0))
|
||||
transition.updateSublayerTransformOffset(layer: strongSelf.countersContainerNode.layer, offset: CGPoint(x: isExtracted ? -16.0 : 0.0, y: 0.0))
|
||||
transition.updateSublayerTransformOffset(layer: strongSelf.offsetContainerNode.layer, offset: CGPoint(x: isExtracted ? 16.0 : 0.0, y: 0.0))
|
||||
|
||||
transition.updateAlpha(node: strongSelf.extractedBackgroundImageNode, alpha: isExtracted ? 1.0 : 0.0, completion: { _ in
|
||||
if !isExtracted {
|
||||
@@ -215,6 +238,7 @@ public class StatsMessageItemNode: ListViewItemNode, ItemListItemNode {
|
||||
let makeTitleLayout = TextNode.asyncLayout(self.titleNode)
|
||||
let makeLabelLayout = TextNode.asyncLayout(self.labelNode)
|
||||
let makeViewsLayout = TextNode.asyncLayout(self.viewsNode)
|
||||
let makeReactionsLayout = TextNode.asyncLayout(self.reactionsNode)
|
||||
let makeForwardsLayout = TextNode.asyncLayout(self.forwardsNode)
|
||||
|
||||
let currentItem = self.item
|
||||
@@ -236,67 +260,100 @@ public class StatsMessageItemNode: ListViewItemNode, ItemListItemNode {
|
||||
let leftInset = 16.0 + params.leftInset
|
||||
let rightInset = 16.0 + params.rightInset
|
||||
var totalLeftInset = leftInset
|
||||
let additionalRightInset: CGFloat = 128.0
|
||||
|
||||
let titleFont = Font.regular(item.presentationData.fontSize.itemListBaseFontSize)
|
||||
let titleFont = Font.semibold(item.presentationData.fontSize.itemListBaseFontSize)
|
||||
let labelFont = Font.regular(floor(item.presentationData.fontSize.itemListBaseFontSize * 13.0 / 17.0))
|
||||
|
||||
let presentationData = item.context.sharedContext.currentPresentationData.with { $0 }
|
||||
let contentKind = messageContentKind(contentSettings: item.context.currentContentSettings.with { $0 }, message: EngineMessage(item.message), strings: item.presentationData.strings, nameDisplayOrder: .firstLast, dateTimeFormat: presentationData.dateTimeFormat, accountPeerId: item.context.account.peerId)
|
||||
var text = !item.message.text.isEmpty ? item.message.text : stringForMediaKind(contentKind, strings: item.presentationData.strings).0.string
|
||||
text = foldLineBreaks(text)
|
||||
|
||||
var text: String
|
||||
var contentImageMedia: Media?
|
||||
for media in item.message.media {
|
||||
if let image = media as? TelegramMediaImage {
|
||||
contentImageMedia = image
|
||||
break
|
||||
} else if let file = media as? TelegramMediaFile {
|
||||
if file.isVideo && !file.isInstantVideo {
|
||||
contentImageMedia = file
|
||||
break
|
||||
}
|
||||
} else if let webpage = media as? TelegramMediaWebpage, case let .Loaded(content) = webpage.content {
|
||||
if let image = content.image {
|
||||
let timestamp: Int32
|
||||
|
||||
switch item.item {
|
||||
case let .message(message):
|
||||
let contentKind: MessageContentKind
|
||||
contentKind = messageContentKind(contentSettings: item.context.currentContentSettings.with { $0 }, message: EngineMessage(message), strings: item.presentationData.strings, nameDisplayOrder: .firstLast, dateTimeFormat: presentationData.dateTimeFormat, accountPeerId: item.context.account.peerId)
|
||||
text = !message.text.isEmpty ? message.text : stringForMediaKind(contentKind, strings: item.presentationData.strings).0.string
|
||||
|
||||
for media in message.media {
|
||||
if let image = media as? TelegramMediaImage {
|
||||
contentImageMedia = image
|
||||
break
|
||||
} else if let file = content.file {
|
||||
} else if let file = media as? TelegramMediaFile {
|
||||
if file.isVideo && !file.isInstantVideo {
|
||||
contentImageMedia = file
|
||||
break
|
||||
}
|
||||
} else if let webpage = media as? TelegramMediaWebpage, case let .Loaded(content) = webpage.content {
|
||||
if let image = content.image {
|
||||
contentImageMedia = image
|
||||
break
|
||||
} else if let file = content.file {
|
||||
if file.isVideo && !file.isInstantVideo {
|
||||
contentImageMedia = file
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
timestamp = message.timestamp
|
||||
case let .story(story):
|
||||
text = item.presentationData.strings.Message_Story
|
||||
timestamp = story.timestamp
|
||||
if let image = story.media._asMedia() as? TelegramMediaImage {
|
||||
contentImageMedia = image
|
||||
break
|
||||
} else if let file = story.media._asMedia() as? TelegramMediaFile {
|
||||
contentImageMedia = file
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
text = foldLineBreaks(text)
|
||||
|
||||
if let _ = contentImageMedia {
|
||||
totalLeftInset += 48.0
|
||||
totalLeftInset += 46.0
|
||||
}
|
||||
|
||||
var updateImageSignal: Signal<(TransformImageArguments) -> DrawingContext?, NoError>?
|
||||
if let contentImageMedia = contentImageMedia {
|
||||
if let currentContentImageMedia = currentContentImageMedia, contentImageMedia.isSemanticallyEqual(to: currentContentImageMedia) {
|
||||
} else {
|
||||
if let image = contentImageMedia as? TelegramMediaImage {
|
||||
updateImageSignal = mediaGridMessagePhoto(account: item.context.account, userLocation: .peer(item.message.id.peerId), photoReference: .message(message: MessageReference(item.message), media: image))
|
||||
} else if let file = contentImageMedia as? TelegramMediaFile {
|
||||
updateImageSignal = mediaGridMessageVideo(postbox: item.context.account.postbox, userLocation: .peer(item.message.id.peerId), videoReference: .message(message: MessageReference(item.message), media: file), autoFetchFullSizeThumbnail: true)
|
||||
switch item.item {
|
||||
case let .message(message):
|
||||
if let image = contentImageMedia as? TelegramMediaImage {
|
||||
updateImageSignal = mediaGridMessagePhoto(account: item.context.account, userLocation: .peer(message.id.peerId), photoReference: .message(message: MessageReference(message), media: image))
|
||||
} else if let file = contentImageMedia as? TelegramMediaFile {
|
||||
updateImageSignal = mediaGridMessageVideo(postbox: item.context.account.postbox, userLocation: .peer(message.id.peerId), videoReference: .message(message: MessageReference(message), media: file), autoFetchFullSizeThumbnail: true)
|
||||
}
|
||||
case let .story(story):
|
||||
if let peerReference = PeerReference(item.peer) {
|
||||
if let image = contentImageMedia as? TelegramMediaImage {
|
||||
updateImageSignal = mediaGridMessagePhoto(account: item.context.account, userLocation: .peer(item.peer.id), photoReference: .story(peer: peerReference, id: story.id, media: image))
|
||||
} else if let file = contentImageMedia as? TelegramMediaFile {
|
||||
updateImageSignal = mediaGridMessageVideo(postbox: item.context.account.postbox, userLocation: .peer(item.peer.id), videoReference: .story(peer: peerReference, id: story.id, media: file), autoFetchFullSizeThumbnail: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: text, font: titleFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - totalLeftInset - rightInset - additionalRightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
let labelFont = Font.regular(floor(item.presentationData.fontSize.itemListBaseFontSize * 13.0 / 17.0))
|
||||
|
||||
let label = stringForMediumDate(timestamp: item.message.timestamp, strings: item.presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat)
|
||||
|
||||
let (labelLayout, labelApply) = makeLabelLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: label, font: labelFont, textColor: item.presentationData.theme.list.itemSecondaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - totalLeftInset - rightInset - additionalRightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
let (viewsLayout, viewsApply) = makeViewsLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.presentationData.strings.Stats_MessageViews(item.views), font: labelFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: 128.0, height: CGFloat.greatestFiniteMagnitude), alignment: .right, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
let (forwardsLayout, forwardsApply) = makeForwardsLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.presentationData.strings.Stats_MessageForwards(item.forwards), font: labelFont, textColor: item.presentationData.theme.list.itemSecondaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: 128.0, height: CGFloat.greatestFiniteMagnitude), alignment: .right, cutout: nil, insets: UIEdgeInsets()))
|
||||
let reactions = item.reactions > 0 ? compactNumericCountString(Int(item.reactions), decimalSeparator: item.presentationData.dateTimeFormat.decimalSeparator) : ""
|
||||
let (reactionsLayout, reactionsApply) = makeReactionsLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: reactions, font: labelFont, textColor: item.presentationData.theme.list.itemSecondaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: 128.0, height: CGFloat.greatestFiniteMagnitude), alignment: .right, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
let verticalInset: CGFloat = 11.0
|
||||
let forwards = item.forwards > 0 ? compactNumericCountString(Int(item.forwards), decimalSeparator: item.presentationData.dateTimeFormat.decimalSeparator) : ""
|
||||
let (forwardsLayout, forwardsApply) = makeForwardsLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: forwards, font: labelFont, textColor: item.presentationData.theme.list.itemSecondaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: 128.0, height: CGFloat.greatestFiniteMagnitude), alignment: .right, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
let additionalRightInset = max(viewsLayout.size.width, reactionsLayout.size.width + forwardsLayout.size.width + 36.0) + 8.0
|
||||
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: text, font: titleFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - totalLeftInset - rightInset - additionalRightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
let label = stringForMediumDate(timestamp: timestamp, strings: item.presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat)
|
||||
let (labelLayout, labelApply) = makeLabelLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: label, font: labelFont, textColor: item.presentationData.theme.list.itemSecondaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - totalLeftInset - rightInset - additionalRightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
let verticalInset: CGFloat = 10.0
|
||||
let titleSpacing: CGFloat = 3.0
|
||||
|
||||
let height: CGFloat = verticalInset * 2.0 + titleLayout.size.height + titleSpacing + labelLayout.size.height
|
||||
@@ -318,8 +375,14 @@ public class StatsMessageItemNode: ListViewItemNode, ItemListItemNode {
|
||||
|
||||
return (ListViewItemNodeLayout(contentSize: contentSize, insets: insets), { [weak self] in
|
||||
if let strongSelf = self {
|
||||
let themeUpdated = strongSelf.item?.presentationData.theme !== item.presentationData.theme
|
||||
strongSelf.item = item
|
||||
|
||||
if themeUpdated {
|
||||
strongSelf.forwardsIconNode.image = PresentationResourcesItemList.statsForwardsIcon(item.presentationData.theme)
|
||||
strongSelf.reactionsIconNode.image = PresentationResourcesItemList.statsReactionsIcon(item.presentationData.theme)
|
||||
}
|
||||
|
||||
let nonExtractedRect = CGRect(origin: CGPoint(), size: CGSize(width: layout.contentSize.width - 16.0, height: layout.contentSize.height))
|
||||
let extractedRect = CGRect(origin: CGPoint(), size: layout.contentSize).insetBy(dx: 16.0 + params.leftInset, dy: 0.0)
|
||||
strongSelf.extractedRect = extractedRect
|
||||
@@ -357,13 +420,21 @@ public class StatsMessageItemNode: ListViewItemNode, ItemListItemNode {
|
||||
dimensions = contentImageMedia.dimensions?.cgSize
|
||||
}
|
||||
|
||||
let contentImageSize = CGSize(width: 40.0, height: 40.0)
|
||||
|
||||
var contentImageSize = CGSize(width: 40.0, height: 40.0)
|
||||
var contentImageInset = leftInset - 6.0
|
||||
if let dimensions = dimensions {
|
||||
let makeImageLayout = strongSelf.contentImageNode.asyncLayout()
|
||||
let imageSize = contentImageSize
|
||||
|
||||
let applyImageLayout = makeImageLayout(TransformImageArguments(corners: ImageCorners(radius: 4.0), imageSize: dimensions.aspectFilled(imageSize), boundingSize: imageSize, intrinsicInsets: UIEdgeInsets()))
|
||||
let cornerRadius: CGFloat
|
||||
if case .story = item.item {
|
||||
contentImageInset += 3.0
|
||||
contentImageSize = CGSize(width: 34.0, height: 34.0)
|
||||
cornerRadius = contentImageSize.width / 2.0
|
||||
} else {
|
||||
cornerRadius = 6.0
|
||||
}
|
||||
|
||||
let applyImageLayout = makeImageLayout(TransformImageArguments(corners: ImageCorners(radius: cornerRadius), imageSize: dimensions.aspectFilled(contentImageSize), boundingSize: contentImageSize, intrinsicInsets: UIEdgeInsets()))
|
||||
applyImageLayout()
|
||||
|
||||
if let updateImageSignal = updateImageSignal {
|
||||
@@ -384,6 +455,7 @@ public class StatsMessageItemNode: ListViewItemNode, ItemListItemNode {
|
||||
let _ = labelApply()
|
||||
let _ = viewsApply()
|
||||
let _ = forwardsApply()
|
||||
let _ = reactionsApply()
|
||||
|
||||
switch item.style {
|
||||
case .plain:
|
||||
@@ -427,7 +499,7 @@ public class StatsMessageItemNode: ListViewItemNode, ItemListItemNode {
|
||||
let bottomStripeInset: CGFloat
|
||||
switch neighbors.bottom {
|
||||
case .sameSection(false):
|
||||
bottomStripeInset = leftInset
|
||||
bottomStripeInset = totalLeftInset
|
||||
strongSelf.bottomStripeNode.isHidden = false
|
||||
default:
|
||||
bottomStripeInset = 0.0
|
||||
@@ -443,22 +515,106 @@ public class StatsMessageItemNode: ListViewItemNode, ItemListItemNode {
|
||||
strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height - separatorHeight), size: CGSize(width: params.width - bottomStripeInset, height: separatorHeight))
|
||||
}
|
||||
|
||||
let contentImageFrame = CGRect(origin: CGPoint(x: leftInset, y: floorToScreenPixels((height - contentImageSize.height) / 2.0)), size: contentImageSize)
|
||||
let contentImageFrame = CGRect(origin: CGPoint(x: contentImageInset, y: floorToScreenPixels((height - contentImageSize.height) / 2.0)), size: contentImageSize)
|
||||
strongSelf.contentImageNode.frame = contentImageFrame
|
||||
|
||||
let titleFrame = CGRect(origin: CGPoint(x: totalLeftInset, y: 11.0), size: titleLayout.size)
|
||||
let titleFrame = CGRect(origin: CGPoint(x: totalLeftInset, y: 9.0), size: titleLayout.size)
|
||||
strongSelf.titleNode.frame = titleFrame
|
||||
|
||||
let labelFrame = CGRect(origin: CGPoint(x: totalLeftInset, y: titleFrame.maxY + titleSpacing), size: labelLayout.size)
|
||||
strongSelf.labelNode.frame = labelFrame
|
||||
|
||||
let viewsFrame = CGRect(origin: CGPoint(x: params.width - rightInset - viewsLayout.size.width, y: 15.0), size: viewsLayout.size)
|
||||
let viewsFrame = CGRect(origin: CGPoint(x: params.width - rightInset - viewsLayout.size.width, y: 13.0), size: viewsLayout.size)
|
||||
strongSelf.viewsNode.frame = viewsFrame
|
||||
|
||||
let forwardsFrame = CGRect(origin: CGPoint(x: params.width - rightInset - forwardsLayout.size.width, y: titleFrame.maxY + titleSpacing), size: forwardsLayout.size)
|
||||
strongSelf.forwardsNode.frame = forwardsFrame
|
||||
|
||||
let iconSpacing: CGFloat = 3.0 - UIScreenPixel
|
||||
|
||||
var rightContentInset: CGFloat = rightInset
|
||||
if forwardsLayout.size.width > 0.0 {
|
||||
strongSelf.forwardsIconNode.isHidden = false
|
||||
strongSelf.forwardsNode.isHidden = false
|
||||
|
||||
let forwardsFrame = CGRect(origin: CGPoint(x: params.width - rightContentInset - forwardsLayout.size.width, y: titleFrame.maxY + titleSpacing), size: forwardsLayout.size)
|
||||
strongSelf.forwardsNode.frame = forwardsFrame
|
||||
|
||||
if let icon = strongSelf.forwardsIconNode.image {
|
||||
let forwardsIconFrame = CGRect(origin: CGPoint(x: params.width - rightContentInset - forwardsLayout.size.width - icon.size.width - iconSpacing, y: titleFrame.maxY + titleSpacing - 2.0 + UIScreenPixel), size: icon.size)
|
||||
strongSelf.forwardsIconNode.frame = forwardsIconFrame
|
||||
|
||||
rightContentInset += forwardsIconFrame.width + forwardsFrame.width + iconSpacing
|
||||
}
|
||||
rightContentInset += 10.0
|
||||
} else {
|
||||
strongSelf.forwardsIconNode.isHidden = true
|
||||
strongSelf.forwardsNode.isHidden = true
|
||||
}
|
||||
|
||||
if reactionsLayout.size.width > 0.0 {
|
||||
strongSelf.reactionsIconNode.isHidden = false
|
||||
strongSelf.reactionsNode.isHidden = false
|
||||
|
||||
let reactionsFrame = CGRect(origin: CGPoint(x: params.width - rightContentInset - reactionsLayout.size.width, y: titleFrame.maxY + titleSpacing), size: reactionsLayout.size)
|
||||
strongSelf.reactionsNode.frame = reactionsFrame
|
||||
|
||||
if let icon = strongSelf.reactionsIconNode.image {
|
||||
let reactionsIconFrame = CGRect(origin: CGPoint(x: params.width - rightContentInset - reactionsLayout.size.width - icon.size.width - iconSpacing, y: titleFrame.maxY + titleSpacing - 2.0 + UIScreenPixel), size: icon.size)
|
||||
strongSelf.reactionsIconNode.frame = reactionsIconFrame
|
||||
|
||||
rightContentInset += reactionsIconFrame.width + reactionsFrame.width + iconSpacing
|
||||
}
|
||||
} else {
|
||||
strongSelf.reactionsIconNode.isHidden = true
|
||||
strongSelf.reactionsNode.isHidden = true
|
||||
}
|
||||
|
||||
strongSelf.highlightedBackgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -UIScreenPixel), size: CGSize(width: params.width, height: height + UIScreenPixel))
|
||||
|
||||
if case .story = item.item {
|
||||
let lineWidth: CGFloat = 1.5
|
||||
let imageSize = CGSize(width: contentImageFrame.width + 6.0, height: contentImageFrame.height + 6.0)
|
||||
let indicatorSize = CGSize(width: imageSize.width - lineWidth * 4.0, height: imageSize.height - lineWidth * 4.0)
|
||||
|
||||
let storyIndicator: ComponentView<Empty>
|
||||
let indicatorTransition: Transition = .immediate
|
||||
if let current = strongSelf.storyIndicator {
|
||||
storyIndicator = current
|
||||
} else {
|
||||
storyIndicator = ComponentView()
|
||||
strongSelf.storyIndicator = storyIndicator
|
||||
}
|
||||
let _ = storyIndicator.update(
|
||||
transition: indicatorTransition,
|
||||
component: AnyComponent(AvatarStoryIndicatorComponent(
|
||||
hasUnseen: true,
|
||||
hasUnseenCloseFriendsItems: false,
|
||||
colors: AvatarStoryIndicatorComponent.Colors(
|
||||
unseenColors: item.presentationData.theme.chatList.storyUnseenColors.array,
|
||||
unseenCloseFriendsColors: item.presentationData.theme.chatList.storyUnseenPrivateColors.array,
|
||||
seenColors: item.presentationData.theme.chatList.storySeenColors.array
|
||||
),
|
||||
activeLineWidth: lineWidth,
|
||||
inactiveLineWidth: lineWidth,
|
||||
counters: AvatarStoryIndicatorComponent.Counters(
|
||||
totalCount: 1,
|
||||
unseenCount: 1
|
||||
),
|
||||
progress: nil
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: indicatorSize
|
||||
)
|
||||
if let storyIndicatorView = storyIndicator.view {
|
||||
if storyIndicatorView.superview == nil {
|
||||
strongSelf.offsetContainerNode.view.addSubview(storyIndicatorView)
|
||||
}
|
||||
indicatorTransition.setFrame(view: storyIndicatorView, frame: CGRect(origin: CGPoint(x: contentImageFrame.midX - indicatorSize.width / 2.0, y: contentImageFrame.midY - indicatorSize.height / 2.0), size: indicatorSize))
|
||||
}
|
||||
} else if let storyIndicator = strongSelf.storyIndicator {
|
||||
if let storyIndicatorView = storyIndicator.view {
|
||||
storyIndicatorView.removeFromSuperview()
|
||||
}
|
||||
strongSelf.storyIndicator = nil
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user