Various improvements

This commit is contained in:
Ilya Laktyushin 2025-01-28 19:59:32 +04:00
parent 004ebd58ad
commit 681b5c9d3a
18 changed files with 123 additions and 31 deletions

View File

@ -492,6 +492,30 @@ public final class AvatarNode: ASDisplayNode {
}
}
public func playCameraAnimation() {
let animationBackgroundNode = ASImageNode()
animationBackgroundNode.isUserInteractionEnabled = false
animationBackgroundNode.frame = self.imageNode.frame
animationBackgroundNode.image = generateGradientFilledCircleImage(diameter: self.imageNode.frame.width, colors: AvatarNode.repostColors.map { $0.cgColor } as NSArray)
self.addSubnode(animationBackgroundNode)
let animationNode = AnimationNode(animation: "anim_camera", colors: [:], scale: 0.082)
animationNode.isUserInteractionEnabled = false
self.addSubnode(animationNode)
if var size = animationNode.preferredSize() {
size = CGSize(width: ceil(size.width), height: ceil(size.height))
animationNode.frame = CGRect(x: floor((self.bounds.width - size.width) / 2.0) + 1.0, y: floor((self.bounds.height - size.height) / 2.0), width: size.width, height: size.height)
Queue.mainQueue().after(0.15, {
animationNode.play()
animationNode.completion = { [weak animationNode, weak animationBackgroundNode] in
animationNode?.removeFromSupernode()
animationBackgroundNode?.removeFromSupernode()
}
})
}
}
public func setPeer(
accountPeerId: EnginePeer.Id,
postbox: Postbox,
@ -1151,6 +1175,10 @@ public final class AvatarNode: ASDisplayNode {
self.contentNode.playRepostAnimation()
}
public func playCameraAnimation() {
self.contentNode.playCameraAnimation ()
}
public func setPeer(
accountPeerId: EnginePeer.Id,
postbox: Postbox,

View File

@ -163,6 +163,7 @@ public final class BrowserBookmarksScreen: ViewController {
}, playMessageEffect: { _ in
}, editMessageFactCheck: { _ in
}, sendGift: { _ in
}, openUniqueGift: { _ in
}, requestMessageUpdate: { _, _ in
}, cancelInteractiveKeyboardGestures: {
}, dismissTextInput: {

View File

@ -137,10 +137,6 @@ final class ChatListNoticeItemNode: ItemListRevealOptionsItemNode {
self.zPosition = 1.0
}
override func didLoad() {
super.didLoad()
}
@objc private func closePressed() {
guard let item = self.item else {
return
@ -500,6 +496,14 @@ final class ChatListNoticeItemNode: ItemListRevealOptionsItemNode {
}
}
override public func selected() {
super.selected()
if case .setupPhoto = self.item?.notice {
self.avatarNode?.playCameraAnimation()
}
}
@objc private func okButtonPressed() {
self.item?.action(.buttonChoice(isPositive: true))
}

View File

@ -791,6 +791,7 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: item.context.currentAppConfiguration.with { $0 })
var credibilityIcon: EmojiStatusComponent.Content?
var credibilityParticleColor: UIColor?
var verifiedIcon: EmojiStatusComponent.Content?
switch item.peer {
case let .peer(peer, _):
@ -801,6 +802,9 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
credibilityIcon = .text(color: item.presentationData.theme.chat.message.incoming.scamColor, string: item.presentationData.strings.Message_FakeAccount.uppercased())
} else if let emojiStatus = peer.emojiStatus {
credibilityIcon = .animation(content: .customEmoji(fileId: emojiStatus.fileId), size: CGSize(width: 20.0, height: 20.0), placeholderColor: item.presentationData.theme.list.mediaPlaceholderColor, themeColor: item.presentationData.theme.list.itemAccentColor, loopMode: .count(2))
if let color = emojiStatus.color {
credibilityParticleColor = UIColor(rgb: UInt32(bitPattern: color))
}
} else if peer.isPremium && !premiumConfiguration.isPremiumDisabled {
credibilityIcon = .premium(color: item.presentationData.theme.list.itemAccentColor)
}
@ -1498,6 +1502,7 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
animationCache: animationCache,
animationRenderer: animationRenderer,
content: credibilityIcon,
particleColor: credibilityParticleColor,
isVisibleForAnimations: strongSelf.visibilityStatus,
action: nil,
emojiFileUpdated: nil

View File

@ -141,6 +141,7 @@ public final class ContextMenuActionItem {
public let textIcon: (PresentationTheme) -> UIImage?
public let textLinkAction: () -> Void
public let action: ((Action) -> Void)?
public let longPressAction: ((Action) -> Void)?
convenience public init(
id: AnyHashable? = nil,
@ -160,7 +161,8 @@ public final class ContextMenuActionItem {
iconAnimation: IconAnimation? = nil,
textIcon: @escaping (PresentationTheme) -> UIImage? = { _ in return nil },
textLinkAction: @escaping () -> Void = {},
action: ((ContextControllerProtocol?, @escaping (ContextMenuActionResult) -> Void) -> Void)?
action: ((ContextControllerProtocol?, @escaping (ContextMenuActionResult) -> Void) -> Void)?,
longPressAction: ((ContextControllerProtocol?, @escaping (ContextMenuActionResult) -> Void) -> Void)? = nil
) {
self.init(
id: id,
@ -184,6 +186,11 @@ public final class ContextMenuActionItem {
return { impl in
action(impl.controller, impl.dismissWithResult)
}
},
longPressAction: longPressAction.flatMap { longPressAction in
return { impl in
longPressAction(impl.controller, impl.dismissWithResult)
}
}
)
}
@ -206,7 +213,8 @@ public final class ContextMenuActionItem {
iconAnimation: IconAnimation? = nil,
textIcon: @escaping (PresentationTheme) -> UIImage? = { _ in return nil },
textLinkAction: @escaping () -> Void = {},
action: ((Action) -> Void)?
action: ((Action) -> Void)?,
longPressAction: ((Action) -> Void)? = nil
) {
self.id = id
self.text = text
@ -226,6 +234,7 @@ public final class ContextMenuActionItem {
self.textIcon = textIcon
self.textLinkAction = textLinkAction
self.action = action
self.longPressAction = longPressAction
}
}

View File

@ -922,6 +922,7 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo
var updatedLabelBadgeImage: UIImage?
var credibilityIcon: EmojiStatusComponent.Content?
var credibilityParticleColor: UIColor?
var verifiedIcon: EmojiStatusComponent.Content?
if case .threatSelfAsSaved = item.aliasHandling, item.peer.id == item.context.accountPeerId {
@ -932,6 +933,9 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo
credibilityIcon = .text(color: item.presentationData.theme.chat.message.incoming.scamColor, string: item.presentationData.strings.Message_FakeAccount.uppercased())
} else if let emojiStatus = item.peer.emojiStatus {
credibilityIcon = .animation(content: .customEmoji(fileId: emojiStatus.fileId), size: CGSize(width: 20.0, height: 20.0), placeholderColor: item.presentationData.theme.list.mediaPlaceholderColor, themeColor: item.presentationData.theme.list.itemAccentColor, loopMode: .count(2))
if let color = emojiStatus.color {
credibilityParticleColor = UIColor(rgb: UInt32(bitPattern: color))
}
} else if item.peer.isPremium && !item.context.isPremiumDisabled {
credibilityIcon = .premium(color: item.presentationData.theme.list.itemAccentColor)
}
@ -1504,6 +1508,7 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo
animationCache: animationCache,
animationRenderer: animationRenderer,
content: credibilityIcon,
particleColor: credibilityParticleColor,
isVisibleForAnimations: strongSelf.visibilityStatus,
action: nil,
emojiFileUpdated: nil

View File

@ -2100,7 +2100,7 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
bottomNodeMergeStatus = .Both
}
var currentCredibilityIcon: EmojiStatusComponent.Content?
var currentCredibilityIcon: (EmojiStatusComponent.Content, UIColor?)?
var initialDisplayHeader = true
if hidesHeaders || item.message.adAttribute != nil {
@ -2163,18 +2163,18 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
if case let .peer(peerId) = item.chatLocation, let authorPeerId = item.message.author?.id, authorPeerId == peerId {
if effectiveAuthor is TelegramChannel, let emojiStatus = effectiveAuthor.emojiStatus {
currentCredibilityIcon = .animation(content: .customEmoji(fileId: emojiStatus.fileId), size: CGSize(width: 20.0, height: 20.0), placeholderColor: incoming ? item.presentationData.theme.theme.chat.message.incoming.mediaPlaceholderColor : item.presentationData.theme.theme.chat.message.outgoing.mediaPlaceholderColor, themeColor: color.withMultipliedAlpha(0.4), loopMode: .count(2))
currentCredibilityIcon = (.animation(content: .customEmoji(fileId: emojiStatus.fileId), size: CGSize(width: 20.0, height: 20.0), placeholderColor: incoming ? item.presentationData.theme.theme.chat.message.incoming.mediaPlaceholderColor : item.presentationData.theme.theme.chat.message.outgoing.mediaPlaceholderColor, themeColor: color.withMultipliedAlpha(0.4), loopMode: .count(2)), nil)
}
} else if effectiveAuthor.isScam {
currentCredibilityIcon = .text(color: incoming ? item.presentationData.theme.theme.chat.message.incoming.scamColor : item.presentationData.theme.theme.chat.message.outgoing.scamColor, string: item.presentationData.strings.Message_ScamAccount.uppercased())
currentCredibilityIcon = (.text(color: incoming ? item.presentationData.theme.theme.chat.message.incoming.scamColor : item.presentationData.theme.theme.chat.message.outgoing.scamColor, string: item.presentationData.strings.Message_ScamAccount.uppercased()), nil)
} else if effectiveAuthor.isFake {
currentCredibilityIcon = .text(color: incoming ? item.presentationData.theme.theme.chat.message.incoming.scamColor : item.presentationData.theme.theme.chat.message.outgoing.scamColor, string: item.presentationData.strings.Message_FakeAccount.uppercased())
currentCredibilityIcon = (.text(color: incoming ? item.presentationData.theme.theme.chat.message.incoming.scamColor : item.presentationData.theme.theme.chat.message.outgoing.scamColor, string: item.presentationData.strings.Message_FakeAccount.uppercased()), nil)
} else if let emojiStatus = effectiveAuthor.emojiStatus {
currentCredibilityIcon = .animation(content: .customEmoji(fileId: emojiStatus.fileId), size: CGSize(width: 20.0, height: 20.0), placeholderColor: incoming ? item.presentationData.theme.theme.chat.message.incoming.mediaPlaceholderColor : item.presentationData.theme.theme.chat.message.outgoing.mediaPlaceholderColor, themeColor: color.withMultipliedAlpha(0.4), loopMode: .count(2))
currentCredibilityIcon = (.animation(content: .customEmoji(fileId: emojiStatus.fileId), size: CGSize(width: 20.0, height: 20.0), placeholderColor: incoming ? item.presentationData.theme.theme.chat.message.incoming.mediaPlaceholderColor : item.presentationData.theme.theme.chat.message.outgoing.mediaPlaceholderColor, themeColor: color.withMultipliedAlpha(0.4), loopMode: .count(2)), emojiStatus.color.flatMap { UIColor(rgb: UInt32(bitPattern: $0)) })
} else if effectiveAuthor.isVerified {
currentCredibilityIcon = .verified(fillColor: item.presentationData.theme.theme.list.itemCheckColors.fillColor, foregroundColor: item.presentationData.theme.theme.list.itemCheckColors.foregroundColor, sizeType: .compact)
currentCredibilityIcon = (.verified(fillColor: item.presentationData.theme.theme.list.itemCheckColors.fillColor, foregroundColor: item.presentationData.theme.theme.list.itemCheckColors.foregroundColor, sizeType: .compact), nil)
} else if effectiveAuthor.isPremium {
currentCredibilityIcon = .premium(color: color.withMultipliedAlpha(0.4))
currentCredibilityIcon = (.premium(color: color.withMultipliedAlpha(0.4)), nil)
}
}
if let rawAuthorNameColor = authorNameColor {
@ -2414,7 +2414,7 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
}
var credibilityIconWidth: CGFloat = 0.0
if let currentCredibilityIcon = currentCredibilityIcon {
if let (currentCredibilityIcon, _) = currentCredibilityIcon {
credibilityIconWidth += 4.0
switch currentCredibilityIcon {
case let .text(_, string):
@ -3223,7 +3223,7 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
nameNodeOriginY: CGFloat,
authorNameColor: UIColor?,
layoutConstants: ChatMessageItemLayoutConstants,
currentCredibilityIcon: EmojiStatusComponent.Content?,
currentCredibilityIcon: (EmojiStatusComponent.Content, UIColor?)?,
adminNodeSizeApply: (CGSize, () -> TextNode?),
boostNodeSizeApply: (CGSize, () -> TextNode?),
contentUpperRightCorner: CGPoint,
@ -3428,7 +3428,7 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
nameHighlightNode.image = generateFilledRoundedRectImage(size: CGSize(width: 8.0, height: 8.0), cornerRadius: 4.0, color: nameColor.withAlphaComponent(0.1))?.stretchableImage(withLeftCapWidth: 4, topCapHeight: 4)
}
if let currentCredibilityIcon = currentCredibilityIcon {
if let (currentCredibilityIcon, currentParticleColor) = currentCredibilityIcon {
let credibilityIconView: ComponentHostView<Empty>
if let current = strongSelf.credibilityIconView {
credibilityIconView = current
@ -3448,6 +3448,7 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
animationCache: item.context.animationCache,
animationRenderer: item.context.animationRenderer,
content: currentCredibilityIcon,
particleColor: currentParticleColor,
isVisibleForAnimations: strongSelf.visibilityStatus,
action: nil
)
@ -5767,16 +5768,20 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
@objc private func credibilityButtonPressed() {
if let item = self.item, let credibilityIconView = self.credibilityIconView, let iconContent = self.credibilityIconContent, let peer = item.message.author {
var emojiFileId: Int64?
switch iconContent {
case let .animation(content, _, _, _, _):
emojiFileId = content.fileId.id
case .premium:
break
default:
return
if case let .starGift(_, _, _, slug, _, _, _, _, _) = peer.emojiStatus?.content {
item.controllerInteraction.openUniqueGift(slug)
} else {
var emojiFileId: Int64?
switch iconContent {
case let .animation(content, _, _, _, _):
emojiFileId = content.fileId.id
case .premium:
break
default:
return
}
item.controllerInteraction.openPremiumStatusInfo(peer.id, credibilityIconView, emojiFileId, peer.nameColor ?? .blue)
}
item.controllerInteraction.openPremiumStatusInfo(peer.id, credibilityIconView, emojiFileId, peer.nameColor ?? .blue)
}
}

View File

@ -632,8 +632,8 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
}, playMessageEffect: { _ in
}, editMessageFactCheck: { _ in
}, sendGift: { _ in
}, requestMessageUpdate: { _, _ in
}, openUniqueGift: { _ in
}, requestMessageUpdate: { _, _ in
}, cancelInteractiveKeyboardGestures: {
}, dismissTextInput: {
}, scrollToMessageId: { _ in

View File

@ -489,6 +489,7 @@ public final class ChatSendGroupMediaMessageContextPreview: UIView, ChatSendMess
}, playMessageEffect: { _ in
}, editMessageFactCheck: { _ in
}, sendGift: { _ in
}, openUniqueGift: { _ in
}, requestMessageUpdate: { _, _ in
}, cancelInteractiveKeyboardGestures: {
}, dismissTextInput: {

View File

@ -268,6 +268,7 @@ public final class ChatControllerInteraction: ChatControllerInteractionProtocol
public let playMessageEffect: (Message) -> Void
public let editMessageFactCheck: (MessageId) -> Void
public let sendGift: (EnginePeer.Id) -> Void
public let openUniqueGift: (String) -> Void
public let requestMessageUpdate: (MessageId, Bool) -> Void
public let cancelInteractiveKeyboardGestures: () -> Void
@ -402,6 +403,7 @@ public final class ChatControllerInteraction: ChatControllerInteractionProtocol
playMessageEffect: @escaping (Message) -> Void,
editMessageFactCheck: @escaping (MessageId) -> Void,
sendGift: @escaping (EnginePeer.Id) -> Void,
openUniqueGift: @escaping (String) -> Void,
requestMessageUpdate: @escaping (MessageId, Bool) -> Void,
cancelInteractiveKeyboardGestures: @escaping () -> Void,
dismissTextInput: @escaping () -> Void,
@ -515,6 +517,7 @@ public final class ChatControllerInteraction: ChatControllerInteractionProtocol
self.playMessageEffect = playMessageEffect
self.editMessageFactCheck = editMessageFactCheck
self.sendGift = sendGift
self.openUniqueGift = openUniqueGift
self.requestMessageUpdate = requestMessageUpdate
self.cancelInteractiveKeyboardGestures = cancelInteractiveKeyboardGestures

View File

@ -229,7 +229,7 @@ public func makeEditorImageComposition(context: CIContext, postbox: Postbox, inp
} else if values.isAvatar {
maskImage = rectangleMaskImage(size: CGSize(width: 1080.0, height: 1080.0))
} else if let outputDimensions {
maskImage = rectangleMaskImage(size: outputDimensions.aspectFitted(CGSize(width: 1080.0, height: 1080.0)))
maskImage = rectangleMaskImage(size: outputDimensions.aspectFitted(CGSize(width: 1080.0, height: 1920.0)))
}
if let drawing = values.drawing, let image = CIImage(image: drawing, options: [.colorSpace: colorSpace]) {
@ -308,8 +308,7 @@ private func makeEditorImageFrameComposition(context: CIContext, inputImage: CII
let scaledSize = CGSize(width: minSize, height: minSize)
resultImage = resultImage.transformed(by: CGAffineTransform(translationX: -(dimensions.width - scaledSize.width) / 2.0, y: -(dimensions.height - scaledSize.height) / 2.0)).cropped(to: CGRect(origin: .zero, size: scaledSize))
} else if values.isCover, let outputDimensions {
let minSize = min(dimensions.width, dimensions.height)
let scaledSize = outputDimensions.aspectFitted(CGSize(width: minSize, height: minSize))
let scaledSize = outputDimensions.aspectFitted(dimensions)
resultImage = resultImage.transformed(by: CGAffineTransform(translationX: -(dimensions.width - scaledSize.width) / 2.0, y: -(dimensions.height - scaledSize.height) / 2.0)).cropped(to: CGRect(origin: .zero, size: scaledSize))
} else if values.isStory {
resultImage = resultImage.cropped(to: CGRect(origin: .zero, size: dimensions))

View File

@ -3680,6 +3680,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
}, playMessageEffect: { _ in
}, editMessageFactCheck: { _ in
}, sendGift: { _ in
}, openUniqueGift: { _ in
}, requestMessageUpdate: { _, _ in
}, cancelInteractiveKeyboardGestures: {
}, dismissTextInput: {
@ -10970,20 +10971,30 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
giftsContext?.updateFilter(updatedFilter)
}
let switchToFilter: (ProfileGiftsContext.Filters) -> Void = { [weak giftsContext] value in
giftsContext?.updateFilter(value)
}
items.append(.action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_Unlimited, icon: { theme in
return filter.contains(.unlimited) ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : nil
}, action: { _, f in
toggleFilter(.unlimited)
}, longPressAction: { _, f in
switchToFilter(.unlimited)
})))
items.append(.action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_Limited, icon: { theme in
return filter.contains(.limited) ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : nil
}, action: { _, f in
toggleFilter(.limited)
}, longPressAction: { _, f in
switchToFilter(.limited)
})))
items.append(.action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_Unique, icon: { theme in
return filter.contains(.unique) ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : nil
}, action: { _, f in
toggleFilter(.unique)
}, longPressAction: { _, f in
switchToFilter(.unique)
})))
if channel.hasPermission(.sendSomething) {
@ -10993,11 +11004,15 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
return filter.contains(.displayed) ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : nil
}, action: { _, f in
toggleFilter(.displayed)
}, longPressAction: { _, f in
switchToFilter(.displayed)
})))
items.append(.action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_Hidden, icon: { theme in
return filter.contains(.hidden) ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : nil
}, action: { _, f in
toggleFilter(.hidden)
}, longPressAction: { _, f in
switchToFilter(.hidden)
})))
}

