Update API

This commit is contained in:
Ilya Laktyushin 2024-05-24 16:29:44 +04:00
parent 16b6083b6e
commit 0bb02041e8
21 changed files with 205 additions and 113 deletions

View File

@ -1045,7 +1045,7 @@ public protocol SharedAccountContext: AnyObject {
func makeStarsPurchaseScreen(context: AccountContext, starsContext: StarsContext, options: [StarsTopUpOption], peerId: EnginePeer.Id?, requiredStars: Int64?, completion: @escaping (Int64) -> Void) -> ViewController func makeStarsPurchaseScreen(context: AccountContext, starsContext: StarsContext, options: [StarsTopUpOption], peerId: EnginePeer.Id?, requiredStars: Int64?, completion: @escaping (Int64) -> Void) -> ViewController
func makeStarsTransferScreen(context: AccountContext, starsContext: StarsContext, invoice: TelegramMediaInvoice, source: BotPaymentInvoiceSource, inputData: Signal<(StarsContext.State, BotPaymentForm, EnginePeer?)?, NoError>) -> ViewController func makeStarsTransferScreen(context: AccountContext, starsContext: StarsContext, invoice: TelegramMediaInvoice, source: BotPaymentInvoiceSource, inputData: Signal<(StarsContext.State, BotPaymentForm, EnginePeer?)?, NoError>) -> ViewController
func makeStarsTransactionScreen(context: AccountContext, transaction: StarsContext.State.Transaction) -> ViewController func makeStarsTransactionScreen(context: AccountContext, transaction: StarsContext.State.Transaction) -> ViewController
func makeStarsReceiptScreen(context: AccountContext, receipt: BotPaymentReceipt, id: String?, date: Int32) -> ViewController func makeStarsReceiptScreen(context: AccountContext, receipt: BotPaymentReceipt) -> ViewController
func makeDebugSettingsController(context: AccountContext?) -> ViewController? func makeDebugSettingsController(context: AccountContext?) -> ViewController?

View File

@ -65,6 +65,7 @@ public final class SheetComponent<ChildEnvironmentType: Equatable>: Component {
public let clipsContent: Bool public let clipsContent: Bool
public let externalState: ExternalState? public let externalState: ExternalState?
public let animateOut: ActionSlot<Action<()>> public let animateOut: ActionSlot<Action<()>>
public let onPan: () -> Void
public init( public init(
content: AnyComponent<ChildEnvironmentType>, content: AnyComponent<ChildEnvironmentType>,
@ -72,7 +73,8 @@ public final class SheetComponent<ChildEnvironmentType: Equatable>: Component {
followContentSizeChanges: Bool = false, followContentSizeChanges: Bool = false,
clipsContent: Bool = false, clipsContent: Bool = false,
externalState: ExternalState? = nil, externalState: ExternalState? = nil,
animateOut: ActionSlot<Action<()>> animateOut: ActionSlot<Action<()>>,
onPan: @escaping () -> Void = {}
) { ) {
self.content = content self.content = content
self.backgroundColor = backgroundColor self.backgroundColor = backgroundColor
@ -80,6 +82,7 @@ public final class SheetComponent<ChildEnvironmentType: Equatable>: Component {
self.clipsContent = clipsContent self.clipsContent = clipsContent
self.externalState = externalState self.externalState = externalState
self.animateOut = animateOut self.animateOut = animateOut
self.onPan = onPan
} }
public static func ==(lhs: SheetComponent, rhs: SheetComponent) -> Bool { public static func ==(lhs: SheetComponent, rhs: SheetComponent) -> Bool {
@ -128,6 +131,8 @@ public final class SheetComponent<ChildEnvironmentType: Equatable>: Component {
return false return false
} }
private var component: SheetComponent<ChildEnvironmentType>?
private let dimView: UIView private let dimView: UIView
private let scrollView: ScrollView private let scrollView: ScrollView
private let backgroundView: UIView private let backgroundView: UIView
@ -199,6 +204,10 @@ public final class SheetComponent<ChildEnvironmentType: Equatable>: Component {
self.dismiss?(true) self.dismiss?(true)
} }
public func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
self.component?.onPan()
}
private var scrollingOut = false private var scrollingOut = false
public func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) { public func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
let contentOffset = (scrollView.contentOffset.y + scrollView.contentInset.top - scrollView.contentSize.height) * -1.0 let contentOffset = (scrollView.contentOffset.y + scrollView.contentInset.top - scrollView.contentSize.height) * -1.0
@ -302,6 +311,7 @@ public final class SheetComponent<ChildEnvironmentType: Equatable>: Component {
} }
} }
self.component = component
self.currentHasInputHeight = sheetEnvironment.hasInputHeight self.currentHasInputHeight = sheetEnvironment.hasInputHeight
switch component.backgroundColor { switch component.backgroundColor {

View File

@ -545,7 +545,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-1281329567] = { return Api.MessageAction.parse_messageActionGroupCallScheduled($0) } dict[-1281329567] = { return Api.MessageAction.parse_messageActionGroupCallScheduled($0) }
dict[-1615153660] = { return Api.MessageAction.parse_messageActionHistoryClear($0) } dict[-1615153660] = { return Api.MessageAction.parse_messageActionHistoryClear($0) }
dict[1345295095] = { return Api.MessageAction.parse_messageActionInviteToGroupCall($0) } dict[1345295095] = { return Api.MessageAction.parse_messageActionInviteToGroupCall($0) }
dict[-1482950556] = { return Api.MessageAction.parse_messageActionPaymentSent($0) } dict[-1776926890] = { return Api.MessageAction.parse_messageActionPaymentSent($0) }
dict[-1892568281] = { return Api.MessageAction.parse_messageActionPaymentSentMe($0) } dict[-1892568281] = { return Api.MessageAction.parse_messageActionPaymentSentMe($0) }
dict[-2132731265] = { return Api.MessageAction.parse_messageActionPhoneCall($0) } dict[-2132731265] = { return Api.MessageAction.parse_messageActionPhoneCall($0) }
dict[-1799538451] = { return Api.MessageAction.parse_messageActionPinMessage($0) } dict[-1799538451] = { return Api.MessageAction.parse_messageActionPinMessage($0) }
@ -1302,7 +1302,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-1610250415] = { return Api.payments.PaymentForm.parse_paymentForm($0) } dict[-1610250415] = { return Api.payments.PaymentForm.parse_paymentForm($0) }
dict[2079764828] = { return Api.payments.PaymentForm.parse_paymentFormStars($0) } dict[2079764828] = { return Api.payments.PaymentForm.parse_paymentFormStars($0) }
dict[1891958275] = { return Api.payments.PaymentReceipt.parse_paymentReceipt($0) } dict[1891958275] = { return Api.payments.PaymentReceipt.parse_paymentReceipt($0) }
dict[-319617530] = { return Api.payments.PaymentReceipt.parse_paymentReceiptStars($0) } dict[-625215430] = { return Api.payments.PaymentReceipt.parse_paymentReceiptStars($0) }
dict[1314881805] = { return Api.payments.PaymentResult.parse_paymentResult($0) } dict[1314881805] = { return Api.payments.PaymentResult.parse_paymentResult($0) }
dict[-666824391] = { return Api.payments.PaymentResult.parse_paymentVerificationNeeded($0) } dict[-666824391] = { return Api.payments.PaymentResult.parse_paymentVerificationNeeded($0) }
dict[-74456004] = { return Api.payments.SavedInfo.parse_savedInfo($0) } dict[-74456004] = { return Api.payments.SavedInfo.parse_savedInfo($0) }

