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 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 makeStarsReceiptScreen(context: AccountContext, receipt: BotPaymentReceipt, id: String?, date: Int32) -> ViewController
func makeStarsReceiptScreen(context: AccountContext, receipt: BotPaymentReceipt) -> 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 externalState: ExternalState?
public let animateOut: ActionSlot<Action<()>>
public let onPan: () -> Void
public init(
content: AnyComponent<ChildEnvironmentType>,
@ -72,7 +73,8 @@ public final class SheetComponent<ChildEnvironmentType: Equatable>: Component {
followContentSizeChanges: Bool = false,
clipsContent: Bool = false,
externalState: ExternalState? = nil,
animateOut: ActionSlot<Action<()>>
animateOut: ActionSlot<Action<()>>,
onPan: @escaping () -> Void = {}
) {
self.content = content
self.backgroundColor = backgroundColor
@ -80,6 +82,7 @@ public final class SheetComponent<ChildEnvironmentType: Equatable>: Component {
self.clipsContent = clipsContent
self.externalState = externalState
self.animateOut = animateOut
self.onPan = onPan
}
public static func ==(lhs: SheetComponent, rhs: SheetComponent) -> Bool {
@ -128,6 +131,8 @@ public final class SheetComponent<ChildEnvironmentType: Equatable>: Component {
return false
}
private var component: SheetComponent<ChildEnvironmentType>?
private let dimView: UIView
private let scrollView: ScrollView
private let backgroundView: UIView
@ -199,6 +204,10 @@ public final class SheetComponent<ChildEnvironmentType: Equatable>: Component {
self.dismiss?(true)
}
public func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
self.component?.onPan()
}
private var scrollingOut = false
public func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
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
switch component.backgroundColor {

View File

@ -545,7 +545,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-1281329567] = { return Api.MessageAction.parse_messageActionGroupCallScheduled($0) }
dict[-1615153660] = { return Api.MessageAction.parse_messageActionHistoryClear($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[-2132731265] = { return Api.MessageAction.parse_messageActionPhoneCall($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[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[-625215430] = { 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) }

View File

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

View File

@ -771,7 +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])
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) {
switch self {
@ -799,9 +799,9 @@ 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):
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 {
buffer.appendInt32(-319617530)
buffer.appendInt32(-625215430)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt32(date, buffer: buffer, boxed: false)
@ -812,6 +812,7 @@ public extension Api.payments {
invoice.serialize(buffer, true)
serializeString(currency, buffer: buffer, boxed: false)
serializeInt64(totalAmount, buffer: buffer, boxed: false)
serializeString(transactionId, buffer: buffer, boxed: false)
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(users.count))
for item in users {
@ -825,8 +826,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)])
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), ("transactionId", transactionId as Any), ("users", users as Any)])
}
}
@ -916,9 +917,11 @@ public extension Api.payments {
_8 = parseString(reader)
var _9: Int64?
_9 = reader.readInt64()
var _10: [Api.User]?
var _10: String?
_10 = parseString(reader)
var _11: [Api.User]?
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 _c2 = _2 != nil
@ -930,8 +933,9 @@ public extension Api.payments {
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!)
let _c11 = _11 != nil
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 {
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))
case .messageActionEmpty:
return nil
case let .messageActionPaymentSent(flags, currency, totalAmount, invoiceSlug, charge):
case let .messageActionPaymentSent(flags, currency, totalAmount, invoiceSlug):
let isRecurringInit = (flags & (1 << 2)) != 0
let isRecurringUsed = (flags & (1 << 3)) != 0
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))
return TelegramMediaAction(action: .paymentSent(currency: currency, totalAmount: totalAmount, invoiceSlug: invoiceSlug, isRecurringInit: isRecurringInit, isRecurringUsed: isRecurringUsed))
case .messageActionPaymentSentMe:
return nil
case .messageActionScreenshotTaken:

View File

