Merge commit 'b9e104bf2d1ce0c7b4b96ccb1a0dbb86fb4599d1'

This commit is contained in:
Isaac 2025-08-12 09:49:30 +02:00
commit 19c72085dd
7 changed files with 57 additions and 33 deletions

View File

@ -177,7 +177,7 @@ func telegramMediaActionFromApiAction(_ action: Api.MessageAction) -> TelegramMe
return TelegramMediaAction(action: .paymentRefunded(peerId: peer.peerId, currency: currency, totalAmount: totalAmount, payload: payload?.makeData(), transactionId: transactionId))
case let .messageActionPrizeStars(flags, stars, transactionId, boostPeer, giveawayMsgId):
return TelegramMediaAction(action: .prizeStars(amount: stars, isUnclaimed: (flags & (1 << 2)) != 0, boostPeerId: boostPeer.peerId, transactionId: transactionId, giveawayMessageId: MessageId(peerId: boostPeer.peerId, namespace: Namespaces.Message.Cloud, id: giveawayMsgId)))
case let .messageActionStarGift(flags, apiGift, message, convertStars, upgradeMessageId, upgradeStars, fromId, peer, savedId, prepaidUpgradeHash, _):
case let .messageActionStarGift(flags, apiGift, message, convertStars, upgradeMessageId, upgradeStars, fromId, peer, savedId, prepaidUpgradeHash, giftMessageId):
let text: String?
let entities: [MessageTextEntity]?
switch message {
@ -191,7 +191,7 @@ func telegramMediaActionFromApiAction(_ action: Api.MessageAction) -> TelegramMe
guard let gift = StarGift(apiStarGift: apiGift) else {
return nil
}
return TelegramMediaAction(action: .starGift(gift: gift, convertStars: convertStars, text: text, entities: entities, nameHidden: (flags & (1 << 0)) != 0, savedToProfile: (flags & (1 << 2)) != 0, converted: (flags & (1 << 3)) != 0, upgraded: (flags & (1 << 5)) != 0, canUpgrade: (flags & (1 << 10)) != 0, upgradeStars: upgradeStars, isRefunded: (flags & (1 << 9)) != 0, isPrepaidUpgrade: (flags & (1 << 13)) != 0, upgradeMessageId: upgradeMessageId, peerId: peer?.peerId, senderId: fromId?.peerId, savedId: savedId, prepaidUpgradeHash: prepaidUpgradeHash))
return TelegramMediaAction(action: .starGift(gift: gift, convertStars: convertStars, text: text, entities: entities, nameHidden: (flags & (1 << 0)) != 0, savedToProfile: (flags & (1 << 2)) != 0, converted: (flags & (1 << 3)) != 0, upgraded: (flags & (1 << 5)) != 0, canUpgrade: (flags & (1 << 10)) != 0, upgradeStars: upgradeStars, isRefunded: (flags & (1 << 9)) != 0, isPrepaidUpgrade: (flags & (1 << 13)) != 0, upgradeMessageId: upgradeMessageId, peerId: peer?.peerId, senderId: fromId?.peerId, savedId: savedId, prepaidUpgradeHash: prepaidUpgradeHash, giftMessageId: giftMessageId))
case let .messageActionStarGiftUnique(flags, apiGift, canExportAt, transferStars, fromId, peer, savedId, resaleAmount, canTransferDate, canResaleDate):
guard let gift = StarGift(apiStarGift: apiGift) else {
return nil

View File

@ -243,7 +243,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
case paymentRefunded(peerId: PeerId, currency: String, totalAmount: Int64, payload: Data?, transactionId: String)
case giftStars(currency: String, amount: Int64, count: Int64, cryptoCurrency: String?, cryptoAmount: Int64?, transactionId: String?)
case prizeStars(amount: Int64, isUnclaimed: Bool, boostPeerId: PeerId?, transactionId: String?, giveawayMessageId: MessageId?)
case starGift(gift: StarGift, convertStars: Int64?, text: String?, entities: [MessageTextEntity]?, nameHidden: Bool, savedToProfile: Bool, converted: Bool, upgraded: Bool, canUpgrade: Bool, upgradeStars: Int64?, isRefunded: Bool, isPrepaidUpgrade: Bool, upgradeMessageId: Int32?, peerId: EnginePeer.Id?, senderId: EnginePeer.Id?, savedId: Int64?, prepaidUpgradeHash: String?)
case starGift(gift: StarGift, convertStars: Int64?, text: String?, entities: [MessageTextEntity]?, nameHidden: Bool, savedToProfile: Bool, converted: Bool, upgraded: Bool, canUpgrade: Bool, upgradeStars: Int64?, isRefunded: Bool, isPrepaidUpgrade: Bool, upgradeMessageId: Int32?, peerId: EnginePeer.Id?, senderId: EnginePeer.Id?, savedId: Int64?, prepaidUpgradeHash: String?, giftMessageId: Int32?)
case starGiftUnique(gift: StarGift, isUpgrade: Bool, isTransferred: Bool, savedToProfile: Bool, canExportDate: Int32?, transferStars: Int64?, isRefunded: Bool, isPrepaidUpgrade: Bool, peerId: EnginePeer.Id?, senderId: EnginePeer.Id?, savedId: Int64?, resaleAmount: CurrencyAmount?, canTransferDate: Int32?, canResaleDate: Int32?)
case paidMessagesRefunded(count: Int32, stars: Int64)
case paidMessagesPriceEdited(stars: Int64, broadcastMessagesAllowed: Bool)
@ -375,7 +375,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
}
self = .prizeStars(amount: decoder.decodeInt64ForKey("amount", orElse: 0), isUnclaimed: decoder.decodeBoolForKey("unclaimed", orElse: false), boostPeerId: boostPeerId, transactionId: decoder.decodeOptionalStringForKey("transactionId"), giveawayMessageId: giveawayMessageId)
case 44:
self = .starGift(gift: decoder.decodeObjectForKey("gift", decoder: { StarGift(decoder: $0) }) as! StarGift, convertStars: decoder.decodeOptionalInt64ForKey("convertStars"), text: decoder.decodeOptionalStringForKey("text"), entities: decoder.decodeOptionalObjectArrayWithDecoderForKey("entities"), nameHidden: decoder.decodeBoolForKey("nameHidden", orElse: false), savedToProfile: decoder.decodeBoolForKey("savedToProfile", orElse: false), converted: decoder.decodeBoolForKey("converted", orElse: false), upgraded: decoder.decodeBoolForKey("upgraded", orElse: false), canUpgrade: decoder.decodeBoolForKey("canUpgrade", orElse: false), upgradeStars: decoder.decodeOptionalInt64ForKey("upgradeStars"), isRefunded: decoder.decodeBoolForKey("isRefunded", orElse: false), isPrepaidUpgrade: decoder.decodeBoolForKey("isPrepaidUpgrade", orElse: false), upgradeMessageId: decoder.decodeOptionalInt32ForKey("upgradeMessageId"), peerId: decoder.decodeOptionalInt64ForKey("peerId").flatMap { EnginePeer.Id($0) }, senderId: decoder.decodeOptionalInt64ForKey("senderId").flatMap { EnginePeer.Id($0) }, savedId: decoder.decodeOptionalInt64ForKey("savedId"), prepaidUpgradeHash: decoder.decodeOptionalStringForKey("prepaidUpgradeHash"))
self = .starGift(gift: decoder.decodeObjectForKey("gift", decoder: { StarGift(decoder: $0) }) as! StarGift, convertStars: decoder.decodeOptionalInt64ForKey("convertStars"), text: decoder.decodeOptionalStringForKey("text"), entities: decoder.decodeOptionalObjectArrayWithDecoderForKey("entities"), nameHidden: decoder.decodeBoolForKey("nameHidden", orElse: false), savedToProfile: decoder.decodeBoolForKey("savedToProfile", orElse: false), converted: decoder.decodeBoolForKey("converted", orElse: false), upgraded: decoder.decodeBoolForKey("upgraded", orElse: false), canUpgrade: decoder.decodeBoolForKey("canUpgrade", orElse: false), upgradeStars: decoder.decodeOptionalInt64ForKey("upgradeStars"), isRefunded: decoder.decodeBoolForKey("isRefunded", orElse: false), isPrepaidUpgrade: decoder.decodeBoolForKey("isPrepaidUpgrade", orElse: false), upgradeMessageId: decoder.decodeOptionalInt32ForKey("upgradeMessageId"), peerId: decoder.decodeOptionalInt64ForKey("peerId").flatMap { EnginePeer.Id($0) }, senderId: decoder.decodeOptionalInt64ForKey("senderId").flatMap { EnginePeer.Id($0) }, savedId: decoder.decodeOptionalInt64ForKey("savedId"), prepaidUpgradeHash: decoder.decodeOptionalStringForKey("prepaidUpgradeHash"), giftMessageId: decoder.decodeOptionalInt32ForKey("giftMessageId"))
case 45:
var resaleAmount: CurrencyAmount?
if let amount = decoder.decodeCodable(CurrencyAmount.self, forKey: "resaleAmount") {
@ -705,7 +705,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
} else {
encoder.encodeNil(forKey: "giveawayMsgId")
}
case let .starGift(gift, convertStars, text, entities, nameHidden, savedToProfile, converted, upgraded, canUpgrade, upgradeStars, isRefunded, isPrepaidUpgrade, upgradeMessageId, peerId, senderId, savedId, prepaidUpgradeHash):
case let .starGift(gift, convertStars, text, entities, nameHidden, savedToProfile, converted, upgraded, canUpgrade, upgradeStars, isRefunded, isPrepaidUpgrade, upgradeMessageId, peerId, senderId, savedId, prepaidUpgradeHash, giftMessageId):
encoder.encodeInt32(44, forKey: "_rawValue")
encoder.encodeObject(gift, forKey: "gift")
if let convertStars {
@ -757,6 +757,11 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
} else {
encoder.encodeNil(forKey: "prepaidUpgradeHash")
}
if let giftMessageId {
encoder.encodeInt32(giftMessageId, forKey: "giftMessageId")
} else {
encoder.encodeNil(forKey: "giftMessageId")
}
case let .starGiftUnique(gift, isUpgrade, isTransferred, savedToProfile, canExportDate, transferStars, isRefunded, isPrepaidUpgrade, peerId, senderId, savedId, resaleAmount, canTransferDate, canResaleDate):
encoder.encodeInt32(45, forKey: "_rawValue")
encoder.encodeObject(gift, forKey: "gift")
@ -882,7 +887,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
return [peerId]
case let .prizeStars(_, _, boostPeerId, _, _):
return boostPeerId.flatMap { [$0] } ?? []
case let .starGift(gift, _, _, _, _, _, _, _, _, _, _, _, _, peerId, senderId, _, _):
case let .starGift(gift, _, _, _, _, _, _, _, _, _, _, _, _, peerId, senderId, _, _, _):
var peerIds: [PeerId] = []
if let peerId {
peerIds.append(peerId)

View File

@ -1134,7 +1134,7 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
attributedString = mutableString
case .prizeStars:
attributedString = NSAttributedString(string: strings.Notification_StarsPrize, font: titleFont, textColor: primaryTextColor)
case let .starGift(gift, _, text, entities, _, _, _, _, _, upgradeStars, _, isPrepaidUpgrade, _, peerId, senderId, _, _):
case let .starGift(gift, _, text, entities, _, _, _, _, _, upgradeStars, _, isPrepaidUpgrade, _, peerId, senderId, _, _, _):
if !forAdditionalServiceMessage {
if let text {
let mutableAttributedString = NSMutableAttributedString(attributedString: stringWithAppliedEntities(text, entities: entities ?? [], baseColor: primaryTextColor, linkColor: primaryTextColor, baseFont: titleFont, linkFont: titleBoldFont, boldFont: titleBoldFont, italicFont: titleFont, boldItalicFont: titleBoldFont, fixedFont: titleFont, blockQuoteFont: titleFont, underlineLinks: false, message: message._asMessage()))
@ -1190,20 +1190,28 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
attributedString = addAttributesToStringWithRanges(strings.Notification_StarsGift_SentYou(starsPrice)._tuple, body: bodyAttributes, argumentAttributes: [0: boldAttributes])
}
} else if let peerId {
peerIds = [(1, peerId)]
var peerName = ""
if let name = message.peers[peerId].flatMap(EnginePeer.init)?.compactDisplayTitle {
peerName = name
}
if let senderId {
peerIds.insert((0, senderId), at: 0)
if let name = message.peers[senderId].flatMap(EnginePeer.init)?.compactDisplayTitle {
authorName = name
if isPrepaidUpgrade {
peerIds = [(1, peerId)]
let starsPrice = strings.Notification_StarsGift_Stars(Int32(clamping: upgradeStars ?? 0))
var attributes = peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: peerIds)
attributes[0] = boldAttributes
attributedString = addAttributesToStringWithRanges(strings.Notification_StarsGift_SentUpgrade(authorName, starsPrice)._tuple, body: bodyAttributes, argumentAttributes: attributes)
} else {
peerIds = [(1, peerId)]
var peerName = ""
if let name = message.peers[peerId].flatMap(EnginePeer.init)?.compactDisplayTitle {
peerName = name
}
if let senderId {
peerIds.insert((0, senderId), at: 0)
if let name = message.peers[senderId].flatMap(EnginePeer.init)?.compactDisplayTitle {
authorName = name
}
}
var attributes = peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: peerIds)
attributes[2] = boldAttributes
attributedString = addAttributesToStringWithRanges(strings.Notification_StarsGift_Channel_Sent(authorName, peerName, starsPrice)._tuple, body: bodyAttributes, argumentAttributes: attributes)
}
var attributes = peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: peerIds)
attributes[2] = boldAttributes
attributedString = addAttributesToStringWithRanges(strings.Notification_StarsGift_Channel_Sent(authorName, peerName, starsPrice)._tuple, body: bodyAttributes, argumentAttributes: attributes)
} else {
var attributes = peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: peerIds)
attributes[1] = boldAttributes

View File

@ -274,7 +274,7 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
for media in item.message.media {
if let action = media as? TelegramMediaAction {
switch action.action {
case let .starGift(gift, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
case let .starGift(gift, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
releasedBy = gift.releasedBy
case let .starGiftUnique(gift, _, _, _, _, _, _, _, _, _, _, _, _, _):
releasedBy = gift.releasedBy
@ -547,7 +547,7 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
buttonTitle = item.presentationData.strings.Notification_PremiumPrize_View
hasServiceMessage = false
}
case let .starGift(gift, convertStars, giftText, giftEntities, _, savedToProfile, converted, upgraded, canUpgrade, upgradeStars, isRefunded, isPrepaidUpgrade, _, channelPeerId, senderPeerId, _, _):
case let .starGift(gift, convertStars, giftText, giftEntities, _, savedToProfile, converted, upgraded, canUpgrade, upgradeStars, isRefunded, isPrepaidUpgrade, _, channelPeerId, senderPeerId, _, _, _):
if case let .generic(gift) = gift {
if let releasedBy = gift.releasedBy, let peer = item.message.peers[releasedBy], let addressName = peer.addressName {
creatorButtonTitle = item.presentationData.strings.Notification_StarGift_ReleasedBy("**@\(addressName)**").string

View File

@ -239,7 +239,7 @@ final class ChatGiftPreviewItemNode: ListViewItemNode {
case let .starGift(gift):
media = [
TelegramMediaAction(
action: .starGift(gift: .generic(gift), convertStars: gift.convertStars, text: item.text, entities: item.entities, nameHidden: false, savedToProfile: false, converted: false, upgraded: false, canUpgrade: gift.upgradeStars != nil, upgradeStars: item.upgradeStars, isRefunded: false, isPrepaidUpgrade: false, upgradeMessageId: nil, peerId: nil, senderId: nil, savedId: nil, prepaidUpgradeHash: nil)
action: .starGift(gift: .generic(gift), convertStars: gift.convertStars, text: item.text, entities: item.entities, nameHidden: false, savedToProfile: false, converted: false, upgraded: false, canUpgrade: gift.upgradeStars != nil, upgradeStars: item.upgradeStars, isRefunded: false, isPrepaidUpgrade: false, upgradeMessageId: nil, peerId: nil, senderId: nil, savedId: nil, prepaidUpgradeHash: nil, giftMessageId: nil)
)
]
}

View File

@ -69,7 +69,8 @@ private final class GiftValueSheetContent: CombinedComponent {
}
final class State: ComponentState {
let minimumPriceTag = GenericComponentViewTag()
let lastSalePriceTag = GenericComponentViewTag()
let floorPriceTag = GenericComponentViewTag()
let averagePriceTag = GenericComponentViewTag()
private let context: AccountContext
@ -154,6 +155,14 @@ private final class GiftValueSheetContent: CombinedComponent {
})
}
func openGiftFragmentResale(url: String) {
guard let controller = self.getController() as? GiftValueScreen, let navigationController = controller.navigationController as? NavigationController else {
return
}
let presentationData = self.context.sharedContext.currentPresentationData.with { $0 }
self.context.sharedContext.openExternalUrl(context: self.context, urlContext: .generic, url: url, forceExternal: true, presentationData: presentationData, navigationController: navigationController, dismissInput: {})
}
func dismiss(animated: Bool) {
guard let controller = self.getController() as? GiftValueScreen else {
return
@ -425,7 +434,7 @@ private final class GiftValueSheetContent: CombinedComponent {
if let lastSalePrice = component.valueInfo.lastSalePrice {
let lastSalePriceString = formatCurrencyAmount(lastSalePrice, currency: component.valueInfo.currency)
let tag = state.minimumPriceTag
let tag = state.lastSalePriceTag
var items: [AnyComponentWithIdentity<Empty>] = []
items.append(
AnyComponentWithIdentity(
@ -436,13 +445,15 @@ private final class GiftValueSheetContent: CombinedComponent {
)
)
let percentage = Double(lastSalePrice) / Double(component.valueInfo.initialSalePrice) * 100.0
let percentage = Int32(floor(Double(lastSalePrice) / Double(component.valueInfo.initialSalePrice) * 100.0 - 100.0))
let percentageString = percentage > 0 ? "+\(percentage)" : "\(percentage)"
items.append(AnyComponentWithIdentity(
id: AnyHashable(1),
component: AnyComponent(Button(
content: AnyComponent(ButtonContentComponent(
context: component.context,
text: "+\(Int32(percentage - 100))%",
text: percentageString,
color: theme.list.itemAccentColor
)),
action: { [weak state] in
@ -464,7 +475,7 @@ private final class GiftValueSheetContent: CombinedComponent {
if let floorPrice = component.valueInfo.floorPrice {
let floorPriceString = formatCurrencyAmount(floorPrice, currency: component.valueInfo.currency)
let tag = state.minimumPriceTag
let tag = state.floorPriceTag
var items: [AnyComponentWithIdentity<Empty>] = []
items.append(
AnyComponentWithIdentity(
@ -492,7 +503,7 @@ private final class GiftValueSheetContent: CombinedComponent {
HStack(items, spacing: 4.0)
)
tableItems.append(.init(
id: "minimumPrice",
id: "floorPrice",
title: "Minumum Price",
hasBackground: false,
component: itemComponent
@ -501,7 +512,6 @@ private final class GiftValueSheetContent: CombinedComponent {
if let averagePrice = component.valueInfo.averagePrice {
let averagePriceString = formatCurrencyAmount(averagePrice, currency: component.valueInfo.currency)
let tag = state.averagePriceTag
var items: [AnyComponentWithIdentity<Empty>] = []
items.append(
@ -603,7 +613,7 @@ private final class GiftValueSheetContent: CombinedComponent {
originY += 12.0
}
if let listedCount = component.valueInfo.fragmentListedCount, let giftIconSubject {
if let listedCount = component.valueInfo.fragmentListedCount, let fragmentListedUrl = component.valueInfo.fragmentListedUrl, let giftIconSubject {
if component.valueInfo.listedCount != nil {
originY += 18.0
}
@ -636,8 +646,8 @@ private final class GiftValueSheetContent: CombinedComponent {
))
], spacing: 0.0)
),
action: {
action: { [weak state] in
state?.openGiftFragmentResale(url: fragmentListedUrl)
},
animateScale: false
),

View File

@ -3994,13 +3994,14 @@ public class GiftViewScreen: ViewControllerComponentContainer {
case let .message(message):
if let action = message.media.first(where: { $0 is TelegramMediaAction }) as? TelegramMediaAction {
switch action.action {
case let .starGift(gift, convertStars, text, entities, nameHidden, savedToProfile, converted, upgraded, canUpgrade, upgradeStars, isRefunded, _, upgradeMessageId, peerId, senderId, savedId, prepaidUpgradeHash):
case let .starGift(gift, convertStars, text, entities, nameHidden, savedToProfile, converted, upgraded, canUpgrade, upgradeStars, isRefunded, _, upgradeMessageId, peerId, senderId, savedId, prepaidUpgradeHash, giftMessageId):
var reference: StarGiftReference
if let peerId, let savedId {
reference = .peer(peerId: peerId, id: savedId)
} else {
reference = .message(messageId: message.id)
}
let _ = giftMessageId
return (message.id.peerId, senderId ?? message.author?.id, message.author?.compactDisplayTitle, message.id, reference, message.flags.contains(.Incoming), gift, message.timestamp, convertStars, text, entities, nameHidden, savedToProfile, nil, converted, upgraded, isRefunded, canUpgrade, upgradeStars, nil, nil, nil, upgradeMessageId, nil, nil, prepaidUpgradeHash)
case let .starGiftUnique(gift, isUpgrade, isTransferred, savedToProfile, canExportDate, transferStars, _, _, peerId, senderId, savedId, _, canTransferDate, canResaleDate):
var reference: StarGiftReference