Various improvements

This commit is contained in:
Ilya Laktyushin 2025-07-02 22:03:34 +02:00
parent 9a414b9f09
commit 72c466ca13
5 changed files with 133 additions and 45 deletions

View File

@ -57,6 +57,7 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
private let ribbonTextNode: TextNode private let ribbonTextNode: TextNode
private let creatorButtonNode: HighlightTrackingButtonNode private let creatorButtonNode: HighlightTrackingButtonNode
private var creatorButtonBackgroundNode: NavigationBackgroundNode?
private let creatorButtonTitleNode: TextNode private let creatorButtonTitleNode: TextNode
private var shimmerEffectNode: ShimmerEffectForegroundNode? private var shimmerEffectNode: ShimmerEffectForegroundNode?
@ -644,6 +645,10 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
if case let .unique(uniqueGift) = gift { if case let .unique(uniqueGift) = gift {
isStarGift = true isStarGift = true
if let releasedBy = gift.releasedBy, let peer = item.message.peers[releasedBy], let addressName = peer.addressName {
creatorButtonTitle = item.presentationData.strings.Notification_StarGift_ReleasedBy("**@\(addressName)**").string
}
let isSelfGift = item.message.id.peerId == item.context.account.peerId let isSelfGift = item.message.id.peerId == item.context.account.peerId
let authorName: String let authorName: String
if isUpgrade { if isUpgrade {
@ -831,9 +836,9 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
} }
), textAlignment: .center) ), textAlignment: .center)
let (creatorButtonTitleLayout, creatorButtonTitleApply) = makeCreatorButtonTitleLayout(TextNodeLayoutArguments(attributedString: creatorButtonAttributedString, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: giftSize.width - 32.0, height: CGFloat.greatestFiniteMagnitude), alignment: .center, cutout: nil, insets: UIEdgeInsets())) let (creatorButtonTitleLayout, creatorButtonTitleApply) = makeCreatorButtonTitleLayout(TextNodeLayoutArguments(attributedString: creatorButtonAttributedString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .middle, constrainedSize: CGSize(width: giftSize.width - 32.0, height: CGFloat.greatestFiniteMagnitude), alignment: .center, cutout: nil, insets: UIEdgeInsets()))
if !creatorButtonTitle.isEmpty { if modelTitle == nil && !creatorButtonTitle.isEmpty {
textSpacing += 28.0 textSpacing += 28.0
} }
@ -841,6 +846,10 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
if let _ = modelTitle { if let _ = modelTitle {
giftSize.height += 70.0 giftSize.height += 70.0
if !creatorButtonTitle.isEmpty {
giftSize.height += 28.0
}
} }
if !buttonTitle.isEmpty { if !buttonTitle.isEmpty {
@ -920,9 +929,11 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
strongSelf.animationNode.isHidden = isStoryEntity strongSelf.animationNode.isHidden = isStoryEntity
strongSelf.buttonNode.isHidden = buttonTitle.isEmpty strongSelf.buttonNode.isHidden = buttonTitle.isEmpty
strongSelf.buttonNode.isUserInteractionEnabled = !item.presentationData.isPreview
strongSelf.buttonTitleNode.isHidden = buttonTitle.isEmpty strongSelf.buttonTitleNode.isHidden = buttonTitle.isEmpty
strongSelf.creatorButtonNode.isHidden = creatorButtonTitle.isEmpty strongSelf.creatorButtonNode.isHidden = creatorButtonTitle.isEmpty
strongSelf.creatorButtonNode.isUserInteractionEnabled = !item.presentationData.isPreview
strongSelf.creatorButtonTitleNode.isHidden = creatorButtonTitle.isEmpty strongSelf.creatorButtonTitleNode.isHidden = creatorButtonTitle.isEmpty
if strongSelf.item == nil && !isStoryEntity { if strongSelf.item == nil && !isStoryEntity {
@ -964,7 +975,6 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
strongSelf.labelNode.isHidden = !hasServiceMessage strongSelf.labelNode.isHidden = !hasServiceMessage
strongSelf.buttonNode.backgroundColor = overlayColor strongSelf.buttonNode.backgroundColor = overlayColor
strongSelf.creatorButtonNode.backgroundColor = overlayColor
strongSelf.animationNode.updateLayout(size: iconSize) strongSelf.animationNode.updateLayout(size: iconSize)
strongSelf.placeholderNode.frame = animationFrame strongSelf.placeholderNode.frame = animationFrame
@ -985,22 +995,45 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
let _ = moreApply() let _ = moreApply()
let _ = creatorButtonTitleApply() let _ = creatorButtonTitleApply()
let labelFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((boundingWidth - labelLayout.size.width) / 2.0), y: 2.0), size: labelLayout.size) let labelFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((boundingWidth - labelLayout.size.width) / 2.0), y: 2.0), size: labelLayout.size)
strongSelf.labelNode.frame = labelFrame strongSelf.labelNode.frame = labelFrame
let titleFrame = CGRect(origin: CGPoint(x: mediaBackgroundFrame.minX + floorToScreenPixels((mediaBackgroundFrame.width - titleLayout.size.width) / 2.0) , y: mediaBackgroundFrame.minY + 151.0), size: titleLayout.size) let titleFrame = CGRect(origin: CGPoint(x: mediaBackgroundFrame.minX + floorToScreenPixels((mediaBackgroundFrame.width - titleLayout.size.width) / 2.0) , y: mediaBackgroundFrame.minY + 151.0), size: titleLayout.size)
strongSelf.titleNode.frame = titleFrame strongSelf.titleNode.frame = titleFrame
let clippingTextFrame = CGRect(origin: CGPoint(x: mediaBackgroundFrame.minX + floorToScreenPixels((mediaBackgroundFrame.width - subtitleLayout.size.width) / 2.0), y: titleFrame.maxY + textSpacing), size: CGSize(width: subtitleLayout.size.width, height: clippedTextHeight))
var attributesOffsetY: CGFloat = 0.0
let creatorButtonSize = CGSize(width: creatorButtonTitleLayout.size.width + 18.0, height: 18.0) let creatorButtonSize = CGSize(width: creatorButtonTitleLayout.size.width + 18.0, height: 18.0)
let creatorButtonOriginY = titleFrame.maxY + 4.0 let creatorButtonOriginY = modelTitle == nil ? titleFrame.maxY + 4.0 : clippingTextFrame.maxY + 5.0
let creatorButtonFrame = CGRect(origin: CGPoint(x: mediaBackgroundFrame.minX + floorToScreenPixels((mediaBackgroundFrame.width - creatorButtonSize.width) / 2.0), y: creatorButtonOriginY), size: creatorButtonSize)
if !creatorButtonTitle.isEmpty {
attributesOffsetY += creatorButtonSize.height + 10.0
}
if !strongSelf.creatorButtonNode.isHidden, modelTitle != nil {
strongSelf.creatorButtonNode.backgroundColor = .clear
let creatorButtonBackgroundNode: NavigationBackgroundNode
if let current = strongSelf.creatorButtonBackgroundNode {
creatorButtonBackgroundNode = current
} else {
creatorButtonBackgroundNode = NavigationBackgroundNode(color: UIColor(rgb: 0x000000, alpha: 0.12), enableBlur: true, enableSaturation: false)
strongSelf.creatorButtonNode.insertSubnode(creatorButtonBackgroundNode, at: 0)
strongSelf.creatorButtonBackgroundNode = creatorButtonBackgroundNode
}
creatorButtonBackgroundNode.update(size: creatorButtonFrame.size, cornerRadius: 9.0, transition: .immediate)
} else {
strongSelf.creatorButtonNode.backgroundColor = overlayColor
if let creatorButtonBackgroundNode = strongSelf.creatorButtonBackgroundNode {
strongSelf.creatorButtonBackgroundNode = nil
creatorButtonBackgroundNode.removeFromSupernode()
}
}
strongSelf.creatorButtonTitleNode.frame = CGRect(origin: CGPoint(x: 9.0, y: 1.0), size: creatorButtonTitleLayout.size) strongSelf.creatorButtonTitleNode.frame = CGRect(origin: CGPoint(x: 9.0, y: 1.0), size: creatorButtonTitleLayout.size)
animation.animator.updateFrame(layer: strongSelf.creatorButtonNode.layer, frame: CGRect(origin: CGPoint(x: mediaBackgroundFrame.minX + floorToScreenPixels((mediaBackgroundFrame.width - creatorButtonSize.width) / 2.0), y: creatorButtonOriginY), size: creatorButtonSize), completion: nil) animation.animator.updateFrame(layer: strongSelf.creatorButtonNode.layer, frame: creatorButtonFrame, completion: nil)
let clippingTextFrame = CGRect(origin: CGPoint(x: mediaBackgroundFrame.minX + floorToScreenPixels((mediaBackgroundFrame.width - subtitleLayout.size.width) / 2.0), y: titleFrame.maxY + textSpacing), size: CGSize(width: subtitleLayout.size.width, height: clippedTextHeight))
let subtitleFrame = CGRect(origin: .zero, size: subtitleLayout.size) let subtitleFrame = CGRect(origin: .zero, size: subtitleLayout.size)
strongSelf.subtitleNode.textNode.frame = subtitleFrame strongSelf.subtitleNode.textNode.frame = subtitleFrame
@ -1084,7 +1117,7 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
} }
let _ = titleApply() let _ = titleApply()
titleTextNode.frame = CGRect( titleTextNode.frame = CGRect(
origin: CGPoint(x: titleMaxX - titleLayout.size.width, y: clippingTextFrame.maxY + yOffset), origin: CGPoint(x: titleMaxX - titleLayout.size.width, y: clippingTextFrame.maxY + attributesOffsetY + yOffset),
size: titleLayout.size size: titleLayout.size
) )
} }
@ -1094,7 +1127,7 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
} }
let _ = valueApply() let _ = valueApply()
valueTextNode.frame = CGRect( valueTextNode.frame = CGRect(
origin: CGPoint(x: valueMinX, y: clippingTextFrame.maxY + yOffset), origin: CGPoint(x: valueMinX, y: clippingTextFrame.maxY + attributesOffsetY + yOffset),
size: valueLayout.size size: valueLayout.size
) )
} }
@ -1125,7 +1158,7 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
var buttonSize = CGSize(width: buttonTitleLayout.size.width + 38.0, height: 34.0) var buttonSize = CGSize(width: buttonTitleLayout.size.width + 38.0, height: 34.0)
var buttonOriginY = clippingTextFrame.maxY + 10.0 var buttonOriginY = clippingTextFrame.maxY + 10.0
if modelTitleLayoutAndApply != nil { if modelTitleLayoutAndApply != nil {
buttonOriginY = clippingTextFrame.maxY + 80.0 buttonOriginY = clippingTextFrame.maxY + attributesOffsetY + 80.0
} }
strongSelf.buttonTitleNode.frame = CGRect(origin: CGPoint(x: 19.0, y: 8.0), size: buttonTitleLayout.size) strongSelf.buttonTitleNode.frame = CGRect(origin: CGPoint(x: 19.0, y: 8.0), size: buttonTitleLayout.size)