@ -101,7 +101,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
case messageAutoremoveTimeoutUpdated(period: Int32, autoSettingSource: PeerId?)
case gameScore(gameId: Int64, score: Int32)
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 botDomainAccessGranted(domain: String)
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)
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:
self = .customText(text: decoder.decodeStringForKey("text", orElse: ""), entities: decoder.decodeObjectArrayWithDecoderForKey("ent"), additionalAttributes: nil)
case 17:
@ -293,7 +293,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
encoder.encodeInt32(13, forKey: "_rawValue")
encoder.encodeInt64(gameId, forKey: "i")
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.encodeString(currency, forKey: "currency")
encoder.encodeInt64(totalAmount, forKey: "ta")
@ -304,11 +304,6 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
}
encoder.encodeBool(isRecurringInit, forKey: "isRecurringInit")
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):
encoder.encodeInt32(14, forKey: "_rawValue")
encoder.encodeInt64(callId, forKey: "i")

View File

@ -563,7 +563,7 @@ func _internal_sendBotPaymentForm(account: Account, formId: Int64, source: BotPa
switch source {
case let .slug(slug):
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 {
receiptMessageId = id
}
@ -615,16 +615,22 @@ func _internal_sendBotPaymentForm(account: Account, formId: Int64, source: BotPa
public struct BotPaymentReceipt : Equatable {
public let invoice: BotPaymentInvoice
public let date: Int32
public let info: BotPaymentRequestedInfo?
public let shippingOption: BotPaymentShippingOption?
public let credentialsTitle: String
public let invoiceMedia: TelegramMediaInvoice
public let tipAmount: Int64?
public let botPaymentId: PeerId
public let transactionId: String?
public static func ==(lhs: BotPaymentReceipt, rhs: BotPaymentReceipt) -> Bool {
if lhs.invoice != rhs.invoice {
return false
}
if lhs.date != rhs.date {
return false
}
if lhs.info != rhs.info {
return false
}
@ -643,6 +649,9 @@ public struct BotPaymentReceipt : Equatable {
if lhs.botPaymentId != rhs.botPaymentId {
return false
}
if lhs.transactionId != rhs.transactionId {
return false
}
return true
}
}
@ -669,7 +678,7 @@ func _internal_requestBotPaymentReceipt(account: Account, messageId: MessageId)
|> mapToSignal { result -> Signal<BotPaymentReceipt, RequestBotPaymentReceiptError> in
return account.postbox.transaction { transaction -> BotPaymentReceipt in
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)
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))
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):
return BotPaymentReceipt(invoice: parsedInvoice, date: date, info: parsedInfo, shippingOption: shippingOption, credentialsTitle: credentialsTitle, invoiceMedia: invoiceMedia, tipAmount: tipAmount, botPaymentId: botPaymentId, transactionId: nil)
case let .paymentReceiptStars(_, date, botId, title, description, photo, invoice, currency, totalAmount, transactionId, users):
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: [], users: users)
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))
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)

View File