View File

@ -604,7 +604,7 @@ public extension Api {
case messageActionGroupCallScheduled(call: Api.InputGroupCall, scheduleDate: Int32) case messageActionGroupCallScheduled(call: Api.InputGroupCall, scheduleDate: Int32)
case messageActionHistoryClear case messageActionHistoryClear
case messageActionInviteToGroupCall(call: Api.InputGroupCall, users: [Int64]) case messageActionInviteToGroupCall(call: Api.InputGroupCall, users: [Int64])
case messageActionPaymentSent(flags: Int32, currency: String, totalAmount: Int64, invoiceSlug: String?, charge: Api.PaymentCharge?) case messageActionPaymentSent(flags: Int32, currency: String, totalAmount: Int64, invoiceSlug: String?)
case messageActionPaymentSentMe(flags: Int32, currency: String, totalAmount: Int64, payload: Buffer, info: Api.PaymentRequestedInfo?, shippingOptionId: String?, charge: Api.PaymentCharge) case messageActionPaymentSentMe(flags: Int32, currency: String, totalAmount: Int64, payload: Buffer, info: Api.PaymentRequestedInfo?, shippingOptionId: String?, charge: Api.PaymentCharge)
case messageActionPhoneCall(flags: Int32, callId: Int64, reason: Api.PhoneCallDiscardReason?, duration: Int32?) case messageActionPhoneCall(flags: Int32, callId: Int64, reason: Api.PhoneCallDiscardReason?, duration: Int32?)
case messageActionPinMessage case messageActionPinMessage
@ -816,15 +816,14 @@ public extension Api {
serializeInt64(item, buffer: buffer, boxed: false) serializeInt64(item, buffer: buffer, boxed: false)
} }
break break
case .messageActionPaymentSent(let flags, let currency, let totalAmount, let invoiceSlug, let charge): case .messageActionPaymentSent(let flags, let currency, let totalAmount, let invoiceSlug):
if boxed { if boxed {
buffer.appendInt32(-1482950556) buffer.appendInt32(-1776926890)
} }
serializeInt32(flags, buffer: buffer, boxed: false) serializeInt32(flags, buffer: buffer, boxed: false)
serializeString(currency, buffer: buffer, boxed: false) serializeString(currency, buffer: buffer, boxed: false)
serializeInt64(totalAmount, buffer: buffer, boxed: false) serializeInt64(totalAmount, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {serializeString(invoiceSlug!, buffer: buffer, boxed: false)} if Int(flags) & Int(1 << 0) != 0 {serializeString(invoiceSlug!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 4) != 0 {charge!.serialize(buffer, true)}
break break
case .messageActionPaymentSentMe(let flags, let currency, let totalAmount, let payload, let info, let shippingOptionId, let charge): case .messageActionPaymentSentMe(let flags, let currency, let totalAmount, let payload, let info, let shippingOptionId, let charge):
if boxed { if boxed {
@ -1018,8 +1017,8 @@ public extension Api {
return ("messageActionHistoryClear", []) return ("messageActionHistoryClear", [])
case .messageActionInviteToGroupCall(let call, let users): case .messageActionInviteToGroupCall(let call, let users):
return ("messageActionInviteToGroupCall", [("call", call as Any), ("users", users as Any)]) return ("messageActionInviteToGroupCall", [("call", call as Any), ("users", users as Any)])
case .messageActionPaymentSent(let flags, let currency, let totalAmount, let invoiceSlug, let charge): case .messageActionPaymentSent(let flags, let currency, let totalAmount, let invoiceSlug):
return ("messageActionPaymentSent", [("flags", flags as Any), ("currency", currency as Any), ("totalAmount", totalAmount as Any), ("invoiceSlug", invoiceSlug as Any), ("charge", charge as Any)]) return ("messageActionPaymentSent", [("flags", flags as Any), ("currency", currency as Any), ("totalAmount", totalAmount as Any), ("invoiceSlug", invoiceSlug as Any)])
case .messageActionPaymentSentMe(let flags, let currency, let totalAmount, let payload, let info, let shippingOptionId, let charge): case .messageActionPaymentSentMe(let flags, let currency, let totalAmount, let payload, let info, let shippingOptionId, let charge):
return ("messageActionPaymentSentMe", [("flags", flags as Any), ("currency", currency as Any), ("totalAmount", totalAmount as Any), ("payload", payload as Any), ("info", info as Any), ("shippingOptionId", shippingOptionId as Any), ("charge", charge as Any)]) return ("messageActionPaymentSentMe", [("flags", flags as Any), ("currency", currency as Any), ("totalAmount", totalAmount as Any), ("payload", payload as Any), ("info", info as Any), ("shippingOptionId", shippingOptionId as Any), ("charge", charge as Any)])
case .messageActionPhoneCall(let flags, let callId, let reason, let duration): case .messageActionPhoneCall(let flags, let callId, let reason, let duration):
@ -1396,17 +1395,12 @@ public extension Api {
_3 = reader.readInt64() _3 = reader.readInt64()
var _4: String? var _4: String?
if Int(_1!) & Int(1 << 0) != 0 {_4 = parseString(reader) } if Int(_1!) & Int(1 << 0) != 0 {_4 = parseString(reader) }
var _5: Api.PaymentCharge?
if Int(_1!) & Int(1 << 4) != 0 {if let signature = reader.readInt32() {
_5 = Api.parse(reader, signature: signature) as? Api.PaymentCharge
} }
let _c1 = _1 != nil let _c1 = _1 != nil
let _c2 = _2 != nil let _c2 = _2 != nil
let _c3 = _3 != nil let _c3 = _3 != nil
let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil
let _c5 = (Int(_1!) & Int(1 << 4) == 0) || _5 != nil if _c1 && _c2 && _c3 && _c4 {
if _c1 && _c2 && _c3 && _c4 && _c5 { return Api.MessageAction.messageActionPaymentSent(flags: _1!, currency: _2!, totalAmount: _3!, invoiceSlug: _4)
return Api.MessageAction.messageActionPaymentSent(flags: _1!, currency: _2!, totalAmount: _3!, invoiceSlug: _4, charge: _5)
} }
else { else {
return nil return nil

View File

@ -771,7 +771,7 @@ public extension Api.payments {
public extension Api.payments { public extension Api.payments {
enum PaymentReceipt: TypeConstructorDescription { 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 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]) case paymentReceiptStars(flags: Int32, date: Int32, botId: Int64, title: String, description: String, photo: Api.WebDocument?, invoice: Api.Invoice, currency: String, totalAmount: Int64, transactionId: String, users: [Api.User])
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self { switch self {
@ -799,9 +799,9 @@ public extension Api.payments {
item.serialize(buffer, true) item.serialize(buffer, true)
} }
break break
case .paymentReceiptStars(let flags, let date, let botId, let title, let description, let photo, let invoice, let currency, let totalAmount, let users): case .paymentReceiptStars(let flags, let date, let botId, let title, let description, let photo, let invoice, let currency, let totalAmount, let transactionId, let users):
if boxed { if boxed {
buffer.appendInt32(-319617530) buffer.appendInt32(-625215430)
} }
serializeInt32(flags, buffer: buffer, boxed: false) serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt32(date, buffer: buffer, boxed: false) serializeInt32(date, buffer: buffer, boxed: false)
@ -812,6 +812,7 @@ public extension Api.payments {
invoice.serialize(buffer, true) invoice.serialize(buffer, true)
serializeString(currency, buffer: buffer, boxed: false) serializeString(currency, buffer: buffer, boxed: false)
serializeInt64(totalAmount, buffer: buffer, boxed: false) serializeInt64(totalAmount, buffer: buffer, boxed: false)
serializeString(transactionId, buffer: buffer, boxed: false)
buffer.appendInt32(481674261) buffer.appendInt32(481674261)
buffer.appendInt32(Int32(users.count)) buffer.appendInt32(Int32(users.count))
for item in users { for item in users {
@ -825,8 +826,8 @@ public extension Api.payments {
switch self { 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): 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)]) 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): case .paymentReceiptStars(let flags, let date, let botId, let title, let description, let photo, let invoice, let currency, let totalAmount, let transactionId, 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)]) 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), ("transactionId", transactionId as Any), ("users", users as Any)])
} }
} }
@ -916,9 +917,11 @@ public extension Api.payments {
_8 = parseString(reader) _8 = parseString(reader)
var _9: Int64? var _9: Int64?
_9 = reader.readInt64() _9 = reader.readInt64()
var _10: [Api.User]? var _10: String?
_10 = parseString(reader)
var _11: [Api.User]?
if let _ = reader.readInt32() { if let _ = reader.readInt32() {
_10 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) _11 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
} }
let _c1 = _1 != nil let _c1 = _1 != nil
let _c2 = _2 != nil let _c2 = _2 != nil
@ -930,8 +933,9 @@ public extension Api.payments {
let _c8 = _8 != nil let _c8 = _8 != nil
let _c9 = _9 != nil let _c9 = _9 != nil
let _c10 = _10 != nil let _c10 = _10 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 { let _c11 = _11 != nil
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!) if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 {
return Api.payments.PaymentReceipt.paymentReceiptStars(flags: _1!, date: _2!, botId: _3!, title: _4!, description: _5!, photo: _6, invoice: _7!, currency: _8!, totalAmount: _9!, transactionId: _10!, users: _11!)
} }
else { else {
return nil return nil

View File

@ -40,18 +40,10 @@ func telegramMediaActionFromApiAction(_ action: Api.MessageAction) -> TelegramMe
return TelegramMediaAction(action: .phoneCall(callId: callId, discardReason: discardReason, duration: duration, isVideo: isVideo)) return TelegramMediaAction(action: .phoneCall(callId: callId, discardReason: discardReason, duration: duration, isVideo: isVideo))
case .messageActionEmpty: case .messageActionEmpty:
return nil return nil
case let .messageActionPaymentSent(flags, currency, totalAmount, invoiceSlug, charge): case let .messageActionPaymentSent(flags, currency, totalAmount, invoiceSlug):
let isRecurringInit = (flags & (1 << 2)) != 0 let isRecurringInit = (flags & (1 << 2)) != 0
let isRecurringUsed = (flags & (1 << 3)) != 0 let isRecurringUsed = (flags & (1 << 3)) != 0
return TelegramMediaAction(action: .paymentSent(currency: currency, totalAmount: totalAmount, invoiceSlug: invoiceSlug, isRecurringInit: isRecurringInit, isRecurringUsed: isRecurringUsed))
let chargeId: String?
switch charge {
case let .paymentCharge(id, _):
chargeId = id
default:
chargeId = nil
}
return TelegramMediaAction(action: .paymentSent(currency: currency, totalAmount: totalAmount, invoiceSlug: invoiceSlug, isRecurringInit: isRecurringInit, isRecurringUsed: isRecurringUsed, chargeId: chargeId))
case .messageActionPaymentSentMe: case .messageActionPaymentSentMe:
return nil return nil
case .messageActionScreenshotTaken: case .messageActionScreenshotTaken:

View File

@ -101,7 +101,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
case messageAutoremoveTimeoutUpdated(period: Int32, autoSettingSource: PeerId?) case messageAutoremoveTimeoutUpdated(period: Int32, autoSettingSource: PeerId?)
case gameScore(gameId: Int64, score: Int32) case gameScore(gameId: Int64, score: Int32)
case phoneCall(callId: Int64, discardReason: PhoneCallDiscardReason?, duration: Int32?, isVideo: Bool) case phoneCall(callId: Int64, discardReason: PhoneCallDiscardReason?, duration: Int32?, isVideo: Bool)
case paymentSent(currency: String, totalAmount: Int64, invoiceSlug: String?, isRecurringInit: Bool, isRecurringUsed: Bool, chargeId: String?) case paymentSent(currency: String, totalAmount: Int64, invoiceSlug: String?, isRecurringInit: Bool, isRecurringUsed: Bool)
case customText(text: String, entities: [MessageTextEntity], additionalAttributes: CustomTextAttributes?) case customText(text: String, entities: [MessageTextEntity], additionalAttributes: CustomTextAttributes?)
case botDomainAccessGranted(domain: String) case botDomainAccessGranted(domain: String)
case botAppAccessGranted(appName: String?, type: BotSendMessageAccessGrantedType?) case botAppAccessGranted(appName: String?, type: BotSendMessageAccessGrantedType?)
@ -164,7 +164,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
} }
self = .phoneCall(callId: decoder.decodeInt64ForKey("i", orElse: 0), discardReason: discardReason, duration: decoder.decodeInt32ForKey("d", orElse: 0), isVideo: decoder.decodeInt32ForKey("vc", orElse: 0) != 0) self = .phoneCall(callId: decoder.decodeInt64ForKey("i", orElse: 0), discardReason: discardReason, duration: decoder.decodeInt32ForKey("d", orElse: 0), isVideo: decoder.decodeInt32ForKey("vc", orElse: 0) != 0)
case 15: case 15:
self = .paymentSent(currency: decoder.decodeStringForKey("currency", orElse: ""), totalAmount: decoder.decodeInt64ForKey("ta", orElse: 0), invoiceSlug: decoder.decodeOptionalStringForKey("invoiceSlug"), isRecurringInit: decoder.decodeBoolForKey("isRecurringInit", orElse: false), isRecurringUsed: decoder.decodeBoolForKey("isRecurringUsed", orElse: false), chargeId: decoder.decodeOptionalStringForKey("chargeId")) self = .paymentSent(currency: decoder.decodeStringForKey("currency", orElse: ""), totalAmount: decoder.decodeInt64ForKey("ta", orElse: 0), invoiceSlug: decoder.decodeOptionalStringForKey("invoiceSlug"), isRecurringInit: decoder.decodeBoolForKey("isRecurringInit", orElse: false), isRecurringUsed: decoder.decodeBoolForKey("isRecurringUsed", orElse: false))
case 16: case 16:
self = .customText(text: decoder.decodeStringForKey("text", orElse: ""), entities: decoder.decodeObjectArrayWithDecoderForKey("ent"), additionalAttributes: nil) self = .customText(text: decoder.decodeStringForKey("text", orElse: ""), entities: decoder.decodeObjectArrayWithDecoderForKey("ent"), additionalAttributes: nil)
case 17: case 17:
@ -293,7 +293,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
encoder.encodeInt32(13, forKey: "_rawValue") encoder.encodeInt32(13, forKey: "_rawValue")
encoder.encodeInt64(gameId, forKey: "i") encoder.encodeInt64(gameId, forKey: "i")
encoder.encodeInt32(score, forKey: "s") encoder.encodeInt32(score, forKey: "s")
case let .paymentSent(currency, totalAmount, invoiceSlug, isRecurringInit, isRecurringUsed, chargeId): case let .paymentSent(currency, totalAmount, invoiceSlug, isRecurringInit, isRecurringUsed):
encoder.encodeInt32(15, forKey: "_rawValue") encoder.encodeInt32(15, forKey: "_rawValue")
encoder.encodeString(currency, forKey: "currency") encoder.encodeString(currency, forKey: "currency")
encoder.encodeInt64(totalAmount, forKey: "ta") encoder.encodeInt64(totalAmount, forKey: "ta")
@ -304,11 +304,6 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
} }
encoder.encodeBool(isRecurringInit, forKey: "isRecurringInit") encoder.encodeBool(isRecurringInit, forKey: "isRecurringInit")
encoder.encodeBool(isRecurringUsed, forKey: "isRecurringUsed") encoder.encodeBool(isRecurringUsed, forKey: "isRecurringUsed")
if let chargeId = chargeId {
encoder.encodeString(chargeId, forKey: "chargeId")
} else {
encoder.encodeNil(forKey: "chargeId")
}
case let .phoneCall(callId, discardReason, duration, isVideo): case let .phoneCall(callId, discardReason, duration, isVideo):
encoder.encodeInt32(14, forKey: "_rawValue") encoder.encodeInt32(14, forKey: "_rawValue")
encoder.encodeInt64(callId, forKey: "i") encoder.encodeInt64(callId, forKey: "i")