View File

@ -835,6 +835,7 @@ public final class PeerListItemComponent: Component {
let avatarFrame = CGRect(origin: CGPoint(x: avatarLeftInset, y: floorToScreenPixels((height - verticalInset * 2.0 - avatarSize) / 2.0)), size: CGSize(width: avatarSize, height: avatarSize))
var statusIcon: EmojiStatusComponent.Content?
var particleColor: UIColor?
if let peer = component.peer {
if peer.isScam {
statusIcon = .text(color: component.theme.chat.message.incoming.scamColor, string: component.strings.Message_ScamAccount.uppercased())
@ -842,6 +843,9 @@ public final class PeerListItemComponent: Component {
statusIcon = .text(color: component.theme.chat.message.incoming.scamColor, string: component.strings.Message_FakeAccount.uppercased())
} else if let emojiStatus = peer.emojiStatus {
statusIcon = .animation(content: .customEmoji(fileId: emojiStatus.fileId), size: CGSize(width: 20.0, height: 20.0), placeholderColor: component.theme.list.mediaPlaceholderColor, themeColor: component.theme.list.itemAccentColor, loopMode: .count(2))
if let color = emojiStatus.color {
particleColor = UIColor(rgb: UInt32(bitPattern: color))
}
} else if peer.isVerified {
statusIcon = .verified(fillColor: component.theme.list.itemCheckColors.fillColor, foregroundColor: component.theme.list.itemCheckColors.foregroundColor, sizeType: .compact)
} else if peer.isPremium {
@ -1086,6 +1090,7 @@ public final class PeerListItemComponent: Component {
animationCache: animationCache,
animationRenderer: animationRenderer,
content: statusIcon,
particleColor: particleColor,
isVisibleForAnimations: true,
action: nil,
emojiFileUpdated: nil

File diff suppressed because one or more lines are too long

View File

@ -4333,6 +4333,7 @@ extension ChatControllerImpl {
guard let self, let peerId = self.chatLocation.peerId else {
return
}
if peerId.namespace == Namespaces.Peer.CloudUser {
self.presentAttachmentMenu(subject: .gift)
Queue.mainQueue().after(0.5) {

View File

@ -4585,6 +4585,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
let controller = self.context.sharedContext.makeGiftOptionsController(context: context, peerId: peerId, premiumOptions: premiumOptions, hasBirthday: hasBirthday, completion: nil)
self.push(controller)
})
}, openUniqueGift: { [weak self] slug in
guard let self else {
return
}
self.openUrl("https://t.me/nft/\(slug)", concealed: false)
}, requestMessageUpdate: { [weak self] id, scroll in
if let self {
self.chatDisplayNode.historyNode.requestMessageUpdate(id, andScrollToItem: scroll)

View File

@ -181,6 +181,7 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, ASGestu
}, playMessageEffect: { _ in
}, editMessageFactCheck: { _ in
}, sendGift: { _ in
}, openUniqueGift: { _ in
}, requestMessageUpdate: { _, _ in
}, cancelInteractiveKeyboardGestures: {
}, dismissTextInput: {

View File

@ -1937,6 +1937,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
}, playMessageEffect: { _ in
}, editMessageFactCheck: { _ in
}, sendGift: { _ in
}, openUniqueGift: { _ in
}, requestMessageUpdate: { _, _ in
}, cancelInteractiveKeyboardGestures: {
}, dismissTextInput: {
@ -3256,15 +3257,18 @@ private func peerInfoControllerImpl(context: AccountContext, updatedPresentation
} else if let _ = peer as? TelegramChannel {
var forumTopicThread: ChatReplyThreadMessage?
var switchToRecommendedChannels = false
var switchToGifts = false
switch mode {
case let .forumTopic(thread):
forumTopicThread = thread
case .recommendedChannels:
switchToRecommendedChannels = true
case .gifts:
switchToGifts = true
default:
break
}
return PeerInfoScreenImpl(context: context, updatedPresentationData: updatedPresentationData, peerId: peer.id, avatarInitiallyExpanded: avatarInitiallyExpanded, isOpenedFromChat: isOpenedFromChat, nearbyPeerDistance: nil, reactionSourceMessageId: nil, callMessages: [], forumTopicThread: forumTopicThread, switchToRecommendedChannels: switchToRecommendedChannels)
return PeerInfoScreenImpl(context: context, updatedPresentationData: updatedPresentationData, peerId: peer.id, avatarInitiallyExpanded: avatarInitiallyExpanded, isOpenedFromChat: isOpenedFromChat, nearbyPeerDistance: nil, reactionSourceMessageId: nil, callMessages: [], forumTopicThread: forumTopicThread, switchToRecommendedChannels: switchToRecommendedChannels, switchToGifts: switchToGifts)
} else if peer is TelegramUser {
var nearbyPeerDistance: Int32?
var reactionSourceMessageId: MessageId?