Various fixes

This commit is contained in:
Ilya Laktyushin 2022-09-23 18:55:00 +04:00
parent 6a07227d8d
commit 5fe2dcdc1c
9 changed files with 162 additions and 100 deletions

View File

@ -234,9 +234,24 @@ public class ChatMessageBackground: ASDisplayNode {
})
}
} else if transition.isAnimated {
if let previousContents = self.imageNode.layer.contents, let image = image {
if (previousContents as AnyObject) !== image.cgImage {
self.imageNode.layer.animate(from: previousContents as AnyObject, to: image.cgImage! as AnyObject, keyPath: "contents", timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue, duration: 0.42)
if let previousContents = self.imageNode.layer.contents {
if let image = image {
if (previousContents as AnyObject) !== image.cgImage {
self.imageNode.layer.animate(from: previousContents as AnyObject, to: image.cgImage! as AnyObject, keyPath: "contents", timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue, duration: 0.42)
}
} else {
let tempLayer = CALayer()
tempLayer.contents = self.imageNode.layer.contents
tempLayer.contentsScale = self.imageNode.layer.contentsScale
tempLayer.rasterizationScale = self.imageNode.layer.rasterizationScale
tempLayer.contentsGravity = self.imageNode.layer.contentsGravity
tempLayer.contentsCenter = self.imageNode.layer.contentsCenter
tempLayer.frame = self.bounds
self.layer.insertSublayer(tempLayer, above: self.imageNode.layer)
transition.updateAlpha(layer: tempLayer, alpha: 0.0, completion: { [weak tempLayer] _ in
tempLayer?.removeFromSuperlayer()
})
}
}
}

View File

@ -14,6 +14,7 @@ swift_library(
"//submodules/Postbox:Postbox",
"//submodules/TelegramCore:TelegramCore",
"//submodules/AccountContext:AccountContext",
"//submodules/StringTransliteration:StringTransliteration",
],
visibility = [
"//visibility:public",

View File

@ -2,6 +2,7 @@ import Foundation
import TelegramCore
import SwiftSignalKit
import AccountContext
import StringTransliteration
public enum SearchPeerMembersScope {
case memberSuggestion
@ -9,6 +10,9 @@ public enum SearchPeerMembersScope {
}
public func searchPeerMembers(context: AccountContext, peerId: EnginePeer.Id, chatLocation: ChatLocation, query: String, scope: SearchPeerMembersScope) -> Signal<[EnginePeer], NoError> {
let normalizedQuery = query.lowercased()
let transformedQuery = postboxTransformedString(normalizedQuery as NSString, true, false) ?? normalizedQuery
if peerId.namespace == Namespaces.Peer.CloudChannel {
return context.engine.data.get(
TelegramEngine.EngineData.Item.Peer.ParticipantCount(id: peerId)
@ -18,21 +22,17 @@ public func searchPeerMembers(context: AccountContext, peerId: EnginePeer.Id, ch
return Signal { subscriber in
let (disposable, _) = context.peerChannelMemberCategoriesContextsManager.recent(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: nil, requestUpdate: false, updated: { state in
if case .ready = state.loadingState {
let normalizedQuery = query.lowercased()
subscriber.putNext((state.list.compactMap { participant -> EnginePeer? in
if participant.peer.isDeleted {
return nil
}
if normalizedQuery.isEmpty {
return EnginePeer(participant.peer)
}
if normalizedQuery.isEmpty {
return EnginePeer(participant.peer)
} else {
if participant.peer.indexName.matchesByTokens(normalizedQuery) {
if participant.peer.indexName.matchesByTokens(normalizedQuery) || participant.peer.indexName.matchesByTokens(transformedQuery) {
return EnginePeer(participant.peer)
}
if let addressName = participant.peer.addressName, addressName.lowercased().hasPrefix(normalizedQuery) {
if let addressName = participant.peer.addressName, addressName.lowercased().hasPrefix(normalizedQuery) || addressName.lowercased().hasPrefix(transformedQuery) {
return EnginePeer(participant.peer)
}
@ -52,7 +52,7 @@ public func searchPeerMembers(context: AccountContext, peerId: EnginePeer.Id, ch
return Signal { subscriber in
switch chatLocation {
case let .peer(peerId):
let (disposable, _) = context.peerChannelMemberCategoriesContextsManager.recent(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: query.isEmpty ? nil : query, updated: { state in
let (disposable, _) = context.peerChannelMemberCategoriesContextsManager.recent(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: normalizedQuery.isEmpty ? nil : normalizedQuery, updated: { state in
if case .ready = state.loadingState {
subscriber.putNext((state.list.compactMap { participant in
if participant.peer.isDeleted {
@ -67,7 +67,7 @@ public func searchPeerMembers(context: AccountContext, peerId: EnginePeer.Id, ch
disposable.dispose()
}
case let .replyThread(replyThreadMessage):
let (disposable, _) = context.peerChannelMemberCategoriesContextsManager.mentions(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, threadMessageId: replyThreadMessage.messageId, searchQuery: query.isEmpty ? nil : query, updated: { state in
let (disposable, _) = context.peerChannelMemberCategoriesContextsManager.mentions(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, threadMessageId: replyThreadMessage.messageId, searchQuery: normalizedQuery.isEmpty ? nil : normalizedQuery, updated: { state in
if case .ready = state.loadingState {
subscriber.putNext((state.list.compactMap { participant in
if participant.peer.isDeleted {
@ -99,17 +99,16 @@ public func searchPeerMembers(context: AccountContext, peerId: EnginePeer.Id, ch
)
|> map { peer -> [EnginePeer] in
var result = result
let normalizedQuery = query.lowercased()
if isReady {
if case let .channel(channel) = peer, case .group = channel.info {
var matches = false
if normalizedQuery.isEmpty {
matches = true
} else {
if channel.indexName.matchesByTokens(normalizedQuery) {
if channel.indexName.matchesByTokens(normalizedQuery) || channel.indexName.matchesByTokens(transformedQuery) {
matches = true
}
if let addressName = channel.addressName, addressName.lowercased().hasPrefix(normalizedQuery) {
if let addressName = channel.addressName, addressName.lowercased().hasPrefix(normalizedQuery) || addressName.lowercased().hasPrefix(transformedQuery) {
matches = true
}
}
@ -123,9 +122,29 @@ public func searchPeerMembers(context: AccountContext, peerId: EnginePeer.Id, ch
}
}
} else {
return context.engine.peers.searchGroupMembers(peerId: peerId, query: query)
|> map { peers -> [EnginePeer] in
return peers.map(EnginePeer.init)
let transliteratedPeers: Signal<[EnginePeer], NoError>
if transformedQuery != normalizedQuery {
transliteratedPeers = context.engine.peers.searchGroupMembers(peerId: peerId, query: transformedQuery)
} else {
transliteratedPeers = .single([])
}
return combineLatest(
context.engine.peers.searchGroupMembers(peerId: peerId, query: normalizedQuery),
transliteratedPeers
)
|> map { peers, transliteratedPeers -> [EnginePeer] in
var existingPeerIds = Set<EnginePeer.Id>()
var result = peers
for peer in peers {
existingPeerIds.insert(peer.id)
}
for peer in transliteratedPeers {
if !existingPeerIds.contains(peer.id) {
result.append(peer)
}
}
return result
}
}
}

View File

@ -242,8 +242,11 @@ public extension TelegramEngine {
return _internal_updateChannelOwnership(account: self.account, accountStateManager: self.account.stateManager, channelId: channelId, memberId: memberId, password: password)
}
public func searchGroupMembers(peerId: PeerId, query: String) -> Signal<[Peer], NoError> {
public func searchGroupMembers(peerId: PeerId, query: String) -> Signal<[EnginePeer], NoError> {
return _internal_searchGroupMembers(postbox: self.account.postbox, network: self.account.network, accountPeerId: self.account.peerId, peerId: peerId, query: query)
|> map { peers -> [EnginePeer] in
return peers.map { EnginePeer($0) }
}
}
public func toggleShouldChannelMessagesSignatures(peerId: PeerId, enabled: Bool) -> Signal<Void, NoError> {

View File

@ -1088,6 +1088,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
allReactionsAreAvailable = false
}
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: context.currentAppConfiguration.with { $0 })
if premiumConfiguration.isPremiumDisabled {
allReactionsAreAvailable = false
}
if allReactionsAreAvailable {
actions.getEmojiContent = { animationCache, animationRenderer in
guard let strongSelf = self else {

View File

@ -210,7 +210,7 @@ private final class ChatMessageActionButtonNode: ASDisplayNode {
node.insertSubnode(backgroundContent, at: 0)
let backgroundColorNode = ASDisplayNode()
backgroundColorNode.backgroundColor = UIColor(rgb: 0x000000, alpha: 0.4)
backgroundColorNode.backgroundColor = UIColor(rgb: 0xffffff, alpha: 0.08)
backgroundContent.addSubnode(backgroundColorNode)
node.backgroundColorNode = backgroundColorNode
}
@ -326,7 +326,7 @@ final class ChatMessageActionButtonsNode: ASDisplayNode {
return { context, theme, chatBubbleCorners, strings, backgroundNode, replyMarkup, message, constrainedWidth in
let buttonHeight: CGFloat = 42.0
let buttonSpacing: CGFloat = 4.0
let buttonSpacing: CGFloat = 2.0
var overallMinimumRowWidth: CGFloat = 0.0
@ -379,7 +379,7 @@ final class ChatMessageActionButtonsNode: ASDisplayNode {
var buttonFramesAndApply: [(CGRect, (ListViewItemUpdateAnimation) -> ChatMessageActionButtonNode)] = []
var verticalRowOffset: CGFloat = 0.0
verticalRowOffset += buttonSpacing
verticalRowOffset += buttonSpacing * 0.5
var rowIndex = 0
for finalizeRowButtonLayouts in finalizeRowLayouts {

View File

@ -2257,7 +2257,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
var layoutSize = CGSize(width: params.width, height: layoutBubbleSize.height)
if let reactionButtonsSizeAndApply = reactionButtonsSizeAndApply {
layoutSize.height += 4.0 + reactionButtonsSizeAndApply.0.height
layoutSize.height += 2.0 + reactionButtonsSizeAndApply.0.height
}
if let actionButtonsSizeAndApply = actionButtonsSizeAndApply {
layoutSize.height += actionButtonsSizeAndApply.0.height
@ -2919,81 +2919,6 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
shareButtonNode.removeFromSupernode()
}
if case let .System(duration, _) = animation/*, !strongSelf.mainContextSourceNode.isExtractedToContextPreview*/ {
if !strongSelf.backgroundNode.frame.equalTo(backgroundFrame) {
if useDisplayLinkAnimations {
let backgroundAnimation = ListViewAnimation(from: strongSelf.backgroundNode.frame, to: backgroundFrame, duration: duration * UIView.animationDurationFactor(), curve: strongSelf.preferredAnimationCurve, beginAt: beginAt, update: { [weak strongSelf] _, frame in
if let strongSelf = strongSelf {
strongSelf.backgroundNode.frame = frame
strongSelf.clippingNode.position = CGPoint(x: frame.midX, y: frame.midY)
strongSelf.clippingNode.bounds = CGRect(origin: CGPoint(x: frame.minX, y: frame.minY), size: frame.size)
strongSelf.backgroundNode.updateLayout(size: frame.size, transition: .immediate)
strongSelf.backgroundWallpaperNode.updateFrame(frame, transition: .immediate)
strongSelf.shadowNode.updateLayout(backgroundFrame: frame, transition: .immediate)
}
})
strongSelf.setAnimationForKey("backgroundNodeFrame", animation: backgroundAnimation)
} else {
animation.animator.updateFrame(layer: strongSelf.backgroundNode.layer, frame: backgroundFrame, completion: nil)
animation.animator.updatePosition(layer: strongSelf.clippingNode.layer, position: backgroundFrame.center, completion: nil)
strongSelf.clippingNode.clipsToBounds = true
animation.animator.updateBounds(layer: strongSelf.clippingNode.layer, bounds: CGRect(origin: CGPoint(x: backgroundFrame.minX, y: backgroundFrame.minY), size: backgroundFrame.size), completion: { [weak strongSelf] _ in
strongSelf?.clippingNode.clipsToBounds = false
})
strongSelf.backgroundNode.updateLayout(size: backgroundFrame.size, transition: animation)
animation.animator.updateFrame(layer: strongSelf.backgroundWallpaperNode.layer, frame: backgroundFrame, completion: nil)
strongSelf.shadowNode.updateLayout(backgroundFrame: backgroundFrame, animator: animation.animator)
strongSelf.backgroundWallpaperNode.updateFrame(backgroundFrame, animator: animation.animator)
}
if let _ = strongSelf.backgroundNode.type {
if !strongSelf.mainContextSourceNode.isExtractedToContextPreview {
if let (rect, size) = strongSelf.absoluteRect {
strongSelf.updateAbsoluteRect(rect, within: size)
}
}
}
strongSelf.messageAccessibilityArea.frame = backgroundFrame
}
if let shareButtonNode = strongSelf.shareButtonNode {
let currentBackgroundFrame = strongSelf.backgroundNode.frame
let buttonSize = shareButtonNode.update(presentationData: item.presentationData, controllerInteraction: item.controllerInteraction, chatLocation: item.chatLocation, subject: item.associatedData.subject, message: item.message, account: item.context.account, disableComments: true)
animation.animator.updateFrame(layer: shareButtonNode.layer, frame: CGRect(origin: CGPoint(x: currentBackgroundFrame.maxX + 8.0, y: currentBackgroundFrame.maxY - buttonSize.width - 1.0), size: buttonSize), completion: nil)
}
} else {
/*if let _ = strongSelf.backgroundFrameTransition {
strongSelf.animateFrameTransition(1.0, backgroundFrame.size.height)
strongSelf.backgroundFrameTransition = nil
}*/
strongSelf.messageAccessibilityArea.frame = backgroundFrame
if let shareButtonNode = strongSelf.shareButtonNode {
let buttonSize = shareButtonNode.update(presentationData: item.presentationData, controllerInteraction: item.controllerInteraction, chatLocation: item.chatLocation, subject: item.associatedData.subject, message: item.message, account: item.context.account, disableComments: true)
shareButtonNode.frame = CGRect(origin: CGPoint(x: backgroundFrame.maxX + 8.0, y: backgroundFrame.maxY - buttonSize.width - 1.0), size: buttonSize)
}
if case .System = animation, strongSelf.mainContextSourceNode.isExtractedToContextPreview {
legacyTransition.updateFrame(node: strongSelf.backgroundNode, frame: backgroundFrame)
legacyTransition.updateFrame(node: strongSelf.clippingNode, frame: backgroundFrame)
legacyTransition.updateBounds(node: strongSelf.clippingNode, bounds: CGRect(origin: CGPoint(x: backgroundFrame.minX, y: backgroundFrame.minY), size: backgroundFrame.size))
strongSelf.backgroundNode.updateLayout(size: backgroundFrame.size, transition: legacyTransition)
strongSelf.backgroundWallpaperNode.updateFrame(backgroundFrame, transition: legacyTransition)
strongSelf.shadowNode.updateLayout(backgroundFrame: backgroundFrame, transition: legacyTransition)
} else {
strongSelf.backgroundNode.frame = backgroundFrame
strongSelf.clippingNode.frame = backgroundFrame
strongSelf.clippingNode.bounds = CGRect(origin: CGPoint(x: backgroundFrame.minX, y: backgroundFrame.minY), size: backgroundFrame.size)
strongSelf.backgroundNode.updateLayout(size: backgroundFrame.size, transition: .immediate)
strongSelf.backgroundWallpaperNode.frame = backgroundFrame
strongSelf.shadowNode.updateLayout(backgroundFrame: backgroundFrame, transition: .immediate)
}
if let (rect, size) = strongSelf.absoluteRect {
strongSelf.updateAbsoluteRect(rect, within: size)
}
}
let offset: CGFloat = params.leftInset + (incoming ? 42.0 : 0.0)
let selectionFrame = CGRect(origin: CGPoint(x: -offset, y: 0.0), size: CGSize(width: params.width, height: layout.contentSize.height))
strongSelf.selectionNode?.frame = selectionFrame
@ -3088,6 +3013,82 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
}
}
if case let .System(duration, _) = animation/*, !strongSelf.mainContextSourceNode.isExtractedToContextPreview*/ {
if !strongSelf.backgroundNode.frame.equalTo(backgroundFrame) {
if useDisplayLinkAnimations {
let backgroundAnimation = ListViewAnimation(from: strongSelf.backgroundNode.frame, to: backgroundFrame, duration: duration * UIView.animationDurationFactor(), curve: strongSelf.preferredAnimationCurve, beginAt: beginAt, update: { [weak strongSelf] _, frame in
if let strongSelf = strongSelf {
strongSelf.backgroundNode.frame = frame
strongSelf.clippingNode.position = CGPoint(x: frame.midX, y: frame.midY)
strongSelf.clippingNode.bounds = CGRect(origin: CGPoint(x: frame.minX, y: frame.minY), size: frame.size)
strongSelf.backgroundNode.updateLayout(size: frame.size, transition: .immediate)
strongSelf.backgroundWallpaperNode.updateFrame(frame, transition: .immediate)
strongSelf.shadowNode.updateLayout(backgroundFrame: frame, transition: .immediate)
}
})
strongSelf.setAnimationForKey("backgroundNodeFrame", animation: backgroundAnimation)
} else {
animation.animator.updateFrame(layer: strongSelf.backgroundNode.layer, frame: backgroundFrame, completion: nil)
animation.animator.updatePosition(layer: strongSelf.clippingNode.layer, position: backgroundFrame.center, completion: nil)
strongSelf.clippingNode.clipsToBounds = true
animation.animator.updateBounds(layer: strongSelf.clippingNode.layer, bounds: CGRect(origin: CGPoint(x: backgroundFrame.minX, y: backgroundFrame.minY), size: backgroundFrame.size), completion: { [weak strongSelf] _ in
strongSelf?.clippingNode.clipsToBounds = false
})
strongSelf.backgroundNode.updateLayout(size: backgroundFrame.size, transition: animation)
animation.animator.updateFrame(layer: strongSelf.backgroundWallpaperNode.layer, frame: backgroundFrame, completion: nil)
strongSelf.shadowNode.updateLayout(backgroundFrame: backgroundFrame, animator: animation.animator)
strongSelf.backgroundWallpaperNode.updateFrame(backgroundFrame, animator: animation.animator)
}
if let _ = strongSelf.backgroundNode.type {
if !strongSelf.mainContextSourceNode.isExtractedToContextPreview {
if let (rect, size) = strongSelf.absoluteRect {
strongSelf.updateAbsoluteRect(rect, within: size)
}
}
}
strongSelf.messageAccessibilityArea.frame = backgroundFrame
}
if let shareButtonNode = strongSelf.shareButtonNode {
let currentBackgroundFrame = strongSelf.backgroundNode.frame
let buttonSize = shareButtonNode.update(presentationData: item.presentationData, controllerInteraction: item.controllerInteraction, chatLocation: item.chatLocation, subject: item.associatedData.subject, message: item.message, account: item.context.account, disableComments: true)
animation.animator.updateFrame(layer: shareButtonNode.layer, frame: CGRect(origin: CGPoint(x: currentBackgroundFrame.maxX + 8.0, y: currentBackgroundFrame.maxY - buttonSize.width - 1.0), size: buttonSize), completion: nil)
}
} else {
/*if let _ = strongSelf.backgroundFrameTransition {
strongSelf.animateFrameTransition(1.0, backgroundFrame.size.height)
strongSelf.backgroundFrameTransition = nil
}*/
strongSelf.messageAccessibilityArea.frame = backgroundFrame
if let shareButtonNode = strongSelf.shareButtonNode {
let buttonSize = shareButtonNode.update(presentationData: item.presentationData, controllerInteraction: item.controllerInteraction, chatLocation: item.chatLocation, subject: item.associatedData.subject, message: item.message, account: item.context.account, disableComments: true)
shareButtonNode.frame = CGRect(origin: CGPoint(x: backgroundFrame.maxX + 8.0, y: backgroundFrame.maxY - buttonSize.width - 1.0), size: buttonSize)
}
if case .System = animation, strongSelf.mainContextSourceNode.isExtractedToContextPreview {
legacyTransition.updateFrame(node: strongSelf.backgroundNode, frame: backgroundFrame)
legacyTransition.updateFrame(node: strongSelf.clippingNode, frame: backgroundFrame)
legacyTransition.updateBounds(node: strongSelf.clippingNode, bounds: CGRect(origin: CGPoint(x: backgroundFrame.minX, y: backgroundFrame.minY), size: backgroundFrame.size))
strongSelf.backgroundNode.updateLayout(size: backgroundFrame.size, transition: legacyTransition)
strongSelf.backgroundWallpaperNode.updateFrame(backgroundFrame, transition: legacyTransition)
strongSelf.shadowNode.updateLayout(backgroundFrame: backgroundFrame, transition: legacyTransition)
} else {
strongSelf.backgroundNode.frame = backgroundFrame
strongSelf.clippingNode.frame = backgroundFrame
strongSelf.clippingNode.bounds = CGRect(origin: CGPoint(x: backgroundFrame.minX, y: backgroundFrame.minY), size: backgroundFrame.size)
strongSelf.backgroundNode.updateLayout(size: backgroundFrame.size, transition: .immediate)
strongSelf.backgroundWallpaperNode.frame = backgroundFrame
strongSelf.shadowNode.updateLayout(backgroundFrame: backgroundFrame, transition: .immediate)
}
if let (rect, size) = strongSelf.absoluteRect {
strongSelf.updateAbsoluteRect(rect, within: size)
}
}
let previousContextContentFrame = strongSelf.mainContextSourceNode.contentRect
strongSelf.mainContextSourceNode.contentRect = backgroundFrame.offsetBy(dx: incomingOffset, dy: 0.0)
strongSelf.mainContainerNode.targetNodeForActivationProgressContentRect = strongSelf.mainContextSourceNode.contentRect
@ -3859,7 +3860,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
let graphics = PresentationResourcesChat.principalGraphics(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper, bubbleCorners: item.presentationData.chatBubbleCorners)
let hasWallpaper = item.presentationData.theme.wallpaper.hasWallpaper
self.backgroundNode.setType(type: backgroundType, highlighted: highlighted, graphics: graphics, maskMode: self.mainContextSourceNode.isExtractedToContextPreview, hasWallpaper: hasWallpaper, transition: animated ? .animated(duration: 0.3, curve: .easeInOut) : .immediate, backgroundNode: item.controllerInteraction.presentationContext.backgroundNode)
self.backgroundNode.setType(type: backgroundType, highlighted: highlighted, graphics: graphics, maskMode: self.backgroundMaskMode, hasWallpaper: hasWallpaper, transition: animated ? .animated(duration: 0.3, curve: .easeInOut) : .immediate, backgroundNode: item.controllerInteraction.presentationContext.backgroundNode)
}
}
}

View File

@ -479,7 +479,7 @@ private final class ChatMessagePollOptionNode: ASDisplayNode {
private var percentageImage: UIImage?
private var titleNode: TextNode?
private let buttonNode: HighlightTrackingButtonNode
private let separatorNode: ASDisplayNode
let separatorNode: ASDisplayNode
private let resultBarNode: ASImageNode
private let resultBarIconNode: ASImageNode
var option: TelegramMediaPollOption?
@ -489,6 +489,8 @@ private final class ChatMessagePollOptionNode: ASDisplayNode {
var selectionUpdated: (() -> Void)?
private var theme: PresentationTheme?
weak var previousOptionNode: ChatMessagePollOptionNode?
override init() {
self.highlightedBackgroundNode = ASDisplayNode()
self.highlightedBackgroundNode.alpha = 0.0
@ -524,9 +526,21 @@ private final class ChatMessagePollOptionNode: ASDisplayNode {
if highlighted {
strongSelf.highlightedBackgroundNode.layer.removeAnimation(forKey: "opacity")
strongSelf.highlightedBackgroundNode.alpha = 1.0
strongSelf.separatorNode.layer.removeAnimation(forKey: "opacity")
strongSelf.separatorNode.alpha = 0.0
strongSelf.previousOptionNode?.separatorNode.layer.removeAnimation(forKey: "opacity")
strongSelf.previousOptionNode?.separatorNode.alpha = 0.0
} else {
strongSelf.highlightedBackgroundNode.alpha = 0.0
strongSelf.highlightedBackgroundNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3)
strongSelf.separatorNode.alpha = 1.0
strongSelf.separatorNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
strongSelf.previousOptionNode?.separatorNode.alpha = 1.0
strongSelf.previousOptionNode?.separatorNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
}
}
}
@ -1373,6 +1387,10 @@ class ChatMessagePollBubbleContentNode: ChatMessageBubbleContentNode {
verticalOffset += size.height
updatedOptionNodes.append(optionNode)
optionNode.isUserInteractionEnabled = canVote && item.controllerInteraction.pollActionState.pollMessageIdsInProgress[item.message.id] == nil
if i > 0 {
optionNode.previousOptionNode = updatedOptionNodes[i - 1]
}
}
for optionNode in strongSelf.optionNodes {
if !updatedOptionNodes.contains(where: { $0 === optionNode }) {

View File

@ -187,7 +187,7 @@ class ChatUnreadItemNode: ListViewItemNode {
if let backgroundContent = self.backgroundContent {
var backgroundFrame = backgroundContent.frame
backgroundFrame.origin.x += rect.minX
backgroundFrame.origin.y += rect.minY
backgroundFrame.origin.y += containerSize.height - rect.minY
backgroundContent.update(rect: backgroundFrame, within: containerSize, transition: .immediate)
}
}