View File

@ -563,7 +563,7 @@ func _internal_sendBotPaymentForm(account: Account, formId: Int64, source: BotPa
switch source { switch source {
case let .slug(slug): case let .slug(slug):
for media in message.media { for media in message.media {
if let action = media as? TelegramMediaAction, case let .paymentSent(_, _, invoiceSlug?, _, _, _) = action.action, invoiceSlug == slug { if let action = media as? TelegramMediaAction, case let .paymentSent(_, _, invoiceSlug?, _, _) = action.action, invoiceSlug == slug {
if case let .Id(id) = message.id { if case let .Id(id) = message.id {
receiptMessageId = id receiptMessageId = id
} }
@ -615,16 +615,22 @@ func _internal_sendBotPaymentForm(account: Account, formId: Int64, source: BotPa
public struct BotPaymentReceipt : Equatable { public struct BotPaymentReceipt : Equatable {
public let invoice: BotPaymentInvoice public let invoice: BotPaymentInvoice
public let date: Int32
public let info: BotPaymentRequestedInfo? public let info: BotPaymentRequestedInfo?
public let shippingOption: BotPaymentShippingOption? public let shippingOption: BotPaymentShippingOption?
public let credentialsTitle: String public let credentialsTitle: String
public let invoiceMedia: TelegramMediaInvoice public let invoiceMedia: TelegramMediaInvoice
public let tipAmount: Int64? public let tipAmount: Int64?
public let botPaymentId: PeerId public let botPaymentId: PeerId
public let transactionId: String?
public static func ==(lhs: BotPaymentReceipt, rhs: BotPaymentReceipt) -> Bool { public static func ==(lhs: BotPaymentReceipt, rhs: BotPaymentReceipt) -> Bool {
if lhs.invoice != rhs.invoice { if lhs.invoice != rhs.invoice {
return false return false
} }
if lhs.date != rhs.date {
return false
}
if lhs.info != rhs.info { if lhs.info != rhs.info {
return false return false
} }
@ -643,6 +649,9 @@ public struct BotPaymentReceipt : Equatable {
if lhs.botPaymentId != rhs.botPaymentId { if lhs.botPaymentId != rhs.botPaymentId {
return false return false
} }
if lhs.transactionId != rhs.transactionId {
return false
}
return true return true
} }
} }
@ -669,7 +678,7 @@ func _internal_requestBotPaymentReceipt(account: Account, messageId: MessageId)
|> mapToSignal { result -> Signal<BotPaymentReceipt, RequestBotPaymentReceiptError> in |> mapToSignal { result -> Signal<BotPaymentReceipt, RequestBotPaymentReceiptError> in
return account.postbox.transaction { transaction -> BotPaymentReceipt in return account.postbox.transaction { transaction -> BotPaymentReceipt in
switch result { switch result {
case let .paymentReceipt(_, _, botId, _, title, description, photo, invoice, info, shipping, tipAmount, currency, totalAmount, credentialsTitle, users): case let .paymentReceipt(_, date, botId, _, title, description, photo, invoice, info, shipping, tipAmount, currency, totalAmount, credentialsTitle, users):
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: [], users: users) let parsedPeers = AccumulatedPeers(transaction: transaction, chats: [], users: users)
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers) updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
@ -692,8 +701,8 @@ func _internal_requestBotPaymentReceipt(account: Account, messageId: MessageId)
let botPaymentId = PeerId.init(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(botId)) 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) return BotPaymentReceipt(invoice: parsedInvoice, date: date, info: parsedInfo, shippingOption: shippingOption, credentialsTitle: credentialsTitle, invoiceMedia: invoiceMedia, tipAmount: tipAmount, botPaymentId: botPaymentId, transactionId: nil)
case let .paymentReceiptStars(_, _, botId, title, description, photo, invoice, currency, totalAmount, users: users): case let .paymentReceiptStars(_, date, botId, title, description, photo, invoice, currency, totalAmount, transactionId, users):
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: [], users: users) let parsedPeers = AccumulatedPeers(transaction: transaction, chats: [], users: users)
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers) updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
@ -713,7 +722,7 @@ func _internal_requestBotPaymentReceipt(account: Account, messageId: MessageId)
) )
let botPaymentId = PeerId.init(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(botId)) 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) return BotPaymentReceipt(invoice: parsedInvoice, date: date, info: nil, shippingOption: nil, credentialsTitle: "", invoiceMedia: invoiceMedia, tipAmount: nil, botPaymentId: botPaymentId, transactionId: transactionId)
} }
} }
|> castError(RequestBotPaymentReceiptError.self) |> castError(RequestBotPaymentReceiptError.self)

View File

@ -366,7 +366,7 @@ func _internal_sendStarsPaymentForm(account: Account, formId: Int64, source: Bot
switch source { switch source {
case let .slug(slug): case let .slug(slug):
for media in message.media { for media in message.media {
if let action = media as? TelegramMediaAction, case let .paymentSent(_, _, invoiceSlug?, _, _, _) = action.action, invoiceSlug == slug { if let action = media as? TelegramMediaAction, case let .paymentSent(_, _, invoiceSlug?, _, _) = action.action, invoiceSlug == slug {
if case let .Id(id) = message.id { if case let .Id(id) = message.id {
receiptMessageId = id receiptMessageId = id
} }

View File

@ -496,7 +496,7 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
var argumentAttributes = peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: [(0, message.author?.id)]) var argumentAttributes = peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: [(0, message.author?.id)])
argumentAttributes[1] = MarkdownAttributeSet(font: titleBoldFont, textColor: primaryTextColor, additionalAttributes: [:]) argumentAttributes[1] = MarkdownAttributeSet(font: titleBoldFont, textColor: primaryTextColor, additionalAttributes: [:])
attributedString = addAttributesToStringWithRanges(formatWithArgumentRanges(baseString, ranges, [authorName, gameTitle ?? ""]), body: bodyAttributes, argumentAttributes: argumentAttributes) attributedString = addAttributesToStringWithRanges(formatWithArgumentRanges(baseString, ranges, [authorName, gameTitle ?? ""]), body: bodyAttributes, argumentAttributes: argumentAttributes)
case let .paymentSent(currency, totalAmount, _, isRecurringInit, isRecurringUsed, _): case let .paymentSent(currency, totalAmount, _, isRecurringInit, isRecurringUsed):
var invoiceMessage: EngineMessage? var invoiceMessage: EngineMessage?
for attribute in message.attributes { for attribute in message.attributes {
if let attribute = attribute as? ReplyMessageAttribute, let message = message.associatedMessages[attribute.messageId] { if let attribute = attribute as? ReplyMessageAttribute, let message = message.associatedMessages[attribute.messageId] {

View File

@ -19,6 +19,7 @@ swift_library(
"//submodules/GZip", "//submodules/GZip",
"//submodules/LegacyComponents", "//submodules/LegacyComponents",
"//submodules/AvatarNode", "//submodules/AvatarNode",
"//submodules/PhotoResources",
"//submodules/TelegramUI/Components/Chat/MergedAvatarsNode", "//submodules/TelegramUI/Components/Chat/MergedAvatarsNode",
"//submodules/Components/MultilineTextComponent:MultilineTextComponent", "//submodules/Components/MultilineTextComponent:MultilineTextComponent",
], ],

View File

@ -13,6 +13,7 @@ import TelegramCore
import MergedAvatarsNode import MergedAvatarsNode
import MultilineTextComponent import MultilineTextComponent
import TelegramPresentationData import TelegramPresentationData
import PhotoResources
private let sceneVersion: Int = 1 private let sceneVersion: Int = 1
@ -73,6 +74,7 @@ public final class GiftAvatarComponent: Component {
private let sceneView: SCNView private let sceneView: SCNView
private let avatarNode: ImageNode private let avatarNode: ImageNode
private var mergedAvatarsNode: MergedAvatarsNode? private var mergedAvatarsNode: MergedAvatarsNode?
private var imageNode: TransformImageNode?
private let badgeBackground = ComponentView<Empty>() private let badgeBackground = ComponentView<Empty>()
private let badge = ComponentView<Empty>() private let badge = ComponentView<Empty>()
@ -81,6 +83,8 @@ public final class GiftAvatarComponent: Component {
private var timer: SwiftSignalKit.Timer? private var timer: SwiftSignalKit.Timer?
private var hasIdleAnimations = false private var hasIdleAnimations = false
private let fetchDisposable = MetaDisposable()
public override init(frame: CGRect) { public override init(frame: CGRect) {
self.sceneView = SCNView(frame: CGRect(origin: .zero, size: CGSize(width: 64.0, height: 64.0))) self.sceneView = SCNView(frame: CGRect(origin: .zero, size: CGSize(width: 64.0, height: 64.0)))
self.sceneView.backgroundColor = .clear self.sceneView.backgroundColor = .clear
@ -109,6 +113,7 @@ public final class GiftAvatarComponent: Component {
deinit { deinit {
self.timer?.invalidate() self.timer?.invalidate()
self.fetchDisposable.dispose()
} }
private let hapticFeedback = HapticFeedback() private let hapticFeedback = HapticFeedback()
@ -297,7 +302,26 @@ public final class GiftAvatarComponent: Component {
self.hasIdleAnimations = component.hasIdleAnimations self.hasIdleAnimations = component.hasIdleAnimations
if component.peers.count > 1 { if let photo = component.photo {
let imageNode: TransformImageNode
if let current = self.imageNode {
imageNode = current
} else {
imageNode = TransformImageNode()
self.addSubview(imageNode.view)
self.imageNode = imageNode
imageNode.setSignal(chatWebFileImage(account: component.context.account, file: photo))
self.fetchDisposable.set(chatMessageWebFileInteractiveFetched(account: component.context.account, userLocation: .other, image: photo).startStrict())
}
let imageSize = CGSize(width: component.avatarSize, height: component.avatarSize)
imageNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((availableSize.width - imageSize.width) / 2.0), y: 113.0 - imageSize.height / 2.0), size: imageSize)
imageNode.asyncLayout()(TransformImageArguments(corners: ImageCorners(radius: imageSize.width / 2.0), imageSize: imageSize, boundingSize: imageSize, intrinsicInsets: UIEdgeInsets()))()
self.avatarNode.isHidden = true
} else if component.peers.count > 1 {
let avatarSize = CGSize(width: 60.0, height: 60.0) let avatarSize = CGSize(width: 60.0, height: 60.0)
let mergedAvatarsNode: MergedAvatarsNode let mergedAvatarsNode: MergedAvatarsNode

View File

@ -293,23 +293,23 @@ public final class PremiumStarComponent: Component {
self.sceneView.scene = scene self.sceneView.scene = scene
self.sceneView.delegate = self self.sceneView.delegate = self
if let node = scene.rootNode.childNode(withName: "star", recursively: false), let colors = self.component?.colors, let _ = colors.first { if let node = scene.rootNode.childNode(withName: "star", recursively: false), let colors = self.component?.colors, let color = colors.first {
node.geometry?.materials.first?.diffuse.contents = generateDiffuseTexture(colors: colors) node.geometry?.materials.first?.diffuse.contents = generateDiffuseTexture(colors: colors)
// let names: [String] = [ let names: [String] = [
// "particles_left", "particles_left",
// "particles_right", "particles_right",
// "particles_left_bottom", "particles_left_bottom",
// "particles_right_bottom", "particles_right_bottom",
// "particles_center" "particles_center"
// ] ]
//
// for name in names { for name in names {
// if let node = scene.rootNode.childNode(withName: name, recursively: false), let particleSystem = node.particleSystems?.first { if let node = scene.rootNode.childNode(withName: name, recursively: false), let particleSystem = node.particleSystems?.first {
// particleSystem.particleColor = color particleSystem.particleColor = color
// particleSystem.particleColorVariation = SCNVector4Make(0, 0, 0, 0) particleSystem.particleColorVariation = SCNVector4Make(0, 0, 0, 0)
// } }
// } }
} }
if self.animateFrom != nil { if self.animateFrom != nil {

View File

@ -42,7 +42,17 @@ private struct StarsProduct: Equatable {
private final class StarsPurchaseScreenContentComponent: CombinedComponent { private final class StarsPurchaseScreenContentComponent: CombinedComponent {
typealias EnvironmentType = (ViewControllerComponentContainer.Environment, ScrollChildEnvironment) typealias EnvironmentType = (ViewControllerComponentContainer.Environment, ScrollChildEnvironment)
public class ExternalState {
public var descriptionHeight: CGFloat = 0.0
public init() {
}
}
let context: AccountContext let context: AccountContext
let externalState: ExternalState
let containerSize: CGSize
let options: [StarsTopUpOption] let options: [StarsTopUpOption]
let peerId: EnginePeer.Id? let peerId: EnginePeer.Id?
let requiredStars: Int64? let requiredStars: Int64?
@ -55,6 +65,8 @@ private final class StarsPurchaseScreenContentComponent: CombinedComponent {
init( init(
context: AccountContext, context: AccountContext,
externalState: ExternalState,
containerSize: CGSize,
options: [StarsTopUpOption], options: [StarsTopUpOption],
peerId: EnginePeer.Id?, peerId: EnginePeer.Id?,
requiredStars: Int64?, requiredStars: Int64?,
@ -66,6 +78,8 @@ private final class StarsPurchaseScreenContentComponent: CombinedComponent {
buy: @escaping (StarsProduct) -> Void buy: @escaping (StarsProduct) -> Void
) { ) {
self.context = context self.context = context
self.externalState = externalState
self.containerSize = containerSize
self.options = options self.options = options
self.peerId = peerId self.peerId = peerId
self.requiredStars = requiredStars self.requiredStars = requiredStars
@ -81,6 +95,9 @@ private final class StarsPurchaseScreenContentComponent: CombinedComponent {
if lhs.context !== rhs.context { if lhs.context !== rhs.context {
return false return false
} }
if lhs.containerSize != rhs.containerSize {
return false
}
if lhs.options != rhs.options { if lhs.options != rhs.options {
return false return false
} }
@ -252,6 +269,8 @@ private final class StarsPurchaseScreenContentComponent: CombinedComponent {
size.height += text.size.height size.height += text.size.height
size.height += 21.0 size.height += 21.0
context.component.externalState.descriptionHeight = text.size.height
let initialValues: [Int64] = [ let initialValues: [Int64] = [
15, 15,
75, 75,
@ -444,6 +463,10 @@ private final class StarsPurchaseScreenContentComponent: CombinedComponent {
size.height += scrollEnvironment.insets.bottom size.height += scrollEnvironment.insets.bottom
if context.component.expanded {
size.height = max(size.height, component.containerSize.height + 150.0 + text.size.height)
}
return size return size
} }
} }
@ -677,6 +700,8 @@ private final class StarsPurchaseScreenComponent: CombinedComponent {
let scrollAction = ActionSlot<CGPoint?>() let scrollAction = ActionSlot<CGPoint?>()
let contentExternalState = StarsPurchaseScreenContentComponent.ExternalState()
return { context in return { context in
let environment = context.environment[EnvironmentType.self].value let environment = context.environment[EnvironmentType.self].value
let state = context.state let state = context.state
@ -773,6 +798,8 @@ private final class StarsPurchaseScreenComponent: CombinedComponent {
component: ScrollComponent<EnvironmentType>( component: ScrollComponent<EnvironmentType>(
content: AnyComponent(StarsPurchaseScreenContentComponent( content: AnyComponent(StarsPurchaseScreenContentComponent(
context: context.component.context, context: context.component.context,
externalState: contentExternalState,
containerSize: context.availableSize,
options: context.component.options, options: context.component.options,
peerId: context.component.peerId, peerId: context.component.peerId,
requiredStars: context.component.requiredStars, requiredStars: context.component.requiredStars,
@ -781,7 +808,7 @@ private final class StarsPurchaseScreenComponent: CombinedComponent {
products: state.products, products: state.products,
expanded: state.isExpanded, expanded: state.isExpanded,
stateUpdated: { [weak state] transition in stateUpdated: { [weak state] transition in
scrollAction.invoke(CGPoint(x: 0.0, y: 170.0)) scrollAction.invoke(CGPoint(x: 0.0, y: 150.0 + contentExternalState.descriptionHeight))
state?.isExpanded = true state?.isExpanded = true
state?.updated(transition: transition) state?.updated(transition: transition)
}, },
@ -798,10 +825,11 @@ private final class StarsPurchaseScreenComponent: CombinedComponent {
} }
}, },
contentOffsetWillCommit: { targetContentOffset in contentOffsetWillCommit: { targetContentOffset in
let anchorOffset = 150.0 + contentExternalState.descriptionHeight
if targetContentOffset.pointee.y < 100.0 { if targetContentOffset.pointee.y < 100.0 {
targetContentOffset.pointee = CGPoint(x: 0.0, y: 0.0) targetContentOffset.pointee = CGPoint(x: 0.0, y: 0.0)
} else if targetContentOffset.pointee.y < 170.0 { } else if targetContentOffset.pointee.y < anchorOffset {
targetContentOffset.pointee = CGPoint(x: 0.0, y: 170.0) targetContentOffset.pointee = CGPoint(x: 0.0, y: anchorOffset)
} }
}, },
resetScroll: scrollAction resetScroll: scrollAction

View File

@ -79,7 +79,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
if case let .peer(peer) = transaction.peer { if case let .peer(peer) = transaction.peer {
peerIds.append(peer.id) peerIds.append(peer.id)
} }
case let .receipt(receipt, _, _): case let .receipt(receipt):
peerIds.append(receipt.botPaymentId) peerIds.append(receipt.botPaymentId)
} }
@ -194,11 +194,11 @@ private final class StarsTransactionSheetContent: CombinedComponent {
toPeer = nil toPeer = nil
} }
photo = transaction.photo photo = transaction.photo
case let .receipt(receipt, id, dateValue): case let .receipt(receipt):
titleText = receipt.invoiceMedia.title titleText = receipt.invoiceMedia.title
count = (receipt.invoice.prices.first?.amount ?? receipt.invoiceMedia.totalAmount) * -1 count = (receipt.invoice.prices.first?.amount ?? receipt.invoiceMedia.totalAmount) * -1
transactionId = id transactionId = receipt.transactionId
date = dateValue date = receipt.date
if let peer = state.peerMap[receipt.botPaymentId] { if let peer = state.peerMap[receipt.botPaymentId] {
toPeer = peer toPeer = peer
} else { } else {
@ -485,7 +485,12 @@ private final class StarsTransactionSheetComponent: CombinedComponent {
followContentSizeChanges: true, followContentSizeChanges: true,
clipsContent: true, clipsContent: true,
externalState: sheetExternalState, externalState: sheetExternalState,
animateOut: animateOut animateOut: animateOut,
onPan: {
if let controller = controller() as? StarsTransactionScreen {
controller.dismissAllTooltips()
}
}
), ),
environment: { environment: {
environment environment
@ -543,7 +548,7 @@ private final class StarsTransactionSheetComponent: CombinedComponent {
public class StarsTransactionScreen: ViewControllerComponentContainer { public class StarsTransactionScreen: ViewControllerComponentContainer {
public enum Subject: Equatable { public enum Subject: Equatable {
case transaction(StarsContext.State.Transaction) case transaction(StarsContext.State.Transaction)
case receipt(receipt: BotPaymentReceipt, id: String?, date: Int32) case receipt(BotPaymentReceipt)
} }
private let context: AccountContext private let context: AccountContext

View File

@ -211,53 +211,75 @@ final class StarsTransactionsListPanelComponent: Component {
let fontBaseDisplaySize = 17.0 let fontBaseDisplaySize = 17.0
let itemTitle: String let itemTitle: String
let itemSubtitle: String let itemSubtitle: String?
let itemDate: String
let itemLabel: NSAttributedString let itemLabel: NSAttributedString
switch item.transaction.peer { switch item.transaction.peer {
case let .peer(peer): case let .peer(peer):
itemTitle = peer.displayTitle(strings: environment.strings, displayOrder: .firstLast) itemTitle = peer.displayTitle(strings: environment.strings, displayOrder: .firstLast)
itemSubtitle = item.transaction.title
itemLabel = NSAttributedString(string: "- \(item.transaction.count * -1)", font: Font.medium(fontBaseDisplaySize), textColor: environment.theme.list.itemDestructiveColor) itemLabel = NSAttributedString(string: "- \(item.transaction.count * -1)", font: Font.medium(fontBaseDisplaySize), textColor: environment.theme.list.itemDestructiveColor)
case .appStore: case .appStore:
itemTitle = "In-App Purchase" itemTitle = "Stars Top-Up"
itemSubtitle = "via App Store"
itemLabel = NSAttributedString(string: "+ \(item.transaction.count)", font: Font.medium(fontBaseDisplaySize), textColor: environment.theme.list.itemDisclosureActions.constructive.fillColor) itemLabel = NSAttributedString(string: "+ \(item.transaction.count)", font: Font.medium(fontBaseDisplaySize), textColor: environment.theme.list.itemDisclosureActions.constructive.fillColor)
case .playMarket: case .playMarket:
itemTitle = "Play Market" itemTitle = "Stars Top-Up"
itemSubtitle = "via Play Market"
itemLabel = NSAttributedString(string: "+ \(item.transaction.count)", font: Font.medium(fontBaseDisplaySize), textColor: environment.theme.list.itemDisclosureActions.constructive.fillColor) itemLabel = NSAttributedString(string: "+ \(item.transaction.count)", font: Font.medium(fontBaseDisplaySize), textColor: environment.theme.list.itemDisclosureActions.constructive.fillColor)
case .fragment: case .fragment:
itemTitle = "Fragment" itemTitle = "Stars Top-Up"
itemSubtitle = "via Fragment"
itemLabel = NSAttributedString(string: "+ \(item.transaction.count)", font: Font.medium(fontBaseDisplaySize), textColor: environment.theme.list.itemDisclosureActions.constructive.fillColor) itemLabel = NSAttributedString(string: "+ \(item.transaction.count)", font: Font.medium(fontBaseDisplaySize), textColor: environment.theme.list.itemDisclosureActions.constructive.fillColor)
case .premiumBot: case .premiumBot:
itemTitle = "Premium Bot" itemTitle = "Stars Top-Up"
itemSubtitle = "via Premium Bot"
itemLabel = NSAttributedString(string: "+ \(item.transaction.count)", font: Font.medium(fontBaseDisplaySize), textColor: environment.theme.list.itemDisclosureActions.constructive.fillColor) itemLabel = NSAttributedString(string: "+ \(item.transaction.count)", font: Font.medium(fontBaseDisplaySize), textColor: environment.theme.list.itemDisclosureActions.constructive.fillColor)
case .unsupported: case .unsupported:
itemTitle = "Unsupported" itemTitle = "Unsupported"
itemSubtitle = nil
itemLabel = NSAttributedString(string: "+ \(item.transaction.count)", font: Font.medium(fontBaseDisplaySize), textColor: environment.theme.list.itemDisclosureActions.constructive.fillColor) itemLabel = NSAttributedString(string: "+ \(item.transaction.count)", font: Font.medium(fontBaseDisplaySize), textColor: environment.theme.list.itemDisclosureActions.constructive.fillColor)
} }
itemSubtitle = stringForMediumCompactDate(timestamp: item.transaction.date, strings: environment.strings, dateTimeFormat: environment.dateTimeFormat) itemDate = stringForMediumCompactDate(timestamp: item.transaction.date, strings: environment.strings, dateTimeFormat: environment.dateTimeFormat)
var titleComponents: [AnyComponentWithIdentity<Empty>] = []
titleComponents.append(
AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: itemTitle,
font: Font.semibold(fontBaseDisplaySize),
textColor: environment.theme.list.itemPrimaryTextColor
)),
maximumNumberOfLines: 1
)))
)
if let itemSubtitle {
titleComponents.append(
AnyComponentWithIdentity(id: AnyHashable(1), component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: itemSubtitle,
font: Font.regular(fontBaseDisplaySize),
textColor: environment.theme.list.itemPrimaryTextColor
)),
maximumNumberOfLines: 1
)))
)
}
titleComponents.append(
AnyComponentWithIdentity(id: AnyHashable(2), component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: itemDate,
font: Font.regular(floor(fontBaseDisplaySize * 14.0 / 17.0)),
textColor: environment.theme.list.itemSecondaryTextColor
)),
maximumNumberOfLines: 1
)))
)
let _ = itemView.update( let _ = itemView.update(
transition: itemTransition, transition: itemTransition,
component: AnyComponent(ListActionItemComponent( component: AnyComponent(ListActionItemComponent(
theme: environment.theme, theme: environment.theme,
title: AnyComponent(VStack([ title: AnyComponent(VStack(titleComponents, alignment: .left, spacing: 2.0)),
AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: itemTitle,
font: Font.semibold(fontBaseDisplaySize),
textColor: environment.theme.list.itemPrimaryTextColor
)),
maximumNumberOfLines: 0
))),
AnyComponentWithIdentity(id: AnyHashable(1), component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: itemSubtitle,
font: Font.regular(floor(fontBaseDisplaySize * 15.0 / 17.0)),
textColor: environment.theme.list.itemSecondaryTextColor
)),
maximumNumberOfLines: 0,
lineSpacing: 0.18
)))
], alignment: .left, spacing: 3.0)),
contentInsets: UIEdgeInsets(top: 9.0, left: 0.0, bottom: 8.0, right: 0.0), contentInsets: UIEdgeInsets(top: 9.0, left: 0.0, bottom: 8.0, right: 0.0),
leftIcon: .custom(AnyComponentWithIdentity(id: "avatar", component: AnyComponent(AvatarComponent(context: component.context, theme: environment.theme, peer: item.transaction.peer))), false), leftIcon: .custom(AnyComponentWithIdentity(id: "avatar", component: AnyComponent(AvatarComponent(context: component.context, theme: environment.theme, peer: item.transaction.peer))), false),
icon: nil, icon: nil,
@ -330,13 +352,21 @@ final class StarsTransactionsListPanelComponent: Component {
AnyComponentWithIdentity(id: AnyHashable(1), component: AnyComponent(MultilineTextComponent( AnyComponentWithIdentity(id: AnyHashable(1), component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString( text: .plain(NSAttributedString(
string: "abc", string: "abc",
font: Font.regular(floor(fontBaseDisplaySize * 15.0 / 17.0)), font: Font.regular(fontBaseDisplaySize),
textColor: environment.theme.list.itemPrimaryTextColor
)),
maximumNumberOfLines: 1
))),
AnyComponentWithIdentity(id: AnyHashable(2), component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: "abc",
font: Font.regular(floor(fontBaseDisplaySize * 14.0 / 17.0)),
textColor: environment.theme.list.itemSecondaryTextColor textColor: environment.theme.list.itemSecondaryTextColor
)), )),
maximumNumberOfLines: 0, maximumNumberOfLines: 0,
lineSpacing: 0.18 lineSpacing: 0.18
))) )))
], alignment: .left, spacing: 3.0)), ], alignment: .left, spacing: 2.0)),
contentInsets: UIEdgeInsets(top: 9.0, left: 0.0, bottom: 8.0, right: 0.0), contentInsets: UIEdgeInsets(top: 9.0, left: 0.0, bottom: 8.0, right: 0.0),
leftIcon: nil, leftIcon: nil,
icon: nil, icon: nil,
@ -441,7 +471,7 @@ private final class AvatarComponent: Component {
super.init(frame: frame) super.init(frame: frame)
self.iconView.contentMode = .center self.iconView.contentMode = .center
self.iconView.image = UIImage(bundleImageName: "Premium/Stars/TopUp") self.iconView.image = UIImage(bundleImageName: "Premium/Stars/Apple")
self.addSubnode(self.avatarNode) self.addSubnode(self.avatarNode)
self.addSubview(self.backgroundView) self.addSubview(self.backgroundView)
@ -458,7 +488,7 @@ private final class AvatarComponent: Component {
let size = CGSize(width: 40.0, height: 40.0) let size = CGSize(width: 40.0, height: 40.0)
let gradientImage = generateGradientFilledCircleImage(diameter: size.width, colors: [UIColor(rgb: 0xf67447).cgColor, UIColor(rgb: 0xfdbe1c).cgColor], direction: .mirroredDiagonal) let gradientImage = generateGradientFilledCircleImage(diameter: size.width, colors: [UIColor(rgb: 0x2a9ef1).cgColor, UIColor(rgb: 0x72d5fd).cgColor], direction: .mirroredDiagonal)
switch component.peer { switch component.peer {
case let .peer(peer): case let .peer(peer):

View File

@ -1041,14 +1041,14 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
if canSetupAutoremoveTimeout { if canSetupAutoremoveTimeout {
strongSelf.presentAutoremoveSetup() strongSelf.presentAutoremoveSetup()
} }
case let .paymentSent(currency, _, _, _, _, id): case let .paymentSent(currency, _, _, _, _):
if currency == "XTR" { if currency == "XTR" {
let _ = (context.engine.payments.requestBotPaymentReceipt(messageId: message.id) let _ = (context.engine.payments.requestBotPaymentReceipt(messageId: message.id)
|> deliverOnMainQueue).start(next: { [weak self] receipt in |> deliverOnMainQueue).start(next: { [weak self] receipt in
guard let self else { guard let self else {
return return
} }
self.push(self.context.sharedContext.makeStarsReceiptScreen(context: self.context, receipt: receipt, id: id, date: message.timestamp)) self.push(self.context.sharedContext.makeStarsReceiptScreen(context: self.context, receipt: receipt))
}) })
} else { } else {
strongSelf.present(BotReceiptController(context: strongSelf.context, messageId: message.id), in: .window(.root), with: ViewControllerPresentationArguments(presentationAnimation: .modalSheet)) strongSelf.present(BotReceiptController(context: strongSelf.context, messageId: message.id), in: .window(.root), with: ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
@ -2929,7 +2929,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
guard let strongSelf = self else { guard let strongSelf = self else {
return return
} }
strongSelf.push(strongSelf.context.sharedContext.makeStarsReceiptScreen(context: strongSelf.context, receipt: receipt, id: nil, date: 0)) strongSelf.push(strongSelf.context.sharedContext.makeStarsReceiptScreen(context: strongSelf.context, receipt: receipt))
}) })
} else { } else {
strongSelf.present(BotReceiptController(context: strongSelf.context, messageId: receiptMessageId), in: .window(.root), with: ViewControllerPresentationArguments(presentationAnimation: .modalSheet)) strongSelf.present(BotReceiptController(context: strongSelf.context, messageId: receiptMessageId), in: .window(.root), with: ViewControllerPresentationArguments(presentationAnimation: .modalSheet))

View File

@ -1714,7 +1714,8 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
} }
if canAddFactCheck { if canAddFactCheck {
let hasFactCheck = message.factCheckAttribute != nil let sortedMessages = messages.sorted(by: { $0.id < $1.id })
let hasFactCheck = sortedMessages[0].factCheckAttribute != nil
let title: String let title: String
if hasFactCheck { if hasFactCheck {
title = chatPresentationInterfaceState.strings.Conversation_ContextMenuEditFactCheck title = chatPresentationInterfaceState.strings.Conversation_ContextMenuEditFactCheck
@ -1725,7 +1726,7 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/FactCheck"), color: theme.actionSheet.primaryTextColor) return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/FactCheck"), color: theme.actionSheet.primaryTextColor)
}, action: { c, f in }, action: { c, f in
c?.dismiss(completion: { c?.dismiss(completion: {
controllerInteraction.editMessageFactCheck(messages[0].id) controllerInteraction.editMessageFactCheck(sortedMessages[0].id)
}) })
}))) })))
} }

View File

@ -2635,8 +2635,8 @@ public final class SharedAccountContextImpl: SharedAccountContext {
return StarsTransactionScreen(context: context, subject: .transaction(transaction), action: {}) return StarsTransactionScreen(context: context, subject: .transaction(transaction), action: {})
} }
public func makeStarsReceiptScreen(context: AccountContext, receipt: BotPaymentReceipt, id: String?, date: Int32) -> ViewController { public func makeStarsReceiptScreen(context: AccountContext, receipt: BotPaymentReceipt) -> ViewController {
return StarsTransactionScreen(context: context, subject: .receipt(receipt: receipt, id: id, date: date), action: {}) return StarsTransactionScreen(context: context, subject: .receipt(receipt), action: {})
} }
} }