@ -366,7 +366,7 @@ func _internal_sendStarsPaymentForm(account: Account, formId: Int64, source: Bot
switch source {
case let .slug(slug):
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 {
receiptMessageId = id
}

View File

@ -496,7 +496,7 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
var argumentAttributes = peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: [(0, message.author?.id)])
argumentAttributes[1] = MarkdownAttributeSet(font: titleBoldFont, textColor: primaryTextColor, additionalAttributes: [:])
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?
for attribute in message.attributes {
if let attribute = attribute as? ReplyMessageAttribute, let message = message.associatedMessages[attribute.messageId] {

View File

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

View File

@ -13,6 +13,7 @@ import TelegramCore
import MergedAvatarsNode
import MultilineTextComponent
import TelegramPresentationData
import PhotoResources
private let sceneVersion: Int = 1
@ -73,6 +74,7 @@ public final class GiftAvatarComponent: Component {
private let sceneView: SCNView
private let avatarNode: ImageNode
private var mergedAvatarsNode: MergedAvatarsNode?
private var imageNode: TransformImageNode?
private let badgeBackground = ComponentView<Empty>()
private let badge = ComponentView<Empty>()
@ -81,6 +83,8 @@ public final class GiftAvatarComponent: Component {
private var timer: SwiftSignalKit.Timer?
private var hasIdleAnimations = false
private let fetchDisposable = MetaDisposable()
public override init(frame: CGRect) {
self.sceneView = SCNView(frame: CGRect(origin: .zero, size: CGSize(width: 64.0, height: 64.0)))
self.sceneView.backgroundColor = .clear
@ -109,6 +113,7 @@ public final class GiftAvatarComponent: Component {
deinit {
self.timer?.invalidate()
self.fetchDisposable.dispose()
}
private let hapticFeedback = HapticFeedback()
@ -297,7 +302,26 @@ public final class GiftAvatarComponent: Component {
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 mergedAvatarsNode: MergedAvatarsNode

View File

@ -293,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 _ = 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)
// 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 {

View File

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

View File

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

View File

@ -211,53 +211,75 @@ final class StarsTransactionsListPanelComponent: Component {
let fontBaseDisplaySize = 17.0
let itemTitle: String
let itemSubtitle: String
let itemSubtitle: String?
let itemDate: String
let itemLabel: NSAttributedString
switch item.transaction.peer {
case let .peer(peer):
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)
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)
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)
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)
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)
case .unsupported:
itemTitle = "Unsupported"
itemSubtitle = nil
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)
let _ = itemView.update(
transition: itemTransition,
component: AnyComponent(ListActionItemComponent(
theme: environment.theme,
title: AnyComponent(VStack([
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: 0
))),
maximumNumberOfLines: 1
)))
)
if let itemSubtitle {
titleComponents.append(
AnyComponentWithIdentity(id: AnyHashable(1), component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: itemSubtitle,
font: Font.regular(floor(fontBaseDisplaySize * 15.0 / 17.0)),
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: 0,
lineSpacing: 0.18
maximumNumberOfLines: 1
)))
], alignment: .left, spacing: 3.0)),
)
let _ = itemView.update(
transition: itemTransition,
component: AnyComponent(ListActionItemComponent(
theme: environment.theme,
title: AnyComponent(VStack(titleComponents, alignment: .left, spacing: 2.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),
icon: nil,
@ -330,13 +352,21 @@ final class StarsTransactionsListPanelComponent: Component {
AnyComponentWithIdentity(id: AnyHashable(1), component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
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
)),
maximumNumberOfLines: 0,
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),
leftIcon: nil,
icon: nil,
@ -441,7 +471,7 @@ private final class AvatarComponent: Component {
super.init(frame: frame)
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.addSubview(self.backgroundView)
@ -458,7 +488,7 @@ private final class AvatarComponent: Component {
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 {
case let .peer(peer):

View File

@ -1041,14 +1041,14 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
if canSetupAutoremoveTimeout {
strongSelf.presentAutoremoveSetup()
}
case let .paymentSent(currency, _, _, _, _, id):
case let .paymentSent(currency, _, _, _, _):
if currency == "XTR" {
let _ = (context.engine.payments.requestBotPaymentReceipt(messageId: message.id)
|> deliverOnMainQueue).start(next: { [weak self] receipt in
guard let self else {
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 {
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 {
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 {
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 {
let hasFactCheck = message.factCheckAttribute != nil
let sortedMessages = messages.sorted(by: { $0.id < $1.id })
let hasFactCheck = sortedMessages[0].factCheckAttribute != nil
let title: String
if hasFactCheck {
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)
}, action: { c, f in
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: {})
}
public func makeStarsReceiptScreen(context: AccountContext, receipt: BotPaymentReceipt, id: String?, date: Int32) -> ViewController {
return StarsTransactionScreen(context: context, subject: .receipt(receipt: receipt, id: id, date: date), action: {})
public func makeStarsReceiptScreen(context: AccountContext, receipt: BotPaymentReceipt) -> ViewController {
return StarsTransactionScreen(context: context, subject: .receipt(receipt), action: {})
}
}