View File

@ -294,7 +294,7 @@ final class ChatGiftPreviewItemNode: ListViewItemNode {
} }
var contentSize = CGSize(width: params.width, height: 4.0 + 4.0) var contentSize = CGSize(width: params.width, height: 4.0 + 4.0)
contentSize.height = 346.0 contentSize.height = 370.0
insets = itemListNeighborsGroupedInsets(neighbors, params) insets = itemListNeighborsGroupedInsets(neighbors, params)
if params.width <= 320.0 { if params.width <= 320.0 {
insets.top = 0.0 insets.top = 0.0

View File

@ -559,25 +559,42 @@ final class GiftSetupScreenComponent: Component {
self.hideName = true self.hideName = true
} }
var releasedBy: EnginePeer.Id?
if case let .starGift(gift, true) = component.subject, gift.upgradeStars != nil { if case let .starGift(gift, true) = component.subject, gift.upgradeStars != nil {
self.includeUpgrade = true self.includeUpgrade = true
} }
if case let .starGift(gift, _) = component.subject {
releasedBy = gift.releasedBy
}
let _ = (component.context.engine.data.get( var peerIds: [EnginePeer.Id] = [
TelegramEngine.EngineData.Item.Peer.Peer(id: component.peerId), component.context.account.peerId,
TelegramEngine.EngineData.Item.Peer.Peer(id: component.context.account.peerId), component.peerId
TelegramEngine.EngineData.Item.Peer.SendPaidMessageStars(id: component.peerId) ]
) if let releasedBy {
|> deliverOnMainQueue).start(next: { [weak self] peer, accountPeer, sendPaidMessageStars in peerIds.append(releasedBy)
}
let _ = combineLatest(queue: Queue.mainQueue(),
component.context.engine.data.get(EngineDataMap(
peerIds.map { peerId -> TelegramEngine.EngineData.Item.Peer.Peer in
return TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)
}
)),
component.context.engine.data.get(
TelegramEngine.EngineData.Item.Peer.SendPaidMessageStars(id: component.peerId)
)
).start(next: { [weak self] peers, sendPaidMessageStars in
guard let self else { guard let self else {
return return
} }
if let peer { var peersMap: [EnginePeer.Id: EnginePeer] = [:]
self.peerMap[peer.id] = peer for (peerId, maybePeer) in peers {
} if let peer = maybePeer {
if let accountPeer { peersMap[peerId] = peer
self.peerMap[accountPeer.id] = accountPeer }
} }
self.peerMap = peersMap
self.sendPaidMessageStars = sendPaidMessageStars self.sendPaidMessageStars = sendPaidMessageStars
self.state?.updated() self.state?.updated()
@ -847,7 +864,7 @@ final class GiftSetupScreenComponent: Component {
let giftConfiguration = GiftConfiguration.with(appConfiguration: component.context.currentAppConfiguration.with { $0 }) let giftConfiguration = GiftConfiguration.with(appConfiguration: component.context.currentAppConfiguration.with { $0 })
var introSectionItems: [AnyComponentWithIdentity<Empty>] = [] var introSectionItems: [AnyComponentWithIdentity<Empty>] = []
introSectionItems.append(AnyComponentWithIdentity(id: introSectionItems.count, component: AnyComponent(Rectangle(color: .clear, height: 346.0, tag: self.introPlaceholderTag)))) introSectionItems.append(AnyComponentWithIdentity(id: introSectionItems.count, component: AnyComponent(Rectangle(color: .clear, height: 370.0, tag: self.introPlaceholderTag))))
if self.sendPaidMessageStars == nil { if self.sendPaidMessageStars == nil {
introSectionItems.append(AnyComponentWithIdentity(id: introSectionItems.count, component: AnyComponent(ListMultilineTextFieldItemComponent( introSectionItems.append(AnyComponentWithIdentity(id: introSectionItems.count, component: AnyComponent(ListMultilineTextFieldItemComponent(
@ -965,6 +982,7 @@ final class GiftSetupScreenComponent: Component {
if let accountPeer = self.peerMap[component.context.account.peerId] { if let accountPeer = self.peerMap[component.context.account.peerId] {
var upgradeStars: Int64? var upgradeStars: Int64?
let subject: ChatGiftPreviewItem.Subject let subject: ChatGiftPreviewItem.Subject
var releasedBy: EnginePeer.Id?
switch component.subject { switch component.subject {
case let .premium(product): case let .premium(product):
if self.payWithStars, let starsPrice = product.starsPrice { if self.payWithStars, let starsPrice = product.starsPrice {
@ -976,12 +994,16 @@ final class GiftSetupScreenComponent: Component {
case let .starGift(gift, _): case let .starGift(gift, _):
subject = .starGift(gift: gift) subject = .starGift(gift: gift)
upgradeStars = gift.upgradeStars upgradeStars = gift.upgradeStars
releasedBy = gift.releasedBy
} }
var peers: [EnginePeer] = [accountPeer] var peers: [EnginePeer] = [accountPeer]
if let peer = self.peerMap[component.peerId] { if let peer = self.peerMap[component.peerId] {
peers.append(peer) peers.append(peer)
} }
if let releasedBy, let peer = self.peerMap[releasedBy] {
peers.append(peer)
}
let introContentSize = self.introContent.update( let introContentSize = self.introContent.update(
transition: transition, transition: transition,

View File

@ -1535,7 +1535,7 @@ private final class GiftViewSheetContent: CombinedComponent {
let title = Child(MultilineTextComponent.self) let title = Child(MultilineTextComponent.self)
let subtitle = Child(MultilineTextComponent.self) let subtitle = Child(MultilineTextComponent.self)
let descriptionButton = Child(RoundedRectangle.self) let descriptionButton = Child(PlainButtonComponent.self)
let description = Child(MultilineTextComponent.self) let description = Child(MultilineTextComponent.self)
let transferButton = Child(PlainButtonComponent.self) let transferButton = Child(PlainButtonComponent.self)
@ -1602,6 +1602,7 @@ private final class GiftViewSheetContent: CombinedComponent {
var isSelfGift = false var isSelfGift = false
var isChannelGift = false var isChannelGift = false
var isMyUniqueGift = false var isMyUniqueGift = false
var releasedByPeer: EnginePeer?
if case let .soldOutGift(gift) = subject { if case let .soldOutGift(gift) = subject {
animationFile = gift.file animationFile = gift.file
@ -1618,6 +1619,7 @@ private final class GiftViewSheetContent: CombinedComponent {
case let .generic(gift): case let .generic(gift):
if let releasedBy = gift.releasedBy, let peer = state.peerMap[releasedBy], let addressName = peer.addressName { if let releasedBy = gift.releasedBy, let peer = state.peerMap[releasedBy], let addressName = peer.addressName {
subtitleString = strings.Gift_View_ReleasedBy("[@\(addressName)]()").string subtitleString = strings.Gift_View_ReleasedBy("[@\(addressName)]()").string
releasedByPeer = peer
} }
animationFile = gift.file animationFile = gift.file
@ -2167,6 +2169,7 @@ private final class GiftViewSheetContent: CombinedComponent {
if let releasedBy = uniqueGift.releasedBy, let peer = state.peerMap[releasedBy], let addressName = peer.addressName { if let releasedBy = uniqueGift.releasedBy, let peer = state.peerMap[releasedBy], let addressName = peer.addressName {
descriptionText = strings.Gift_Unique_CollectibleBy("#\(presentationStringsFormattedNumber(uniqueGift.number, environment.dateTimeFormat.groupingSeparator))", "[@\(addressName)]()").string descriptionText = strings.Gift_Unique_CollectibleBy("#\(presentationStringsFormattedNumber(uniqueGift.number, environment.dateTimeFormat.groupingSeparator))", "[@\(addressName)]()").string
hasDescriptionButton = true hasDescriptionButton = true
releasedByPeer = peer
} }
} else if soldOut { } else if soldOut {
descriptionText = strings.Gift_View_UnavailableDescription descriptionText = strings.Gift_View_UnavailableDescription
@ -2235,16 +2238,34 @@ private final class GiftViewSheetContent: CombinedComponent {
var descriptionOffset: CGFloat = 0.0 var descriptionOffset: CGFloat = 0.0
if let subtitleString { if let subtitleString {
let textColor = theme.actionSheet.secondaryTextColor
let textFont = Font.regular(13.0)
let subtitleAttributedString = parseMarkdownIntoAttributedString(
subtitleString,
attributes: MarkdownAttributes(body: MarkdownAttributeSet(font: textFont, textColor: textColor), bold: MarkdownAttributeSet(font: textFont, textColor: textColor), link: MarkdownAttributeSet(font: textFont, textColor: theme.actionSheet.controlAccentColor), linkAttribute: { contents in
return (TelegramTextAttributes.URL, contents)
}),
textAlignment: .center
)
let subtitle = subtitle.update( let subtitle = subtitle.update(
component: MultilineTextComponent( component: MultilineTextComponent(
text: .plain(NSAttributedString( text: .plain(subtitleAttributedString),
string: subtitleString,
font: Font.regular(13.0),
textColor: theme.actionSheet.secondaryTextColor,
paragraphAlignment: .center
)),
horizontalAlignment: .center, horizontalAlignment: .center,
maximumNumberOfLines: 1 maximumNumberOfLines: 1,
highlightColor: theme.actionSheet.controlAccentColor.withAlphaComponent(0.1),
highlightAction: { attributes in
if let _ = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)] {
return NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)
} else {
return nil
}
},
tapAction: { [weak state] attributes, _ in
if let _ = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)] as? String, let peer = releasedByPeer {
state?.openPeer(peer)
}
}
), ),
availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0 - 60.0, height: CGFloat.greatestFiniteMagnitude), availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0 - 60.0, height: CGFloat.greatestFiniteMagnitude),
transition: .immediate transition: .immediate
@ -2275,7 +2296,7 @@ private final class GiftViewSheetContent: CombinedComponent {
if let _ = uniqueGift { if let _ = uniqueGift {
textFont = Font.regular(13.0) textFont = Font.regular(13.0)
if hasDescriptionButton { if hasDescriptionButton {
textColor = vibrantColor.mixedWith(UIColor.white, alpha: 0.5) textColor = vibrantColor.mixedWith(UIColor.white, alpha: 0.4)
} else { } else {
textColor = vibrantColor textColor = vibrantColor
} }
@ -2307,14 +2328,14 @@ private final class GiftViewSheetContent: CombinedComponent {
highlightColor: linkColor.withAlphaComponent(0.1), highlightColor: linkColor.withAlphaComponent(0.1),
highlightInset: UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: -8.0), highlightInset: UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: -8.0),
highlightAction: { attributes in highlightAction: { attributes in
if let _ = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)] { if !hasDescriptionButton, let _ = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)] {
return NSAttributedString.Key(rawValue: TelegramTextAttributes.URL) return NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)
} else { } else {
return nil return nil
} }
}, },
tapAction: { [weak state] attributes, _ in tapAction: { [weak state] attributes, _ in
if let _ = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)] as? String { if !hasDescriptionButton, let _ = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)] as? String {
state?.openStarsIntro() state?.openStarsIntro()
} }
} }
@ -2322,10 +2343,26 @@ private final class GiftViewSheetContent: CombinedComponent {
availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0 - 50.0, height: CGFloat.greatestFiniteMagnitude), availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0 - 50.0, height: CGFloat.greatestFiniteMagnitude),
transition: .immediate transition: .immediate
) )
context.add(description
.position(CGPoint(x: context.availableSize.width / 2.0, y: 207.0 + descriptionOffset + description.size.height / 2.0))
.appear(.default(alpha: true))
.disappear(.default(alpha: true))
)
if hasDescriptionButton { if hasDescriptionButton {
let descriptionButton = descriptionButton.update( let descriptionButton = descriptionButton.update(
component: RoundedRectangle(color: UIColor.white.withAlphaComponent(0.15), cornerRadius: 9.5), component: PlainButtonComponent(
content: AnyComponent(
RoundedRectangle(color: UIColor.white.withAlphaComponent(0.15), cornerRadius: 9.5)
),
effectAlignment: .center,
action: { [weak state] in
if let releasedByPeer {
state?.openPeer(releasedByPeer)
}
},
animateScale: false
),
environment: {}, environment: {},
availableSize: CGSize(width: description.size.width + 18.0, height: 19.0), availableSize: CGSize(width: description.size.width + 18.0, height: 19.0),
transition: .immediate transition: .immediate
@ -2337,12 +2374,6 @@ private final class GiftViewSheetContent: CombinedComponent {
) )
} }
context.add(description
.position(CGPoint(x: context.availableSize.width / 2.0, y: 207.0 + descriptionOffset + description.size.height / 2.0))
.appear(.default(alpha: true))
.disappear(.default(alpha: true))
)
originY += descriptionOffset originY += descriptionOffset
if uniqueGift != nil { if uniqueGift != nil {

View File

@ -588,6 +588,8 @@ private let textUrlEdgeCharacters: CharacterSet = {
var set: CharacterSet = .alphanumerics var set: CharacterSet = .alphanumerics
set.formUnion(.symbols) set.formUnion(.symbols)
set.formUnion(.punctuationCharacters) set.formUnion(.punctuationCharacters)
set.remove("(")
set.remove(")")
return set return set
}() }()