Various fixes

This commit is contained in:
Ilya Laktyushin 2024-12-28 18:10:39 +04:00
parent acae4de3fb
commit 9c95be3766
7 changed files with 161 additions and 35 deletions

View File

@ -13578,10 +13578,14 @@ Sorry for the inconvenience.";
"Notification.StarGift.Subtitle.Other" = "%1$@ can turn this gift to a unique collectible."; "Notification.StarGift.Subtitle.Other" = "%1$@ can turn this gift to a unique collectible.";
"Notification.StarGift.Subtitle.Upgraded" = "This gift was upgraded.";
"Stars.Transaction.GiftFrom" = "Gift From"; "Stars.Transaction.GiftFrom" = "Gift From";
"Stars.Transaction.GiftUpgrade" = "Gift Upgrade"; "Stars.Transaction.GiftUpgrade" = "Gift Upgrade";
"Gift.View.KeepOrUpgradeDescription" = "Tap \"Unpack\" to turn this gift to a unique collectible."; "Gift.View.KeepOrUpgradeDescription" = "Tap \"Unpack\" to turn this gift to a unique collectible.";
"Gift.View.UpgradedDescription" = "This gift was turned to a unique collectible.";
"Gift.View.ViewUpgraded" = "View Upgraded Gift";
"VideoChat.IncomingVideoQuality.AudioOnly" = "Audio Only"; "VideoChat.IncomingVideoQuality.AudioOnly" = "Audio Only";
"VideoChat.IncomingVideoQuality.Title" = "Receive Video Quality"; "VideoChat.IncomingVideoQuality.Title" = "Receive Video Quality";

View File

