diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 66be514ea9..48836fd6d4 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -15008,3 +15008,6 @@ Sorry for the inconvenience."; "ProfileLevelInfo.RatingTitle" = "Rating"; "ProfileLevelInfo.FutureRatingTitle" = "Future Rating"; +"Gift.Options.Gift.Filter.Collectibles" = "Collectibles"; + +"Gift.Options.Collectibles.Text" = "Collectible gifts are unique digital items you can exchange or sell."; diff --git a/submodules/TelegramApi/Sources/Api0.swift b/submodules/TelegramApi/Sources/Api0.swift index ad00f2f471..07641c811d 100644 --- a/submodules/TelegramApi/Sources/Api0.swift +++ b/submodules/TelegramApi/Sources/Api0.swift @@ -389,6 +389,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[-191267262] = { return Api.InputInvoice.parse_inputInvoiceBusinessBotTransferStars($0) } dict[887591921] = { return Api.InputInvoice.parse_inputInvoiceChatInviteSubscription($0) } dict[-977967015] = { return Api.InputInvoice.parse_inputInvoiceMessage($0) } + dict[1048049172] = { return Api.InputInvoice.parse_inputInvoicePremiumAuthCode($0) } dict[-1734841331] = { return Api.InputInvoice.parse_inputInvoicePremiumGiftCode($0) } dict[-625298705] = { return Api.InputInvoice.parse_inputInvoicePremiumGiftStars($0) } dict[-1020867857] = { return Api.InputInvoice.parse_inputInvoiceSlug($0) } @@ -969,6 +970,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[1219145276] = { return Api.StarGiftAttributeId.parse_starGiftAttributeIdModel($0) } dict[1242965043] = { return Api.StarGiftAttributeId.parse_starGiftAttributeIdPattern($0) } dict[-1653926992] = { return Api.StarGiftCollection.parse_starGiftCollection($0) } + dict[-1712704739] = { return Api.StarGiftUpgradePrice.parse_starGiftUpgradePrice($0) } dict[-586389774] = { return Api.StarRefProgram.parse_starRefProgram($0) } dict[-1145654109] = { return Api.StarsAmount.parse_starsAmount($0) } dict[1957618656] = { return Api.StarsAmount.parse_starsTonAmount($0) } @@ -1230,7 +1232,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[1674235686] = { return Api.account.AutoDownloadSettings.parse_autoDownloadSettings($0) } dict[1279133341] = { return Api.account.AutoSaveSettings.parse_autoSaveSettings($0) } dict[-331111727] = { return Api.account.BusinessChatLinks.parse_businessChatLinks($0) } - dict[373835863] = { return Api.account.ChatThemes.parse_chatThemes($0) } + dict[-1106673293] = { return Api.account.ChatThemes.parse_chatThemes($0) } dict[-535699004] = { return Api.account.ChatThemes.parse_chatThemesNotModified($0) } dict[400029819] = { return Api.account.ConnectedBots.parse_connectedBots($0) } dict[1474462241] = { return Api.account.ContentSettings.parse_contentSettings($0) } @@ -1275,7 +1277,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[957176926] = { return Api.auth.LoginToken.parse_loginTokenSuccess($0) } dict[326715557] = { return Api.auth.PasswordRecovery.parse_passwordRecovery($0) } dict[1577067778] = { return Api.auth.SentCode.parse_sentCode($0) } - dict[-677184263] = { return Api.auth.SentCode.parse_sentCodePaymentRequired($0) } + dict[-527082948] = { return Api.auth.SentCode.parse_sentCodePaymentRequired($0) } dict[596704836] = { return Api.auth.SentCode.parse_sentCodeSuccess($0) } dict[1035688326] = { return Api.auth.SentCodeType.parse_sentCodeTypeApp($0) } dict[1398007207] = { return Api.auth.SentCodeType.parse_sentCodeTypeCall($0) } @@ -1457,7 +1459,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[-1779201615] = { return Api.payments.SavedStarGifts.parse_savedStarGifts($0) } dict[-1977011469] = { return Api.payments.StarGiftCollections.parse_starGiftCollections($0) } dict[-1598402793] = { return Api.payments.StarGiftCollections.parse_starGiftCollectionsNotModified($0) } - dict[377215243] = { return Api.payments.StarGiftUpgradePreview.parse_starGiftUpgradePreview($0) } + dict[1038213101] = { return Api.payments.StarGiftUpgradePreview.parse_starGiftUpgradePreview($0) } dict[-2069218660] = { return Api.payments.StarGiftWithdrawalUrl.parse_starGiftWithdrawalUrl($0) } dict[785918357] = { return Api.payments.StarGifts.parse_starGifts($0) } dict[-1551326360] = { return Api.payments.StarGifts.parse_starGiftsNotModified($0) } @@ -2182,6 +2184,8 @@ public extension Api { _1.serialize(buffer, boxed) case let _1 as Api.StarGiftCollection: _1.serialize(buffer, boxed) + case let _1 as Api.StarGiftUpgradePrice: + _1.serialize(buffer, boxed) case let _1 as Api.StarRefProgram: _1.serialize(buffer, boxed) case let _1 as Api.StarsAmount: diff --git a/submodules/TelegramApi/Sources/Api10.swift b/submodules/TelegramApi/Sources/Api10.swift index 381dad6f6e..da1c5b0399 100644 --- a/submodules/TelegramApi/Sources/Api10.swift +++ b/submodules/TelegramApi/Sources/Api10.swift @@ -251,6 +251,7 @@ public extension Api { case inputInvoiceBusinessBotTransferStars(bot: Api.InputUser, stars: Int64) case inputInvoiceChatInviteSubscription(hash: String) case inputInvoiceMessage(peer: Api.InputPeer, msgId: Int32) + case inputInvoicePremiumAuthCode(purpose: Api.InputStorePaymentPurpose) case inputInvoicePremiumGiftCode(purpose: Api.InputStorePaymentPurpose, option: Api.PremiumGiftCodeOption) case inputInvoicePremiumGiftStars(flags: Int32, userId: Api.InputUser, months: Int32, message: Api.TextWithEntities?) case inputInvoiceSlug(slug: String) @@ -283,6 +284,12 @@ public extension Api { peer.serialize(buffer, true) serializeInt32(msgId, buffer: buffer, boxed: false) break + case .inputInvoicePremiumAuthCode(let purpose): + if boxed { + buffer.appendInt32(1048049172) + } + purpose.serialize(buffer, true) + break case .inputInvoicePremiumGiftCode(let purpose, let option): if boxed { buffer.appendInt32(-1734841331) @@ -360,6 +367,8 @@ public extension Api { return ("inputInvoiceChatInviteSubscription", [("hash", hash as Any)]) case .inputInvoiceMessage(let peer, let msgId): return ("inputInvoiceMessage", [("peer", peer as Any), ("msgId", msgId as Any)]) + case .inputInvoicePremiumAuthCode(let purpose): + return ("inputInvoicePremiumAuthCode", [("purpose", purpose as Any)]) case .inputInvoicePremiumGiftCode(let purpose, let option): return ("inputInvoicePremiumGiftCode", [("purpose", purpose as Any), ("option", option as Any)]) case .inputInvoicePremiumGiftStars(let flags, let userId, let months, let message): @@ -424,6 +433,19 @@ public extension Api { return nil } } + public static func parse_inputInvoicePremiumAuthCode(_ reader: BufferReader) -> InputInvoice? { + var _1: Api.InputStorePaymentPurpose? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.InputStorePaymentPurpose + } + let _c1 = _1 != nil + if _c1 { + return Api.InputInvoice.inputInvoicePremiumAuthCode(purpose: _1!) + } + else { + return nil + } + } public static func parse_inputInvoicePremiumGiftCode(_ reader: BufferReader) -> InputInvoice? { var _1: Api.InputStorePaymentPurpose? if let signature = reader.readInt32() { diff --git a/submodules/TelegramApi/Sources/Api25.swift b/submodules/TelegramApi/Sources/Api25.swift index 25f6c4b10d..71a606a363 100644 --- a/submodules/TelegramApi/Sources/Api25.swift +++ b/submodules/TelegramApi/Sources/Api25.swift @@ -834,6 +834,46 @@ public extension Api { } } +public extension Api { + enum StarGiftUpgradePrice: TypeConstructorDescription { + case starGiftUpgradePrice(date: Int32, upgradeStars: Int64) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .starGiftUpgradePrice(let date, let upgradeStars): + if boxed { + buffer.appendInt32(-1712704739) + } + serializeInt32(date, buffer: buffer, boxed: false) + serializeInt64(upgradeStars, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .starGiftUpgradePrice(let date, let upgradeStars): + return ("starGiftUpgradePrice", [("date", date as Any), ("upgradeStars", upgradeStars as Any)]) + } + } + + public static func parse_starGiftUpgradePrice(_ reader: BufferReader) -> StarGiftUpgradePrice? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int64? + _2 = reader.readInt64() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.StarGiftUpgradePrice.starGiftUpgradePrice(date: _1!, upgradeStars: _2!) + } + else { + return nil + } + } + + } +} public extension Api { enum StarRefProgram: TypeConstructorDescription { case starRefProgram(flags: Int32, botId: Int64, commissionPermille: Int32, durationMonths: Int32?, endDate: Int32?, dailyRevenuePerUser: Api.StarsAmount?) diff --git a/submodules/TelegramApi/Sources/Api29.swift b/submodules/TelegramApi/Sources/Api29.swift index b2a68ca7b1..b46d5caec3 100644 --- a/submodules/TelegramApi/Sources/Api29.swift +++ b/submodules/TelegramApi/Sources/Api29.swift @@ -570,14 +570,14 @@ public extension Api.account { } public extension Api.account { enum ChatThemes: TypeConstructorDescription { - case chatThemes(flags: Int32, hash: Int64, themes: [Api.ChatTheme], chats: [Api.Chat], users: [Api.User], nextOffset: Int32?) + case chatThemes(flags: Int32, hash: Int64, themes: [Api.ChatTheme], chats: [Api.Chat], users: [Api.User], nextOffset: String?) case chatThemesNotModified public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { case .chatThemes(let flags, let hash, let themes, let chats, let users, let nextOffset): if boxed { - buffer.appendInt32(373835863) + buffer.appendInt32(-1106673293) } serializeInt32(flags, buffer: buffer, boxed: false) serializeInt64(hash, buffer: buffer, boxed: false) @@ -596,7 +596,7 @@ public extension Api.account { for item in users { item.serialize(buffer, true) } - if Int(flags) & Int(1 << 0) != 0 {serializeInt32(nextOffset!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 0) != 0 {serializeString(nextOffset!, buffer: buffer, boxed: false)} break case .chatThemesNotModified: if boxed { @@ -633,8 +633,8 @@ public extension Api.account { if let _ = reader.readInt32() { _5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) } - var _6: Int32? - if Int(_1!) & Int(1 << 0) != 0 {_6 = reader.readInt32() } + var _6: String? + if Int(_1!) & Int(1 << 0) != 0 {_6 = parseString(reader) } let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = _3 != nil diff --git a/submodules/TelegramApi/Sources/Api30.swift b/submodules/TelegramApi/Sources/Api30.swift index cd4d6eb155..d2be22c3b9 100644 --- a/submodules/TelegramApi/Sources/Api30.swift +++ b/submodules/TelegramApi/Sources/Api30.swift @@ -701,7 +701,7 @@ public extension Api.auth { public extension Api.auth { enum SentCode: TypeConstructorDescription { case sentCode(flags: Int32, type: Api.auth.SentCodeType, phoneCodeHash: String, nextType: Api.auth.CodeType?, timeout: Int32?) - case sentCodePaymentRequired(storeProduct: String, phoneCodeHash: String, supportEmailAddress: String, supportEmailSubject: String) + case sentCodePaymentRequired(storeProduct: String, phoneCodeHash: String, supportEmailAddress: String, supportEmailSubject: String, currency: String, amount: Int64) case sentCodeSuccess(authorization: Api.auth.Authorization) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { @@ -716,14 +716,16 @@ public extension Api.auth { if Int(flags) & Int(1 << 1) != 0 {nextType!.serialize(buffer, true)} if Int(flags) & Int(1 << 2) != 0 {serializeInt32(timeout!, buffer: buffer, boxed: false)} break - case .sentCodePaymentRequired(let storeProduct, let phoneCodeHash, let supportEmailAddress, let supportEmailSubject): + case .sentCodePaymentRequired(let storeProduct, let phoneCodeHash, let supportEmailAddress, let supportEmailSubject, let currency, let amount): if boxed { - buffer.appendInt32(-677184263) + buffer.appendInt32(-527082948) } serializeString(storeProduct, buffer: buffer, boxed: false) serializeString(phoneCodeHash, buffer: buffer, boxed: false) serializeString(supportEmailAddress, buffer: buffer, boxed: false) serializeString(supportEmailSubject, buffer: buffer, boxed: false) + serializeString(currency, buffer: buffer, boxed: false) + serializeInt64(amount, buffer: buffer, boxed: false) break case .sentCodeSuccess(let authorization): if boxed { @@ -738,8 +740,8 @@ public extension Api.auth { switch self { case .sentCode(let flags, let type, let phoneCodeHash, let nextType, let timeout): return ("sentCode", [("flags", flags as Any), ("type", type as Any), ("phoneCodeHash", phoneCodeHash as Any), ("nextType", nextType as Any), ("timeout", timeout as Any)]) - case .sentCodePaymentRequired(let storeProduct, let phoneCodeHash, let supportEmailAddress, let supportEmailSubject): - return ("sentCodePaymentRequired", [("storeProduct", storeProduct as Any), ("phoneCodeHash", phoneCodeHash as Any), ("supportEmailAddress", supportEmailAddress as Any), ("supportEmailSubject", supportEmailSubject as Any)]) + case .sentCodePaymentRequired(let storeProduct, let phoneCodeHash, let supportEmailAddress, let supportEmailSubject, let currency, let amount): + return ("sentCodePaymentRequired", [("storeProduct", storeProduct as Any), ("phoneCodeHash", phoneCodeHash as Any), ("supportEmailAddress", supportEmailAddress as Any), ("supportEmailSubject", supportEmailSubject as Any), ("currency", currency as Any), ("amount", amount as Any)]) case .sentCodeSuccess(let authorization): return ("sentCodeSuccess", [("authorization", authorization as Any)]) } @@ -781,12 +783,18 @@ public extension Api.auth { _3 = parseString(reader) var _4: String? _4 = parseString(reader) + var _5: String? + _5 = parseString(reader) + var _6: Int64? + _6 = reader.readInt64() let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = _3 != nil let _c4 = _4 != nil - if _c1 && _c2 && _c3 && _c4 { - return Api.auth.SentCode.sentCodePaymentRequired(storeProduct: _1!, phoneCodeHash: _2!, supportEmailAddress: _3!, supportEmailSubject: _4!) + let _c5 = _5 != nil + let _c6 = _6 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { + return Api.auth.SentCode.sentCodePaymentRequired(storeProduct: _1!, phoneCodeHash: _2!, supportEmailAddress: _3!, supportEmailSubject: _4!, currency: _5!, amount: _6!) } else { return nil diff --git a/submodules/TelegramApi/Sources/Api36.swift b/submodules/TelegramApi/Sources/Api36.swift index e81a788632..4fa648bea2 100644 --- a/submodules/TelegramApi/Sources/Api36.swift +++ b/submodules/TelegramApi/Sources/Api36.swift @@ -332,27 +332,37 @@ public extension Api.payments { } public extension Api.payments { enum StarGiftUpgradePreview: TypeConstructorDescription { - case starGiftUpgradePreview(sampleAttributes: [Api.StarGiftAttribute]) + case starGiftUpgradePreview(sampleAttributes: [Api.StarGiftAttribute], prices: [Api.StarGiftUpgradePrice], nextPrices: [Api.StarGiftUpgradePrice]) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .starGiftUpgradePreview(let sampleAttributes): + case .starGiftUpgradePreview(let sampleAttributes, let prices, let nextPrices): if boxed { - buffer.appendInt32(377215243) + buffer.appendInt32(1038213101) } buffer.appendInt32(481674261) buffer.appendInt32(Int32(sampleAttributes.count)) for item in sampleAttributes { item.serialize(buffer, true) } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(prices.count)) + for item in prices { + item.serialize(buffer, true) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(nextPrices.count)) + for item in nextPrices { + item.serialize(buffer, true) + } break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .starGiftUpgradePreview(let sampleAttributes): - return ("starGiftUpgradePreview", [("sampleAttributes", sampleAttributes as Any)]) + case .starGiftUpgradePreview(let sampleAttributes, let prices, let nextPrices): + return ("starGiftUpgradePreview", [("sampleAttributes", sampleAttributes as Any), ("prices", prices as Any), ("nextPrices", nextPrices as Any)]) } } @@ -361,9 +371,19 @@ public extension Api.payments { if let _ = reader.readInt32() { _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StarGiftAttribute.self) } + var _2: [Api.StarGiftUpgradePrice]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StarGiftUpgradePrice.self) + } + var _3: [Api.StarGiftUpgradePrice]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StarGiftUpgradePrice.self) + } let _c1 = _1 != nil - if _c1 { - return Api.payments.StarGiftUpgradePreview.starGiftUpgradePreview(sampleAttributes: _1!) + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.payments.StarGiftUpgradePreview.starGiftUpgradePreview(sampleAttributes: _1!, prices: _2!, nextPrices: _3!) } else { return nil diff --git a/submodules/TelegramApi/Sources/Api39.swift b/submodules/TelegramApi/Sources/Api39.swift index cc06769894..ee81572381 100644 --- a/submodules/TelegramApi/Sources/Api39.swift +++ b/submodules/TelegramApi/Sources/Api39.swift @@ -839,10 +839,10 @@ public extension Api.functions.account { } } public extension Api.functions.account { - static func getUniqueGiftChatThemes(offset: Int32, limit: Int32, hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + static func getUniqueGiftChatThemes(offset: String, limit: Int32, hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { let buffer = Buffer() - buffer.appendInt32(-25890913) - serializeInt32(offset, buffer: buffer, boxed: false) + buffer.appendInt32(-466818615) + serializeString(offset, buffer: buffer, boxed: false) serializeInt32(limit, buffer: buffer, boxed: false) serializeInt64(hash, buffer: buffer, boxed: false) return (FunctionDescription(name: "account.getUniqueGiftChatThemes", parameters: [("offset", String(describing: offset)), ("limit", String(describing: limit)), ("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.account.ChatThemes? in @@ -1974,6 +1974,23 @@ public extension Api.functions.auth { }) } } +public extension Api.functions.auth { + static func checkPaidAuth(phoneNumber: String, phoneCodeHash: String, formId: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1457889180) + serializeString(phoneNumber, buffer: buffer, boxed: false) + serializeString(phoneCodeHash, buffer: buffer, boxed: false) + serializeInt64(formId, buffer: buffer, boxed: false) + return (FunctionDescription(name: "auth.checkPaidAuth", parameters: [("phoneNumber", String(describing: phoneNumber)), ("phoneCodeHash", String(describing: phoneCodeHash)), ("formId", String(describing: formId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.auth.SentCode? in + let reader = BufferReader(buffer) + var result: Api.auth.SentCode? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.auth.SentCode + } + return result + }) + } +} public extension Api.functions.auth { static func checkPassword(password: Api.InputCheckPasswordSRP) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { let buffer = Buffer() diff --git a/submodules/TelegramCore/Sources/Authorization.swift b/submodules/TelegramCore/Sources/Authorization.swift index a146932d6f..1d6523c759 100644 --- a/submodules/TelegramCore/Sources/Authorization.swift +++ b/submodules/TelegramCore/Sources/Authorization.swift @@ -518,7 +518,7 @@ private func internalResendAuthorizationCode(accountManager: AccountManager UInt { - return 214 + return 215 } public func parseMessage(_ data: Data!) -> Any! { diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Payments/StarGifts.swift b/submodules/TelegramCore/Sources/TelegramEngine/Payments/StarGifts.swift index 9464fa8bf1..d69355f39d 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Payments/StarGifts.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Payments/StarGifts.swift @@ -1266,7 +1266,17 @@ func _internal_upgradeStarGift(account: Account, formId: Int64?, reference: Star } } -func _internal_starGiftUpgradePreview(account: Account, giftId: Int64) -> Signal<[StarGift.UniqueGift.Attribute], NoError> { +public struct StarGiftUpgradePreview: Equatable { + public struct Price: Equatable { + let stars: Int64 + let date: Int32 + } + public let attributes: [StarGift.UniqueGift.Attribute] + public let prices: [Price] + public let nextPrices: [Price] +} + +func _internal_starGiftUpgradePreview(account: Account, giftId: Int64) -> Signal { return account.network.request(Api.functions.payments.getStarGiftUpgradePreview(giftId: giftId)) |> map(Optional.init) |> `catch` { _ -> Signal in @@ -1274,11 +1284,26 @@ func _internal_starGiftUpgradePreview(account: Account, giftId: Int64) -> Signal } |> map { result in guard let result else { - return [] + return nil } switch result { - case let .starGiftUpgradePreview(sampleAttributes): - return sampleAttributes.compactMap { StarGift.UniqueGift.Attribute(apiAttribute: $0) } + case let .starGiftUpgradePreview(apiSampleAttributes, apiPrices, apiNextPrices): + let attributes = apiSampleAttributes.compactMap { StarGift.UniqueGift.Attribute(apiAttribute: $0) } + var prices: [StarGiftUpgradePreview.Price] = [] + var nextPrices: [StarGiftUpgradePreview.Price] = [] + for price in apiPrices { + switch price { + case let .starGiftUpgradePrice(date, upgradeStars): + prices.append(StarGiftUpgradePreview.Price(stars: upgradeStars, date: date)) + } + } + for price in apiNextPrices { + switch price { + case let .starGiftUpgradePrice(date, upgradeStars): + nextPrices.append(StarGiftUpgradePreview.Price(stars: upgradeStars, date: date)) + } + } + return StarGiftUpgradePreview(attributes: attributes, prices: prices, nextPrices: nextPrices) } } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Payments/TelegramEnginePayments.swift b/submodules/TelegramCore/Sources/TelegramEngine/Payments/TelegramEnginePayments.swift index bfbd3d48b2..d1e4183ffb 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Payments/TelegramEnginePayments.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Payments/TelegramEnginePayments.swift @@ -137,7 +137,7 @@ public extension TelegramEngine { return _internal_upgradeStarGift(account: self.account, formId: formId, reference: reference, keepOriginalInfo: keepOriginalInfo) } - public func starGiftUpgradePreview(giftId: Int64) -> Signal<[StarGift.UniqueGift.Attribute], NoError> { + public func starGiftUpgradePreview(giftId: Int64) -> Signal { return _internal_starGiftUpgradePreview(account: self.account, giftId: giftId) } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Themes/ChatThemes.swift b/submodules/TelegramCore/Sources/TelegramEngine/Themes/ChatThemes.swift index d946ce72ca..cd920db4a2 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Themes/ChatThemes.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Themes/ChatThemes.swift @@ -497,7 +497,7 @@ public final class UniqueGiftChatThemesContext { private let cacheDisposable = MetaDisposable() private var themes: [ChatTheme] = [] - private var nextOffset: Int32 = 0 + private var nextOffset: String? private var dataState: UniqueGiftChatThemesContext.State.DataState = .ready(canLoadMore: true) private let stateValue = Promise() @@ -518,7 +518,7 @@ public final class UniqueGiftChatThemesContext { public func reload() { self.themes = [] - self.nextOffset = 0 + self.nextOffset = nil self.dataState = .ready(canLoadMore: true) self.loadMore(reload: true) } @@ -552,16 +552,16 @@ public final class UniqueGiftChatThemesContext { self.pushState() } - let signal = network.request(Api.functions.account.getUniqueGiftChatThemes(offset: offset, limit: 50, hash: 0)) + let signal = network.request(Api.functions.account.getUniqueGiftChatThemes(offset: offset ?? "", limit: 50, hash: 0)) |> map(Optional.init) |> `catch` { error in return .single(nil) } - |> mapToSignal { result -> Signal<([ChatTheme], Int32?), NoError> in + |> mapToSignal { result -> Signal<([ChatTheme], String?), NoError> in guard let result else { return .single(([], nil)) } - return postbox.transaction { transaction -> ([ChatTheme], Int32?) in + return postbox.transaction { transaction -> ([ChatTheme], String?) in switch result { case let .chatThemes(_, _, themes, chats, users, nextOffset): let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users) @@ -578,7 +578,7 @@ public final class UniqueGiftChatThemesContext { guard let self else { return } - if offset == 0 || reload { + if offset == nil || reload { self.themes = themes self.cacheDisposable.set(self.account.postbox.transaction { transaction in if let entry = CodableEntry(CachedUniqueGiftChatThemes(themes: themes)) { diff --git a/submodules/TelegramUI/Components/Gifts/GiftOptionsScreen/Sources/GiftOptionsScreen.swift b/submodules/TelegramUI/Components/Gifts/GiftOptionsScreen/Sources/GiftOptionsScreen.swift index d38abd89a4..637ae69fd4 100644 --- a/submodules/TelegramUI/Components/Gifts/GiftOptionsScreen/Sources/GiftOptionsScreen.swift +++ b/submodules/TelegramUI/Components/Gifts/GiftOptionsScreen/Sources/GiftOptionsScreen.swift @@ -141,6 +141,8 @@ final class GiftOptionsScreenComponent: Component { private var starsItems: [AnyHashable: ComponentView] = [:] private let tabSelector = ComponentView() private var starsFilter: StarsFilter = .all + private var appliedStarsFilter: StarsFilter = .all + private var switchingFilter = false private var loadingGiftId: Int64? @@ -869,6 +871,9 @@ final class GiftOptionsScreenComponent: Component { self.environment = environment self.state = state + let previousStarsFilter = self.appliedStarsFilter + self.appliedStarsFilter = self.starsFilter + if self.component == nil { self.starsStateDisposable = (component.starsContext.state |> deliverOnMainQueue).start(next: { [weak self] state in @@ -1109,7 +1114,8 @@ final class GiftOptionsScreenComponent: Component { }) let peerName = state.peer?.compactDisplayTitle ?? "" - let premiumDescriptionRawString: String + var premiumDescriptionRawString: String + var isPremiumDescription = false if isSelfGift { premiumDescriptionRawString = strings.Gift_Options_GiftSelf_Text } else if isChannelGift { @@ -1118,7 +1124,12 @@ final class GiftOptionsScreenComponent: Component { premiumDescriptionRawString = strings.Gift_Options_Gift_Text(peerName).string } else { premiumDescriptionRawString = strings.Gift_Options_Premium_Text(peerName).string + isPremiumDescription = true } + if !isPremiumDescription && self.starsFilter == .resale { + premiumDescriptionRawString = strings.Gift_Options_Collectibles_Text + } + let premiumDescriptionString = parseMarkdownIntoAttributedString(premiumDescriptionRawString, attributes: markdownAttributes).mutableCopy() as! NSMutableAttributedString if let range = premiumDescriptionString.string.range(of: ">"), let chevronImage = self.chevronImage?.0 { premiumDescriptionString.addAttribute(.attachment, value: chevronImage, range: NSRange(range, in: premiumDescriptionString.string)) @@ -1332,12 +1343,30 @@ final class GiftOptionsScreenComponent: Component { transition.setBounds(view: starsTitleView, bounds: CGRect(origin: .zero, size: starsTitleSize)) } - let starsDescriptionString = parseMarkdownIntoAttributedString(strings.Gift_Options_Gift_Text(peerName).string, attributes: markdownAttributes).mutableCopy() as! NSMutableAttributedString + var starsDescriptionRawString = strings.Gift_Options_Gift_Text(peerName).string + if self.starsFilter == .resale { + starsDescriptionRawString = strings.Gift_Options_Collectibles_Text + } + let starsDescriptionString = parseMarkdownIntoAttributedString(starsDescriptionRawString, attributes: markdownAttributes).mutableCopy() as! NSMutableAttributedString if let range = starsDescriptionString.string.range(of: ">"), let chevronImage = self.chevronImage?.0 { starsDescriptionString.addAttribute(.attachment, value: chevronImage, range: NSRange(range, in: starsDescriptionString.string)) } + + var descriptionTransition = transition + if previousStarsFilter != self.appliedStarsFilter, let starsDescriptionView = self.starsDescription.view { + descriptionTransition = .immediate + if let snapshotView = starsDescriptionView.snapshotView(afterScreenUpdates: false) { + snapshotView.frame = starsDescriptionView.frame + self.scrollView.addSubview(snapshotView) + snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.25, removeOnCompletion: false, completion: { _ in + snapshotView.removeFromSuperview() + }) + starsDescriptionView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25) + } + } + let starsDescriptionSize = self.starsDescription.update( - transition: transition, + transition: descriptionTransition, component: AnyComponent(BalancedTextComponent( text: .plain(starsDescriptionString), horizontalAlignment: .center, @@ -1376,7 +1405,7 @@ final class GiftOptionsScreenComponent: Component { if starsDescriptionView.superview == nil { self.scrollView.addSubview(starsDescriptionView) } - transition.setFrame(view: starsDescriptionView, frame: starsDescriptionFrame) + descriptionTransition.setFrame(view: starsDescriptionView, frame: starsDescriptionFrame) } contentHeight += starsDescriptionSize.height contentHeight += 16.0 @@ -1397,7 +1426,6 @@ final class GiftOptionsScreenComponent: Component { )) } - var hasLimited = false var hasResale = false var starsAmountsSet = Set() if let starGifts = self.state?.starGifts { @@ -1405,7 +1433,6 @@ final class GiftOptionsScreenComponent: Component { if case let .generic(gift) = gift { starsAmountsSet.insert(gift.price) if let availability = gift.availability { - hasLimited = true if availability.remains == 0 && availability.resale > 0 { hasResale = true } @@ -1414,30 +1441,10 @@ final class GiftOptionsScreenComponent: Component { } } - if hasLimited { - tabSelectorItems.append(TabSelectorComponent.Item( - id: AnyHashable(StarsFilter.limited.rawValue), - title: strings.Gift_Options_Gift_Filter_Limited - )) - } - - tabSelectorItems.append(TabSelectorComponent.Item( - id: AnyHashable(StarsFilter.inStock.rawValue), - title: strings.Gift_Options_Gift_Filter_InStock - )) - if hasResale { tabSelectorItems.append(TabSelectorComponent.Item( id: AnyHashable(StarsFilter.resale.rawValue), - title: strings.Gift_Options_Gift_Filter_Resale - )) - } - - let starsAmounts = Array(starsAmountsSet).sorted() - for amount in starsAmounts { - tabSelectorItems.append(TabSelectorComponent.Item( - id: AnyHashable(StarsFilter.stars(amount).rawValue), - title: "⭐️\(amount)" + title: strings.Gift_Options_Gift_Filter_Collectibles )) } diff --git a/submodules/TelegramUI/Components/Gifts/GiftSetupScreen/Sources/GiftSetupScreen.swift b/submodules/TelegramUI/Components/Gifts/GiftSetupScreen/Sources/GiftSetupScreen.swift index 3dedd98b87..8002c57a46 100644 --- a/submodules/TelegramUI/Components/Gifts/GiftSetupScreen/Sources/GiftSetupScreen.swift +++ b/submodules/TelegramUI/Components/Gifts/GiftSetupScreen/Sources/GiftSetupScreen.swift @@ -142,7 +142,7 @@ final class GiftSetupScreenComponent: Component { } } private let optionsPromise = ValuePromise<[StarsTopUpOption]?>(nil) - private let previewPromise = Promise<[StarGift.UniqueGift.Attribute]?>(nil) + private let previewPromise = Promise(nil) private var cachedChevronImage: (UIImage, PresentationTheme)? @@ -736,9 +736,10 @@ final class GiftSetupScreenComponent: Component { if let _ = gift.upgradeStars { self.previewPromise.set( component.context.engine.payments.starGiftUpgradePreview(giftId: gift.id) - |> map(Optional.init) ) } + + self.updateDisposable = component.context.engine.payments.keepStarGiftsUpdated().start() } } @@ -1227,13 +1228,13 @@ final class GiftSetupScreenComponent: Component { } let _ = (self.previewPromise.get() |> take(1) - |> deliverOnMainQueue).start(next: { [weak self] attributes in - guard let self, let component = self.component, let controller = self.environment?.controller(), let attributes else { + |> deliverOnMainQueue).start(next: { [weak self] upgradePreview in + guard let self, let component = self.component, let controller = self.environment?.controller(), let upgradePreview else { return } let previewController = GiftViewScreen( context: component.context, - subject: .upgradePreview(attributes, peerName) + subject: .upgradePreview(upgradePreview.attributes, peerName) ) controller.push(previewController) }) diff --git a/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftTransferAlertController.swift b/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftTransferAlertController.swift index 63e4708941..73e10e24e2 100644 --- a/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftTransferAlertController.swift +++ b/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftTransferAlertController.swift @@ -14,6 +14,9 @@ import Markdown import GiftItemComponent import ChatMessagePaymentAlertController import ActivityIndicator +import TooltipUI +import MultilineTextComponent +import TelegramStringFormatting private final class GiftTransferAlertContentNode: AlertContentNode { private let context: AccountContext @@ -28,6 +31,13 @@ private final class GiftTransferAlertContentNode: AlertContentNode { private let textNode: ASTextNode private let arrowNode: ASImageNode private let avatarNode: AvatarNode + private let tableView = ComponentView() + + private let modelButtonTag = GenericComponentViewTag() + private let backdropButtonTag = GenericComponentViewTag() + private let symbolButtonTag = GenericComponentViewTag() + + fileprivate var getController: () -> ViewController? = { return nil} private let actionNodesSeparator: ASDisplayNode private let actionNodes: [TextAlertContentActionNode] @@ -143,9 +153,45 @@ private final class GiftTransferAlertContentNode: AlertContentNode { } } + fileprivate func dismissAllTooltips() { + guard let controller = self.getController() else { + return + } + controller.window?.forEachController({ controller in + if let controller = controller as? TooltipScreen { + controller.dismiss(inPlace: false) + } + }) + controller.forEachController({ controller in + if let controller = controller as? TooltipScreen { + controller.dismiss(inPlace: false) + } + return true + }) + } + + func showAttributeInfo(tag: Any, text: String) { + guard let controller = self.getController() else { + return + } + self.dismissAllTooltips() + + guard let sourceView = self.tableView.findTaggedView(tag: tag), let absoluteLocation = sourceView.superview?.convert(sourceView.center, to: controller.view) else { + return + } + + let location = CGRect(origin: CGPoint(x: absoluteLocation.x, y: absoluteLocation.y - 12.0), size: CGSize()) + let tooltipController = TooltipScreen(account: self.context.account, sharedContext: self.context.sharedContext, text: .plain(text: text), style: .wide, location: .point(location, .bottom), displayDuration: .default, inset: 16.0, shouldDismissOnTouch: { _, _ in + return .dismiss(consume: false) + }) + controller.present(tooltipController, in: .current) + } + override func updateLayout(size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize { var size = size - size.width = min(size.width, 270.0) + size.width = min(size.width, 310.0) + + let strings = self.strings self.validLayout = size @@ -162,7 +208,7 @@ private final class GiftTransferAlertContentNode: AlertContentNode { GiftItemComponent( context: self.context, theme: self.presentationTheme, - strings: self.strings, + strings: strings, peer: nil, subject: .uniqueGift(gift: self.gift, price: nil), mode: .thumbnail @@ -212,20 +258,126 @@ private final class GiftTransferAlertContentNode: AlertContentNode { let actionsHeight = actionButtonHeight * CGFloat(self.actionNodes.count) - let resultSize = CGSize(width: contentWidth, height: avatarSize.height + titleSize.height + textSize.height + actionsHeight + 24.0 + insets.top + insets.bottom) + let tableFont = Font.regular(15.0) + let tableTextColor = self.presentationTheme.list.itemPrimaryTextColor + + var tableItems: [TableComponent.Item] = [] + let order: [StarGift.UniqueGift.Attribute.AttributeType] = [ + .model, .pattern, .backdrop, .originalInfo + ] + + var attributeMap: [StarGift.UniqueGift.Attribute.AttributeType: StarGift.UniqueGift.Attribute] = [:] + for attribute in self.gift.attributes { + attributeMap[attribute.attributeType] = attribute + } + + for type in order { + if let attribute = attributeMap[type] { + let id: String? + let title: String? + let value: NSAttributedString + let percentage: Float? + let tag: AnyObject? + + switch attribute { + case let .model(name, _, rarity): + id = "model" + title = strings.Gift_Unique_Model + value = NSAttributedString(string: name, font: tableFont, textColor: tableTextColor) + percentage = Float(rarity) * 0.1 + tag = self.modelButtonTag + case let .backdrop(name, _, _, _, _, _, rarity): + id = "backdrop" + title = strings.Gift_Unique_Backdrop + value = NSAttributedString(string: name, font: tableFont, textColor: tableTextColor) + percentage = Float(rarity) * 0.1 + tag = self.backdropButtonTag + case let .pattern(name, _, rarity): + id = "pattern" + title = strings.Gift_Unique_Symbol + value = NSAttributedString(string: name, font: tableFont, textColor: tableTextColor) + percentage = Float(rarity) * 0.1 + tag = self.symbolButtonTag + case .originalInfo: + continue + } + + var items: [AnyComponentWithIdentity] = [] + items.append( + AnyComponentWithIdentity( + id: AnyHashable(0), + component: AnyComponent( + MultilineTextComponent(text: .plain(value)) + ) + ) + ) + if let percentage, let tag { + items.append(AnyComponentWithIdentity( + id: AnyHashable(1), + component: AnyComponent(Button( + content: AnyComponent(ButtonContentComponent( + context: self.context, + text: formatPercentage(percentage), + color: self.presentationTheme.list.itemAccentColor + )), + action: { [weak self] in + self?.showAttributeInfo(tag: tag, text: strings.Gift_Unique_AttributeDescription(formatPercentage(percentage)).string) + } + ).tagged(tag)) + )) + } + let itemComponent = AnyComponent( + HStack(items, spacing: 4.0) + ) + + tableItems.append(.init( + id: id, + title: title, + hasBackground: false, + component: itemComponent + )) + } + } + + if let valueAmount = self.gift.valueAmount, let valueCurrency = self.gift.valueCurrency { + tableItems.append(.init( + id: "fiatValue", + title: strings.Gift_Unique_Value, + component: AnyComponent( + MultilineTextComponent(text: .plain(NSAttributedString(string: "≈\(formatCurrencyAmount(valueAmount, currency: valueCurrency))", font: tableFont, textColor: tableTextColor))) + ), + insets: UIEdgeInsets(top: 0.0, left: 10.0, bottom: 0.0, right: 12.0) + )) + } + + let tableSize = self.tableView.update( + transition: .immediate, + component: AnyComponent( + TableComponent( + theme: self.presentationTheme, + items: tableItems + ) + ), + environment: {}, + containerSize: CGSize(width: contentWidth - 32.0, height: size.height) + ) + let tableFrame = CGRect(origin: CGPoint(x: 16.0, y: avatarSize.height + titleSize.height + textSize.height + 60.0), size: tableSize) + if let view = self.tableView.view { + if view.superview == nil { + self.view.addSubview(view) + } + view.frame = tableFrame + } + + let resultSize = CGSize(width: contentWidth, height: avatarSize.height + titleSize.height + textSize.height + tableSize.height + actionsHeight + 40.0 + insets.top + insets.bottom) transition.updateFrame(node: self.actionNodesSeparator, frame: CGRect(origin: CGPoint(x: 0.0, y: resultSize.height - actionsHeight - UIScreenPixel), size: CGSize(width: resultSize.width, height: UIScreenPixel))) var actionOffset: CGFloat = 0.0 - //let actionWidth: CGFloat = floor(resultSize.width / CGFloat(self.actionNodes.count)) var separatorIndex = -1 var nodeIndex = 0 for actionNode in self.actionNodes { if separatorIndex >= 0 { let separatorNode = self.actionVerticalSeparators[separatorIndex] - /*switch effectiveActionLayout { - case .horizontal: - transition.updateFrame(node: separatorNode, frame: CGRect(origin: CGPoint(x: actionOffset - UIScreenPixel, y: resultSize.height - actionsHeight), size: CGSize(width: UIScreenPixel, height: actionsHeight - UIScreenPixel))) - case .vertical:*/ do { transition.updateFrame(node: separatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: resultSize.height - actionsHeight + actionOffset - UIScreenPixel), size: CGSize(width: resultSize.width, height: UIScreenPixel))) } @@ -233,27 +385,14 @@ private final class GiftTransferAlertContentNode: AlertContentNode { separatorIndex += 1 let currentActionWidth: CGFloat - /*switch effectiveActionLayout { - case .horizontal: - if nodeIndex == self.actionNodes.count - 1 { - currentActionWidth = resultSize.width - actionOffset - } else { - currentActionWidth = actionWidth - } - case .vertical:*/ do { currentActionWidth = resultSize.width } let actionNodeFrame: CGRect - /*switch effectiveActionLayout { - case .horizontal: - actionNodeFrame = CGRect(origin: CGPoint(x: actionOffset, y: resultSize.height - actionsHeight), size: CGSize(width: currentActionWidth, height: actionButtonHeight)) - actionOffset += currentActionWidth - case .vertical:*/ do { - actionNodeFrame = CGRect(origin: CGPoint(x: 0.0, y: resultSize.height - actionsHeight + actionOffset), size: CGSize(width: currentActionWidth, height: actionButtonHeight)) - actionOffset += actionButtonHeight + actionNodeFrame = CGRect(origin: CGPoint(x: 0.0, y: resultSize.height - actionsHeight + actionOffset), size: CGSize(width: currentActionWidth, height: actionButtonHeight)) + actionOffset += actionButtonHeight } transition.updateFrame(node: actionNode, frame: actionNodeFrame) @@ -316,6 +455,9 @@ public func giftTransferAlertController( contentNode = GiftTransferAlertContentNode(context: context, theme: AlertControllerTheme(presentationData: presentationData), ptheme: presentationData.theme, strings: strings, gift: gift, peer: peer, title: title, text: text, actions: actions) let controller = ChatMessagePaymentAlertController(context: context, presentationData: presentationData, contentNode: contentNode!, navigationController: navigationController, chatPeerId: context.account.peerId, showBalance: transferStars > 0) + contentNode?.getController = { [weak controller] in + return controller + } dismissImpl = { [weak controller] animated in if animated { controller?.dismissAnimated() diff --git a/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift b/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift index 4c3a90a7ea..ce40d564ce 100644 --- a/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift +++ b/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift @@ -125,8 +125,8 @@ private final class GiftViewSheetContent: CombinedComponent { var pendingWear = false var pendingTakeOff = false - var sampleGiftAttributes: [StarGift.UniqueGift.Attribute]? - let sampleDisposable = DisposableSet() + var upgradePreview: StarGiftUpgradePreview? + let upgradePreviewDisposable = DisposableSet() var keepOriginalInfo = false @@ -218,19 +218,19 @@ private final class GiftViewSheetContent: CombinedComponent { if self.testUpgradeAnimation { if gift.giftId != 0 { - self.sampleDisposable.add((context.engine.payments.starGiftUpgradePreview(giftId: gift.giftId) - |> deliverOnMainQueue).start(next: { [weak self] attributes in - guard let self else { + self.upgradePreviewDisposable.add((context.engine.payments.starGiftUpgradePreview(giftId: gift.giftId) + |> deliverOnMainQueue).start(next: { [weak self] upgradePreview in + guard let self, let upgradePreview else { return } - self.sampleGiftAttributes = attributes + self.upgradePreview = upgradePreview - for attribute in attributes { + for attribute in upgradePreview.attributes { switch attribute { case let .model(_, file, _): - self.sampleDisposable.add(freeMediaFileResourceInteractiveFetched(account: self.context.account, userLocation: .other, fileReference: .standalone(media: file), resource: file.resource).start()) + self.upgradePreviewDisposable.add(freeMediaFileResourceInteractiveFetched(account: self.context.account, userLocation: .other, fileReference: .standalone(media: file), resource: file.resource).start()) case let .pattern(_, file, _): - self.sampleDisposable.add(freeMediaFileResourceInteractiveFetched(account: self.context.account, userLocation: .other, fileReference: .standalone(media: file), resource: file.resource).start()) + self.upgradePreviewDisposable.add(freeMediaFileResourceInteractiveFetched(account: self.context.account, userLocation: .other, fileReference: .standalone(media: file), resource: file.resource).start()) default: break } @@ -245,19 +245,19 @@ private final class GiftViewSheetContent: CombinedComponent { peerIds.append(releasedBy) } if arguments.canUpgrade || arguments.upgradeStars != nil || arguments.prepaidUpgradeHash != nil { - self.sampleDisposable.add((context.engine.payments.starGiftUpgradePreview(giftId: gift.id) - |> deliverOnMainQueue).start(next: { [weak self] attributes in - guard let self else { + self.upgradePreviewDisposable.add((context.engine.payments.starGiftUpgradePreview(giftId: gift.id) + |> deliverOnMainQueue).start(next: { [weak self] upgradePreview in + guard let self, let upgradePreview else { return } - self.sampleGiftAttributes = attributes + self.upgradePreview = upgradePreview - for attribute in attributes { + for attribute in upgradePreview.attributes { switch attribute { case let .model(_, file, _): - self.sampleDisposable.add(freeMediaFileResourceInteractiveFetched(account: self.context.account, userLocation: .other, fileReference: .standalone(media: file), resource: file.resource).start()) + self.upgradePreviewDisposable.add(freeMediaFileResourceInteractiveFetched(account: self.context.account, userLocation: .other, fileReference: .standalone(media: file), resource: file.resource).start()) case let .pattern(_, file, _): - self.sampleDisposable.add(freeMediaFileResourceInteractiveFetched(account: self.context.account, userLocation: .other, fileReference: .standalone(media: file), resource: file.resource).start()) + self.upgradePreviewDisposable.add(freeMediaFileResourceInteractiveFetched(account: self.context.account, userLocation: .other, fileReference: .standalone(media: file), resource: file.resource).start()) default: break } @@ -348,7 +348,7 @@ private final class GiftViewSheetContent: CombinedComponent { deinit { self.disposable?.dispose() - self.sampleDisposable.dispose() + self.upgradePreviewDisposable.dispose() self.upgradeFormDisposable?.dispose() self.upgradeDisposable?.dispose() self.buyFormDisposable?.dispose() @@ -973,7 +973,7 @@ private final class GiftViewSheetContent: CombinedComponent { if let resellStars = gift.resellAmounts?.first, resellStars.amount.value > 0, !update { let alertController = textAlertController( - context: context, + context: self.context, title: presentationData.strings.Gift_View_Resale_Unlist_Title, text: presentationData.strings.Gift_View_Resale_Unlist_Text, actions: [ @@ -1031,7 +1031,7 @@ private final class GiftViewSheetContent: CombinedComponent { return } - let _ = ((controller.updateResellStars?(reference, price) ?? context.engine.payments.updateStarGiftResalePrice(reference: reference, price: price)) + let _ = ((controller.updateResellStars?(reference, price) ?? self.context.engine.payments.updateStarGiftResalePrice(reference: reference, price: price)) |> deliverOnMainQueue).startStandalone(error: { [weak self, weak controller] error in guard let self else { return @@ -2115,7 +2115,7 @@ private final class GiftViewSheetContent: CombinedComponent { } var showUpgradePreview = false - if state.inUpgradePreview, let _ = state.sampleGiftAttributes { + if state.inUpgradePreview, let _ = state.upgradePreview { showUpgradePreview = true } else if case .upgradePreview = component.subject { showUpgradePreview = true @@ -2174,8 +2174,8 @@ private final class GiftViewSheetContent: CombinedComponent { } else { headerHeight = 240.0 } - headerSubject = .unique(state.justUpgraded ? state.sampleGiftAttributes : nil, uniqueGift) - } else if state.inUpgradePreview, let attributes = state.sampleGiftAttributes { + headerSubject = .unique(state.justUpgraded ? state.upgradePreview?.attributes : nil, uniqueGift) + } else if state.inUpgradePreview, let attributes = state.upgradePreview?.attributes { headerHeight = 258.0 headerSubject = .preview(attributes) } else if case let .upgradePreview(attributes, _) = component.subject { @@ -3368,7 +3368,7 @@ private final class GiftViewSheetContent: CombinedComponent { percentage = Float(rarity) * 0.1 tag = state.modelButtonTag - if state.justUpgraded, let sampleAttributes = state.sampleGiftAttributes { + if state.justUpgraded, let sampleAttributes = state.upgradePreview?.attributes { for sampleAttribute in sampleAttributes { if case let .model(name, _, rarity) = sampleAttribute { otherValuesAndPercentages.append((name, Float(rarity) * 0.1)) @@ -3382,7 +3382,7 @@ private final class GiftViewSheetContent: CombinedComponent { percentage = Float(rarity) * 0.1 tag = state.backdropButtonTag - if state.justUpgraded, let sampleAttributes = state.sampleGiftAttributes { + if state.justUpgraded, let sampleAttributes = state.upgradePreview?.attributes { for sampleAttribute in sampleAttributes { if case let .backdrop(name, _, _, _, _, _, rarity) = sampleAttribute { otherValuesAndPercentages.append((name, Float(rarity) * 0.1)) @@ -3396,7 +3396,7 @@ private final class GiftViewSheetContent: CombinedComponent { percentage = Float(rarity) * 0.1 tag = state.symbolButtonTag - if state.justUpgraded, let sampleAttributes = state.sampleGiftAttributes { + if state.justUpgraded, let sampleAttributes = state.upgradePreview?.attributes { for sampleAttribute in sampleAttributes { if case let .pattern(name, _, rarity) = sampleAttribute { otherValuesAndPercentages.append((name, Float(rarity) * 0.1))