Update API [skip ci]

This commit is contained in:
Ilya Laktyushin 2025-11-27 19:55:24 +04:00
parent ddcea95734
commit b04eee8289
30 changed files with 687 additions and 125 deletions

View file

@ -15432,3 +15432,5 @@ Error: %8$@";
"LiveStream.ErrorMaxAllowedEmoji.Text_1" = "You can send up to %d emoji.";
"LiveStream.ErrorMaxAllowedEmoji.Text_any" = "You can send up to %d emoji.";
"Stars.Purchase.StarGiftOfferInfo" = "Buy Stars to make a gift buy offer.";

View file

@ -1178,6 +1178,7 @@ public enum StarsWithdrawalScreenSubject {
case enterAmount(current: StarsAmount, minValue: StarsAmount, fractionAfterCommission: Int, kind: PaidMessageKind, completion: (Int64) -> Void)
case postSuggestion(channel: EnginePeer, isFromAdmin: Bool, current: CurrencyAmount, timestamp: Int32?, completion: (CurrencyAmount, Int32?) -> Void)
case postSuggestionModification(current: CurrencyAmount, timestamp: Int32?, completion: (CurrencyAmount, Int32?) -> Void)
case starGiftOffer(peer: EnginePeer, gift: StarGift.UniqueGift, completion: (CurrencyAmount, Int32) -> Void)
}
public enum ChannelMembersSearchControllerMode {

View file

@ -144,6 +144,7 @@ public enum StarsPurchasePurpose: Equatable {
case sendMessage(peerId: EnginePeer.Id, requiredStars: Int64)
case buyStarGift(requiredStars: Int64)
case removeOriginalDetailsStarGift(requiredStars: Int64)
case starGiftOffer(requiredStars: Int64)
}
public struct PremiumConfiguration {

View file

@ -621,6 +621,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[1348510708] = { return Api.MessageAction.parse_messageActionSetChatWallPaper($0) }
dict[1007897979] = { return Api.MessageAction.parse_messageActionSetMessagesTTL($0) }
dict[-614898352] = { return Api.MessageAction.parse_messageActionStarGift($0) }
dict[2000845012] = { return Api.MessageAction.parse_messageActionStarGiftPurchaseOffer($0) }
dict[1940760427] = { return Api.MessageAction.parse_messageActionStarGiftPurchaseOfferDeclined($0) }
dict[-1787656893] = { return Api.MessageAction.parse_messageActionStarGiftUnique($0) }
dict[747579941] = { return Api.MessageAction.parse_messageActionSuggestBirthday($0) }
dict[1474192222] = { return Api.MessageAction.parse_messageActionSuggestProfilePhoto($0) }
@ -979,7 +981,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[1124938064] = { return Api.SponsoredMessageReportOption.parse_sponsoredMessageReportOption($0) }
dict[-963180333] = { return Api.SponsoredPeer.parse_sponsoredPeer($0) }
dict[463097215] = { return Api.StarGift.parse_starGift($0) }
dict[-1329630181] = { return Api.StarGift.parse_starGiftUnique($0) }
dict[-1624264554] = { return Api.StarGift.parse_starGiftUnique($0) }
dict[-753154979] = { return Api.StarGiftActiveAuctionState.parse_starGiftActiveAuctionState($0) }
dict[-650279524] = { return Api.StarGiftAttribute.parse_starGiftAttributeBackdrop($0) }
dict[970559507] = { return Api.StarGiftAttribute.parse_starGiftAttributeModel($0) }

View file

@ -1070,6 +1070,8 @@ public extension Api {
case messageActionSetChatWallPaper(flags: Int32, wallpaper: Api.WallPaper)
case messageActionSetMessagesTTL(flags: Int32, period: Int32, autoSettingFrom: Int64?)
case messageActionStarGift(flags: Int32, gift: Api.StarGift, message: Api.TextWithEntities?, convertStars: Int64?, upgradeMsgId: Int32?, upgradeStars: Int64?, fromId: Api.Peer?, peer: Api.Peer?, savedId: Int64?, prepaidUpgradeHash: String?, giftMsgId: Int32?, toId: Api.Peer?)
case messageActionStarGiftPurchaseOffer(flags: Int32, gift: Api.StarGift, price: Api.StarsAmount, expiresAt: Int32)
case messageActionStarGiftPurchaseOfferDeclined(flags: Int32, gift: Api.StarGift, price: Api.StarsAmount)
case messageActionStarGiftUnique(flags: Int32, gift: Api.StarGift, canExportAt: Int32?, transferStars: Int64?, fromId: Api.Peer?, peer: Api.Peer?, savedId: Int64?, resaleAmount: Api.StarsAmount?, canTransferAt: Int32?, canResellAt: Int32?, dropOriginalDetailsStars: Int64?)
case messageActionSuggestBirthday(birthday: Api.Birthday)
case messageActionSuggestProfilePhoto(photo: Api.Photo)
@ -1477,6 +1479,23 @@ public extension Api {
if Int(flags) & Int(1 << 15) != 0 {serializeInt32(giftMsgId!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 18) != 0 {toId!.serialize(buffer, true)}
break
case .messageActionStarGiftPurchaseOffer(let flags, let gift, let price, let expiresAt):
if boxed {
buffer.appendInt32(2000845012)
}
serializeInt32(flags, buffer: buffer, boxed: false)
gift.serialize(buffer, true)
price.serialize(buffer, true)
serializeInt32(expiresAt, buffer: buffer, boxed: false)
break
case .messageActionStarGiftPurchaseOfferDeclined(let flags, let gift, let price):
if boxed {
buffer.appendInt32(1940760427)
}
serializeInt32(flags, buffer: buffer, boxed: false)
gift.serialize(buffer, true)
price.serialize(buffer, true)
break
case .messageActionStarGiftUnique(let flags, let gift, let canExportAt, let transferStars, let fromId, let peer, let savedId, let resaleAmount, let canTransferAt, let canResellAt, let dropOriginalDetailsStars):
if boxed {
buffer.appendInt32(-1787656893)
@ -1680,6 +1699,10 @@ public extension Api {
return ("messageActionSetMessagesTTL", [("flags", flags as Any), ("period", period as Any), ("autoSettingFrom", autoSettingFrom as Any)])
case .messageActionStarGift(let flags, let gift, let message, let convertStars, let upgradeMsgId, let upgradeStars, let fromId, let peer, let savedId, let prepaidUpgradeHash, let giftMsgId, let toId):
return ("messageActionStarGift", [("flags", flags as Any), ("gift", gift as Any), ("message", message as Any), ("convertStars", convertStars as Any), ("upgradeMsgId", upgradeMsgId as Any), ("upgradeStars", upgradeStars as Any), ("fromId", fromId as Any), ("peer", peer as Any), ("savedId", savedId as Any), ("prepaidUpgradeHash", prepaidUpgradeHash as Any), ("giftMsgId", giftMsgId as Any), ("toId", toId as Any)])
case .messageActionStarGiftPurchaseOffer(let flags, let gift, let price, let expiresAt):
return ("messageActionStarGiftPurchaseOffer", [("flags", flags as Any), ("gift", gift as Any), ("price", price as Any), ("expiresAt", expiresAt as Any)])
case .messageActionStarGiftPurchaseOfferDeclined(let flags, let gift, let price):
return ("messageActionStarGiftPurchaseOfferDeclined", [("flags", flags as Any), ("gift", gift as Any), ("price", price as Any)])
case .messageActionStarGiftUnique(let flags, let gift, let canExportAt, let transferStars, let fromId, let peer, let savedId, let resaleAmount, let canTransferAt, let canResellAt, let dropOriginalDetailsStars):
return ("messageActionStarGiftUnique", [("flags", flags as Any), ("gift", gift as Any), ("canExportAt", canExportAt as Any), ("transferStars", transferStars as Any), ("fromId", fromId as Any), ("peer", peer as Any), ("savedId", savedId as Any), ("resaleAmount", resaleAmount as Any), ("canTransferAt", canTransferAt as Any), ("canResellAt", canResellAt as Any), ("dropOriginalDetailsStars", dropOriginalDetailsStars as Any)])
case .messageActionSuggestBirthday(let birthday):
@ -2473,6 +2496,51 @@ public extension Api {
return nil
}
}
public static func parse_messageActionStarGiftPurchaseOffer(_ reader: BufferReader) -> MessageAction? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Api.StarGift?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.StarGift
}
var _3: Api.StarsAmount?
if let signature = reader.readInt32() {
_3 = Api.parse(reader, signature: signature) as? Api.StarsAmount
}
var _4: Int32?
_4 = reader.readInt32()
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
if _c1 && _c2 && _c3 && _c4 {
return Api.MessageAction.messageActionStarGiftPurchaseOffer(flags: _1!, gift: _2!, price: _3!, expiresAt: _4!)
}
else {
return nil
}
}
public static func parse_messageActionStarGiftPurchaseOfferDeclined(_ reader: BufferReader) -> MessageAction? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Api.StarGift?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.StarGift
}
var _3: Api.StarsAmount?
if let signature = reader.readInt32() {
_3 = Api.parse(reader, signature: signature) as? Api.StarsAmount
}
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
if _c1 && _c2 && _c3 {
return Api.MessageAction.messageActionStarGiftPurchaseOfferDeclined(flags: _1!, gift: _2!, price: _3!)
}
else {
return nil
}
}
public static func parse_messageActionStarGiftUnique(_ reader: BufferReader) -> MessageAction? {
var _1: Int32?
_1 = reader.readInt32()

View file

@ -289,7 +289,7 @@ public extension Api {
public extension Api {
enum StarGift: TypeConstructorDescription {
case starGift(flags: Int32, id: Int64, sticker: Api.Document, stars: Int64, availabilityRemains: Int32?, availabilityTotal: Int32?, availabilityResale: Int64?, convertStars: Int64, firstSaleDate: Int32?, lastSaleDate: Int32?, upgradeStars: Int64?, resellMinStars: Int64?, title: String?, releasedBy: Api.Peer?, perUserTotal: Int32?, perUserRemains: Int32?, lockedUntilDate: Int32?, auctionSlug: String?, giftsPerRound: Int32?)
case starGiftUnique(flags: Int32, id: Int64, giftId: Int64, title: String, slug: String, num: Int32, ownerId: Api.Peer?, ownerName: String?, ownerAddress: String?, attributes: [Api.StarGiftAttribute], availabilityIssued: Int32, availabilityTotal: Int32, giftAddress: String?, resellAmount: [Api.StarsAmount]?, releasedBy: Api.Peer?, valueAmount: Int64?, valueCurrency: String?, themePeer: Api.Peer?, peerColor: Api.PeerColor?, hostId: Api.Peer?)
case starGiftUnique(flags: Int32, id: Int64, giftId: Int64, title: String, slug: String, num: Int32, ownerId: Api.Peer?, ownerName: String?, ownerAddress: String?, attributes: [Api.StarGiftAttribute], availabilityIssued: Int32, availabilityTotal: Int32, giftAddress: String?, resellAmount: [Api.StarsAmount]?, releasedBy: Api.Peer?, valueAmount: Int64?, valueCurrency: String?, themePeer: Api.Peer?, peerColor: Api.PeerColor?, hostId: Api.Peer?, offerMinStars: Int32?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
@ -317,9 +317,9 @@ public extension Api {
if Int(flags) & Int(1 << 11) != 0 {serializeString(auctionSlug!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 11) != 0 {serializeInt32(giftsPerRound!, buffer: buffer, boxed: false)}
break
case .starGiftUnique(let flags, let id, let giftId, let title, let slug, let num, let ownerId, let ownerName, let ownerAddress, let attributes, let availabilityIssued, let availabilityTotal, let giftAddress, let resellAmount, let releasedBy, let valueAmount, let valueCurrency, let themePeer, let peerColor, let hostId):
case .starGiftUnique(let flags, let id, let giftId, let title, let slug, let num, let ownerId, let ownerName, let ownerAddress, let attributes, let availabilityIssued, let availabilityTotal, let giftAddress, let resellAmount, let releasedBy, let valueAmount, let valueCurrency, let themePeer, let peerColor, let hostId, let offerMinStars):
if boxed {
buffer.appendInt32(-1329630181)
buffer.appendInt32(-1624264554)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt64(id, buffer: buffer, boxed: false)
@ -349,6 +349,7 @@ public extension Api {
if Int(flags) & Int(1 << 10) != 0 {themePeer!.serialize(buffer, true)}
if Int(flags) & Int(1 << 11) != 0 {peerColor!.serialize(buffer, true)}
if Int(flags) & Int(1 << 12) != 0 {hostId!.serialize(buffer, true)}
if Int(flags) & Int(1 << 13) != 0 {serializeInt32(offerMinStars!, buffer: buffer, boxed: false)}
break
}
}
@ -357,8 +358,8 @@ public extension Api {
switch self {
case .starGift(let flags, let id, let sticker, let stars, let availabilityRemains, let availabilityTotal, let availabilityResale, let convertStars, let firstSaleDate, let lastSaleDate, let upgradeStars, let resellMinStars, let title, let releasedBy, let perUserTotal, let perUserRemains, let lockedUntilDate, let auctionSlug, let giftsPerRound):
return ("starGift", [("flags", flags as Any), ("id", id as Any), ("sticker", sticker as Any), ("stars", stars as Any), ("availabilityRemains", availabilityRemains as Any), ("availabilityTotal", availabilityTotal as Any), ("availabilityResale", availabilityResale as Any), ("convertStars", convertStars as Any), ("firstSaleDate", firstSaleDate as Any), ("lastSaleDate", lastSaleDate as Any), ("upgradeStars", upgradeStars as Any), ("resellMinStars", resellMinStars as Any), ("title", title as Any), ("releasedBy", releasedBy as Any), ("perUserTotal", perUserTotal as Any), ("perUserRemains", perUserRemains as Any), ("lockedUntilDate", lockedUntilDate as Any), ("auctionSlug", auctionSlug as Any), ("giftsPerRound", giftsPerRound as Any)])
case .starGiftUnique(let flags, let id, let giftId, let title, let slug, let num, let ownerId, let ownerName, let ownerAddress, let attributes, let availabilityIssued, let availabilityTotal, let giftAddress, let resellAmount, let releasedBy, let valueAmount, let valueCurrency, let themePeer, let peerColor, let hostId):
return ("starGiftUnique", [("flags", flags as Any), ("id", id as Any), ("giftId", giftId as Any), ("title", title as Any), ("slug", slug as Any), ("num", num as Any), ("ownerId", ownerId as Any), ("ownerName", ownerName as Any), ("ownerAddress", ownerAddress as Any), ("attributes", attributes as Any), ("availabilityIssued", availabilityIssued as Any), ("availabilityTotal", availabilityTotal as Any), ("giftAddress", giftAddress as Any), ("resellAmount", resellAmount as Any), ("releasedBy", releasedBy as Any), ("valueAmount", valueAmount as Any), ("valueCurrency", valueCurrency as Any), ("themePeer", themePeer as Any), ("peerColor", peerColor as Any), ("hostId", hostId as Any)])
case .starGiftUnique(let flags, let id, let giftId, let title, let slug, let num, let ownerId, let ownerName, let ownerAddress, let attributes, let availabilityIssued, let availabilityTotal, let giftAddress, let resellAmount, let releasedBy, let valueAmount, let valueCurrency, let themePeer, let peerColor, let hostId, let offerMinStars):
return ("starGiftUnique", [("flags", flags as Any), ("id", id as Any), ("giftId", giftId as Any), ("title", title as Any), ("slug", slug as Any), ("num", num as Any), ("ownerId", ownerId as Any), ("ownerName", ownerName as Any), ("ownerAddress", ownerAddress as Any), ("attributes", attributes as Any), ("availabilityIssued", availabilityIssued as Any), ("availabilityTotal", availabilityTotal as Any), ("giftAddress", giftAddress as Any), ("resellAmount", resellAmount as Any), ("releasedBy", releasedBy as Any), ("valueAmount", valueAmount as Any), ("valueCurrency", valueCurrency as Any), ("themePeer", themePeer as Any), ("peerColor", peerColor as Any), ("hostId", hostId as Any), ("offerMinStars", offerMinStars as Any)])
}
}
@ -486,6 +487,8 @@ public extension Api {
if Int(_1!) & Int(1 << 12) != 0 {if let signature = reader.readInt32() {
_20 = Api.parse(reader, signature: signature) as? Api.Peer
} }
var _21: Int32?
if Int(_1!) & Int(1 << 13) != 0 {_21 = reader.readInt32() }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
@ -506,8 +509,9 @@ public extension Api {
let _c18 = (Int(_1!) & Int(1 << 10) == 0) || _18 != nil
let _c19 = (Int(_1!) & Int(1 << 11) == 0) || _19 != nil
let _c20 = (Int(_1!) & Int(1 << 12) == 0) || _20 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 && _c20 {
return Api.StarGift.starGiftUnique(flags: _1!, id: _2!, giftId: _3!, title: _4!, slug: _5!, num: _6!, ownerId: _7, ownerName: _8, ownerAddress: _9, attributes: _10!, availabilityIssued: _11!, availabilityTotal: _12!, giftAddress: _13, resellAmount: _14, releasedBy: _15, valueAmount: _16, valueCurrency: _17, themePeer: _18, peerColor: _19, hostId: _20)
let _c21 = (Int(_1!) & Int(1 << 13) == 0) || _21 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 && _c20 && _c21 {
return Api.StarGift.starGiftUnique(flags: _1!, id: _2!, giftId: _3!, title: _4!, slug: _5!, num: _6!, ownerId: _7, ownerName: _8, ownerAddress: _9, attributes: _10!, availabilityIssued: _11!, availabilityTotal: _12!, giftAddress: _13, resellAmount: _14, releasedBy: _15, valueAmount: _16, valueCurrency: _17, themePeer: _18, peerColor: _19, hostId: _20, offerMinStars: _21)
}
else {
return nil

View file

@ -5830,9 +5830,9 @@ public extension Api.functions.messages {
}
}
public extension Api.functions.messages {
static func forwardMessages(flags: Int32, fromPeer: Api.InputPeer, id: [Int32], randomId: [Int64], toPeer: Api.InputPeer, topMsgId: Int32?, replyTo: Api.InputReplyTo?, scheduleDate: Int32?, scheduleRepeatPeriod: Int32?, sendAs: Api.InputPeer?, quickReplyShortcut: Api.InputQuickReplyShortcut?, videoTimestamp: Int32?, allowPaidStars: Int64?, suggestedPost: Api.SuggestedPost?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
static func forwardMessages(flags: Int32, fromPeer: Api.InputPeer, id: [Int32], randomId: [Int64], toPeer: Api.InputPeer, topMsgId: Int32?, replyTo: Api.InputReplyTo?, scheduleDate: Int32?, scheduleRepeatPeriod: Int32?, sendAs: Api.InputPeer?, quickReplyShortcut: Api.InputQuickReplyShortcut?, effect: Int64?, videoTimestamp: Int32?, allowPaidStars: Int64?, suggestedPost: Api.SuggestedPost?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
let buffer = Buffer()
buffer.appendInt32(1104419550)
buffer.appendInt32(326126204)
serializeInt32(flags, buffer: buffer, boxed: false)
fromPeer.serialize(buffer, true)
buffer.appendInt32(481674261)
@ -5852,10 +5852,11 @@ public extension Api.functions.messages {
if Int(flags) & Int(1 << 24) != 0 {serializeInt32(scheduleRepeatPeriod!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 13) != 0 {sendAs!.serialize(buffer, true)}
if Int(flags) & Int(1 << 17) != 0 {quickReplyShortcut!.serialize(buffer, true)}
if Int(flags) & Int(1 << 18) != 0 {serializeInt64(effect!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 20) != 0 {serializeInt32(videoTimestamp!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 21) != 0 {serializeInt64(allowPaidStars!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 23) != 0 {suggestedPost!.serialize(buffer, true)}
return (FunctionDescription(name: "messages.forwardMessages", parameters: [("flags", String(describing: flags)), ("fromPeer", String(describing: fromPeer)), ("id", String(describing: id)), ("randomId", String(describing: randomId)), ("toPeer", String(describing: toPeer)), ("topMsgId", String(describing: topMsgId)), ("replyTo", String(describing: replyTo)), ("scheduleDate", String(describing: scheduleDate)), ("scheduleRepeatPeriod", String(describing: scheduleRepeatPeriod)), ("sendAs", String(describing: sendAs)), ("quickReplyShortcut", String(describing: quickReplyShortcut)), ("videoTimestamp", String(describing: videoTimestamp)), ("allowPaidStars", String(describing: allowPaidStars)), ("suggestedPost", String(describing: suggestedPost))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
return (FunctionDescription(name: "messages.forwardMessages", parameters: [("flags", String(describing: flags)), ("fromPeer", String(describing: fromPeer)), ("id", String(describing: id)), ("randomId", String(describing: randomId)), ("toPeer", String(describing: toPeer)), ("topMsgId", String(describing: topMsgId)), ("replyTo", String(describing: replyTo)), ("scheduleDate", String(describing: scheduleDate)), ("scheduleRepeatPeriod", String(describing: scheduleRepeatPeriod)), ("sendAs", String(describing: sendAs)), ("quickReplyShortcut", String(describing: quickReplyShortcut)), ("effect", String(describing: effect)), ("videoTimestamp", String(describing: videoTimestamp)), ("allowPaidStars", String(describing: allowPaidStars)), ("suggestedPost", String(describing: suggestedPost))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
let reader = BufferReader(buffer)
var result: Api.Updates?
if let signature = reader.readInt32() {
@ -10225,6 +10226,22 @@ public extension Api.functions.payments {
})
}
}
public extension Api.functions.payments {
static func resolveStarGiftOffer(flags: Int32, offerMsgId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
let buffer = Buffer()
buffer.appendInt32(-372344804)
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt32(offerMsgId, buffer: buffer, boxed: false)
return (FunctionDescription(name: "payments.resolveStarGiftOffer", parameters: [("flags", String(describing: flags)), ("offerMsgId", String(describing: offerMsgId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
let reader = BufferReader(buffer)
var result: Api.Updates?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.Updates
}
return result
})
}
}
public extension Api.functions.payments {
static func saveStarGift(flags: Int32, stargift: Api.InputSavedStarGift) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
let buffer = Buffer()
@ -10262,6 +10279,27 @@ public extension Api.functions.payments {
})
}
}
public extension Api.functions.payments {
static func sendStarGiftOffer(flags: Int32, peer: Api.InputPeer, slug: String, price: Api.StarsAmount, duration: Int32, randomId: Int64, allowPaidStars: Int64?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
let buffer = Buffer()
buffer.appendInt32(-1883739327)
serializeInt32(flags, buffer: buffer, boxed: false)
peer.serialize(buffer, true)
serializeString(slug, buffer: buffer, boxed: false)
price.serialize(buffer, true)
serializeInt32(duration, buffer: buffer, boxed: false)
serializeInt64(randomId, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {serializeInt64(allowPaidStars!, buffer: buffer, boxed: false)}
return (FunctionDescription(name: "payments.sendStarGiftOffer", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("slug", String(describing: slug)), ("price", String(describing: price)), ("duration", String(describing: duration)), ("randomId", String(describing: randomId)), ("allowPaidStars", String(describing: allowPaidStars))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
let reader = BufferReader(buffer)
var result: Api.Updates?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.Updates
}
return result
})
}
}
public extension Api.functions.payments {
static func sendStarsForm(formId: Int64, invoice: Api.InputInvoice) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.payments.PaymentResult>) {
let buffer = Buffer()

View file

@ -232,7 +232,7 @@ func apiMessagePeerIds(_ message: Api.Message) -> [PeerId] {
}
switch action {
case .messageActionChannelCreate, .messageActionChatDeletePhoto, .messageActionChatEditPhoto, .messageActionChatEditTitle, .messageActionEmpty, .messageActionPinMessage, .messageActionHistoryClear, .messageActionGameScore, .messageActionPaymentSent, .messageActionPaymentSentMe, .messageActionPhoneCall, .messageActionScreenshotTaken, .messageActionCustomAction, .messageActionBotAllowed, .messageActionSecureValuesSent, .messageActionSecureValuesSentMe, .messageActionContactSignUp, .messageActionGroupCall, .messageActionSetMessagesTTL, .messageActionGroupCallScheduled, .messageActionSetChatTheme, .messageActionChatJoinedByRequest, .messageActionWebViewDataSent, .messageActionWebViewDataSentMe, .messageActionGiftPremium, .messageActionGiftStars, .messageActionTopicCreate, .messageActionTopicEdit, .messageActionSuggestProfilePhoto, .messageActionSetChatWallPaper, .messageActionGiveawayLaunch, .messageActionGiveawayResults, .messageActionBoostApply, .messageActionRequestedPeerSentMe, .messageActionStarGift, .messageActionStarGiftUnique, .messageActionPaidMessagesRefunded, .messageActionPaidMessagesPrice, .messageActionTodoCompletions, .messageActionTodoAppendTasks, .messageActionSuggestedPostApproval, .messageActionGiftTon, .messageActionSuggestedPostSuccess, .messageActionSuggestedPostRefund, .messageActionSuggestBirthday:
case .messageActionChannelCreate, .messageActionChatDeletePhoto, .messageActionChatEditPhoto, .messageActionChatEditTitle, .messageActionEmpty, .messageActionPinMessage, .messageActionHistoryClear, .messageActionGameScore, .messageActionPaymentSent, .messageActionPaymentSentMe, .messageActionPhoneCall, .messageActionScreenshotTaken, .messageActionCustomAction, .messageActionBotAllowed, .messageActionSecureValuesSent, .messageActionSecureValuesSentMe, .messageActionContactSignUp, .messageActionGroupCall, .messageActionSetMessagesTTL, .messageActionGroupCallScheduled, .messageActionSetChatTheme, .messageActionChatJoinedByRequest, .messageActionWebViewDataSent, .messageActionWebViewDataSentMe, .messageActionGiftPremium, .messageActionGiftStars, .messageActionTopicCreate, .messageActionTopicEdit, .messageActionSuggestProfilePhoto, .messageActionSetChatWallPaper, .messageActionGiveawayLaunch, .messageActionGiveawayResults, .messageActionBoostApply, .messageActionRequestedPeerSentMe, .messageActionStarGift, .messageActionStarGiftUnique, .messageActionPaidMessagesRefunded, .messageActionPaidMessagesPrice, .messageActionTodoCompletions, .messageActionTodoAppendTasks, .messageActionSuggestedPostApproval, .messageActionGiftTon, .messageActionSuggestedPostSuccess, .messageActionSuggestedPostRefund, .messageActionSuggestBirthday, .messageActionStarGiftPurchaseOffer, .messageActionStarGiftPurchaseOfferDeclined:
break
case let .messageActionChannelMigrateFrom(_, chatId):
result.append(PeerId(namespace: Namespaces.Peer.CloudGroup, id: PeerId.Id._internalFromInt64Value(chatId)))

View file

@ -200,7 +200,7 @@ func telegramMediaActionFromApiAction(_ action: Api.MessageAction) -> TelegramMe
guard let gift = StarGift(apiStarGift: apiGift) else {
return nil
}
return TelegramMediaAction(action: .starGiftUnique(gift: gift, isUpgrade: (flags & (1 << 0)) != 0, isTransferred: (flags & (1 << 1)) != 0, savedToProfile: (flags & (1 << 2)) != 0, canExportDate: canExportAt, transferStars: transferStars, isRefunded: (flags & (1 << 5)) != 0, isPrepaidUpgrade: (flags & (1 << 11)) != 0, peerId: peer?.peerId, senderId: fromId?.peerId, savedId: savedId, resaleAmount: resaleAmount.flatMap { CurrencyAmount(apiAmount: $0) }, canTransferDate: canTransferDate, canResaleDate: canResaleDate, dropOriginalDetailsStars: dropOriginalDetailsStars, assigned: (flags & (1 << 13)) != 0))
return TelegramMediaAction(action: .starGiftUnique(gift: gift, isUpgrade: (flags & (1 << 0)) != 0, isTransferred: (flags & (1 << 1)) != 0, savedToProfile: (flags & (1 << 2)) != 0, canExportDate: canExportAt, transferStars: transferStars, isRefunded: (flags & (1 << 5)) != 0, isPrepaidUpgrade: (flags & (1 << 11)) != 0, peerId: peer?.peerId, senderId: fromId?.peerId, savedId: savedId, resaleAmount: resaleAmount.flatMap { CurrencyAmount(apiAmount: $0) }, canTransferDate: canTransferDate, canResaleDate: canResaleDate, dropOriginalDetailsStars: dropOriginalDetailsStars, assigned: (flags & (1 << 13)) != 0, fromOffer: (flags & (1 << 14)) != 0))
case let .messageActionPaidMessagesRefunded(count, stars):
return TelegramMediaAction(action: .paidMessagesRefunded(count: count, stars: stars))
case let .messageActionPaidMessagesPrice(flags, stars):
@ -274,6 +274,17 @@ func telegramMediaActionFromApiAction(_ action: Api.MessageAction) -> TelegramMe
return TelegramMediaAction(action: .suggestedPostRefund(TelegramMediaActionType.SuggestedPostRefund(isUserInitiated: (flags & (1 << 0)) != 0)))
case let .messageActionSuggestBirthday(birthday):
return TelegramMediaAction(action: .suggestedBirthday(TelegramBirthday(apiBirthday: birthday)))
case let .messageActionStarGiftPurchaseOffer(flags, apiGift, price, expiresAt):
guard let gift = StarGift(apiStarGift: apiGift) else {
return nil
}
return TelegramMediaAction(action: .starGiftPurchaseOffer(gift: gift, amount: CurrencyAmount(apiAmount: price), expireDate: expiresAt, isAccepted: (flags & (1 << 0)) != 0, isDeclined: (flags & (1 << 1)) != 0))
case let .messageActionStarGiftPurchaseOfferDeclined(flags, apiGift, price):
guard let gift = StarGift(apiStarGift: apiGift) else {
return nil
}
return TelegramMediaAction(action: .starGiftPurchaseOfferDeclined(gift: gift, amount: CurrencyAmount(apiAmount: price), hasExpired: (flags & (1 << 0)) != 0))
}
}

View file

@ -499,7 +499,7 @@ private func sendUploadedMessageContent(
}
if let forwardSourceInfoAttribute = forwardSourceInfoAttribute, let sourcePeer = transaction.getPeer(forwardSourceInfoAttribute.messageId.peerId), let sourceInputPeer = apiInputPeer(sourcePeer) {
sendMessageRequest = network.request(Api.functions.messages.forwardMessages(flags: flags, fromPeer: sourceInputPeer, id: [sourceInfo.messageId.id], randomId: [uniqueId], toPeer: inputPeer, topMsgId: topMsgId, replyTo: nil, scheduleDate: scheduleTime, scheduleRepeatPeriod: scheduleRepeatPeriod, sendAs: sendAsInputPeer, quickReplyShortcut: nil, videoTimestamp: videoTimestamp, allowPaidStars: allowPaidStars, suggestedPost: nil), tag: dependencyTag)
sendMessageRequest = network.request(Api.functions.messages.forwardMessages(flags: flags, fromPeer: sourceInputPeer, id: [sourceInfo.messageId.id], randomId: [uniqueId], toPeer: inputPeer, topMsgId: topMsgId, replyTo: nil, scheduleDate: scheduleTime, scheduleRepeatPeriod: scheduleRepeatPeriod, sendAs: sendAsInputPeer, quickReplyShortcut: nil, effect: nil, videoTimestamp: videoTimestamp, allowPaidStars: allowPaidStars, suggestedPost: nil), tag: dependencyTag)
|> map(NetworkRequestResult.result)
} else {
sendMessageRequest = .fail(MTRpcError(errorCode: 400, errorDescription: "internal"))

View file

@ -363,7 +363,8 @@ func managedUniqueStarGifts(accountPeerId: PeerId, postbox: Postbox, network: Ne
flags: [],
themePeerId: nil,
peerColor: nil,
hostPeerId: nil
hostPeerId: nil,
minOfferStars: nil
)
if let entry = CodableEntry(RecentStarGiftItem(gift)) {
items.append(OrderedItemListEntry(id: RecentStarGiftItemId(id).rawValue, contents: entry))

View file

@ -1133,7 +1133,7 @@ public final class PendingMessageManager {
} else if let inputSourcePeerId = forwardPeerIds.first, let inputSourcePeer = transaction.getPeer(inputSourcePeerId).flatMap(apiInputPeer) {
let dependencyTag = PendingMessageRequestDependencyTag(messageId: messages[0].0.id)
sendMessageRequest = network.request(Api.functions.messages.forwardMessages(flags: flags, fromPeer: inputSourcePeer, id: forwardIds.map { $0.0.id }, randomId: forwardIds.map { $0.1 }, toPeer: inputPeer, topMsgId: topMsgId, replyTo: replyTo, scheduleDate: scheduleTime, scheduleRepeatPeriod: scheduleRepeatPeriod, sendAs: sendAsInputPeer, quickReplyShortcut: quickReplyShortcut, videoTimestamp: videoTimestamp, allowPaidStars: allowPaidStars, suggestedPost: suggestedPost), tag: dependencyTag)
sendMessageRequest = network.request(Api.functions.messages.forwardMessages(flags: flags, fromPeer: inputSourcePeer, id: forwardIds.map { $0.0.id }, randomId: forwardIds.map { $0.1 }, toPeer: inputPeer, topMsgId: topMsgId, replyTo: replyTo, scheduleDate: scheduleTime, scheduleRepeatPeriod: scheduleRepeatPeriod, sendAs: sendAsInputPeer, quickReplyShortcut: quickReplyShortcut, effect: nil, videoTimestamp: videoTimestamp, allowPaidStars: allowPaidStars, suggestedPost: suggestedPost), tag: dependencyTag)
} else {
assertionFailure()
sendMessageRequest = .fail(MTRpcError(errorCode: 400, errorDescription: "Invalid forward source"))
@ -1831,7 +1831,7 @@ public final class PendingMessageManager {
}
if let forwardSourceInfoAttribute = forwardSourceInfoAttribute, let sourcePeer = transaction.getPeer(forwardSourceInfoAttribute.messageId.peerId), let sourceInputPeer = apiInputPeer(sourcePeer) {
sendMessageRequest = network.request(Api.functions.messages.forwardMessages(flags: flags, fromPeer: sourceInputPeer, id: [sourceInfo.messageId.id], randomId: [uniqueId], toPeer: inputPeer, topMsgId: topMsgId, replyTo: replyTo, scheduleDate: scheduleTime, scheduleRepeatPeriod: scheduleRepeatPeriod, sendAs: sendAsInputPeer, quickReplyShortcut: quickReplyShortcut, videoTimestamp: videoTimestamp, allowPaidStars: allowPaidStars, suggestedPost: suggestedPost), tag: dependencyTag)
sendMessageRequest = network.request(Api.functions.messages.forwardMessages(flags: flags, fromPeer: sourceInputPeer, id: [sourceInfo.messageId.id], randomId: [uniqueId], toPeer: inputPeer, topMsgId: topMsgId, replyTo: replyTo, scheduleDate: scheduleTime, scheduleRepeatPeriod: scheduleRepeatPeriod, sendAs: sendAsInputPeer, quickReplyShortcut: quickReplyShortcut, effect: nil, videoTimestamp: videoTimestamp, allowPaidStars: allowPaidStars, suggestedPost: suggestedPost), tag: dependencyTag)
|> map(NetworkRequestResult.result)
} else {
sendMessageRequest = .fail(MTRpcError(errorCode: 400, errorDescription: "internal"))

View file

@ -210,7 +210,7 @@ public class BoxedMessage: NSObject {
public class Serialization: NSObject, MTSerialization {
public func currentLayer() -> UInt {
return 219
return 220
}
public func parseMessage(_ data: Data!) -> Any! {

View file

@ -256,7 +256,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
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?, giftMessageId: Int32?, upgradeSeparate: Bool, isAuctionAcquired: Bool, toPeerId: EnginePeer.Id?)
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?, dropOriginalDetailsStars: Int64?, assigned: Bool)
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?, dropOriginalDetailsStars: Int64?, assigned: Bool, fromOffer: Bool)
case paidMessagesRefunded(count: Int32, stars: Int64)
case paidMessagesPriceEdited(stars: Int64, broadcastMessagesAllowed: Bool)
case conferenceCall(ConferenceCall)
@ -267,6 +267,8 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
case suggestedPostSuccess(amount: CurrencyAmount)
case suggestedPostRefund(SuggestedPostRefund)
case suggestedBirthday(TelegramBirthday)
case starGiftPurchaseOffer(gift: StarGift, amount: CurrencyAmount, expireDate: Int32, isAccepted: Bool, isDeclined: Bool)
case starGiftPurchaseOfferDeclined(gift: StarGift, amount: CurrencyAmount, hasExpired: Bool)
public init(decoder: PostboxDecoder) {
let rawValue: Int32 = decoder.decodeInt32ForKey("_rawValue", orElse: 0)
@ -402,7 +404,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
} else if let stars = decoder.decodeOptionalInt64ForKey("resaleStars") {
resaleAmount = CurrencyAmount(amount: StarsAmount(value: stars, nanos: 0), currency: .stars)
}
self = .starGiftUnique(gift: decoder.decodeObjectForKey("gift", decoder: { StarGift(decoder: $0) }) as! StarGift, isUpgrade: decoder.decodeBoolForKey("isUpgrade", orElse: false), isTransferred: decoder.decodeBoolForKey("isTransferred", orElse: false), savedToProfile: decoder.decodeBoolForKey("savedToProfile", orElse: false), canExportDate: decoder.decodeOptionalInt32ForKey("canExportDate"), transferStars: decoder.decodeOptionalInt64ForKey("transferStars"), isRefunded: decoder.decodeBoolForKey("isRefunded", orElse: false), isPrepaidUpgrade: decoder.decodeBoolForKey("isPrepaidUpgrade", orElse: false), peerId: decoder.decodeOptionalInt64ForKey("peerId").flatMap { EnginePeer.Id($0) }, senderId: decoder.decodeOptionalInt64ForKey("senderId").flatMap { EnginePeer.Id($0) }, savedId: decoder.decodeOptionalInt64ForKey("savedId"), resaleAmount: resaleAmount, canTransferDate: decoder.decodeOptionalInt32ForKey("canTransferDate"), canResaleDate: decoder.decodeOptionalInt32ForKey("canResaleDate"), dropOriginalDetailsStars: decoder.decodeOptionalInt64ForKey("dropOriginalDetailsStars"), assigned: decoder.decodeBoolForKey("assigned", orElse: false))
self = .starGiftUnique(gift: decoder.decodeObjectForKey("gift", decoder: { StarGift(decoder: $0) }) as! StarGift, isUpgrade: decoder.decodeBoolForKey("isUpgrade", orElse: false), isTransferred: decoder.decodeBoolForKey("isTransferred", orElse: false), savedToProfile: decoder.decodeBoolForKey("savedToProfile", orElse: false), canExportDate: decoder.decodeOptionalInt32ForKey("canExportDate"), transferStars: decoder.decodeOptionalInt64ForKey("transferStars"), isRefunded: decoder.decodeBoolForKey("isRefunded", orElse: false), isPrepaidUpgrade: decoder.decodeBoolForKey("isPrepaidUpgrade", orElse: false), peerId: decoder.decodeOptionalInt64ForKey("peerId").flatMap { EnginePeer.Id($0) }, senderId: decoder.decodeOptionalInt64ForKey("senderId").flatMap { EnginePeer.Id($0) }, savedId: decoder.decodeOptionalInt64ForKey("savedId"), resaleAmount: resaleAmount, canTransferDate: decoder.decodeOptionalInt32ForKey("canTransferDate"), canResaleDate: decoder.decodeOptionalInt32ForKey("canResaleDate"), dropOriginalDetailsStars: decoder.decodeOptionalInt64ForKey("dropOriginalDetailsStars"), assigned: decoder.decodeBoolForKey("assigned", orElse: false), fromOffer: decoder.decodeBoolForKey("fromOffer", orElse: false))
case 46:
self = .paidMessagesRefunded(count: decoder.decodeInt32ForKey("count", orElse: 0), stars: decoder.decodeInt64ForKey("stars", orElse: 0))
case 47:
@ -434,6 +436,10 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
self = .suggestedPostRefund(decoder.decodeCodable(SuggestedPostRefund.self, forKey: "s") ?? SuggestedPostRefund(isUserInitiated: true))
case 55:
self = .suggestedBirthday(decoder.decodeCodable(TelegramBirthday.self, forKey: "birthday") ?? TelegramBirthday(day: 1, month: 1, year: nil))
case 56:
self = .starGiftPurchaseOffer(gift: decoder.decodeObjectForKey("gift", decoder: { StarGift(decoder: $0) }) as! StarGift, amount: decoder.decodeCodable(CurrencyAmount.self, forKey: "amount")!, expireDate: decoder.decodeInt32ForKey("expireDate", orElse: 0), isAccepted: decoder.decodeBoolForKey("isAccepted", orElse: false), isDeclined: decoder.decodeBoolForKey("isDeclined", orElse: false))
case 57:
self = .starGiftPurchaseOfferDeclined(gift: decoder.decodeObjectForKey("gift", decoder: { StarGift(decoder: $0) }) as! StarGift, amount: decoder.decodeCodable(CurrencyAmount.self, forKey: "amount")!, hasExpired: decoder.decodeBoolForKey("hasExpired", orElse: false))
default:
self = .unknown
}
@ -792,7 +798,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
} else {
encoder.encodeNil(forKey: "toPeerId")
}
case let .starGiftUnique(gift, isUpgrade, isTransferred, savedToProfile, canExportDate, transferStars, isRefunded, isPrepaidUpgrade, peerId, senderId, savedId, resaleAmount, canTransferDate, canResaleDate, dropOriginalDetailsStars, assigned):
case let .starGiftUnique(gift, isUpgrade, isTransferred, savedToProfile, canExportDate, transferStars, isRefunded, isPrepaidUpgrade, peerId, senderId, savedId, resaleAmount, canTransferDate, canResaleDate, dropOriginalDetailsStars, assigned, fromOffer):
encoder.encodeInt32(45, forKey: "_rawValue")
encoder.encodeObject(gift, forKey: "gift")
encoder.encodeBool(isUpgrade, forKey: "isUpgrade")
@ -846,6 +852,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
encoder.encodeNil(forKey: "dropOriginalDetailsStars")
}
encoder.encodeBool(assigned, forKey: "assigned")
encoder.encodeBool(fromOffer, forKey: "fromOffer")
case let .paidMessagesRefunded(count, stars):
encoder.encodeInt32(46, forKey: "_rawValue")
encoder.encodeInt32(count, forKey: "count")
@ -899,6 +906,18 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
case let .suggestedBirthday(birthday):
encoder.encodeInt32(55, forKey: "_rawValue")
encoder.encodeCodable(birthday, forKey: "birthday")
case let .starGiftPurchaseOffer(gift, amount, expireDate, isAccepted, isDeclined):
encoder.encodeInt32(56, forKey: "_rawValue")
encoder.encodeObject(gift, forKey: "gift")
encoder.encodeCodable(amount, forKey: "amount")
encoder.encodeInt32(expireDate, forKey: "expireDate")
encoder.encodeBool(isAccepted, forKey: "isAccepted")
encoder.encodeBool(isDeclined, forKey: "isDeclined")
case let .starGiftPurchaseOfferDeclined(gift, amount, hasExpired):
encoder.encodeInt32(57, forKey: "_rawValue")
encoder.encodeObject(gift, forKey: "gift")
encoder.encodeCodable(amount, forKey: "amount")
encoder.encodeBool(hasExpired, forKey: "hasExpired")
}
}
@ -941,7 +960,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
peerIds.append(toPeerId)
}
return peerIds
case let .starGiftUnique(gift, _, _, _, _, _, _, _, peerId, senderId, _, _, _, _, _, _):
case let .starGiftUnique(gift, _, _, _, _, _, _, _, peerId, senderId, _, _, _, _, _, _, _):
var peerIds: [PeerId] = []
if let peerId {
peerIds.append(peerId)

View file

@ -14,7 +14,7 @@ func _internal_forwardGameWithScore(account: Account, messageId: MessageId, to p
flags |= (1 << 13)
}
return account.network.request(Api.functions.messages.forwardMessages(flags: flags, fromPeer: fromInputPeer, id: [messageId.id], randomId: [Int64.random(in: Int64.min ... Int64.max)], toPeer: toInputPeer, topMsgId: threadId.flatMap { Int32(clamping: $0) }, replyTo: nil, scheduleDate: nil, scheduleRepeatPeriod: nil, sendAs: sendAsInputPeer, quickReplyShortcut: nil, videoTimestamp: nil, allowPaidStars: nil, suggestedPost: nil))
return account.network.request(Api.functions.messages.forwardMessages(flags: flags, fromPeer: fromInputPeer, id: [messageId.id], randomId: [Int64.random(in: Int64.min ... Int64.max)], toPeer: toInputPeer, topMsgId: threadId.flatMap { Int32(clamping: $0) }, replyTo: nil, scheduleDate: nil, scheduleRepeatPeriod: nil, sendAs: sendAsInputPeer, quickReplyShortcut: nil, effect: nil, videoTimestamp: nil, allowPaidStars: nil, suggestedPost: nil))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.Updates?, NoError> in
return .single(nil)

View file

@ -346,6 +346,7 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
case themePeerId
case peerColor
case hostPeerId
case minOfferStars
}
public struct Flags: OptionSet {
@ -635,8 +636,9 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
public let themePeerId: EnginePeer.Id?
public let peerColor: PeerCollectibleColor?
public let hostPeerId: EnginePeer.Id?
public let minOfferStars: Int64?
public init(id: Int64, giftId: Int64, title: String, number: Int32, slug: String, owner: Owner, attributes: [Attribute], availability: Availability, giftAddress: String?, resellAmounts: [CurrencyAmount]?, resellForTonOnly: Bool, releasedBy: EnginePeer.Id?, valueAmount: Int64?, valueCurrency: String?, flags: Flags, themePeerId: EnginePeer.Id?, peerColor: PeerCollectibleColor?, hostPeerId: EnginePeer.Id?) {
public init(id: Int64, giftId: Int64, title: String, number: Int32, slug: String, owner: Owner, attributes: [Attribute], availability: Availability, giftAddress: String?, resellAmounts: [CurrencyAmount]?, resellForTonOnly: Bool, releasedBy: EnginePeer.Id?, valueAmount: Int64?, valueCurrency: String?, flags: Flags, themePeerId: EnginePeer.Id?, peerColor: PeerCollectibleColor?, hostPeerId: EnginePeer.Id?, minOfferStars: Int64?) {
self.id = id
self.giftId = giftId
self.title = title
@ -655,6 +657,7 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
self.themePeerId = themePeerId
self.peerColor = peerColor
self.hostPeerId = hostPeerId
self.minOfferStars = minOfferStars
}
public init(from decoder: Decoder) throws {
@ -691,6 +694,7 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
self.themePeerId = try container.decodeIfPresent(Int64.self, forKey: .themePeerId).flatMap { EnginePeer.Id($0) }
self.peerColor = try container.decodeIfPresent(PeerCollectibleColor.self, forKey: .peerColor)
self.hostPeerId = try container.decodeIfPresent(Int64.self, forKey: .hostPeerId).flatMap { EnginePeer.Id($0) }
self.minOfferStars = try container.decodeIfPresent(Int64.self, forKey: .minOfferStars)
}
public init(decoder: PostboxDecoder) {
@ -726,6 +730,7 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
self.themePeerId = decoder.decodeOptionalInt64ForKey(CodingKeys.themePeerId.rawValue).flatMap { EnginePeer.Id($0) }
self.peerColor = decoder.decodeCodable(PeerCollectibleColor.self, forKey: CodingKeys.peerColor.rawValue)
self.hostPeerId = decoder.decodeOptionalInt64ForKey(CodingKeys.hostPeerId.rawValue).flatMap { EnginePeer.Id($0) }
self.minOfferStars = decoder.decodeOptionalInt64ForKey(CodingKeys.minOfferStars.rawValue)
}
public func encode(to encoder: Encoder) throws {
@ -755,6 +760,7 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
try container.encodeIfPresent(self.themePeerId?.toInt64(), forKey: .themePeerId)
try container.encodeIfPresent(self.peerColor, forKey: .peerColor)
try container.encodeIfPresent(self.hostPeerId?.toInt64(), forKey: .hostPeerId)
try container.encodeIfPresent(self.minOfferStars, forKey: .minOfferStars)
}
public func encode(_ encoder: PostboxEncoder) {
@ -812,6 +818,11 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
} else {
encoder.encodeNil(forKey: CodingKeys.hostPeerId.rawValue)
}
if let minOfferStars = self.minOfferStars {
encoder.encodeInt64(minOfferStars, forKey: CodingKeys.minOfferStars.rawValue)
} else {
encoder.encodeNil(forKey: CodingKeys.minOfferStars.rawValue)
}
}
public func withResellAmounts(_ resellAmounts: [CurrencyAmount]?) -> UniqueGift {
@ -833,7 +844,8 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
flags: self.flags,
themePeerId: self.themePeerId,
peerColor: self.peerColor,
hostPeerId: self.hostPeerId
hostPeerId: self.hostPeerId,
minOfferStars: self.minOfferStars
)
}
@ -856,7 +868,8 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
flags: self.flags,
themePeerId: self.themePeerId,
peerColor: self.peerColor,
hostPeerId: self.hostPeerId
hostPeerId: self.hostPeerId,
minOfferStars: self.minOfferStars
)
}
@ -879,7 +892,8 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
flags: self.flags,
themePeerId: themePeerId,
peerColor: self.peerColor,
hostPeerId: self.hostPeerId
hostPeerId: self.hostPeerId,
minOfferStars: self.minOfferStars
)
}
@ -902,7 +916,8 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
flags: self.flags,
themePeerId: self.themePeerId,
peerColor: self.peerColor,
hostPeerId: self.hostPeerId
hostPeerId: self.hostPeerId,
minOfferStars: self.minOfferStars
)
}
}
@ -1027,7 +1042,7 @@ extension StarGift {
return nil
}
self = .generic(StarGift.Gift(id: id, title: title, file: file, price: stars, convertStars: convertStars, availability: availability, soldOut: soldOut, flags: flags, upgradeStars: upgradeStars, releasedBy: releasedBy?.peerId, perUserLimit: perUserLimit, lockedUntilDate: lockedUntilDate, auctionSlug: auctionSlug, auctionGiftsPerRound: giftsPerRound))
case let .starGiftUnique(apiFlags, id, giftId, title, slug, num, ownerPeerId, ownerName, ownerAddress, attributes, availabilityIssued, availabilityTotal, giftAddress, resellAmounts, releasedBy, valueAmount, valueCurrency, themePeer, peerColor, hostPeerId):
case let .starGiftUnique(apiFlags, id, giftId, title, slug, num, ownerPeerId, ownerName, ownerAddress, attributes, availabilityIssued, availabilityTotal, giftAddress, resellAmounts, releasedBy, valueAmount, valueCurrency, themePeer, peerColor, hostPeerId, minOfferStars):
let owner: StarGift.UniqueGift.Owner
if let ownerAddress {
owner = .address(ownerAddress)
@ -1059,7 +1074,7 @@ extension StarGift {
break
}
self = .unique(StarGift.UniqueGift(id: id, giftId: giftId, title: title, number: num, slug: slug, owner: owner, attributes: attributes.compactMap { UniqueGift.Attribute(apiAttribute: $0) }, availability: UniqueGift.Availability(issued: availabilityIssued, total: availabilityTotal), giftAddress: giftAddress, resellAmounts: resellAmounts, resellForTonOnly: (apiFlags & (1 << 7)) != 0, releasedBy: releasedBy?.peerId, valueAmount: valueAmount, valueCurrency: valueCurrency, flags: flags, themePeerId: themePeer?.peerId, peerColor: peerCollectibleColor, hostPeerId: hostPeerId?.peerId))
self = .unique(StarGift.UniqueGift(id: id, giftId: giftId, title: title, number: num, slug: slug, owner: owner, attributes: attributes.compactMap { UniqueGift.Attribute(apiAttribute: $0) }, availability: UniqueGift.Availability(issued: availabilityIssued, total: availabilityTotal), giftAddress: giftAddress, resellAmounts: resellAmounts, resellForTonOnly: (apiFlags & (1 << 7)) != 0, releasedBy: releasedBy?.peerId, valueAmount: valueAmount, valueCurrency: valueCurrency, flags: flags, themePeerId: themePeer?.peerId, peerColor: peerCollectibleColor, hostPeerId: hostPeerId?.peerId, minOfferStars: minOfferStars.flatMap { Int64($0) }))
}
}
}
@ -1270,7 +1285,7 @@ func _internal_dropStarGiftOriginalDetails(account: Account, reference: StarGift
storeForwardInfo = StoreMessageForwardInfo(authorId: forwardInfo.author?.id, sourceId: forwardInfo.source?.id, sourceMessageId: forwardInfo.sourceMessageId, date: forwardInfo.date, authorSignature: forwardInfo.authorSignature, psaType: forwardInfo.psaType, flags: forwardInfo.flags)
}
var media = currentMessage.media
if let action = media.first(where: { $0 is TelegramMediaAction }) as? TelegramMediaAction, case let .starGiftUnique(gift, isUpgrade, isTransferred, savedToProfile, canExportDate, transferStars, isRefunded, isPrepaidUpgrade, peerId, senderId, savedId, resaleAmount, canTransferDate, canResaleDate, _, assigned) = action.action, case let .unique(uniqueGift) = gift {
if let action = media.first(where: { $0 is TelegramMediaAction }) as? TelegramMediaAction, case let .starGiftUnique(gift, isUpgrade, isTransferred, savedToProfile, canExportDate, transferStars, isRefunded, isPrepaidUpgrade, peerId, senderId, savedId, resaleAmount, canTransferDate, canResaleDate, _, assigned, fromOffer) = action.action, case let .unique(uniqueGift) = gift {
let updatedAttributes = uniqueGift.attributes.filter { $0.attributeType != .originalInfo }
media = [
TelegramMediaAction(
@ -1290,7 +1305,9 @@ func _internal_dropStarGiftOriginalDetails(account: Account, reference: StarGift
canTransferDate: canTransferDate,
canResaleDate: canResaleDate,
dropOriginalDetailsStars: nil,
assigned: assigned)
assigned: assigned,
fromOffer: fromOffer
)
)
]
}
@ -1395,7 +1412,7 @@ func _internal_upgradeStarGift(account: Account, formId: Int64?, reference: Star
case let .updateNewMessage(message, _, _):
if let message = StoreMessage(apiMessage: message, accountPeerId: account.peerId, peerIsForum: false) {
for media in message.media {
if let action = media as? TelegramMediaAction, case let .starGiftUnique(gift, _, _, savedToProfile, canExportDate, transferStars, _, _, peerId, _, savedId, _, canTransferDate, canResaleDate, dropOriginalDetailsStars, _) = action.action, case let .Id(messageId) = message.id {
if let action = media as? TelegramMediaAction, case let .starGiftUnique(gift, _, _, savedToProfile, canExportDate, transferStars, _, _, peerId, _, savedId, _, canTransferDate, canResaleDate, dropOriginalDetailsStars, _, _) = action.action, case let .Id(messageId) = message.id {
let reference: StarGiftReference
if let peerId, let savedId {
reference = .peer(peerId: peerId, id: savedId)
@ -1422,7 +1439,7 @@ func _internal_upgradeStarGift(account: Account, formId: Int64?, reference: Star
collectionIds: nil,
prepaidUpgradeHash: nil,
upgradeSeparate: false,
dropOriginalDetailsStars: dropOriginalDetailsStars
dropOriginalDetailsStars: dropOriginalDetailsStars
))
}
}

View file

@ -0,0 +1,55 @@
import Foundation
import Postbox
import MtProtoKit
import SwiftSignalKit
import TelegramApi
public enum ResolveStarGiftOfferError {
case generic
}
func _internal_resolveStarGiftOffer(account: Account, messageId: EngineMessage.Id, accept: Bool) -> Signal<Never, ResolveStarGiftOfferError> {
var flags: Int32 = 0
if !accept {
flags |= (1 << 0)
}
return account.network.request(Api.functions.payments.resolveStarGiftOffer(flags: flags, offerMsgId: messageId.id))
|> mapError { _ -> ResolveStarGiftOfferError in
return .generic
}
|> mapToSignal { updates -> Signal<Never, ResolveStarGiftOfferError> in
account.stateManager.addUpdates(updates)
return .complete()
}
|> ignoreValues
}
public enum SendStarGiftOfferError {
case generic
}
func _internal_sendStarGiftOffer(account: Account, peerId: EnginePeer.Id, slug: String, amount: CurrencyAmount, duration: Int32, allowPaidStars: Int64?) -> Signal<Never, SendStarGiftOfferError> {
var flags: Int32 = 0
if let _ = allowPaidStars {
flags |= (1 << 0)
}
return account.postbox.transaction { transaction in
return transaction.getPeer(peerId).flatMap(apiInputPeer)
}
|> castError(SendStarGiftOfferError.self)
|> mapToSignal { inputPeer -> Signal<Never, SendStarGiftOfferError> in
guard let inputPeer else {
return .fail(.generic)
}
return account.network.request(Api.functions.payments.sendStarGiftOffer(flags: flags, peer: inputPeer, slug: slug, price: amount.apiAmount, duration: duration, randomId: Int64.random(in: .min ..< .max), allowPaidStars: allowPaidStars))
|> mapError { _ -> SendStarGiftOfferError in
return .generic
}
|> mapToSignal { updates -> Signal<Never, SendStarGiftOfferError> in
account.stateManager.addUpdates(updates)
return .complete()
}
}
|> ignoreValues
}

View file

@ -735,6 +735,9 @@ private extension StarsContext.State.Transaction {
if (apiFlags & (1 << 28)) != 0 {
flags.insert(.isStarGiftAuctionBid)
}
if (apiFlags & (1 << 29)) != 0 {
flags.insert(.isStarGiftOffer)
}
let media = extendedMedia.flatMap({ $0.compactMap { textMediaAndExpirationTimerFromApiMedia($0, PeerId(0)).media } }) ?? []
@ -793,6 +796,7 @@ public final class StarsContext {
public static let isStarGiftDropOriginalDetails = Flags(rawValue: 1 << 12)
public static let isStarGiftAuctionBid = Flags(rawValue: 1 << 13)
public static let isLiveStreamPaidMessage = Flags(rawValue: 1 << 14)
public static let isStarGiftOffer = Flags(rawValue: 1 << 15)
}
public enum Peer: Equatable {
@ -1640,7 +1644,7 @@ func _internal_sendStarsPaymentForm(account: Account, formId: Int64, source: Bot
case .giftCode, .stars, .starsGift, .starsChatSubscription, .starGift, .starGiftUpgrade, .starGiftTransfer, .premiumGift, .starGiftResale, .starGiftPrepaidUpgrade, .starGiftDropOriginalDetails, .starGiftAuctionBid:
receiptMessageId = nil
}
} else if case let .starGiftUnique(gift, _, _, savedToProfile, canExportDate, transferStars, _, _, peerId, _, savedId, _, canTransferDate, canResaleDate, dropOriginalDetailsStars, _) = action.action, case let .Id(messageId) = message.id {
} else if case let .starGiftUnique(gift, _, _, savedToProfile, canExportDate, transferStars, _, _, peerId, _, savedId, _, canTransferDate, canResaleDate, dropOriginalDetailsStars, _, _) = action.action, case let .Id(messageId) = message.id {
let reference: StarGiftReference
if let peerId, let savedId {
reference = .peer(peerId: peerId, id: savedId)

View file

@ -180,6 +180,14 @@ public extension TelegramEngine {
public func getStarsTransaction(reference: StarsTransactionReference) -> Signal<StarsContext.State.Transaction?, NoError> {
return _internal_getStarsTransaction(accountPeerId: self.account.peerId, postbox: self.account.postbox, network: self.account.network, transactionReference: reference)
}
public func resolveStarGiftOffer(messageId: EngineMessage.Id, accept: Bool) -> Signal<Never, ResolveStarGiftOfferError> {
return _internal_resolveStarGiftOffer(account: self.account, messageId: messageId, accept: accept)
}
public func sendStarGiftOffer(peerId: EnginePeer.Id, slug: String, amount: CurrencyAmount, duration: Int32, allowPaidStars: Int64?) -> Signal<Never, SendStarGiftOfferError> {
return _internal_sendStarGiftOffer(account: self.account, peerId: peerId, slug: slug, amount: amount, duration: duration, allowPaidStars: allowPaidStars)
}
}
}

View file

@ -1262,7 +1262,7 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
attributedString = addAttributesToStringWithRanges(strings.Notification_StarsGift_Sent(authorName, starsPrice)._tuple, body: bodyAttributes, argumentAttributes: attributes)
}
}
case let .starGiftUnique(gift, isUpgrade, _, _, _, _, _, isPrepaidUpgrade, peerId, senderId, _, resaleStars, _, _, _, assigned):
case let .starGiftUnique(gift, isUpgrade, _, _, _, _, _, isPrepaidUpgrade, peerId, senderId, _, resaleStars, _, _, _, assigned, _):
if case let .unique(gift) = gift {
if !forAdditionalServiceMessage && !"".isEmpty {
attributedString = NSAttributedString(string: "\(gift.title) #\(presentationStringsFormattedNumber(gift.number, dateTimeFormat.groupingSeparator))", font: titleFont, textColor: primaryTextColor)
@ -1616,6 +1616,10 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
attributedString = addAttributesToStringWithRanges(strings.Notification_StarsGift_Sent(authorName, price)._tuple, body: bodyAttributes, argumentAttributes: attributes)
}
}
case .starGiftPurchaseOffer:
attributedString = nil
case .starGiftPurchaseOfferDeclined:
attributedString = nil
case .unknown:
attributedString = nil
}

View file

@ -282,7 +282,7 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
switch action.action {
case let .starGift(gift, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
releasedBy = gift.releasedBy
case let .starGiftUnique(gift, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
case let .starGiftUnique(gift, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
releasedBy = gift.releasedBy
default:
break
@ -686,7 +686,7 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
}
}
}
case let .starGiftUnique(gift, isUpgrade, _, _, _, _, isRefunded, _, _, _, _, _, _, _, _, _):
case let .starGiftUnique(gift, isUpgrade, _, _, _, _, isRefunded, _, _, _, _, _, _, _, _, _, _):
if case let .unique(uniqueGift) = gift {
isStarGift = true

View file

@ -167,8 +167,6 @@ final class GiftStoreScreenComponent: Component {
return
}
//, self.state?.starGiftsState?.dataState != .loading
let availableWidth = self.scrollView.bounds.width
let availableHeight = self.scrollView.bounds.height
let contentOffset = self.scrollView.contentOffset.y

View file

@ -720,8 +720,7 @@ private final class GiftViewSheetContent: CombinedComponent {
if let dropOriginalDetailsImpl {
signal = dropOriginalDetailsImpl(reference)
} else {
signal = (context.engine.payments.dropStarGiftOriginalDetails(reference: reference)
|> deliverOnMainQueue)
signal = context.engine.payments.dropStarGiftOriginalDetails(reference: reference)
}
self.upgradeDisposable = (signal
@ -738,7 +737,7 @@ private final class GiftViewSheetContent: CombinedComponent {
let updatedAttributes = uniqueGift.attributes.filter { $0.attributeType != .originalInfo }
self.subject = .profileGift(peerId, gift.withGift(.unique(uniqueGift.withAttributes(updatedAttributes))))
case let .message(message):
if let action = message.media.first(where: { $0 is TelegramMediaAction }) as? TelegramMediaAction, case let .starGiftUnique(gift, isUpgrade, isTransferred, savedToProfile, canExportDate, transferStars, isRefunded, isPrepaidUpgrade, peerId, senderId, savedId, resaleAmount, canTransferDate, canResaleDate, _, assigned) = action.action, case let .unique(uniqueGift) = gift {
if let action = message.media.first(where: { $0 is TelegramMediaAction }) as? TelegramMediaAction, case let .starGiftUnique(gift, isUpgrade, isTransferred, savedToProfile, canExportDate, transferStars, isRefunded, isPrepaidUpgrade, peerId, senderId, savedId, resaleAmount, canTransferDate, canResaleDate, _, assigned, fromOffer) = action.action, case let .unique(uniqueGift) = gift {
let updatedAttributes = uniqueGift.attributes.filter { $0.attributeType != .originalInfo }
let updatedMedia: [Media] = [
TelegramMediaAction(
@ -758,7 +757,9 @@ private final class GiftViewSheetContent: CombinedComponent {
canTransferDate: canTransferDate,
canResaleDate: canResaleDate,
dropOriginalDetailsStars: nil,
assigned: assigned)
assigned: assigned,
fromOffer: fromOffer
)
)
]
@ -1323,7 +1324,7 @@ private final class GiftViewSheetContent: CombinedComponent {
}
}
func viewUpgradedGift(messageId: EngineMessage.Id) {
func viewUpgradedGift(messageId: EngineMessage.Id, delay: Bool) {
guard let controller = self.getController(), let navigationController = controller.navigationController as? NavigationController else {
return
}
@ -1334,7 +1335,17 @@ private final class GiftViewSheetContent: CombinedComponent {
guard let self, let navigationController, let peer else {
return
}
self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(peer), subject: .message(id: .id(messageId), highlight: ChatControllerSubject.MessageHighlight(quote: nil), timecode: nil, setupReply: false), keepStack: .always, useExisting: true, purposefulAction: {}, peekData: nil, forceAnimatedScroll: true))
let action = {
self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(peer), subject: .message(id: .id(messageId), highlight: ChatControllerSubject.MessageHighlight(quote: nil), timecode: nil, setupReply: false), keepStack: .always, useExisting: true, purposefulAction: {}, peekData: nil, forceAnimatedScroll: true))
}
if delay {
Queue.mainQueue().after(0.3) {
action()
}
} else {
action()
}
})
}
@ -1425,6 +1436,17 @@ private final class GiftViewSheetContent: CombinedComponent {
self?.shareGift()
})))
//TODO:localize
if case let .unique(uniqueGift) = arguments.gift, case let .peerId(ownerPeerId) = uniqueGift.owner, ownerPeerId != self.context.account.peerId {
items.append(.action(ContextMenuActionItem(text: "Offer to Buy", icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Media Grid/Paid"), color: theme.contextMenu.primaryColor)
}, action: { [weak self] c, _ in
c?.dismiss(completion: nil)
self?.openGiftBuyOffer()
})))
}
if gift.flags.contains(.isThemeAvailable) {
items.append(.action(ContextMenuActionItem(text: presentationData.strings.Gift_View_Context_SetAsTheme, icon: { theme in
@ -2310,6 +2332,118 @@ private final class GiftViewSheetContent: CombinedComponent {
controller.switchToNextUpgradable()
}
}
func openGiftBuyOffer() {
guard let gift = self.subject.arguments?.gift, case let .unique(uniqueGift) = gift, case let .peerId(ownerPeerId) = uniqueGift.owner, let controller = self.getController() else {
return
}
let _ = (self.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: ownerPeerId))
|> deliverOnMainQueue).start(next: { [weak self] peer in
guard let self, let peer else {
return
}
let buyController = self.context.sharedContext.makeStarsWithdrawalScreen(context: self.context, subject: .starGiftOffer(peer: peer, gift: uniqueGift, completion: { [weak self] amount, duration in
guard let self else {
return
}
self.commitGiftBuyOffer(peer: peer, price: amount, duration: duration)
}))
controller.push(buyController)
})
}
func commitGiftBuyOffer(peer: EnginePeer, price: CurrencyAmount, duration: Int32) {
guard let gift = self.subject.arguments?.gift, case let .unique(uniqueGift) = gift, let starsContext = self.context.starsContext, let starsState = starsContext.currentState else {
return
}
let context = self.context
let proceed = { [weak self, weak starsContext] in
guard let self else {
return
}
self.upgradeDisposable = (context.engine.payments.sendStarGiftOffer(peerId: peer.id, slug: uniqueGift.slug, amount: price, duration: duration, allowPaidStars: nil)
|> deliverOnMainQueue).start(error: { _ in
}, completed: { [weak self, weak starsContext] in
guard let self else {
return
}
Queue.mainQueue().after(0.5) {
starsContext?.load(force: true)
}
self.openPeer(peer, dismiss: true)
})
}
if price.currency == .stars, starsState.balance < price.amount {
let _ = (self.starsTopUpOptionsPromise.get()
|> filter { $0 != nil }
|> take(1)
|> deliverOnMainQueue).startStandalone(next: { [weak self] options in
guard let self, let controller = self.getController() else {
return
}
let purchaseController = context.sharedContext.makeStarsPurchaseScreen(
context: context,
starsContext: starsContext,
options: options ?? [],
purpose: .starGiftOffer(requiredStars: price.amount.value),
targetPeerId: nil,
customTheme: nil,
completion: { [weak self, weak starsContext] stars in
guard let self, let starsContext else {
return
}
self.inProgress = true
self.updated()
starsContext.add(balance: StarsAmount(value: stars, nanos: 0))
let _ = (starsContext.onUpdate
|> deliverOnMainQueue).start(next: { [weak self] in
guard let self else {
return
}
Queue.mainQueue().after(0.1, { [weak self] in
guard let self, let starsContext = self.context.starsContext, let starsState = starsContext.currentState else {
return
}
if starsState.balance < price.amount {
self.inProgress = false
self.updated()
self.commitGiftBuyOffer(peer: peer, price: price, duration: duration)
} else {
proceed()
}
});
})
}
)
controller.push(purchaseController)
})
} else if price.currency == .ton, let tonState = context.tonContext?.currentState, tonState.balance < price.amount {
guard let controller = self.getController() else {
return
}
let needed = price.amount - tonState.balance
var fragmentUrl = "https://fragment.com/ads/topup"
if let data = self.context.currentAppConfiguration.with({ $0 }).data, let value = data["ton_topup_url"] as? String {
fragmentUrl = value
}
controller.push(BalanceNeededScreen(
context: self.context,
amount: needed,
buttonAction: { [weak self] in
guard let self else {
return
}
self.context.sharedContext.applicationBindings.openUrl(fragmentUrl)
}
))
} else {
proceed()
}
}
}
func makeState() -> State {
@ -4735,7 +4869,14 @@ private final class GiftViewSheetContent: CombinedComponent {
transition: .spring(duration: 0.2)
)
} else if upgraded, let arguments = subject.arguments, let upgradeMessageIdId = arguments.upgradeMessageId, let originalMessageId = arguments.messageId, !arguments.upgradeSeparate {
let upgradeMessageId = MessageId(peerId: originalMessageId.peerId, namespace: originalMessageId.namespace, id: upgradeMessageIdId)
var delay = false
var peerId: EnginePeer.Id = originalMessageId.peerId
if peerId.isTelegramNotifications {
peerId = component.context.account.peerId
delay = true
}
let upgradeMessageId = MessageId(peerId: peerId, namespace: originalMessageId.namespace, id: upgradeMessageIdId)
let buttonTitle = strings.Gift_View_ViewUpgraded
buttonChild = button.update(
component: ButtonComponent(
@ -4748,7 +4889,7 @@ private final class GiftViewSheetContent: CombinedComponent {
displaysProgress: false,
action: { [weak state] in
state?.dismiss(animated: true)
state?.viewUpgradedGift(messageId: upgradeMessageId)
state?.viewUpgradedGift(messageId: upgradeMessageId, delay: delay)
}),
availableSize: buttonSize,
transition: context.transition
@ -5216,7 +5357,7 @@ public class GiftViewScreen: ViewControllerComponentContainer {
let fromPeerId = senderId ?? message.author?.id
return (message.id.peerId, fromPeerId, message.author?.debugDisplayTitle, 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, upgradeSeparate, nil, toPeerId)
case let .starGiftUnique(gift, isUpgrade, isTransferred, savedToProfile, canExportDate, transferStars, _, _, peerId, senderId, savedId, _, canTransferDate, canResaleDate, dropOriginalDetailsStars, _):
case let .starGiftUnique(gift, isUpgrade, isTransferred, savedToProfile, canExportDate, transferStars, _, _, peerId, senderId, savedId, _, canTransferDate, canResaleDate, dropOriginalDetailsStars, _, _):
var reference: StarGiftReference
if let peerId, let savedId {
reference = .peer(peerId: peerId, id: savedId)

View file

@ -70,6 +70,7 @@ public final class ListActionItemComponent: Component {
case arrow
case toggle(Toggle)
case activity
case expandArrows
case custom(CustomAccessory)
}
@ -373,6 +374,8 @@ public final class ListActionItemComponent: Component {
}
case .arrow:
contentRightInset = 30.0
case .expandArrows:
contentRightInset = 36.0
case .toggle:
contentRightInset = 76.0
case .activity:
@ -645,6 +648,32 @@ public final class ListActionItemComponent: Component {
}
}
if case .expandArrows = component.accessory {
let arrowView: UIImageView
var arrowTransition = transition
if let current = self.arrowView {
arrowView = current
if themeUpdated {
arrowView.image = PresentationResourcesItemList.disclosureOptionArrowsImage(component.theme)
}
} else {
arrowTransition = arrowTransition.withAnimation(.none)
arrowView = UIImageView(image: PresentationResourcesItemList.disclosureOptionArrowsImage(component.theme))
self.arrowView = arrowView
self.addSubview(arrowView)
}
if let image = arrowView.image {
let arrowFrame = CGRect(origin: CGPoint(x: availableSize.width - 16.0 - image.size.width, y: floor((contentHeight - image.size.height) * 0.5)), size: image.size)
arrowTransition.setFrame(view: arrowView, frame: arrowFrame)
}
} else {
if let arrowView = self.arrowView {
self.arrowView = nil
arrowView.removeFromSuperview()
}
}
if case let .toggle(toggle) = component.accessory {
switch toggle.style {
case .regular:

View file

@ -777,7 +777,8 @@ final class UserAppearanceScreenComponent: Component {
flags: [],
themePeerId: nil,
peerColor: nil,
hostPeerId: nil
hostPeerId: nil,
minOfferStars: nil
)
signal = component.context.engine.accountData.setStarGiftStatus(starGift: gift, expirationDate: emojiStatus.expirationDate)
} else {

View file

@ -253,6 +253,8 @@ private final class StarsPurchaseScreenContentComponent: CombinedComponent {
textString = strings.Stars_Purchase_BuyStarGiftInfo
case .removeOriginalDetailsStarGift:
textString = strings.Stars_Purchase_RemoveOriginalDetailsStarGiftInfo
case .starGiftOffer:
textString = strings.Stars_Purchase_StarGiftOfferInfo
}
let markdownAttributes = MarkdownAttributes(body: MarkdownAttributeSet(font: textFont, textColor: textColor), bold: MarkdownAttributeSet(font: boldTextFont, textColor: textColor), link: MarkdownAttributeSet(font: textFont, textColor: accentColor), linkAttribute: { contents in
@ -843,7 +845,7 @@ private final class StarsPurchaseScreenComponent: CombinedComponent {
titleText = strings.Stars_Purchase_GetStars
case .gift:
titleText = strings.Stars_Purchase_GiftStars
case let .topUp(requiredStars, _), let .transfer(_, requiredStars), let .reactions(_, requiredStars), let .subscription(_, requiredStars, _), let .unlockMedia(requiredStars), let .starGift(_, requiredStars), let .upgradeStarGift(requiredStars), let .transferStarGift(requiredStars), let .sendMessage(_, requiredStars), let .buyStarGift(requiredStars), let .removeOriginalDetailsStarGift(requiredStars):
case let .topUp(requiredStars, _), let .transfer(_, requiredStars), let .reactions(_, requiredStars), let .subscription(_, requiredStars, _), let .unlockMedia(requiredStars), let .starGift(_, requiredStars), let .upgradeStarGift(requiredStars), let .transferStarGift(requiredStars), let .sendMessage(_, requiredStars), let .buyStarGift(requiredStars), let .removeOriginalDetailsStarGift(requiredStars), let .starGiftOffer(requiredStars):
titleText = strings.Stars_Purchase_StarsNeeded(Int32(requiredStars))
}
@ -1312,6 +1314,10 @@ private extension StarsPurchasePurpose {
return requiredStars
case let .buyStarGift(requiredStars):
return requiredStars
case let .removeOriginalDetailsStarGift(requiredStars):
return requiredStars
case let .starGiftOffer(requiredStars):
return requiredStars
default:
return nil
}

View file

@ -61,6 +61,7 @@ private final class SheetContent: CombinedComponent {
let currencyToggle = Child(TabSelectorComponent.self)
let amountSection = Child(ListSectionComponent.self)
let amountAdditionalLabel = Child(MultilineTextComponent.self)
let periodSection = Child(ListSectionComponent.self)
let timestampSection = Child(ListSectionComponent.self)
let onlyTonSection = Child(ListSectionComponent.self)
let button = Child(ButtonComponent.self)
@ -177,7 +178,7 @@ private final class SheetContent: CombinedComponent {
if let usdWithdrawRate = withdrawConfiguration.usdWithdrawRate, let amount = state.amount, amount > StarsAmount.zero {
let usdRate = Double(usdWithdrawRate) / 1000.0 / 100.0
amountLabel = "\(formatTonUsdValue(amount.value, divide: false, rate: usdRate, dateTimeFormat: environment.dateTimeFormat))"
amountLabel = "~\(formatTonUsdValue(amount.value, divide: false, rate: usdRate, dateTimeFormat: environment.dateTimeFormat))"
}
case .reaction:
titleString = environment.strings.Stars_SendStars_Title
@ -231,10 +232,33 @@ private final class SheetContent: CombinedComponent {
switch state.currency {
case .stars:
let usdRate = Double(usdWithdrawRate) / 1000.0 / 100.0
amountLabel = "\(formatTonUsdValue(amount.value, divide: false, rate: usdRate, dateTimeFormat: environment.dateTimeFormat))"
amountLabel = "~\(formatTonUsdValue(amount.value, divide: false, rate: usdRate, dateTimeFormat: environment.dateTimeFormat))"
case .ton:
let usdRate = Double(tonUsdRate) / 1000.0 / 1000000.0
amountLabel = "\(formatTonUsdValue(amount.value, divide: false, rate: usdRate, dateTimeFormat: environment.dateTimeFormat))"
amountLabel = "~\(formatTonUsdValue(amount.value, divide: false, rate: usdRate, dateTimeFormat: environment.dateTimeFormat))"
}
}
case .starGiftOffer:
titleString = "Offer to Buy"
switch state.currency {
case .stars:
amountTitle = "STARS TO OFFER"
minAmount = StarsAmount(value: resaleConfiguration.channelMessageSuggestionMinStarsAmount, nanos: 0)
case .ton:
amountTitle = "TON TO OFFER"
minAmount = StarsAmount(value: 0, nanos: 0)
}
maxAmount = nil
amountPlaceholder = "Price"
if let usdWithdrawRate = withdrawConfiguration.usdWithdrawRate, let tonUsdRate = withdrawConfiguration.tonUsdRate, let amount = state.amount, amount > StarsAmount.zero {
switch state.currency {
case .stars:
let usdRate = Double(usdWithdrawRate) / 1000.0 / 100.0
amountLabel = "~\(formatTonUsdValue(amount.value, divide: false, rate: usdRate, dateTimeFormat: environment.dateTimeFormat))"
case .ton:
let usdRate = Double(tonUsdRate) / 1000.0 / 1000000.0
amountLabel = "~\(formatTonUsdValue(amount.value, divide: false, rate: usdRate, dateTimeFormat: environment.dateTimeFormat))"
}
}
}
@ -309,8 +333,12 @@ private final class SheetContent: CombinedComponent {
tonBalanceValue = tonBalance
}
if case let .suggestedPost(mode, _, _, _) = component.mode {
var displayCurrencySelector = false
let selectedId: AnyHashable = state.currency == .stars ? AnyHashable(0 as Int) : AnyHashable(1 as Int)
let starsTitle: String
let tonTitle: String
var displayCurrencySelector = false
switch component.mode {
case let .suggestedPost(mode, _, _, _):
switch mode {
case let .sender(_, isFromAdmin):
if isFromAdmin {
@ -320,74 +348,74 @@ private final class SheetContent: CombinedComponent {
displayCurrencySelector = true
}
}
starsTitle = environment.strings.Chat_PostSuggestion_Suggest_OfferStars
tonTitle = environment.strings.Chat_PostSuggestion_Suggest_OfferTon
case .admin:
displayCurrencySelector = true
starsTitle = environment.strings.Chat_PostSuggestion_Suggest_RequestStars
tonTitle = environment.strings.Chat_PostSuggestion_Suggest_RequestTon
}
if displayCurrencySelector {
let selectedId: AnyHashable = state.currency == .stars ? AnyHashable(0 as Int) : AnyHashable(1 as Int)
let starsTitle: String
let tonTitle: String
switch mode {
case .sender:
starsTitle = environment.strings.Chat_PostSuggestion_Suggest_OfferStars
tonTitle = environment.strings.Chat_PostSuggestion_Suggest_OfferTon
case .admin:
starsTitle = environment.strings.Chat_PostSuggestion_Suggest_RequestStars
tonTitle = environment.strings.Chat_PostSuggestion_Suggest_RequestTon
}
let currencyToggle = currencyToggle.update(
component: TabSelectorComponent(
colors: TabSelectorComponent.Colors(
foreground: theme.list.itemSecondaryTextColor,
selection: theme.list.itemSecondaryTextColor.withMultipliedAlpha(0.15),
simple: true
),
theme: theme,
customLayout: TabSelectorComponent.CustomLayout(
font: Font.medium(14.0),
spacing: 10.0
),
items: [
TabSelectorComponent.Item(
id: AnyHashable(0),
content: .component(AnyComponent(CurrencyTabItemComponent(icon: .stars, title: starsTitle, theme: theme)))
),
TabSelectorComponent.Item(
id: AnyHashable(1),
content: .component(AnyComponent(CurrencyTabItemComponent(icon: .ton, title: tonTitle, theme: theme)))
)
],
selectedId: selectedId,
setSelectedId: { [weak state] id in
guard let state else {
return
}
let currency: CurrencyAmount.Currency
if id == AnyHashable(0) {
currency = .stars
} else {
currency = .ton
}
if state.currency != currency {
state.currency = currency
state.amount = nil
}
state.updated(transition: .spring(duration: 0.4))
}
case .starGiftOffer:
displayCurrencySelector = true
starsTitle = "Offer Stars"
tonTitle = "Offer TON"
default:
starsTitle = ""
tonTitle = ""
}
if displayCurrencySelector {
let currencyToggle = currencyToggle.update(
component: TabSelectorComponent(
colors: TabSelectorComponent.Colors(
foreground: theme.list.itemSecondaryTextColor,
selection: theme.list.itemSecondaryTextColor.withMultipliedAlpha(0.15),
simple: true
),
availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0, height: 100.0),
transition: context.transition
)
contentSize.height -= 17.0
let currencyToggleFrame = CGRect(origin: CGPoint(x: floor((context.availableSize.width - currencyToggle.size.width) * 0.5), y: contentSize.height), size: currencyToggle.size)
context.add(currencyToggle
.position(currencyToggle.size.centered(in: currencyToggleFrame).center))
contentSize.height += currencyToggle.size.height + 29.0
}
theme: theme,
style: .glass,
customLayout: TabSelectorComponent.CustomLayout(
font: Font.medium(14.0),
spacing: 10.0
),
items: [
TabSelectorComponent.Item(
id: AnyHashable(0),
content: .component(AnyComponent(CurrencyTabItemComponent(icon: .stars, title: starsTitle, theme: theme)))
),
TabSelectorComponent.Item(
id: AnyHashable(1),
content: .component(AnyComponent(CurrencyTabItemComponent(icon: .ton, title: tonTitle, theme: theme)))
)
],
selectedId: selectedId,
setSelectedId: { [weak state] id in
guard let state else {
return
}
let currency: CurrencyAmount.Currency
if id == AnyHashable(0) {
currency = .stars
} else {
currency = .ton
}
if state.currency != currency {
state.currency = currency
state.amount = nil
}
state.updated(transition: .spring(duration: 0.4))
}
),
availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0, height: 100.0),
transition: context.transition
)
contentSize.height -= 17.0
let currencyToggleFrame = CGRect(origin: CGPoint(x: floor((context.availableSize.width - currencyToggle.size.width) * 0.5), y: contentSize.height), size: currencyToggle.size)
context.add(currencyToggle
.position(currencyToggle.size.centered(in: currencyToggleFrame).center))
contentSize.height += currencyToggle.size.height + 29.0
}
let amountFont = Font.regular(13.0)
@ -446,7 +474,7 @@ private final class SheetContent: CombinedComponent {
if let usdWithdrawRate = withdrawConfiguration.usdWithdrawRate {
let usdRate = Double(usdWithdrawRate) / 1000.0 / 100.0
amountRightLabel = "\(formatTonUsdValue(Int64(starsValue), divide: false, rate: usdRate, dateTimeFormat: environment.dateTimeFormat))"
amountRightLabel = "~\(formatTonUsdValue(Int64(starsValue), divide: false, rate: usdRate, dateTimeFormat: environment.dateTimeFormat))"
}
} else {
amountInfoString = NSAttributedString(attributedString: parseMarkdownIntoAttributedString(environment.strings.Stars_SellGift_AmountInfo("\(resaleConfiguration.starGiftCommissionStarsPermille / 10)%").string, attributes: amountMarkdownAttributes, textAlignment: .natural))
@ -458,7 +486,7 @@ private final class SheetContent: CombinedComponent {
amountInfoString = NSAttributedString(attributedString: parseMarkdownIntoAttributedString(environment.strings.Stars_SellGift_AmountInfo(tonString).string, attributes: amountMarkdownAttributes, textAlignment: .natural))
if let tonUsdRate = withdrawConfiguration.tonUsdRate {
amountRightLabel = "\(formatTonUsdValue(tonValue, divide: true, rate: tonUsdRate, dateTimeFormat: environment.dateTimeFormat))"
amountRightLabel = "~\(formatTonUsdValue(tonValue, divide: true, rate: tonUsdRate, dateTimeFormat: environment.dateTimeFormat))"
}
} else {
amountInfoString = NSAttributedString(attributedString: parseMarkdownIntoAttributedString(environment.strings.Stars_SellGift_AmountInfo("\(resaleConfiguration.starGiftCommissionTonPermille / 10)%").string, attributes: amountMarkdownAttributes, textAlignment: .natural))
@ -519,6 +547,20 @@ private final class SheetContent: CombinedComponent {
maximumNumberOfLines: 0
))
}
case let .starGiftOffer(_, uniqueGift, _):
let giftTitle = "\(uniqueGift.title) #\(formatCollectibleNumber(uniqueGift.number, dateTimeFormat: environment.dateTimeFormat))"
let string: String
switch state.currency {
case .stars:
string = "Enter the number of Stars you'd like to offer for **\(giftTitle)**."
case .ton:
string = "Enter the number of TON you'd like to offer for **\(giftTitle)**."
}
let amountInfoString = NSAttributedString(attributedString: parseMarkdownIntoAttributedString(string, attributes: amountMarkdownAttributes, textAlignment: .natural))
amountFooter = AnyComponent(MultilineTextComponent(
text: .plain(amountInfoString),
maximumNumberOfLines: 0
))
default:
amountFooter = nil
}
@ -595,12 +637,14 @@ private final class SheetContent: CombinedComponent {
let onlyTonSection = onlyTonSection.update(
component: ListSectionComponent(
theme: theme,
style: .glass,
header: nil,
footer: onlyTonFooter,
items: [AnyComponentWithIdentity(
id: "switch",
component: AnyComponent(ListActionItemComponent(
theme: theme,
style: .glass,
title: AnyComponent(VStack([
AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
@ -686,12 +730,14 @@ private final class SheetContent: CombinedComponent {
let timestampSection = timestampSection.update(
component: ListSectionComponent(
theme: theme,
style: .glass,
header: nil,
footer: timestampFooter,
items: [AnyComponentWithIdentity(
id: "timestamp",
component: AnyComponent(ListActionItemComponent(
theme: theme,
style: .glass,
title: AnyComponent(VStack([
AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
@ -743,6 +789,71 @@ private final class SheetContent: CombinedComponent {
.cornerRadius(10.0)
)
contentSize.height += timestampSection.size.height
} else if case let .starGiftOffer(peer, _, _) = component.mode {
contentSize.height += 24.0
let peerName = peer.compactDisplayTitle
let footerString: String
switch state.currency {
case .stars:
footerString = "Choose how long **\(peerName)** can accept your offer. When the time expires, your Stars will be automatically refunded."
case .ton:
footerString = "Choose how long **\(peerName)** can accept your offer. When the time expires, your TON will be automatically refunded."
}
let periodFooterString = NSAttributedString(attributedString: parseMarkdownIntoAttributedString(footerString, attributes: amountMarkdownAttributes, textAlignment: .natural))
let periodFooter = AnyComponent(MultilineTextComponent(
text: .plain(periodFooterString),
maximumNumberOfLines: 0
))
let periodSection = periodSection.update(
component: ListSectionComponent(
theme: theme,
style: .glass,
header: nil,
footer: periodFooter,
items: [AnyComponentWithIdentity(
id: "timestamp",
component: AnyComponent(ListActionItemComponent(
theme: theme,
style: .glass,
title: AnyComponent(VStack([
AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: "Offer Duration",
font: Font.regular(presentationData.listsFontSize.baseDisplaySize),
textColor: environment.theme.list.itemPrimaryTextColor
)),
maximumNumberOfLines: 1
))),
], alignment: .left, spacing: 2.0)),
icon: ListActionItemComponent.Icon(component: AnyComponentWithIdentity(id: 0, component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: "48 Hours",
font: Font.regular(presentationData.listsFontSize.baseDisplaySize),
textColor: environment.theme.list.itemSecondaryTextColor
)),
maximumNumberOfLines: 1
)))),
accessory: .expandArrows,
action: { _ in
}
))
)]
),
environment: {},
availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0, height: .greatestFiniteMagnitude),
transition: context.transition
)
context.add(periodSection
.position(CGPoint(x: context.availableSize.width / 2.0, y: contentSize.height + periodSection.size.height / 2.0))
.clipsToBounds(true)
.cornerRadius(10.0)
)
contentSize.height += periodSection.size.height
}
contentSize.height += 32.0
@ -789,6 +900,22 @@ private final class SheetContent: CombinedComponent {
case .admin:
buttonString = environment.strings.Chat_PostSuggestion_Suggest_UpdateButton
}
} else if case .starGiftOffer = component.mode {
if let amount = state.amount {
let currencySymbol: String
let currencyAmount: String
switch state.currency {
case .stars:
currencySymbol = "#"
currencyAmount = presentationStringsFormattedNumber(amount, environment.dateTimeFormat.groupingSeparator)
case .ton:
currencySymbol = "$"
currencyAmount = formatTonAmountText(amount.value, dateTimeFormat: environment.dateTimeFormat, maxDecimalPositions: nil)
}
buttonString = "Offer \(currencySymbol) \(currencyAmount)"
} else {
buttonString = "Offer"
}
} else if let amount = state.amount {
buttonString = "\(environment.strings.Stars_Withdraw_Withdraw) # \(presentationStringsFormattedNumber(amount, environment.dateTimeFormat.groupingSeparator))"
} else {
@ -913,8 +1040,9 @@ private final class SheetContent: CombinedComponent {
}
}
}
completion(CurrencyAmount(amount: amount, currency: state.currency), state.timestamp)
case let .starGiftOffer(_, _, completion):
completion(CurrencyAmount(amount: amount, currency: state.currency), state.duration)
}
controller.dismissAnimated()
@ -952,6 +1080,7 @@ private final class SheetContent: CombinedComponent {
fileprivate var amount: StarsAmount?
fileprivate var currency: CurrencyAmount.Currency = .stars
fileprivate var timestamp: Int32?
fileprivate var duration: Int32 = 120
fileprivate var starsBalance: StarsAmount?
private var starsStateDisposable: Disposable?
@ -986,6 +1115,8 @@ private final class SheetContent: CombinedComponent {
currency = initialValue.currency
amount = initialValue.amount
self.timestamp = initialTimestamp
case .starGiftOffer:
amount = nil
}
self.currency = currency
@ -1178,6 +1309,7 @@ public final class StarsWithdrawScreen: ViewControllerComponentContainer {
case starGiftResell(StarGift.UniqueGift, Bool, completion: (CurrencyAmount) -> Void)
case paidMessages(current: Int64, minValue: Int64, fractionAfterCommission: Int, kind: StarsWithdrawalScreenSubject.PaidMessageKind, completion: (Int64) -> Void)
case suggestedPost(mode: SuggestedPostMode, price: CurrencyAmount, timestamp: Int32?, completion: (CurrencyAmount, Int32?) -> Void)
case starGiftOffer(peer: EnginePeer, gift: StarGift.UniqueGift, completion: (CurrencyAmount, Int32) -> Void)
}
private let context: AccountContext

View file

@ -10,6 +10,11 @@ import AccountContext
import TelegramPresentationData
public final class TabSelectorComponent: Component {
public enum Style {
case glass
case legacy
}
public final class TransitionHint {
public let scrollToEnd: Bool
@ -124,6 +129,7 @@ public final class TabSelectorComponent: Component {
public let context: AccountContext?
public let colors: Colors
public let theme: PresentationTheme
public let style: Style
public let customLayout: CustomLayout?
public let items: [Item]
public let selectedId: AnyHashable?
@ -135,6 +141,7 @@ public final class TabSelectorComponent: Component {
context: AccountContext? = nil,
colors: Colors,
theme: PresentationTheme,
style: Style = .legacy,
customLayout: CustomLayout? = nil,
items: [Item],
selectedId: AnyHashable?,
@ -145,6 +152,7 @@ public final class TabSelectorComponent: Component {
self.context = context
self.colors = colors
self.theme = theme
self.style = style
self.customLayout = customLayout
self.items = items
self.selectedId = selectedId
@ -163,6 +171,9 @@ public final class TabSelectorComponent: Component {
if lhs.theme !== rhs.theme {
return false
}
if lhs.style != rhs.style {
return false
}
if lhs.customLayout != rhs.customLayout {
return false
}
@ -519,7 +530,14 @@ public final class TabSelectorComponent: Component {
self.reorderRecognizer?.isEnabled = component.reorderItem != nil
let baseHeight: CGFloat = 28.0
let baseHeight: CGFloat
switch component.style {
case .glass:
baseHeight = 32.0
case .legacy:
baseHeight = 28.0
}
var verticalInset: CGFloat = 0.0
if let customLayout = component.customLayout {

View file

@ -1131,7 +1131,7 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
let sendGiftTitle: String
var isIncoming = message.effectivelyIncoming(context.account.peerId)
for media in message.media {
if let action = media as? TelegramMediaAction, case let .starGiftUnique(_, isUpgrade, _, _, _, _, _, _, _, _, _, _, _, _, _, _) = action.action {
if let action = media as? TelegramMediaAction, case let .starGiftUnique(_, isUpgrade, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) = action.action {
if isUpgrade && message.author?.id == context.account.peerId {
isIncoming = true
}

View file

@ -3805,6 +3805,8 @@ public final class SharedAccountContextImpl: SharedAccountContext {
mode = .suggestedPost(mode: .sender(channel: channel, isFromAdmin: isFromAdmin), price: current, timestamp: timestamp, completion: completion)
case let .postSuggestionModification(current, timestamp, completion):
mode = .suggestedPost(mode: .admin, price: current, timestamp: timestamp, completion: completion)
case let .starGiftOffer(peer, gift, completion):
mode = .starGiftOffer(peer: peer, gift: gift, completion: completion)
}
return StarsWithdrawScreen(context: context, mode: mode)
}