@ -60,7 +60,7 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
private let buttonNode: HighlightTrackingButtonNode private let buttonNode: HighlightTrackingButtonNode
private let buttonStarsNode: PremiumStarsNode private let buttonStarsNode: PremiumStarsNode
private let buttonTitleNode: TextNode private let buttonTitleNode: TextNode
private let buttonIconNode: ASImageNode private var buttonIconNode: DefaultAnimatedStickerNodeImpl?
private let moreTextNode: TextNode private let moreTextNode: TextNode
@ -166,10 +166,6 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
self.buttonTitleNode.isUserInteractionEnabled = false self.buttonTitleNode.isUserInteractionEnabled = false
self.buttonTitleNode.displaysAsynchronously = false self.buttonTitleNode.displaysAsynchronously = false
self.buttonIconNode = ASImageNode()
self.buttonIconNode.displaysAsynchronously = false
self.buttonIconNode.isUserInteractionEnabled = false
self.ribbonBackgroundNode = ASImageNode() self.ribbonBackgroundNode = ASImageNode()
self.ribbonBackgroundNode.displaysAsynchronously = false self.ribbonBackgroundNode.displaysAsynchronously = false
@ -195,7 +191,6 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
self.addSubnode(self.buttonNode) self.addSubnode(self.buttonNode)
self.buttonNode.addSubnode(self.buttonStarsNode) self.buttonNode.addSubnode(self.buttonStarsNode)
self.buttonNode.addSubnode(self.buttonTitleNode) self.buttonNode.addSubnode(self.buttonTitleNode)
self.buttonNode.addSubnode(self.buttonIconNode)
self.addSubnode(self.ribbonBackgroundNode) self.addSubnode(self.ribbonBackgroundNode)
self.addSubnode(self.ribbonTextNode) self.addSubnode(self.ribbonTextNode)
@ -478,6 +473,8 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
} else { } else {
if isRefunded { if isRefunded {
text = item.presentationData.strings.Notification_StarGift_Subtitle_Refunded text = item.presentationData.strings.Notification_StarGift_Subtitle_Refunded
} else if upgraded {
text = item.presentationData.strings.Notification_StarGift_Subtitle_Upgraded
} else if incoming { } else if incoming {
if converted { if converted {
text = item.presentationData.strings.Notification_StarGift_Subtitle_Converted(item.presentationData.strings.Notification_StarGift_Subtitle_Converted_Stars(Int32(convertStars ?? 0))).string text = item.presentationData.strings.Notification_StarGift_Subtitle_Converted(item.presentationData.strings.Notification_StarGift_Subtitle_Converted_Stars(Int32(convertStars ?? 0))).string
@ -530,7 +527,7 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
} }
if incoming || item.presentationData.isPreview, let upgradeStars, upgradeStars > 0, !upgraded { if incoming || item.presentationData.isPreview, let upgradeStars, upgradeStars > 0, !upgraded {
buttonTitle = item.presentationData.strings.Notification_StarGift_Unpack buttonTitle = item.presentationData.strings.Notification_StarGift_Unpack
buttonIcon = "Premium/GiftUnpack" buttonIcon = "GiftUnpack"
} else { } else {
buttonTitle = item.presentationData.strings.Notification_StarGift_View buttonTitle = item.presentationData.strings.Notification_StarGift_View
} }
@ -754,7 +751,6 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
strongSelf.buttonNode.isHidden = buttonTitle.isEmpty strongSelf.buttonNode.isHidden = buttonTitle.isEmpty
strongSelf.buttonTitleNode.isHidden = buttonTitle.isEmpty strongSelf.buttonTitleNode.isHidden = buttonTitle.isEmpty
strongSelf.buttonIconNode.isHidden = buttonIcon == nil
if strongSelf.item == nil { if strongSelf.item == nil {
strongSelf.animationNode.started = { [weak self] in strongSelf.animationNode.started = { [weak self] in
@ -930,14 +926,27 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
if modelTitleLayoutAndApply != nil { if modelTitleLayoutAndApply != nil {
buttonOriginY = clippingTextFrame.maxY + 80.0 buttonOriginY = clippingTextFrame.maxY + 80.0
} }
strongSelf.buttonTitleNode.frame = CGRect(origin: CGPoint(x: 19.0, y: 8.0), size: buttonTitleLayout.size)
if let buttonIcon { if let buttonIcon {
buttonSize.width += 15.0 buttonSize.width += 15.0
if strongSelf.buttonIconNode.image == nil {
strongSelf.buttonIconNode.image = generateTintedImage(image: UIImage(bundleImageName: buttonIcon), color: .white) let buttonIconNode: DefaultAnimatedStickerNodeImpl
if let current = strongSelf.buttonIconNode {
buttonIconNode = current
} else {
buttonIconNode = DefaultAnimatedStickerNodeImpl()
buttonIconNode.setup(source: AnimatedStickerNodeLocalFileSource(name: buttonIcon), width: 60, height: 60, playbackMode: .loop, mode: .direct(cachePathPrefix: nil))
strongSelf.buttonNode.addSubnode(buttonIconNode)
strongSelf.buttonIconNode = buttonIconNode
buttonIconNode.playLoop()
} }
let iconSize = CGSize(width: 20.0, height: 20.0)
buttonIconNode.frame = CGRect(origin: CGPoint(x: buttonSize.width - iconSize.width - 13.0, y: 7.0), size: iconSize)
buttonIconNode.updateLayout(size: iconSize)
buttonIconNode.visibility = strongSelf.visibilityStatus == true
buttonIconNode.dynamicColor = primaryTextColor
} }
strongSelf.buttonTitleNode.frame = CGRect(origin: CGPoint(x: 19.0, y: 8.0), size: buttonTitleLayout.size)
strongSelf.buttonIconNode.frame = CGRect(origin: CGPoint(x: buttonSize.width - 30.0, y: 9.0), size: CGSize(width: 14.0, height: 14.0))
animation.animator.updateFrame(layer: strongSelf.buttonNode.layer, frame: CGRect(origin: CGPoint(x: mediaBackgroundFrame.minX + floorToScreenPixels((mediaBackgroundFrame.width - buttonSize.width) / 2.0), y: buttonOriginY), size: buttonSize), completion: nil) animation.animator.updateFrame(layer: strongSelf.buttonNode.layer, frame: CGRect(origin: CGPoint(x: mediaBackgroundFrame.minX + floorToScreenPixels((mediaBackgroundFrame.width - buttonSize.width) / 2.0), y: buttonOriginY), size: buttonSize), completion: nil)
strongSelf.buttonStarsNode.frame = CGRect(origin: .zero, size: buttonSize) strongSelf.buttonStarsNode.frame = CGRect(origin: .zero, size: buttonSize)
@ -1236,6 +1245,7 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
self.isPlaying = isPlaying self.isPlaying = isPlaying
self.animationNode.visibility = isPlaying self.animationNode.visibility = isPlaying
} }
self.buttonIconNode?.visibility = isPlaying
if isPlaying && self.setupTimestamp == nil { if isPlaying && self.setupTimestamp == nil {
self.setupTimestamp = CACurrentMediaTime() self.setupTimestamp = CACurrentMediaTime()

View File

@ -172,6 +172,7 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
public let titleRightIconNode: ASImageNode public let titleRightIconNode: ASImageNode
public let titleCredibilityIconView: ComponentHostView<Empty> public let titleCredibilityIconView: ComponentHostView<Empty>
public let titleVerifiedIconView: ComponentHostView<Empty> public let titleVerifiedIconView: ComponentHostView<Empty>
public let titleStatusIconView: ComponentHostView<Empty>
public let activityNode: ChatTitleActivityNode public let activityNode: ChatTitleActivityNode
private let button: HighlightTrackingButtonNode private let button: HighlightTrackingButtonNode
@ -185,6 +186,7 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
private var titleRightIcon: ChatTitleIcon = .none private var titleRightIcon: ChatTitleIcon = .none
private var titleCredibilityIcon: ChatTitleCredibilityIcon = .none private var titleCredibilityIcon: ChatTitleCredibilityIcon = .none
private var titleVerifiedIcon: ChatTitleCredibilityIcon = .none private var titleVerifiedIcon: ChatTitleCredibilityIcon = .none
private var titleStatusIcon: ChatTitleCredibilityIcon = .none
private var presenceManager: PeerPresenceStatusManager? private var presenceManager: PeerPresenceStatusManager?
@ -232,6 +234,7 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
var titleRightIcon: ChatTitleIcon = .none var titleRightIcon: ChatTitleIcon = .none
var titleCredibilityIcon: ChatTitleCredibilityIcon = .none var titleCredibilityIcon: ChatTitleCredibilityIcon = .none
var titleVerifiedIcon: ChatTitleCredibilityIcon = .none var titleVerifiedIcon: ChatTitleCredibilityIcon = .none
var titleStatusIcon: ChatTitleCredibilityIcon = .none
var isEnabled = true var isEnabled = true
switch titleContent { switch titleContent {
case let .peer(peerView, customTitle, _, isScheduledMessages, isMuted, _, isEnabledValue): case let .peer(peerView, customTitle, _, isScheduledMessages, isMuted, _, isEnabledValue):
@ -272,15 +275,15 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
} else if peer.isScam { } else if peer.isScam {
titleCredibilityIcon = .scam titleCredibilityIcon = .scam
} else if let emojiStatus = peer.emojiStatus, !premiumConfiguration.isPremiumDisabled { } else if let emojiStatus = peer.emojiStatus, !premiumConfiguration.isPremiumDisabled {
if peer is TelegramChannel, peer.isVerified { titleStatusIcon = .emojiStatus(emojiStatus)
titleVerifiedIcon = .verified
}
titleCredibilityIcon = .emojiStatus(emojiStatus)
} else if peer.isVerified {
titleVerifiedIcon = .verified
} else if peer.isPremium && !premiumConfiguration.isPremiumDisabled { } else if peer.isPremium && !premiumConfiguration.isPremiumDisabled {
titleCredibilityIcon = .premium titleCredibilityIcon = .premium
} else if let verificationIconFileId = peer.verificationIconFileId { }
if peer.isVerified {
titleCredibilityIcon = .verified
}
if let verificationIconFileId = peer.verificationIconFileId {
titleVerifiedIcon = .emojiStatus(PeerEmojiStatus(fileId: verificationIconFileId, expirationDate: nil)) titleVerifiedIcon = .emojiStatus(PeerEmojiStatus(fileId: verificationIconFileId, expirationDate: nil))
} }
} }
@ -412,6 +415,11 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
updated = true updated = true
} }
if titleStatusIcon != self.titleStatusIcon {
self.titleStatusIcon = titleStatusIcon
updated = true
}
if titleRightIcon != self.titleRightIcon { if titleRightIcon != self.titleRightIcon {
self.titleRightIcon = titleRightIcon self.titleRightIcon = titleRightIcon
switch titleRightIcon { switch titleRightIcon {
@ -720,6 +728,9 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
self.titleVerifiedIconView = ComponentHostView() self.titleVerifiedIconView = ComponentHostView()
self.titleVerifiedIconView.isUserInteractionEnabled = false self.titleVerifiedIconView.isUserInteractionEnabled = false
self.titleStatusIconView = ComponentHostView()
self.titleStatusIconView.isUserInteractionEnabled = false
self.activityNode = ChatTitleActivityNode() self.activityNode = ChatTitleActivityNode()
self.button = HighlightTrackingButtonNode() self.button = HighlightTrackingButtonNode()
@ -746,6 +757,7 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
strongSelf.activityNode.layer.removeAnimation(forKey: "opacity") strongSelf.activityNode.layer.removeAnimation(forKey: "opacity")
strongSelf.titleCredibilityIconView.layer.removeAnimation(forKey: "opacity") strongSelf.titleCredibilityIconView.layer.removeAnimation(forKey: "opacity")
strongSelf.titleVerifiedIconView.layer.removeAnimation(forKey: "opacity") strongSelf.titleVerifiedIconView.layer.removeAnimation(forKey: "opacity")
strongSelf.titleStatusIconView.layer.removeAnimation(forKey: "opacity")
strongSelf.titleTextNode.alpha = 0.4 strongSelf.titleTextNode.alpha = 0.4
strongSelf.activityNode.alpha = 0.4 strongSelf.activityNode.alpha = 0.4
strongSelf.titleCredibilityIconView.alpha = 0.4 strongSelf.titleCredibilityIconView.alpha = 0.4
@ -755,6 +767,7 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
strongSelf.activityNode.alpha = 1.0 strongSelf.activityNode.alpha = 1.0
strongSelf.titleCredibilityIconView.alpha = 1.0 strongSelf.titleCredibilityIconView.alpha = 1.0
strongSelf.titleVerifiedIconView.alpha = 1.0 strongSelf.titleVerifiedIconView.alpha = 1.0
strongSelf.titleStatusIconView.alpha = 1.0
strongSelf.titleTextNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2) strongSelf.titleTextNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2)
strongSelf.activityNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2) strongSelf.activityNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2)
} }
@ -803,6 +816,7 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
var rightIconWidth: CGFloat = 0.0 var rightIconWidth: CGFloat = 0.0
var credibilityIconWidth: CGFloat = 0.0 var credibilityIconWidth: CGFloat = 0.0
var verifiedIconWidth: CGFloat = 0.0 var verifiedIconWidth: CGFloat = 0.0
var statusIconWidth: CGFloat = 0.0
if let image = self.titleLeftIconNode.image { if let image = self.titleLeftIconNode.image {
if self.titleLeftIconNode.supernode == nil { if self.titleLeftIconNode.supernode == nil {
@ -845,6 +859,14 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
titleVerifiedContent = .animation(content: .customEmoji(fileId: emojiStatus.fileId), size: CGSize(width: 32.0, height: 32.0), placeholderColor: self.theme.list.mediaPlaceholderColor, themeColor: self.theme.list.itemAccentColor, loopMode: .count(2)) titleVerifiedContent = .animation(content: .customEmoji(fileId: emojiStatus.fileId), size: CGSize(width: 32.0, height: 32.0), placeholderColor: self.theme.list.mediaPlaceholderColor, themeColor: self.theme.list.itemAccentColor, loopMode: .count(2))
} }
let titleStatusContent: EmojiStatusComponent.Content
switch self.titleStatusIcon {
case let .emojiStatus(emojiStatus):
titleStatusContent = .animation(content: .customEmoji(fileId: emojiStatus.fileId), size: CGSize(width: 32.0, height: 32.0), placeholderColor: self.theme.list.mediaPlaceholderColor, themeColor: self.theme.list.itemAccentColor, loopMode: .count(2))
default:
titleStatusContent = .none
}
let titleCredibilitySize = self.titleCredibilityIconView.update( let titleCredibilitySize = self.titleCredibilityIconView.update(
transition: .immediate, transition: .immediate,
component: AnyComponent(EmojiStatusComponent( component: AnyComponent(EmojiStatusComponent(
@ -873,6 +895,20 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
containerSize: CGSize(width: 20.0, height: 20.0) containerSize: CGSize(width: 20.0, height: 20.0)
) )
let titleStatusSize = self.titleStatusIconView.update(
transition: .immediate,
component: AnyComponent(EmojiStatusComponent(
context: self.context,
animationCache: self.animationCache,
animationRenderer: self.animationRenderer,
content: titleStatusContent,
isVisibleForAnimations: true,
action: nil
)),
environment: {},
containerSize: CGSize(width: 20.0, height: 20.0)
)
if self.titleCredibilityIcon != .none { if self.titleCredibilityIcon != .none {
self.titleTextNode.view.addSubview(self.titleCredibilityIconView) self.titleTextNode.view.addSubview(self.titleCredibilityIconView)
credibilityIconWidth = titleCredibilitySize.width + 3.0 credibilityIconWidth = titleCredibilitySize.width + 3.0
@ -891,6 +927,15 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
} }
} }
if self.titleStatusIcon != .none {
self.titleTextNode.view.addSubview(self.titleStatusIconView)
statusIconWidth = titleStatusSize.width + 3.0
} else {
if self.titleStatusIconView.superview != nil {
self.titleStatusIconView.removeFromSuperview()
}
}
if let image = self.titleRightIconNode.image { if let image = self.titleRightIconNode.image {
if self.titleRightIconNode.supernode == nil { if self.titleRightIconNode.supernode == nil {
self.titleTextNode.addSubnode(self.titleRightIconNode) self.titleTextNode.addSubnode(self.titleRightIconNode)
@ -913,9 +958,10 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
titleInsets.left = verifiedIconWidth + 2.0 titleInsets.left = verifiedIconWidth + 2.0
} }
var titleSize = self.titleTextNode.updateLayout(size: CGSize(width: clearBounds.width - leftIconWidth - credibilityIconWidth - verifiedIconWidth - rightIconWidth - titleSideInset * 2.0, height: size.height), insets: titleInsets, animated: titleTransition.isAnimated) var titleSize = self.titleTextNode.updateLayout(size: CGSize(width: clearBounds.width - leftIconWidth - credibilityIconWidth - verifiedIconWidth - statusIconWidth - rightIconWidth - titleSideInset * 2.0, height: size.height), insets: titleInsets, animated: titleTransition.isAnimated)
titleSize.width += credibilityIconWidth titleSize.width += credibilityIconWidth
titleSize.width += verifiedIconWidth titleSize.width += verifiedIconWidth
titleSize.width += statusIconWidth
let activitySize = self.activityNode.updateLayout(CGSize(width: clearBounds.size.width - titleSideInset * 2.0, height: clearBounds.size.height), alignment: .center) let activitySize = self.activityNode.updateLayout(CGSize(width: clearBounds.size.width - titleSideInset * 2.0, height: clearBounds.size.height), alignment: .center)
let titleInfoSpacing: CGFloat = 0.0 let titleInfoSpacing: CGFloat = 0.0
@ -967,22 +1013,25 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
self.titleCredibilityIconView.frame = CGRect(origin: CGPoint(x: nextIconX - titleCredibilitySize.width, y: floor((titleFrame.height - titleCredibilitySize.height) / 2.0)), size: titleCredibilitySize) self.titleCredibilityIconView.frame = CGRect(origin: CGPoint(x: nextIconX - titleCredibilitySize.width, y: floor((titleFrame.height - titleCredibilitySize.height) / 2.0)), size: titleCredibilitySize)
nextIconX -= titleCredibilitySize.width nextIconX -= titleCredibilitySize.width
self.titleStatusIconView.frame = CGRect(origin: CGPoint(x: nextIconX - titleStatusSize.width, y: floor((titleFrame.height - titleStatusSize.height) / 2.0)), size: titleStatusSize)
nextIconX -= titleStatusSize.width
if let image = self.titleRightIconNode.image { if let image = self.titleRightIconNode.image {
self.titleRightIconNode.frame = CGRect(origin: CGPoint(x: titleFrame.width + 3.0 + UIScreenPixel, y: 6.0), size: image.size) self.titleRightIconNode.frame = CGRect(origin: CGPoint(x: titleFrame.width + 3.0 + UIScreenPixel, y: 6.0), size: image.size)
} }
} else { } else {
let titleSize = self.titleTextNode.updateLayout(size: CGSize(width: floor(clearBounds.width / 2.0 - leftIconWidth - credibilityIconWidth - verifiedIconWidth - rightIconWidth - titleSideInset * 2.0), height: size.height), animated: titleTransition.isAnimated) let titleSize = self.titleTextNode.updateLayout(size: CGSize(width: floor(clearBounds.width / 2.0 - leftIconWidth - credibilityIconWidth - verifiedIconWidth - statusIconWidth - rightIconWidth - titleSideInset * 2.0), height: size.height), animated: titleTransition.isAnimated)
let activitySize = self.activityNode.updateLayout(CGSize(width: floor(clearBounds.width / 2.0), height: size.height), alignment: .center) let activitySize = self.activityNode.updateLayout(CGSize(width: floor(clearBounds.width / 2.0), height: size.height), alignment: .center)
let titleInfoSpacing: CGFloat = 8.0 let titleInfoSpacing: CGFloat = 8.0
let combinedWidth = titleSize.width + leftIconWidth + credibilityIconWidth + verifiedIconWidth + rightIconWidth + activitySize.width + titleInfoSpacing let combinedWidth = titleSize.width + leftIconWidth + credibilityIconWidth + verifiedIconWidth + statusIconWidth + rightIconWidth + activitySize.width + titleInfoSpacing
titleFrame = CGRect(origin: CGPoint(x: leftIconWidth + floor((clearBounds.width - combinedWidth) / 2.0), y: floor((size.height - titleSize.height) / 2.0)), size: titleSize) titleFrame = CGRect(origin: CGPoint(x: leftIconWidth + floor((clearBounds.width - combinedWidth) / 2.0), y: floor((size.height - titleSize.height) / 2.0)), size: titleSize)
titleTransition.updateFrameAdditiveToCenter(view: self.titleContainerView, frame: titleFrame) titleTransition.updateFrameAdditiveToCenter(view: self.titleContainerView, frame: titleFrame)
titleTransition.updateFrameAdditiveToCenter(node: self.titleTextNode, frame: CGRect(origin: CGPoint(), size: titleFrame.size)) titleTransition.updateFrameAdditiveToCenter(node: self.titleTextNode, frame: CGRect(origin: CGPoint(), size: titleFrame.size))
self.activityNode.frame = CGRect(origin: CGPoint(x: floor((clearBounds.width - combinedWidth) / 2.0 + titleSize.width + leftIconWidth + credibilityIconWidth + verifiedIconWidth + rightIconWidth + titleInfoSpacing), y: floor((size.height - activitySize.height) / 2.0)), size: activitySize) self.activityNode.frame = CGRect(origin: CGPoint(x: floor((clearBounds.width - combinedWidth) / 2.0 + titleSize.width + leftIconWidth + credibilityIconWidth + verifiedIconWidth + statusIconWidth + rightIconWidth + titleInfoSpacing), y: floor((size.height - activitySize.height) / 2.0)), size: activitySize)
if let image = self.titleLeftIconNode.image { if let image = self.titleLeftIconNode.image {
self.titleLeftIconNode.frame = CGRect(origin: CGPoint(x: titleFrame.minX, y: titleFrame.minY + 4.0), size: image.size) self.titleLeftIconNode.frame = CGRect(origin: CGPoint(x: titleFrame.minX, y: titleFrame.minY + 4.0), size: image.size)
@ -995,6 +1044,9 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
self.titleCredibilityIconView.frame = CGRect(origin: CGPoint(x: nextIconX - titleCredibilitySize.width, y: floor((titleFrame.height - titleCredibilitySize.height) / 2.0)), size: titleCredibilitySize) self.titleCredibilityIconView.frame = CGRect(origin: CGPoint(x: nextIconX - titleCredibilitySize.width, y: floor((titleFrame.height - titleCredibilitySize.height) / 2.0)), size: titleCredibilitySize)
nextIconX -= titleCredibilitySize.width nextIconX -= titleCredibilitySize.width
self.titleStatusIconView.frame = CGRect(origin: CGPoint(x: nextIconX - titleStatusSize.width, y: floor((titleFrame.height - titleStatusSize.height) / 2.0)), size: titleStatusSize)
nextIconX -= titleStatusSize.width
if let image = self.titleRightIconNode.image { if let image = self.titleRightIconNode.image {
self.titleRightIconNode.frame = CGRect(origin: CGPoint(x: titleFrame.maxX - image.size.width, y: titleFrame.minY + 6.0), size: image.size) self.titleRightIconNode.frame = CGRect(origin: CGPoint(x: titleFrame.maxX - image.size.width, y: titleFrame.minY + 6.0), size: image.size)
} }

View File

@ -28,6 +28,7 @@ import PlainButtonComponent
import CheckComponent import CheckComponent
import TooltipUI import TooltipUI
import GiftAnimationComponent import GiftAnimationComponent
import LottieComponent
private let modelButtonTag = GenericComponentViewTag() private let modelButtonTag = GenericComponentViewTag()
private let backdropButtonTag = GenericComponentViewTag() private let backdropButtonTag = GenericComponentViewTag()
@ -48,6 +49,7 @@ private final class GiftViewSheetContent: CombinedComponent {
let transferGift: () -> Void let transferGift: () -> Void
let upgradeGift: ((Int64?, Bool) -> Signal<ProfileGiftsContext.State.StarGift, UpgradeStarGiftError>) let upgradeGift: ((Int64?, Bool) -> Signal<ProfileGiftsContext.State.StarGift, UpgradeStarGiftError>)
let showAttributeInfo: (Any, Float) -> Void let showAttributeInfo: (Any, Float) -> Void
let viewUpgraded: (EngineMessage.Id) -> Void
let getController: () -> ViewController? let getController: () -> ViewController?
init( init(
@ -63,6 +65,7 @@ private final class GiftViewSheetContent: CombinedComponent {
transferGift: @escaping () -> Void, transferGift: @escaping () -> Void,
upgradeGift: @escaping ((Int64?, Bool) -> Signal<ProfileGiftsContext.State.StarGift, UpgradeStarGiftError>), upgradeGift: @escaping ((Int64?, Bool) -> Signal<ProfileGiftsContext.State.StarGift, UpgradeStarGiftError>),
showAttributeInfo: @escaping (Any, Float) -> Void, showAttributeInfo: @escaping (Any, Float) -> Void,
viewUpgraded: @escaping (EngineMessage.Id) -> Void,
getController: @escaping () -> ViewController? getController: @escaping () -> ViewController?
) { ) {
self.context = context self.context = context
@ -77,6 +80,7 @@ private final class GiftViewSheetContent: CombinedComponent {
self.transferGift = transferGift self.transferGift = transferGift
self.upgradeGift = upgradeGift self.upgradeGift = upgradeGift
self.showAttributeInfo = showAttributeInfo self.showAttributeInfo = showAttributeInfo
self.viewUpgraded = viewUpgraded
self.getController = getController self.getController = getController
} }
@ -701,6 +705,8 @@ private final class GiftViewSheetContent: CombinedComponent {
descriptionText = "\(strings.Gift_Unique_Collectible) #\(uniqueGift.number)" descriptionText = "\(strings.Gift_Unique_Collectible) #\(uniqueGift.number)"
} else if soldOut { } else if soldOut {
descriptionText = strings.Gift_View_UnavailableDescription descriptionText = strings.Gift_View_UnavailableDescription
} else if upgraded {
descriptionText = strings.Gift_View_UpgradedDescription
} else if incoming { } else if incoming {
if let convertStars, !upgraded { if let convertStars, !upgraded {
if !converted { if !converted {
@ -1426,6 +1432,29 @@ private final class GiftViewSheetContent: CombinedComponent {
availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0, height: 50.0), availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0, height: 50.0),
transition: context.transition transition: context.transition
) )
} else if upgraded, let upgradeMessageIdId = subject.arguments?.upgradeMessageId, let originalMessageId = subject.arguments?.messageId {
let upgradeMessageId = MessageId(peerId: originalMessageId.peerId, namespace: originalMessageId.namespace, id: upgradeMessageIdId)
let buttonTitle = strings.Gift_View_ViewUpgraded
buttonChild = button.update(
component: ButtonComponent(
background: ButtonComponent.Background(
color: theme.list.itemCheckColors.fillColor,
foreground: theme.list.itemCheckColors.foregroundColor,
pressedColor: theme.list.itemCheckColors.fillColor.withMultipliedAlpha(0.9),
cornerRadius: 10.0
),
content: AnyComponentWithIdentity(
id: AnyHashable("button"),
component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: buttonTitle, font: Font.semibold(17.0), textColor: theme.list.itemCheckColors.foregroundColor, paragraphAlignment: .center))))
),
isEnabled: true,
displaysProgress: false,
action: {
component.viewUpgraded(upgradeMessageId)
}),
availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0, height: 50.0),
transition: context.transition
)
} else if incoming && !converted && !upgraded, let upgradeStars, upgradeStars > 0 { } else if incoming && !converted && !upgraded, let upgradeStars, upgradeStars > 0 {
let buttonTitle = strings.Gift_View_UpgradeForFree let buttonTitle = strings.Gift_View_UpgradeForFree
buttonChild = button.update( buttonChild = button.update(
@ -1443,8 +1472,16 @@ private final class GiftViewSheetContent: CombinedComponent {
AnyComponentWithIdentity(id: 0, component: AnyComponent( AnyComponentWithIdentity(id: 0, component: AnyComponent(
MultilineTextComponent(text: .plain(NSAttributedString(string: buttonTitle, font: Font.semibold(17.0), textColor: theme.list.itemCheckColors.foregroundColor, paragraphAlignment: .center)) MultilineTextComponent(text: .plain(NSAttributedString(string: buttonTitle, font: Font.semibold(17.0), textColor: theme.list.itemCheckColors.foregroundColor, paragraphAlignment: .center))
))), ))),
AnyComponentWithIdentity(id: 1, component: AnyComponent(BundleIconComponent(name: "Premium/GiftUpgrade", tintColor: theme.list.itemCheckColors.foregroundColor))) AnyComponentWithIdentity(id: 1, component: AnyComponent(
], spacing: 6.0)) LottieComponent(
content: LottieComponent.AppBundleContent(
name: "GiftUpgrade"
),
size: CGSize(width: 30.0, height: 30.0),
loop: true
)
))
], spacing: 5.0))
), ),
isEnabled: true, isEnabled: true,
displaysProgress: state.inProgress, displaysProgress: state.inProgress,
@ -1531,6 +1568,7 @@ private final class GiftViewSheetComponent: CombinedComponent {
let openMyGifts: () -> Void let openMyGifts: () -> Void
let transferGift: () -> Void let transferGift: () -> Void
let upgradeGift: ((Int64?, Bool) -> Signal<ProfileGiftsContext.State.StarGift, UpgradeStarGiftError>) let upgradeGift: ((Int64?, Bool) -> Signal<ProfileGiftsContext.State.StarGift, UpgradeStarGiftError>)
let viewUpgraded: (EngineMessage.Id) -> Void
let showAttributeInfo: (Any, Float) -> Void let showAttributeInfo: (Any, Float) -> Void
init( init(
@ -1544,6 +1582,7 @@ private final class GiftViewSheetComponent: CombinedComponent {
openMyGifts: @escaping () -> Void, openMyGifts: @escaping () -> Void,
transferGift: @escaping () -> Void, transferGift: @escaping () -> Void,
upgradeGift: @escaping ((Int64?, Bool) -> Signal<ProfileGiftsContext.State.StarGift, UpgradeStarGiftError>), upgradeGift: @escaping ((Int64?, Bool) -> Signal<ProfileGiftsContext.State.StarGift, UpgradeStarGiftError>),
viewUpgraded: @escaping (EngineMessage.Id) -> Void,
showAttributeInfo: @escaping (Any, Float) -> Void showAttributeInfo: @escaping (Any, Float) -> Void
) { ) {
self.context = context self.context = context
@ -1556,6 +1595,7 @@ private final class GiftViewSheetComponent: CombinedComponent {
self.openMyGifts = openMyGifts self.openMyGifts = openMyGifts
self.transferGift = transferGift self.transferGift = transferGift
self.upgradeGift = upgradeGift self.upgradeGift = upgradeGift
self.viewUpgraded = viewUpgraded
self.showAttributeInfo = showAttributeInfo self.showAttributeInfo = showAttributeInfo
} }
@ -1605,6 +1645,7 @@ private final class GiftViewSheetComponent: CombinedComponent {
transferGift: context.component.transferGift, transferGift: context.component.transferGift,
upgradeGift: context.component.upgradeGift, upgradeGift: context.component.upgradeGift,
showAttributeInfo: context.component.showAttributeInfo, showAttributeInfo: context.component.showAttributeInfo,
viewUpgraded: context.component.viewUpgraded,
getController: controller getController: controller
)), )),
backgroundColor: .color(environment.theme.actionSheet.opaqueItemBackgroundColor), backgroundColor: .color(environment.theme.actionSheet.opaqueItemBackgroundColor),
@ -1678,25 +1719,25 @@ public class GiftViewScreen: ViewControllerComponentContainer {
case soldOutGift(StarGift.Gift) case soldOutGift(StarGift.Gift)
case upgradePreview([StarGift.UniqueGift.Attribute], String) case upgradePreview([StarGift.UniqueGift.Attribute], String)
var arguments: (peerId: EnginePeer.Id, fromPeerId: EnginePeer.Id?, fromPeerName: String?, messageId: EngineMessage.Id?, incoming: Bool, gift: StarGift, date: Int32, convertStars: Int64?, text: String?, entities: [MessageTextEntity]?, nameHidden: Bool, savedToProfile: Bool, converted: Bool, upgraded: Bool, canUpgrade: Bool, upgradeStars: Int64?, transferStars: Int64?, canExportDate: Int32?)? { var arguments: (peerId: EnginePeer.Id, fromPeerId: EnginePeer.Id?, fromPeerName: String?, messageId: EngineMessage.Id?, incoming: Bool, gift: StarGift, date: Int32, convertStars: Int64?, text: String?, entities: [MessageTextEntity]?, nameHidden: Bool, savedToProfile: Bool, converted: Bool, upgraded: Bool, canUpgrade: Bool, upgradeStars: Int64?, transferStars: Int64?, canExportDate: Int32?, upgradeMessageId: Int32?)? {
switch self { switch self {
case let .message(message): case let .message(message):
if let action = message.media.first(where: { $0 is TelegramMediaAction }) as? TelegramMediaAction { if let action = message.media.first(where: { $0 is TelegramMediaAction }) as? TelegramMediaAction {
switch action.action { switch action.action {
case let .starGift(gift, convertStars, text, entities, nameHidden, savedToProfile, converted, upgraded, canUpgrade, upgradeStars, _, _): case let .starGift(gift, convertStars, text, entities, nameHidden, savedToProfile, converted, upgraded, canUpgrade, upgradeStars, _, upgradeMessageId):
return (message.id.peerId, message.author?.id, message.author?.compactDisplayTitle, message.id, message.flags.contains(.Incoming), gift, message.timestamp, convertStars, text, entities, nameHidden, savedToProfile, converted, upgraded, canUpgrade, upgradeStars, nil, nil) return (message.id.peerId, message.author?.id, message.author?.compactDisplayTitle, message.id, message.flags.contains(.Incoming), gift, message.timestamp, convertStars, text, entities, nameHidden, savedToProfile, converted, upgraded, canUpgrade, upgradeStars, nil, nil, upgradeMessageId)
case let .starGiftUnique(gift, isUpgrade, _, savedToProfile, canExportDate, transferStars, _): case let .starGiftUnique(gift, isUpgrade, _, savedToProfile, canExportDate, transferStars, _):
var incoming = message.flags.contains(.Incoming) var incoming = message.flags.contains(.Incoming)
if isUpgrade && message.author?.id != message.id.peerId { if isUpgrade && message.author?.id != message.id.peerId {
incoming = true incoming = true
} }
return (message.id.peerId, message.author?.id, message.author?.compactDisplayTitle, message.id, incoming, gift, message.timestamp, nil, nil, nil, false, savedToProfile, false, false, false, nil, transferStars, canExportDate) return (message.id.peerId, message.author?.id, message.author?.compactDisplayTitle, message.id, incoming, gift, message.timestamp, nil, nil, nil, false, savedToProfile, false, false, false, nil, transferStars, canExportDate, nil)
default: default:
return nil return nil
} }
} }
case let .profileGift(peerId, gift): case let .profileGift(peerId, gift):
return (peerId, gift.fromPeer?.id, gift.fromPeer?.compactDisplayTitle, gift.messageId, false, gift.gift, gift.date, gift.convertStars, gift.text, gift.entities, gift.nameHidden, gift.savedToProfile, false, false, gift.canUpgrade, gift.upgradeStars, gift.transferStars, gift.canExportDate) return (peerId, gift.fromPeer?.id, gift.fromPeer?.compactDisplayTitle, gift.messageId, false, gift.gift, gift.date, gift.convertStars, gift.text, gift.entities, gift.nameHidden, gift.savedToProfile, false, false, gift.canUpgrade, gift.upgradeStars, gift.transferStars, gift.canExportDate, nil)
case .soldOutGift: case .soldOutGift:
return nil return nil
case .upgradePreview: case .upgradePreview:
@ -1733,6 +1774,7 @@ public class GiftViewScreen: ViewControllerComponentContainer {
var transferGiftImpl: (() -> Void)? var transferGiftImpl: (() -> Void)?
var showAttributeInfoImpl: ((Any, Float) -> Void)? var showAttributeInfoImpl: ((Any, Float) -> Void)?
var upgradeGiftImpl: ((Int64?, Bool) -> Signal<ProfileGiftsContext.State.StarGift, UpgradeStarGiftError>)? var upgradeGiftImpl: ((Int64?, Bool) -> Signal<ProfileGiftsContext.State.StarGift, UpgradeStarGiftError>)?
var viewUpgradedImpl: ((EngineMessage.Id) -> Void)?
super.init( super.init(
context: context, context: context,
@ -1763,6 +1805,9 @@ public class GiftViewScreen: ViewControllerComponentContainer {
upgradeGift: { formId, keepOriginalInfo in upgradeGift: { formId, keepOriginalInfo in
return upgradeGiftImpl?(formId, keepOriginalInfo) ?? .complete() return upgradeGiftImpl?(formId, keepOriginalInfo) ?? .complete()
}, },
viewUpgraded: { messageId in
viewUpgradedImpl?(messageId)
},
showAttributeInfo: { tag, rarity in showAttributeInfo: { tag, rarity in
showAttributeInfoImpl?(tag, rarity) showAttributeInfoImpl?(tag, rarity)
} }
@ -2018,6 +2063,21 @@ public class GiftViewScreen: ViewControllerComponentContainer {
} }
} }
viewUpgradedImpl = { [weak self] messageId in
guard let self else {
return
}
let _ = (context.engine.data.get(
TelegramEngine.EngineData.Item.Peer.Peer(id: messageId.peerId)
)
|> deliverOnMainQueue).start(next: { peer in
guard let peer, let navigationController = self.navigationController as? NavigationController else {
return
}
context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer), subject: .message(id: .id(messageId), highlight: ChatControllerSubject.MessageHighlight(quote: nil), timecode: nil, setupReply: false), keepStack: .always, useExisting: false, purposefulAction: {}, peekData: nil))
})
}
showAttributeInfoImpl = { [weak self] tag, rarity in showAttributeInfoImpl = { [weak self] tag, rarity in
guard let self else { guard let self else {
return return

View File

@ -781,8 +781,8 @@ final class PeerInfoHeaderNode: ASDisplayNode {
emojiRegularStatusContent = .premium(color: navigationContentsAccentColor) emojiRegularStatusContent = .premium(color: navigationContentsAccentColor)
emojiExpandedStatusContent = .premium(color: navigationContentsAccentColor) emojiExpandedStatusContent = .premium(color: navigationContentsAccentColor)
case .verified: case .verified:
emojiRegularStatusContent = .none emojiRegularStatusContent = .verified(fillColor: presentationData.theme.list.itemCheckColors.fillColor, foregroundColor: presentationData.theme.list.itemCheckColors.foregroundColor, sizeType: .large)
emojiExpandedStatusContent = .none emojiExpandedStatusContent = .verified(fillColor: navigationContentsAccentColor, foregroundColor: .clear, sizeType: .large)
case .fake: case .fake:
emojiRegularStatusContent = .text(color: presentationData.theme.chat.message.incoming.scamColor, string: presentationData.strings.Message_FakeAccount.uppercased()) emojiRegularStatusContent = .text(color: presentationData.theme.chat.message.incoming.scamColor, string: presentationData.strings.Message_FakeAccount.uppercased())
emojiExpandedStatusContent = emojiRegularStatusContent emojiExpandedStatusContent = emojiRegularStatusContent

File diff suppressed because one or more lines are too long