mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-10-09 03:20:48 +00:00
Various improvements
This commit is contained in:
parent
4e55e3aab0
commit
2007f15998
Binary file not shown.
@ -196,7 +196,16 @@ class CreateGiveawayHeaderItemNode: ItemListControllerHeaderItemNode {
|
||||
|
||||
self.backgroundNode.update(size: CGSize(width: layout.size.width, height: navigationBarHeight), transition: transition)
|
||||
|
||||
let component = AnyComponent(PremiumStarComponent(isIntro: true, isVisible: true, hasIdleAnimations: true))
|
||||
let component = AnyComponent(PremiumStarComponent(
|
||||
isIntro: true,
|
||||
isVisible: true,
|
||||
hasIdleAnimations: true,
|
||||
colors: [
|
||||
UIColor(rgb: 0x6a94ff),
|
||||
UIColor(rgb: 0x9472fd),
|
||||
UIColor(rgb: 0xe26bd3)
|
||||
]
|
||||
))
|
||||
let containerSize = CGSize(width: min(414.0, layout.size.width), height: 220.0)
|
||||
|
||||
if let hostView = self.hostView {
|
||||
|
@ -266,7 +266,16 @@ private final class PremiumGiftCodeSheetContent: CombinedComponent {
|
||||
)
|
||||
|
||||
let star = star.update(
|
||||
component: PremiumStarComponent(isIntro: false, isVisible: true, hasIdleAnimations: true),
|
||||
component: PremiumStarComponent(
|
||||
isIntro: false,
|
||||
isVisible: true,
|
||||
hasIdleAnimations: true,
|
||||
colors: [
|
||||
UIColor(rgb: 0x6a94ff),
|
||||
UIColor(rgb: 0x9472fd),
|
||||
UIColor(rgb: 0xe26bd3)
|
||||
]
|
||||
),
|
||||
availableSize: CGSize(width: context.availableSize.width, height: 200.0),
|
||||
transition: .immediate
|
||||
)
|
||||
|
@ -3212,7 +3212,12 @@ private final class PremiumIntroScreenComponent: CombinedComponent {
|
||||
component: PremiumStarComponent(
|
||||
isIntro: isIntro,
|
||||
isVisible: starIsVisible,
|
||||
hasIdleAnimations: state.hasIdleAnimations
|
||||
hasIdleAnimations: state.hasIdleAnimations,
|
||||
colors: [
|
||||
UIColor(rgb: 0x6a94ff),
|
||||
UIColor(rgb: 0x9472fd),
|
||||
UIColor(rgb: 0xe26bd3)
|
||||
]
|
||||
),
|
||||
availableSize: CGSize(width: min(414.0, context.availableSize.width), height: 220.0),
|
||||
transition: context.transition
|
||||
|
@ -870,7 +870,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[-1108478618] = { return Api.SponsoredMessage.parse_sponsoredMessage($0) }
|
||||
dict[1124938064] = { return Api.SponsoredMessageReportOption.parse_sponsoredMessageReportOption($0) }
|
||||
dict[198776256] = { return Api.StarsTopupOption.parse_starsTopupOption($0) }
|
||||
dict[1600878860] = { return Api.StarsTransaction.parse_starsTransaction($0) }
|
||||
dict[-865044046] = { return Api.StarsTransaction.parse_starsTransaction($0) }
|
||||
dict[-670195363] = { return Api.StarsTransactionPeer.parse_starsTransactionPeer($0) }
|
||||
dict[-1269320843] = { return Api.StarsTransactionPeer.parse_starsTransactionPeerAppStore($0) }
|
||||
dict[-382740222] = { return Api.StarsTransactionPeer.parse_starsTransactionPeerFragment($0) }
|
||||
@ -1302,6 +1302,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[-1610250415] = { return Api.payments.PaymentForm.parse_paymentForm($0) }
|
||||
dict[2079764828] = { return Api.payments.PaymentForm.parse_paymentFormStars($0) }
|
||||
dict[1891958275] = { return Api.payments.PaymentReceipt.parse_paymentReceipt($0) }
|
||||
dict[-319617530] = { return Api.payments.PaymentReceipt.parse_paymentReceiptStars($0) }
|
||||
dict[1314881805] = { return Api.payments.PaymentResult.parse_paymentResult($0) }
|
||||
dict[-666824391] = { return Api.payments.PaymentResult.parse_paymentVerificationNeeded($0) }
|
||||
dict[-74456004] = { return Api.payments.SavedInfo.parse_savedInfo($0) }
|
||||
@ -1379,7 +1380,7 @@ public extension Api {
|
||||
return parser(reader)
|
||||
}
|
||||
else {
|
||||
telegramApiLog("Type constructor \(String(UInt32(bitPattern: signature), radix: 16, uppercase: false)) not found")
|
||||
telegramApiLog("Type constructor \(String(signature, radix: 16, uppercase: false)) not found")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
@ -656,46 +656,64 @@ public extension Api {
|
||||
}
|
||||
public extension Api {
|
||||
enum StarsTransaction: TypeConstructorDescription {
|
||||
case starsTransaction(id: String, stars: Int64, date: Int32, peer: Api.StarsTransactionPeer)
|
||||
case starsTransaction(flags: Int32, id: String, stars: Int64, date: Int32, peer: Api.StarsTransactionPeer, title: String?, description: String?, photo: Api.WebDocument?)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .starsTransaction(let id, let stars, let date, let peer):
|
||||
case .starsTransaction(let flags, let id, let stars, let date, let peer, let title, let description, let photo):
|
||||
if boxed {
|
||||
buffer.appendInt32(1600878860)
|
||||
buffer.appendInt32(-865044046)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeString(id, buffer: buffer, boxed: false)
|
||||
serializeInt64(stars, buffer: buffer, boxed: false)
|
||||
serializeInt32(date, buffer: buffer, boxed: false)
|
||||
peer.serialize(buffer, true)
|
||||
if Int(flags) & Int(1 << 0) != 0 {serializeString(title!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeString(description!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 2) != 0 {photo!.serialize(buffer, true)}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .starsTransaction(let id, let stars, let date, let peer):
|
||||
return ("starsTransaction", [("id", id as Any), ("stars", stars as Any), ("date", date as Any), ("peer", peer as Any)])
|
||||
case .starsTransaction(let flags, let id, let stars, let date, let peer, let title, let description, let photo):
|
||||
return ("starsTransaction", [("flags", flags as Any), ("id", id as Any), ("stars", stars as Any), ("date", date as Any), ("peer", peer as Any), ("title", title as Any), ("description", description as Any), ("photo", photo as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_starsTransaction(_ reader: BufferReader) -> StarsTransaction? {
|
||||
var _1: String?
|
||||
_1 = parseString(reader)
|
||||
var _2: Int64?
|
||||
_2 = reader.readInt64()
|
||||
var _3: Int32?
|
||||
_3 = reader.readInt32()
|
||||
var _4: Api.StarsTransactionPeer?
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: String?
|
||||
_2 = parseString(reader)
|
||||
var _3: Int64?
|
||||
_3 = reader.readInt64()
|
||||
var _4: Int32?
|
||||
_4 = reader.readInt32()
|
||||
var _5: Api.StarsTransactionPeer?
|
||||
if let signature = reader.readInt32() {
|
||||
_4 = Api.parse(reader, signature: signature) as? Api.StarsTransactionPeer
|
||||
_5 = Api.parse(reader, signature: signature) as? Api.StarsTransactionPeer
|
||||
}
|
||||
var _6: String?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {_6 = parseString(reader) }
|
||||
var _7: String?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {_7 = parseString(reader) }
|
||||
var _8: Api.WebDocument?
|
||||
if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() {
|
||||
_8 = Api.parse(reader, signature: signature) as? Api.WebDocument
|
||||
} }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 {
|
||||
return Api.StarsTransaction.starsTransaction(id: _1!, stars: _2!, date: _3!, peer: _4!)
|
||||
let _c5 = _5 != nil
|
||||
let _c6 = (Int(_1!) & Int(1 << 0) == 0) || _6 != nil
|
||||
let _c7 = (Int(_1!) & Int(1 << 1) == 0) || _7 != nil
|
||||
let _c8 = (Int(_1!) & Int(1 << 2) == 0) || _8 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 {
|
||||
return Api.StarsTransaction.starsTransaction(flags: _1!, id: _2!, stars: _3!, date: _4!, peer: _5!, title: _6, description: _7, photo: _8)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
|
@ -771,6 +771,7 @@ public extension Api.payments {
|
||||
public extension Api.payments {
|
||||
enum PaymentReceipt: TypeConstructorDescription {
|
||||
case paymentReceipt(flags: Int32, date: Int32, botId: Int64, providerId: Int64, title: String, description: String, photo: Api.WebDocument?, invoice: Api.Invoice, info: Api.PaymentRequestedInfo?, shipping: Api.ShippingOption?, tipAmount: Int64?, currency: String, totalAmount: Int64, credentialsTitle: String, users: [Api.User])
|
||||
case paymentReceiptStars(flags: Int32, date: Int32, botId: Int64, title: String, description: String, photo: Api.WebDocument?, invoice: Api.Invoice, currency: String, totalAmount: Int64, users: [Api.User])
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
@ -798,6 +799,25 @@ public extension Api.payments {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
break
|
||||
case .paymentReceiptStars(let flags, let date, let botId, let title, let description, let photo, let invoice, let currency, let totalAmount, let users):
|
||||
if boxed {
|
||||
buffer.appendInt32(-319617530)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeInt32(date, buffer: buffer, boxed: false)
|
||||
serializeInt64(botId, buffer: buffer, boxed: false)
|
||||
serializeString(title, buffer: buffer, boxed: false)
|
||||
serializeString(description, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 2) != 0 {photo!.serialize(buffer, true)}
|
||||
invoice.serialize(buffer, true)
|
||||
serializeString(currency, buffer: buffer, boxed: false)
|
||||
serializeInt64(totalAmount, buffer: buffer, boxed: false)
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(users.count))
|
||||
for item in users {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@ -805,6 +825,8 @@ public extension Api.payments {
|
||||
switch self {
|
||||
case .paymentReceipt(let flags, let date, let botId, let providerId, let title, let description, let photo, let invoice, let info, let shipping, let tipAmount, let currency, let totalAmount, let credentialsTitle, let users):
|
||||
return ("paymentReceipt", [("flags", flags as Any), ("date", date as Any), ("botId", botId as Any), ("providerId", providerId as Any), ("title", title as Any), ("description", description as Any), ("photo", photo as Any), ("invoice", invoice as Any), ("info", info as Any), ("shipping", shipping as Any), ("tipAmount", tipAmount as Any), ("currency", currency as Any), ("totalAmount", totalAmount as Any), ("credentialsTitle", credentialsTitle as Any), ("users", users as Any)])
|
||||
case .paymentReceiptStars(let flags, let date, let botId, let title, let description, let photo, let invoice, let currency, let totalAmount, let users):
|
||||
return ("paymentReceiptStars", [("flags", flags as Any), ("date", date as Any), ("botId", botId as Any), ("title", title as Any), ("description", description as Any), ("photo", photo as Any), ("invoice", invoice as Any), ("currency", currency as Any), ("totalAmount", totalAmount as Any), ("users", users as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
@ -871,6 +893,50 @@ public extension Api.payments {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_paymentReceiptStars(_ reader: BufferReader) -> PaymentReceipt? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Int32?
|
||||
_2 = reader.readInt32()
|
||||
var _3: Int64?
|
||||
_3 = reader.readInt64()
|
||||
var _4: String?
|
||||
_4 = parseString(reader)
|
||||
var _5: String?
|
||||
_5 = parseString(reader)
|
||||
var _6: Api.WebDocument?
|
||||
if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() {
|
||||
_6 = Api.parse(reader, signature: signature) as? Api.WebDocument
|
||||
} }
|
||||
var _7: Api.Invoice?
|
||||
if let signature = reader.readInt32() {
|
||||
_7 = Api.parse(reader, signature: signature) as? Api.Invoice
|
||||
}
|
||||
var _8: String?
|
||||
_8 = parseString(reader)
|
||||
var _9: Int64?
|
||||
_9 = reader.readInt64()
|
||||
var _10: [Api.User]?
|
||||
if let _ = reader.readInt32() {
|
||||
_10 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
let _c5 = _5 != nil
|
||||
let _c6 = (Int(_1!) & Int(1 << 2) == 0) || _6 != nil
|
||||
let _c7 = _7 != nil
|
||||
let _c8 = _8 != nil
|
||||
let _c9 = _9 != nil
|
||||
let _c10 = _10 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 {
|
||||
return Api.payments.PaymentReceipt.paymentReceiptStars(flags: _1!, date: _2!, botId: _3!, title: _4!, description: _5!, photo: _6, invoice: _7!, currency: _8!, totalAmount: _9!, users: _10!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -1612,67 +1678,3 @@ public extension Api.photos {
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api.premium {
|
||||
enum BoostsList: TypeConstructorDescription {
|
||||
case boostsList(flags: Int32, count: Int32, boosts: [Api.Boost], nextOffset: String?, users: [Api.User])
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .boostsList(let flags, let count, let boosts, let nextOffset, let users):
|
||||
if boxed {
|
||||
buffer.appendInt32(-2030542532)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeInt32(count, buffer: buffer, boxed: false)
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(boosts.count))
|
||||
for item in boosts {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
if Int(flags) & Int(1 << 0) != 0 {serializeString(nextOffset!, buffer: buffer, boxed: false)}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(users.count))
|
||||
for item in users {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .boostsList(let flags, let count, let boosts, let nextOffset, let users):
|
||||
return ("boostsList", [("flags", flags as Any), ("count", count as Any), ("boosts", boosts as Any), ("nextOffset", nextOffset as Any), ("users", users as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_boostsList(_ reader: BufferReader) -> BoostsList? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Int32?
|
||||
_2 = reader.readInt32()
|
||||
var _3: [Api.Boost]?
|
||||
if let _ = reader.readInt32() {
|
||||
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Boost.self)
|
||||
}
|
||||
var _4: String?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {_4 = parseString(reader) }
|
||||
var _5: [Api.User]?
|
||||
if let _ = reader.readInt32() {
|
||||
_5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil
|
||||
let _c5 = _5 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 {
|
||||
return Api.premium.BoostsList.boostsList(flags: _1!, count: _2!, boosts: _3!, nextOffset: _4, users: _5!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,67 @@
|
||||
public extension Api.premium {
|
||||
enum BoostsList: TypeConstructorDescription {
|
||||
case boostsList(flags: Int32, count: Int32, boosts: [Api.Boost], nextOffset: String?, users: [Api.User])
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .boostsList(let flags, let count, let boosts, let nextOffset, let users):
|
||||
if boxed {
|
||||
buffer.appendInt32(-2030542532)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeInt32(count, buffer: buffer, boxed: false)
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(boosts.count))
|
||||
for item in boosts {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
if Int(flags) & Int(1 << 0) != 0 {serializeString(nextOffset!, buffer: buffer, boxed: false)}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(users.count))
|
||||
for item in users {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .boostsList(let flags, let count, let boosts, let nextOffset, let users):
|
||||
return ("boostsList", [("flags", flags as Any), ("count", count as Any), ("boosts", boosts as Any), ("nextOffset", nextOffset as Any), ("users", users as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_boostsList(_ reader: BufferReader) -> BoostsList? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Int32?
|
||||
_2 = reader.readInt32()
|
||||
var _3: [Api.Boost]?
|
||||
if let _ = reader.readInt32() {
|
||||
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Boost.self)
|
||||
}
|
||||
var _4: String?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {_4 = parseString(reader) }
|
||||
var _5: [Api.User]?
|
||||
if let _ = reader.readInt32() {
|
||||
_5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil
|
||||
let _c5 = _5 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 {
|
||||
return Api.premium.BoostsList.boostsList(flags: _1!, count: _2!, boosts: _3!, nextOffset: _4, users: _5!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api.premium {
|
||||
enum BoostsStatus: TypeConstructorDescription {
|
||||
case boostsStatus(flags: Int32, level: Int32, currentLevelBoosts: Int32, boosts: Int32, giftBoosts: Int32?, nextLevelBoosts: Int32?, premiumAudience: Api.StatsPercentValue?, boostUrl: String, prepaidGiveaways: [Api.PrepaidGiveaway]?, myBoostSlots: [Int32]?)
|
||||
|
@ -8794,6 +8794,23 @@ public extension Api.functions.payments {
|
||||
})
|
||||
}
|
||||
}
|
||||
public extension Api.functions.payments {
|
||||
static func refundStarsCharge(userId: Api.InputUser, msgId: Int32, chargeId: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(-258950164)
|
||||
userId.serialize(buffer, true)
|
||||
serializeInt32(msgId, buffer: buffer, boxed: false)
|
||||
serializeString(chargeId, buffer: buffer, boxed: false)
|
||||
return (FunctionDescription(name: "payments.refundStarsCharge", parameters: [("userId", String(describing: userId)), ("msgId", String(describing: msgId)), ("chargeId", String(describing: chargeId))]), 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 sendPaymentForm(flags: Int32, formId: Int64, invoice: Api.InputInvoice, requestedInfoId: String?, shippingOptionId: String?, credentials: Api.InputPaymentCredentials, tipAmount: Int64?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.payments.PaymentResult>) {
|
||||
let buffer = Buffer()
|
||||
|
@ -693,6 +693,27 @@ func _internal_requestBotPaymentReceipt(account: Account, messageId: MessageId)
|
||||
let botPaymentId = PeerId.init(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(botId))
|
||||
|
||||
return BotPaymentReceipt(invoice: parsedInvoice, info: parsedInfo, shippingOption: shippingOption, credentialsTitle: credentialsTitle, invoiceMedia: invoiceMedia, tipAmount: tipAmount, botPaymentId: botPaymentId)
|
||||
case let .paymentReceiptStars(_, _, botId, title, description, photo, invoice, currency, totalAmount, users: users):
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: [], users: users)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
|
||||
let parsedInvoice = BotPaymentInvoice(apiInvoice: invoice)
|
||||
|
||||
let invoiceMedia = TelegramMediaInvoice(
|
||||
title: title,
|
||||
description: description,
|
||||
photo: photo.flatMap(TelegramMediaWebFile.init),
|
||||
receiptMessageId: nil,
|
||||
currency: currency,
|
||||
totalAmount: totalAmount,
|
||||
startParam: "",
|
||||
extendedMedia: nil,
|
||||
flags: [],
|
||||
version: TelegramMediaInvoice.lastVersion
|
||||
)
|
||||
|
||||
let botPaymentId = PeerId.init(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(botId))
|
||||
return BotPaymentReceipt(invoice: parsedInvoice, info: nil, shippingOption: nil, credentialsTitle: "", invoiceMedia: invoiceMedia, tipAmount: nil, botPaymentId: botPaymentId)
|
||||
}
|
||||
}
|
||||
|> castError(RequestBotPaymentReceiptError.self)
|
||||
|
@ -183,7 +183,7 @@ private final class StarsContextImpl {
|
||||
func add(balance: Int64) {
|
||||
if var state = self._state {
|
||||
var transactions = state.transactions
|
||||
transactions.insert(.init(id: "\(arc4random())", count: balance, date: Int32(Date().timeIntervalSince1970), peer: .appStore), at: 0)
|
||||
transactions.insert(.init(id: "\(arc4random())", count: balance, date: Int32(Date().timeIntervalSince1970), peer: .appStore, title: nil, description: nil, photo: nil), at: 0)
|
||||
|
||||
state.balance = state.balance + balance
|
||||
self._state = state
|
||||
@ -216,7 +216,7 @@ private final class StarsContextImpl {
|
||||
private extension StarsContext.State.Transaction {
|
||||
init?(apiTransaction: Api.StarsTransaction, transaction: Transaction) {
|
||||
switch apiTransaction {
|
||||
case let .starsTransaction(id, stars, date, transactionPeer):
|
||||
case let .starsTransaction(_, id, stars, date, transactionPeer, title, description, photo):
|
||||
let parsedPeer: StarsContext.State.Transaction.Peer
|
||||
switch transactionPeer {
|
||||
case .starsTransactionPeerAppStore:
|
||||
@ -235,7 +235,7 @@ private extension StarsContext.State.Transaction {
|
||||
}
|
||||
parsedPeer = .peer(EnginePeer(peer))
|
||||
}
|
||||
self.init(id: id, count: stars, date: date, peer: parsedPeer)
|
||||
self.init(id: id, count: stars, date: date, peer: parsedPeer, title: title, description: description, photo: photo.flatMap(TelegramMediaWebFile.init))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -256,12 +256,26 @@ public final class StarsContext {
|
||||
public let count: Int64
|
||||
public let date: Int32
|
||||
public let peer: Peer
|
||||
public let title: String?
|
||||
public let description: String?
|
||||
public let photo: TelegramMediaWebFile?
|
||||
|
||||
init(id: String, count: Int64, date: Int32, peer: Peer) {
|
||||
init(
|
||||
id: String,
|
||||
count: Int64,
|
||||
date: Int32,
|
||||
peer: Peer,
|
||||
title: String?,
|
||||
description: String?,
|
||||
photo: TelegramMediaWebFile?
|
||||
) {
|
||||
self.id = id
|
||||
self.count = count
|
||||
self.date = date
|
||||
self.peer = peer
|
||||
self.title = title
|
||||
self.description = description
|
||||
self.photo = photo
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -175,7 +175,7 @@ public final class ChatBotInfoItemNode: ListViewItemNode {
|
||||
break
|
||||
case .ignore:
|
||||
return .fail
|
||||
case .url, .phone, .peerMention, .textMention, .botCommand, .hashtag, .instantPage, .wallpaper, .theme, .call, .openMessage, .timecode, .bankCard, .tooltip, .openPollResults, .copy, .largeEmoji, .customEmoji:
|
||||
case .url, .phone, .peerMention, .textMention, .botCommand, .hashtag, .instantPage, .wallpaper, .theme, .call, .openMessage, .timecode, .bankCard, .tooltip, .openPollResults, .copy, .largeEmoji, .customEmoji, .custom:
|
||||
return .waitForSingleTap
|
||||
}
|
||||
}
|
||||
|
@ -172,6 +172,7 @@ private final class ChatMessageActionButtonNode: ASDisplayNode {
|
||||
let incoming = message.effectivelyIncoming(context.account.peerId)
|
||||
let graphics = PresentationResourcesChat.additionalGraphics(theme.theme, wallpaper: theme.wallpaper, bubbleCorners: bubbleCorners)
|
||||
|
||||
var isStarsPayment = false
|
||||
let iconImage: UIImage?
|
||||
switch button.action {
|
||||
case .text:
|
||||
@ -191,7 +192,8 @@ private final class ChatMessageActionButtonNode: ASDisplayNode {
|
||||
case .switchInline:
|
||||
iconImage = incoming ? graphics.chatBubbleActionButtonIncomingShareIconImage : graphics.chatBubbleActionButtonOutgoingShareIconImage
|
||||
case .payment:
|
||||
if button.title.contains("Pay XTR") {
|
||||
if button.title.contains("⭐️") {
|
||||
isStarsPayment = true
|
||||
iconImage = nil
|
||||
} else {
|
||||
iconImage = incoming ? graphics.chatBubbleActionButtonIncomingPaymentIconImage : graphics.chatBubbleActionButtonOutgoingPaymentIconImage
|
||||
@ -222,10 +224,10 @@ private final class ChatMessageActionButtonNode: ASDisplayNode {
|
||||
|
||||
let titleColor = bubbleVariableColor(variableColor: messageTheme.actionButtonsTextColor, wallpaper: theme.wallpaper)
|
||||
let attributedTitle: NSAttributedString
|
||||
if title.contains("Pay XTR") {
|
||||
let stars = title.replacingOccurrences(of: "Pay XTR", with: "")
|
||||
let buttonAttributedString = NSMutableAttributedString(string: "Pay > \(stars)", font: titleFont, textColor: titleColor, paragraphAlignment: .center)
|
||||
if let range = buttonAttributedString.string.range(of: ">"), let starImage = UIImage(bundleImageName: "Item List/PremiumIcon") {
|
||||
if isStarsPayment {
|
||||
let updatedTitle = title.replacingOccurrences(of: "⭐️", with: " # ")
|
||||
let buttonAttributedString = NSMutableAttributedString(string: updatedTitle, font: titleFont, textColor: titleColor, paragraphAlignment: .center)
|
||||
if let range = buttonAttributedString.string.range(of: "#"), let starImage = UIImage(bundleImageName: "Item List/PremiumIcon") {
|
||||
buttonAttributedString.addAttribute(.attachment, value: starImage, range: NSRange(range, in: buttonAttributedString.string))
|
||||
buttonAttributedString.addAttribute(.foregroundColor, value: titleColor, range: NSRange(range, in: buttonAttributedString.string))
|
||||
buttonAttributedString.addAttribute(.baselineOffset, value: 1.0, range: NSRange(range, in: buttonAttributedString.string))
|
||||
|
@ -159,6 +159,7 @@ public struct ChatMessageBubbleContentTapAction {
|
||||
case copy(String)
|
||||
case largeEmoji(String, String?, TelegramMediaFile)
|
||||
case customEmoji(TelegramMediaFile)
|
||||
case custom(() -> Void)
|
||||
}
|
||||
|
||||
public var content: Content
|
||||
|
@ -1178,7 +1178,7 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
|
||||
break
|
||||
case .ignore:
|
||||
return .fail
|
||||
case .url, .phone, .peerMention, .textMention, .botCommand, .hashtag, .instantPage, .wallpaper, .theme, .call, .openMessage, .timecode, .bankCard, .tooltip, .openPollResults, .copy, .largeEmoji, .customEmoji:
|
||||
case .url, .phone, .peerMention, .textMention, .botCommand, .hashtag, .instantPage, .wallpaper, .theme, .call, .openMessage, .timecode, .bankCard, .tooltip, .openPollResults, .copy, .largeEmoji, .customEmoji, .custom:
|
||||
return .waitForSingleTap
|
||||
}
|
||||
}
|
||||
@ -4623,6 +4623,10 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
|
||||
return .action(InternalBubbleTapAction.Action {
|
||||
})
|
||||
}
|
||||
case let .custom(action):
|
||||
return .action(InternalBubbleTapAction.Action({
|
||||
action()
|
||||
}, contextMenuOnLongPress: !tapAction.hasLongTapAction))
|
||||
case let .url(url):
|
||||
if case .longTap = gesture, !tapAction.hasLongTapAction, let item = self.item {
|
||||
let tapMessage = item.content.firstMessage
|
||||
@ -4872,6 +4876,8 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
|
||||
break
|
||||
case .customEmoji:
|
||||
break
|
||||
case .custom:
|
||||
break
|
||||
}
|
||||
}
|
||||
if let tapMessage = tapMessage {
|
||||
|
@ -24,6 +24,7 @@ swift_library(
|
||||
"//submodules/TelegramUI/Components/Chat/ChatMessageBubbleContentNode",
|
||||
"//submodules/TelegramUI/Components/Chat/ChatMessageItemCommon",
|
||||
"//submodules/TelegramUI/Components/Chat/MessageInlineBlockBackgroundView",
|
||||
"//submodules/TextSelectionNode",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
|
@ -12,6 +12,7 @@ import ChatMessageDateAndStatusNode
|
||||
import ChatMessageBubbleContentNode
|
||||
import ChatMessageItemCommon
|
||||
import MessageInlineBlockBackgroundView
|
||||
import TextSelectionNode
|
||||
import Geocoding
|
||||
import UrlEscaping
|
||||
|
||||
@ -44,6 +45,7 @@ public class ChatMessageFactCheckBubbleContentNode: ChatMessageBubbleContentNode
|
||||
private let textNode: TextNode
|
||||
private let additionalTextNode: TextNode
|
||||
private var linkHighlightingNode: LinkHighlightingNode?
|
||||
private var textSelectionNode: TextSelectionNode?
|
||||
|
||||
private let lineNode: ASDisplayNode
|
||||
|
||||
@ -51,7 +53,6 @@ public class ChatMessageFactCheckBubbleContentNode: ChatMessageBubbleContentNode
|
||||
private var maskOverlayView: UIView?
|
||||
|
||||
private var expandIcon: ASImageNode
|
||||
private var expandButton: HighlightTrackingButtonNode?
|
||||
|
||||
private let statusNode: ChatMessageDateAndStatusNode
|
||||
|
||||
@ -136,10 +137,58 @@ public class ChatMessageFactCheckBubbleContentNode: ChatMessageBubbleContentNode
|
||||
let _ = item.controllerInteraction.requestMessageUpdate(item.message.id, false)
|
||||
}
|
||||
|
||||
public override func tapActionAtPoint(_ point: CGPoint, gesture: TapLongTapOrDoubleTapGesture, isEstimating: Bool) -> ChatMessageBubbleContentTapAction {
|
||||
if let expandButton = self.expandButton, expandButton.frame.contains(point) {
|
||||
return ChatMessageBubbleContentTapAction(content: .ignore)
|
||||
public override func willUpdateIsExtractedToContextPreview(_ value: Bool) {
|
||||
if !value {
|
||||
if let textSelectionNode = self.textSelectionNode {
|
||||
self.textSelectionNode = nil
|
||||
textSelectionNode.highlightAreaNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false)
|
||||
textSelectionNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak textSelectionNode] _ in
|
||||
textSelectionNode?.highlightAreaNode.removeFromSupernode()
|
||||
textSelectionNode?.removeFromSupernode()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override func updateIsExtractedToContextPreview(_ value: Bool) {
|
||||
if value {
|
||||
if self.textSelectionNode == nil, let item = self.item, let rootNode = item.controllerInteraction.chatControllerNode() {
|
||||
let selectionColor: UIColor = item.presentationData.theme.theme.chat.message.incoming.textSelectionColor
|
||||
let knobColor: UIColor = item.presentationData.theme.theme.chat.message.incoming.textSelectionKnobColor
|
||||
|
||||
let textSelectionNode = TextSelectionNode(theme: TextSelectionTheme(selection: selectionColor, knob: knobColor, isDark: item.presentationData.theme.theme.overallDarkAppearance), strings: item.presentationData.strings, textNode: self.textNode, updateIsActive: { [weak self] value in
|
||||
self?.updateIsTextSelectionActive?(value)
|
||||
}, present: { [weak self] c, a in
|
||||
self?.item?.controllerInteraction.presentGlobalOverlayController(c, a)
|
||||
}, rootNode: { [weak rootNode] in
|
||||
return rootNode
|
||||
}, performAction: { [weak self] text, action in
|
||||
guard let strongSelf = self, let item = strongSelf.item else {
|
||||
return
|
||||
}
|
||||
item.controllerInteraction.performTextSelectionAction(item.message, true, text, action)
|
||||
})
|
||||
textSelectionNode.enableQuote = false
|
||||
self.textSelectionNode = textSelectionNode
|
||||
self.addSubnode(textSelectionNode)
|
||||
self.insertSubnode(textSelectionNode.highlightAreaNode, belowSubnode: self.textClippingNode)
|
||||
textSelectionNode.frame = self.textClippingNode.view.convert(self.textNode.frame, to: self.view)
|
||||
textSelectionNode.highlightAreaNode.frame = textSelectionNode.frame
|
||||
}
|
||||
} else {
|
||||
if let textSelectionNode = self.textSelectionNode {
|
||||
self.textSelectionNode = nil
|
||||
self.updateIsTextSelectionActive?(false)
|
||||
textSelectionNode.highlightAreaNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false)
|
||||
textSelectionNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak textSelectionNode] _ in
|
||||
textSelectionNode?.highlightAreaNode.removeFromSupernode()
|
||||
textSelectionNode?.removeFromSupernode()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override func tapActionAtPoint(_ point: CGPoint, gesture: TapLongTapOrDoubleTapGesture, isEstimating: Bool) -> ChatMessageBubbleContentTapAction {
|
||||
if let titleBadgeButton = self.titleBadgeButton, titleBadgeButton.frame.contains(point) {
|
||||
return ChatMessageBubbleContentTapAction(content: .ignore)
|
||||
}
|
||||
@ -162,6 +211,11 @@ public class ChatMessageFactCheckBubbleContentNode: ChatMessageBubbleContentNode
|
||||
return ChatMessageBubbleContentTapAction(content: .hashtag(hashtag.peerName, hashtag.hashtag))
|
||||
}
|
||||
}
|
||||
if let backgroundView = self.backgroundView, backgroundView.frame.contains(point), case .tap = gesture {
|
||||
return ChatMessageBubbleContentTapAction(content: .custom({ [weak self] in
|
||||
self?.expandPressed()
|
||||
}), hasLongTapAction: false)
|
||||
}
|
||||
return ChatMessageBubbleContentTapAction(content: .none)
|
||||
}
|
||||
|
||||
@ -585,35 +639,21 @@ public class ChatMessageFactCheckBubbleContentNode: ChatMessageBubbleContentNode
|
||||
}
|
||||
strongSelf.expandIcon.bounds = CGRect(origin: .zero, size: expandIconFrame.size)
|
||||
}
|
||||
|
||||
let expandButtonFrame = expandIconFrame.insetBy(dx: -8.0, dy: -8.0)
|
||||
|
||||
let expandButton: HighlightTrackingButtonNode
|
||||
if let current = strongSelf.expandButton {
|
||||
expandButton = current
|
||||
} else {
|
||||
expandButton = HighlightTrackingButtonNode()
|
||||
expandButton.addTarget(self, action: #selector(strongSelf.expandPressed), forControlEvents: .touchUpInside)
|
||||
expandButton.highligthedChanged = { [weak self] highlighted in
|
||||
if let strongSelf = self {
|
||||
if highlighted {
|
||||
strongSelf.expandIcon.layer.removeAnimation(forKey: "opacity")
|
||||
strongSelf.expandIcon.alpha = 0.4
|
||||
} else {
|
||||
strongSelf.expandIcon.alpha = 1.0
|
||||
strongSelf.expandIcon.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2)
|
||||
}
|
||||
}
|
||||
}
|
||||
strongSelf.expandButton = expandButton
|
||||
strongSelf.addSubnode(expandButton)
|
||||
}
|
||||
expandButton.frame = expandButtonFrame
|
||||
} else {
|
||||
strongSelf.expandIcon.isHidden = true
|
||||
strongSelf.textClippingNode.view.mask = nil
|
||||
}
|
||||
|
||||
if let textSelectionNode = strongSelf.textSelectionNode {
|
||||
let shouldUpdateLayout = textSelectionNode.frame.size != textFrame.size
|
||||
textSelectionNode.frame = strongSelf.textClippingNode.view.convert(strongSelf.textNode.frame, to: strongSelf.view)
|
||||
textSelectionNode.highlightAreaNode.frame = textSelectionNode.frame
|
||||
|
||||
if shouldUpdateLayout {
|
||||
textSelectionNode.updateLayout()
|
||||
}
|
||||
}
|
||||
|
||||
if let statusSizeAndApply = statusSizeAndApply {
|
||||
strongSelf.statusNode.reactionSelected = { [weak strongSelf] _, value, sourceView in
|
||||
guard let strongSelf, let item = strongSelf.item else {
|
||||
|
@ -494,7 +494,12 @@ public class ChatMessageThreadInfoNode: ASDisplayNode {
|
||||
node.contentNode.addSubnode(avatarNode)
|
||||
}
|
||||
avatarNode.frame = CGRect(origin: CGPoint(x: -1.0, y: -3.0), size: CGSize(width: 26.0, height: 26.0))
|
||||
avatarNode.setPeer(context: arguments.context, theme: arguments.presentationData.theme.theme, peer: peer)
|
||||
|
||||
var overrideImage: AvatarNodeImageOverride?
|
||||
if peer.id.isReplies {
|
||||
overrideImage = .repliesIcon
|
||||
}
|
||||
avatarNode.setPeer(context: arguments.context, theme: arguments.presentationData.theme.theme, peer: peer, overrideImage: overrideImage)
|
||||
} else {
|
||||
let titleTopicIconView: ComponentHostView<Empty>
|
||||
if let current = node.titleTopicIconView {
|
||||
|
@ -222,7 +222,7 @@ private final class FactCheckAlertContentNode: AlertContentNode {
|
||||
characterLimit: 1024,
|
||||
emptyLineHandling: .oneConsecutive,
|
||||
formatMenuAvailability: .available([.bold, .italic, .link]),
|
||||
returnKeyType: .done,
|
||||
returnKeyType: .default,
|
||||
lockedFormatAction: {
|
||||
},
|
||||
present: { [weak self] c in
|
||||
|
@ -33,7 +33,11 @@ private func generateShineTexture() -> UIImage {
|
||||
private func generateDiffuseTexture(colors: [UIColor]) -> UIImage {
|
||||
return generateImage(CGSize(width: 256, height: 256), rotatedContext: { size, context in
|
||||
let colorsArray: [CGColor] = colors.map { $0.cgColor }
|
||||
var locations: [CGFloat] = [0.0, 0.25, 0.5, 0.75, 1.0]
|
||||
var locations: [CGFloat] = []
|
||||
for i in 0 ..< colors.count {
|
||||
let t = CGFloat(i) / CGFloat(colors.count - 1)
|
||||
locations.append(t)
|
||||
}
|
||||
let gradient = CGGradient(colorsSpace: deviceColorSpace, colors: colorsArray as CFArray, locations: &locations)!
|
||||
|
||||
context.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: size.height), end: CGPoint(x: size.width, y: 0.0), options: CGGradientDrawingOptions())
|
||||
@ -281,7 +285,7 @@ public final class PremiumStarComponent: Component {
|
||||
|
||||
private var didSetup = false
|
||||
private func setup() {
|
||||
guard !self.didSetup, let scene = loadCompressedScene(name: "star", version: sceneVersion) else {
|
||||
guard !self.didSetup, let scene = loadCompressedScene(name: "star2", version: sceneVersion) else {
|
||||
return
|
||||
}
|
||||
|
||||
@ -289,23 +293,23 @@ public final class PremiumStarComponent: Component {
|
||||
self.sceneView.scene = scene
|
||||
self.sceneView.delegate = self
|
||||
|
||||
if let node = scene.rootNode.childNode(withName: "star", recursively: false), let colors = self.component?.colors, let color = colors.first {
|
||||
if let node = scene.rootNode.childNode(withName: "star", recursively: false), let colors = self.component?.colors, let _ = colors.first {
|
||||
node.geometry?.materials.first?.diffuse.contents = generateDiffuseTexture(colors: colors)
|
||||
|
||||
let names: [String] = [
|
||||
"particles_left",
|
||||
"particles_right",
|
||||
"particles_left_bottom",
|
||||
"particles_right_bottom",
|
||||
"particles_center"
|
||||
]
|
||||
|
||||
for name in names {
|
||||
if let node = scene.rootNode.childNode(withName: name, recursively: false), let particleSystem = node.particleSystems?.first {
|
||||
particleSystem.particleColor = color
|
||||
particleSystem.particleColorVariation = SCNVector4Make(0, 0, 0, 0)
|
||||
}
|
||||
}
|
||||
// let names: [String] = [
|
||||
// "particles_left",
|
||||
// "particles_right",
|
||||
// "particles_left_bottom",
|
||||
// "particles_right_bottom",
|
||||
// "particles_center"
|
||||
// ]
|
||||
//
|
||||
// for name in names {
|
||||
// if let node = scene.rootNode.childNode(withName: name, recursively: false), let particleSystem = node.particleSystems?.first {
|
||||
// particleSystem.particleColor = color
|
||||
// particleSystem.particleColorVariation = SCNVector4Make(0, 0, 0, 0)
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
if self.animateFrom != nil {
|
||||
@ -450,9 +454,9 @@ public final class PremiumStarComponent: Component {
|
||||
return
|
||||
}
|
||||
|
||||
if #available(iOS 17.0, *), let material = node.geometry?.materials.first {
|
||||
material.metalness.intensity = 0.2
|
||||
}
|
||||
// if let material = node.geometry?.materials.first {
|
||||
// material.metalness.intensity = 0.4
|
||||
// }
|
||||
|
||||
let animation = CABasicAnimation(keyPath: "contentsTransform")
|
||||
animation.fillMode = .forwards
|
||||
|
@ -696,10 +696,10 @@ private final class StarsPurchaseScreenComponent: CombinedComponent {
|
||||
isVisible: starIsVisible,
|
||||
hasIdleAnimations: state.hasIdleAnimations,
|
||||
colors: [
|
||||
UIColor(rgb: 0xea8904),
|
||||
UIColor(rgb: 0xe57d02),
|
||||
UIColor(rgb: 0xf09903),
|
||||
UIColor(rgb: 0xfec209),
|
||||
UIColor(rgb: 0xfed31a)
|
||||
UIColor(rgb: 0xf9b004),
|
||||
UIColor(rgb: 0xfdd219)
|
||||
]
|
||||
),
|
||||
availableSize: CGSize(width: min(414.0, context.availableSize.width), height: 220.0),
|
||||
|
@ -371,10 +371,10 @@ final class StarsTransactionsScreenComponent: Component {
|
||||
isVisible: true,
|
||||
hasIdleAnimations: true,
|
||||
colors: [
|
||||
UIColor(rgb: 0xea8904),
|
||||
UIColor(rgb: 0xe57d02),
|
||||
UIColor(rgb: 0xf09903),
|
||||
UIColor(rgb: 0xfec209),
|
||||
UIColor(rgb: 0xfed31a)
|
||||
UIColor(rgb: 0xf9b004),
|
||||
UIColor(rgb: 0xfdd219)
|
||||
]
|
||||
)),
|
||||
environment: {},
|
||||
|
@ -216,7 +216,8 @@ private final class SheetContent: CombinedComponent {
|
||||
|
||||
let constrainedTitleWidth = context.availableSize.width - 16.0 * 2.0
|
||||
|
||||
contentSize.height += 130.0
|
||||
contentSize.height += 126.0
|
||||
|
||||
let title = title.update(
|
||||
component: Text(text: strings.Stars_Transfer_Title, font: Font.bold(24.0), color: theme.list.itemPrimaryTextColor),
|
||||
availableSize: CGSize(width: constrainedTitleWidth, height: context.availableSize.height),
|
||||
@ -258,13 +259,14 @@ private final class SheetContent: CombinedComponent {
|
||||
.position(CGPoint(x: context.availableSize.width / 2.0, y: contentSize.height + text.size.height / 2.0))
|
||||
)
|
||||
contentSize.height += text.size.height
|
||||
contentSize.height += 24.0
|
||||
contentSize.height += 28.0
|
||||
|
||||
if state.cachedChevronImage == nil || state.cachedChevronImage?.1 !== theme {
|
||||
state.cachedChevronImage = (generateTintedImage(image: UIImage(bundleImageName: "Premium/Stars/Star"), color: UIColor(rgb: 0xf09903))!, theme)
|
||||
}
|
||||
|
||||
let balanceAttributedString = parseMarkdownIntoAttributedString("\(strings.Stars_Transfer_Balance)\n # **\(state.balance ?? 0)**", attributes: markdownAttributes).mutableCopy() as! NSMutableAttributedString
|
||||
let balanceAttributedString = NSMutableAttributedString(string: strings.Stars_Transfer_Balance, font: Font.regular(14.0), textColor: textColor)
|
||||
balanceAttributedString.append(NSMutableAttributedString(string: "\n # \(state.balance ?? 0)", font: Font.semibold(16.0), textColor: textColor))
|
||||
if let range = balanceAttributedString.string.range(of: "#"), let chevronImage = state.cachedChevronImage?.0 {
|
||||
balanceAttributedString.addAttribute(.attachment, value: chevronImage, range: NSRange(range, in: balanceAttributedString.string))
|
||||
balanceAttributedString.addAttribute(.foregroundColor, value: UIColor(rgb: 0xf09903), range: NSRange(range, in: balanceAttributedString.string))
|
||||
@ -274,13 +276,14 @@ private final class SheetContent: CombinedComponent {
|
||||
component: MultilineTextComponent(
|
||||
text: .plain(balanceAttributedString),
|
||||
horizontalAlignment: .left,
|
||||
maximumNumberOfLines: 0
|
||||
maximumNumberOfLines: 0,
|
||||
lineSpacing: 0.25
|
||||
),
|
||||
availableSize: CGSize(width: constrainedTitleWidth, height: context.availableSize.height),
|
||||
transition: .immediate
|
||||
)
|
||||
context.add(balanceText
|
||||
.position(CGPoint(x: 16.0 + balanceText.size.width / 2.0, y: 29.0))
|
||||
.position(CGPoint(x: 16.0 + balanceText.size.width / 2.0, y: 31.0))
|
||||
)
|
||||
|
||||
if state.cachedStarImage == nil || state.cachedStarImage?.1 !== theme {
|
||||
@ -315,14 +318,17 @@ private final class SheetContent: CombinedComponent {
|
||||
isEnabled: true,
|
||||
displaysProgress: state.inProgress,
|
||||
action: { [weak state, weak controller] in
|
||||
state?.buy(requestTopUp: { [weak controller] _ in
|
||||
state?.buy(requestTopUp: { [weak controller] completion in
|
||||
let purchaseController = accountContext.sharedContext.makeStarsPurchaseScreen(
|
||||
context: accountContext,
|
||||
starsContext: starsContext,
|
||||
options: state?.options ?? [],
|
||||
peerId: state?.peer?.id,
|
||||
requiredStars: invoice.totalAmount,
|
||||
completion: { _ in }
|
||||
completion: { [weak starsContext] stars in
|
||||
starsContext?.add(balance: stars)
|
||||
completion()
|
||||
}
|
||||
)
|
||||
controller?.push(purchaseController)
|
||||
}, completion: { [weak controller] in
|
||||
|
Loading…
x
Reference in New Issue
Block a user