Update API [skip ci]

This commit is contained in:
Isaac 2025-06-23 21:52:31 +02:00
parent 2180826318
commit 9a14b076c6
22 changed files with 195 additions and 165 deletions

View File

@ -1033,8 +1033,8 @@ public enum StarsWithdrawalScreenSubject {
case withdraw(completion: (Int64) -> Void)
case enterAmount(current: StarsAmount, minValue: StarsAmount, fractionAfterCommission: Int, kind: PaidMessageKind, completion: (Int64) -> Void)
case postSuggestion(channel: EnginePeer, currency: TelegramCurrency, current: StarsAmount, timestamp: Int32?, completion: (TelegramCurrency, Int64, Int32?) -> Void)
case postSuggestionModification(currency: TelegramCurrency, current: StarsAmount, timestamp: Int32?, completion: (TelegramCurrency, Int64, Int32?) -> Void)
case postSuggestion(channel: EnginePeer, current: CurrencyAmount, timestamp: Int32?, completion: (CurrencyAmount, Int32?) -> Void)
case postSuggestionModification(current: CurrencyAmount, timestamp: Int32?, completion: (CurrencyAmount, Int32?) -> Void)
}
public protocol SharedAccountContext: AnyObject {

View File

@ -497,13 +497,11 @@ public final class ChatInterfaceState: Codable, Equatable {
public struct PostSuggestionState: Codable, Equatable {
public var editingOriginalMessageId: MessageId?
public var currency: TelegramCurrency
public var price: Int64
public var price: CurrencyAmount?
public var timestamp: Int32?
public init(editingOriginalMessageId: MessageId?, currency: TelegramCurrency, price: Int64, timestamp: Int32?) {
public init(editingOriginalMessageId: MessageId?, price: CurrencyAmount?, timestamp: Int32?) {
self.editingOriginalMessageId = editingOriginalMessageId
self.currency = currency
self.price = price
self.timestamp = timestamp
}

View File

@ -608,7 +608,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[1192749220] = { return Api.MessageAction.parse_messageActionStarGift($0) }
dict[775611918] = { return Api.MessageAction.parse_messageActionStarGiftUnique($0) }
dict[1474192222] = { return Api.MessageAction.parse_messageActionSuggestProfilePhoto($0) }
dict[-1354584535] = { return Api.MessageAction.parse_messageActionSuggestedPostApproval($0) }
dict[-293988970] = { return Api.MessageAction.parse_messageActionSuggestedPostApproval($0) }
dict[-940721021] = { return Api.MessageAction.parse_messageActionTodoAppendTasks($0) }
dict[-864265079] = { return Api.MessageAction.parse_messageActionTodoCompletions($0) }
dict[228168278] = { return Api.MessageAction.parse_messageActionTopicCreate($0) }
@ -1002,7 +1002,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-1870436597] = { return Api.StoryView.parse_storyViewPublicForward($0) }
dict[-1116418231] = { return Api.StoryView.parse_storyViewPublicRepost($0) }
dict[-1923523370] = { return Api.StoryViews.parse_storyViews($0) }
dict[-1779537299] = { return Api.SuggestedPost.parse_suggestedPost($0) }
dict[244201445] = { return Api.SuggestedPost.parse_suggestedPost($0) }
dict[1964978502] = { return Api.TextWithEntities.parse_textWithEntities($0) }
dict[-1609668650] = { return Api.Theme.parse_theme($0) }
dict[-94849324] = { return Api.ThemeSettings.parse_themeSettings($0) }
@ -1151,7 +1151,6 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-245208620] = { return Api.Update.parse_updateSmsJob($0) }
dict[1317053305] = { return Api.Update.parse_updateStarsBalance($0) }
dict[-1518030823] = { return Api.Update.parse_updateStarsRevenueStatus($0) }
dict[-1944619808] = { return Api.Update.parse_updateStarsTonBalance($0) }
dict[834816008] = { return Api.Update.parse_updateStickerSets($0) }
dict[196268545] = { return Api.Update.parse_updateStickerSetsOrder($0) }
dict[738741697] = { return Api.Update.parse_updateStoriesStealthMode($0) }

View File

@ -396,7 +396,7 @@ public extension Api {
case messageActionStarGift(flags: Int32, gift: Api.StarGift, message: Api.TextWithEntities?, convertStars: Int64?, upgradeMsgId: Int32?, upgradeStars: Int64?, fromId: Api.Peer?, peer: Api.Peer?, savedId: Int64?)
case messageActionStarGiftUnique(flags: Int32, gift: Api.StarGift, canExportAt: Int32?, transferStars: Int64?, fromId: Api.Peer?, peer: Api.Peer?, savedId: Int64?, resaleStars: Int64?, canTransferAt: Int32?, canResellAt: Int32?)
case messageActionSuggestProfilePhoto(photo: Api.Photo)
case messageActionSuggestedPostApproval(flags: Int32, rejectComment: String?, scheduleDate: Int32?, starsAmount: Int64?)
case messageActionSuggestedPostApproval(flags: Int32, rejectComment: String?, scheduleDate: Int32?, price: Api.StarsAmount?)
case messageActionTodoAppendTasks(list: [Api.TodoItem])
case messageActionTodoCompletions(completed: [Int32], incompleted: [Int32])
case messageActionTopicCreate(flags: Int32, title: String, iconColor: Int32, iconEmojiId: Int64?)
@ -816,14 +816,14 @@ public extension Api {
}
photo.serialize(buffer, true)
break
case .messageActionSuggestedPostApproval(let flags, let rejectComment, let scheduleDate, let starsAmount):
case .messageActionSuggestedPostApproval(let flags, let rejectComment, let scheduleDate, let price):
if boxed {
buffer.appendInt32(-1354584535)
buffer.appendInt32(-293988970)
}
serializeInt32(flags, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 2) != 0 {serializeString(rejectComment!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 3) != 0 {serializeInt32(scheduleDate!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 4) != 0 {serializeInt64(starsAmount!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 4) != 0 {price!.serialize(buffer, true)}
break
case .messageActionTodoAppendTasks(let list):
if boxed {
@ -983,8 +983,8 @@ public extension Api {
return ("messageActionStarGiftUnique", [("flags", flags as Any), ("gift", gift as Any), ("canExportAt", canExportAt as Any), ("transferStars", transferStars as Any), ("fromId", fromId as Any), ("peer", peer as Any), ("savedId", savedId as Any), ("resaleStars", resaleStars as Any), ("canTransferAt", canTransferAt as Any), ("canResellAt", canResellAt as Any)])
case .messageActionSuggestProfilePhoto(let photo):
return ("messageActionSuggestProfilePhoto", [("photo", photo as Any)])
case .messageActionSuggestedPostApproval(let flags, let rejectComment, let scheduleDate, let starsAmount):
return ("messageActionSuggestedPostApproval", [("flags", flags as Any), ("rejectComment", rejectComment as Any), ("scheduleDate", scheduleDate as Any), ("starsAmount", starsAmount as Any)])
case .messageActionSuggestedPostApproval(let flags, let rejectComment, let scheduleDate, let price):
return ("messageActionSuggestedPostApproval", [("flags", flags as Any), ("rejectComment", rejectComment as Any), ("scheduleDate", scheduleDate as Any), ("price", price as Any)])
case .messageActionTodoAppendTasks(let list):
return ("messageActionTodoAppendTasks", [("list", list as Any)])
case .messageActionTodoCompletions(let completed, let incompleted):
@ -1817,14 +1817,16 @@ public extension Api {
if Int(_1!) & Int(1 << 2) != 0 {_2 = parseString(reader) }
var _3: Int32?
if Int(_1!) & Int(1 << 3) != 0 {_3 = reader.readInt32() }
var _4: Int64?
if Int(_1!) & Int(1 << 4) != 0 {_4 = reader.readInt64() }
var _4: Api.StarsAmount?
if Int(_1!) & Int(1 << 4) != 0 {if let signature = reader.readInt32() {
_4 = Api.parse(reader, signature: signature) as? Api.StarsAmount
} }
let _c1 = _1 != nil
let _c2 = (Int(_1!) & Int(1 << 2) == 0) || _2 != nil
let _c3 = (Int(_1!) & Int(1 << 3) == 0) || _3 != nil
let _c4 = (Int(_1!) & Int(1 << 4) == 0) || _4 != nil
if _c1 && _c2 && _c3 && _c4 {
return Api.MessageAction.messageActionSuggestedPostApproval(flags: _1!, rejectComment: _2, scheduleDate: _3, starsAmount: _4)
return Api.MessageAction.messageActionSuggestedPostApproval(flags: _1!, rejectComment: _2, scheduleDate: _3, price: _4)
}
else {
return nil

View File

@ -682,16 +682,16 @@ public extension Api {
}
public extension Api {
enum SuggestedPost: TypeConstructorDescription {
case suggestedPost(flags: Int32, starsAmount: Int64, scheduleDate: Int32?)
case suggestedPost(flags: Int32, price: Api.StarsAmount?, scheduleDate: Int32?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .suggestedPost(let flags, let starsAmount, let scheduleDate):
case .suggestedPost(let flags, let price, let scheduleDate):
if boxed {
buffer.appendInt32(-1779537299)
buffer.appendInt32(244201445)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt64(starsAmount, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 3) != 0 {price!.serialize(buffer, true)}
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(scheduleDate!, buffer: buffer, boxed: false)}
break
}
@ -699,23 +699,25 @@ public extension Api {
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .suggestedPost(let flags, let starsAmount, let scheduleDate):
return ("suggestedPost", [("flags", flags as Any), ("starsAmount", starsAmount as Any), ("scheduleDate", scheduleDate as Any)])
case .suggestedPost(let flags, let price, let scheduleDate):
return ("suggestedPost", [("flags", flags as Any), ("price", price as Any), ("scheduleDate", scheduleDate as Any)])
}
}
public static func parse_suggestedPost(_ reader: BufferReader) -> SuggestedPost? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Int64?
_2 = reader.readInt64()
var _2: Api.StarsAmount?
if Int(_1!) & Int(1 << 3) != 0 {if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.StarsAmount
} }
var _3: Int32?
if Int(_1!) & Int(1 << 0) != 0 {_3 = reader.readInt32() }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c2 = (Int(_1!) & Int(1 << 3) == 0) || _2 != nil
let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil
if _c1 && _c2 && _c3 {
return Api.SuggestedPost.suggestedPost(flags: _1!, starsAmount: _2!, scheduleDate: _3)
return Api.SuggestedPost.suggestedPost(flags: _1!, price: _2, scheduleDate: _3)
}
else {
return nil

View File

@ -182,7 +182,6 @@ public extension Api {
case updateSmsJob(jobId: String)
case updateStarsBalance(balance: Api.StarsAmount)
case updateStarsRevenueStatus(peer: Api.Peer, status: Api.StarsRevenueStatus)
case updateStarsTonBalance(balance: Api.StarsAmount)
case updateStickerSets(flags: Int32)
case updateStickerSetsOrder(flags: Int32, order: [Int64])
case updateStoriesStealthMode(stealthMode: Api.StoriesStealthMode)
@ -1355,12 +1354,6 @@ public extension Api {
peer.serialize(buffer, true)
status.serialize(buffer, true)
break
case .updateStarsTonBalance(let balance):
if boxed {
buffer.appendInt32(-1944619808)
}
balance.serialize(buffer, true)
break
case .updateStickerSets(let flags):
if boxed {
buffer.appendInt32(834816008)
@ -1740,8 +1733,6 @@ public extension Api {
return ("updateStarsBalance", [("balance", balance as Any)])
case .updateStarsRevenueStatus(let peer, let status):
return ("updateStarsRevenueStatus", [("peer", peer as Any), ("status", status as Any)])
case .updateStarsTonBalance(let balance):
return ("updateStarsTonBalance", [("balance", balance as Any)])
case .updateStickerSets(let flags):
return ("updateStickerSets", [("flags", flags as Any)])
case .updateStickerSetsOrder(let flags, let order):
@ -4121,19 +4112,6 @@ public extension Api {
return nil
}
}
public static func parse_updateStarsTonBalance(_ reader: BufferReader) -> Update? {
var _1: Api.StarsAmount?
if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.StarsAmount
}
let _c1 = _1 != nil
if _c1 {
return Api.Update.updateStarsTonBalance(balance: _1!)
}
else {
return nil
}
}
public static func parse_updateStickerSets(_ reader: BufferReader) -> Update? {
var _1: Int32?
_1 = reader.readInt32()

View File

@ -130,7 +130,7 @@ enum AccountStateMutationOperation {
case UpdateNewAuthorization(isUnconfirmed: Bool, hash: Int64, date: Int32, device: String, location: String)
case UpdateWallpaper(peerId: PeerId, wallpaper: TelegramWallpaper?)
case UpdateRevenueBalances(peerId: PeerId, balances: RevenueStats.Balances)
case UpdateStarsBalance(peerId: PeerId, ton: Bool, balance: Api.StarsAmount)
case UpdateStarsBalance(peerId: PeerId, currency: CurrencyAmount.Currency, balance: StarsAmount)
case UpdateStarsRevenueStatus(peerId: PeerId, status: StarsRevenueStats.Balances)
case UpdateStarsReactionsDefaultPrivacy(privacy: TelegramPaidReactionPrivacy)
case ReportMessageDelivery([MessageId])
@ -696,8 +696,8 @@ struct AccountMutableState {
self.addOperation(.UpdateRevenueBalances(peerId: peerId, balances: balances))
}
mutating func updateStarsBalance(peerId: PeerId, ton: Bool, balance: Api.StarsAmount) {
self.addOperation(.UpdateStarsBalance(peerId: peerId, ton: ton, balance: balance))
mutating func updateStarsBalance(peerId: PeerId, currency: CurrencyAmount.Currency, balance: StarsAmount) {
self.addOperation(.UpdateStarsBalance(peerId: peerId, currency: currency, balance: balance))
}
mutating func updateStarsRevenueStatus(peerId: PeerId, status: StarsRevenueStats.Balances) {

View File

@ -233,15 +233,33 @@ func telegramMediaActionFromApiAction(_ action: Api.MessageAction) -> TelegramMe
if (flags & (1 << 0)) != 0 {
let reason: TelegramMediaActionType.SuggestedPostApprovalStatus.RejectionReason
if (flags & (1 << 1)) != 0 {
reason = .lowBalance(balanceNeeded: starsAmount ?? 0)
let balanceNeeded: CurrencyAmount
switch starsAmount {
case .none:
balanceNeeded = CurrencyAmount(amount: .zero, currency: .stars)
case let .starsAmount(amount, nanos):
balanceNeeded = CurrencyAmount(amount: StarsAmount(value: amount, nanos: nanos), currency: .stars)
case let .starsTonAmount(amount):
balanceNeeded = CurrencyAmount(amount: StarsAmount(value: amount, nanos: 0), currency: .ton)
}
reason = .lowBalance(balanceNeeded: balanceNeeded)
} else {
reason = .generic
}
status = .rejected(reason: reason, comment: rejectComment)
} else if (flags & (1 << 1)) != 0 {
status = .rejected(reason: .lowBalance(balanceNeeded: starsAmount ?? 0), comment: nil)
let amountValue: CurrencyAmount
switch starsAmount {
case .none:
amountValue = CurrencyAmount(amount: .zero, currency: .stars)
case let .starsAmount(amount, nanos):
amountValue = CurrencyAmount(amount: StarsAmount(value: amount, nanos: nanos), currency: .stars)
case let .starsTonAmount(amount):
amountValue = CurrencyAmount(amount: StarsAmount(value: amount, nanos: 0), currency: .ton)
}
status = .rejected(reason: .lowBalance(balanceNeeded: amountValue), comment: nil)
} else {
status = .approved(timestamp: scheduleDate, amount: starsAmount ?? 0)
status = .approved(timestamp: scheduleDate, amount: starsAmount.flatMap(CurrencyAmount.init(apiAmount:)))
}
return TelegramMediaAction(action: .suggestedPostApprovalStatus(status: status))
case let .messageActionGiftTon(_, currency, amount, cryptoCurrency, cryptoAmount, transactionId):

View File

@ -1589,7 +1589,7 @@ private func finalStateWithUpdatesAndServerTime(accountPeerId: PeerId, postbox:
if let suggestedPost {
switch suggestedPost {
case let .suggestedPost(_, starsAmount, scheduleDate):
parsedSuggestedPost = SynchronizeableChatInputState.SuggestedPost(price: starsAmount, timestamp: scheduleDate)
parsedSuggestedPost = SynchronizeableChatInputState.SuggestedPost(price: starsAmount.flatMap(CurrencyAmount.init(apiAmount:)), timestamp: scheduleDate)
}
}
if let replyToMsgHeader {
@ -1839,9 +1839,8 @@ private func finalStateWithUpdatesAndServerTime(accountPeerId: PeerId, postbox:
case let .updateBroadcastRevenueTransactions(peer, balances):
updatedState.updateRevenueBalances(peerId: peer.peerId, balances: RevenueStats.Balances(apiRevenueBalances: balances))
case let .updateStarsBalance(balance):
updatedState.updateStarsBalance(peerId: accountPeerId, ton: false, balance: balance)
case let .updateStarsTonBalance(balance):
updatedState.updateStarsBalance(peerId: accountPeerId, ton: true, balance: balance)
let amount = CurrencyAmount(apiAmount: balance)
updatedState.updateStarsBalance(peerId: accountPeerId, currency: amount.currency, balance: amount.amount)
case let .updateStarsRevenueStatus(peer, status):
updatedState.updateStarsRevenueStatus(peerId: peer.peerId, status: StarsRevenueStats.Balances(apiStarsRevenueStatus: status))
case let .updatePaidReactionPrivacy(privacy):
@ -5172,11 +5171,12 @@ func replayFinalState(
}
case let .UpdateRevenueBalances(peerId, balances):
updatedRevenueBalances[peerId] = balances
case let .UpdateStarsBalance(peerId, ton, balance):
if ton {
updatedTonBalance[peerId] = StarsAmount(apiAmount: balance)
} else {
updatedStarsBalance[peerId] = StarsAmount(apiAmount: balance)
case let .UpdateStarsBalance(peerId, currency, balance):
switch currency {
case .ton:
updatedTonBalance[peerId] = balance
case .stars:
updatedStarsBalance[peerId] = balance
}
case let .UpdateStarsRevenueStatus(peerId, status):
updatedStarsRevenueStatus[peerId] = status

View File

@ -229,7 +229,7 @@ private func synchronizeChatInputState(transaction: Transaction, postbox: Postbo
if suggestedPost.timestamp != nil {
flags |= 1 << 0
}
return .suggestedPost(flags: flags, starsAmount: suggestedPost.price, scheduleDate: suggestedPost.timestamp)
return .suggestedPost(flags: flags, price: suggestedPost.price?.apiAmount ?? .starsAmount(amount: 0, nanos: 0), scheduleDate: suggestedPost.timestamp)
}
if suggestedPost != nil {
flags |= 1 << 8

View File

@ -8,28 +8,28 @@ public final class SuggestedPostMessageAttribute: Equatable, MessageAttribute {
case rejected = 1
}
public let currency: TelegramCurrency
public let amount: Int64
public let amount: CurrencyAmount?
public let timestamp: Int32?
public let state: State?
public init(currency: TelegramCurrency, amount: Int64, timestamp: Int32?, state: State?) {
self.currency = currency
public init(amount: CurrencyAmount?, timestamp: Int32?, state: State?) {
self.amount = amount
self.timestamp = timestamp
self.state = state
}
required public init(decoder: PostboxDecoder) {
self.currency = decoder.decodeCodable(TelegramCurrency.self, forKey: "cur") ?? .stars
self.amount = decoder.decodeInt64ForKey("am", orElse: 0)
self.amount = decoder.decodeCodable(CurrencyAmount.self, forKey: "amt")
self.timestamp = decoder.decodeOptionalInt32ForKey("ts")
self.state = decoder.decodeOptionalInt32ForKey("st").flatMap(State.init(rawValue:))
}
public func encode(_ encoder: PostboxEncoder) {
encoder.encodeCodable(self.currency, forKey: "cur")
encoder.encodeInt64(self.amount, forKey: "am")
if let amount = self.amount {
encoder.encodeCodable(amount, forKey: "amt")
} else {
encoder.encodeNil(forKey: "amt")
}
if let timestamp = self.timestamp {
encoder.encodeInt32(timestamp, forKey: "ts")
} else {
@ -43,9 +43,6 @@ public final class SuggestedPostMessageAttribute: Equatable, MessageAttribute {
}
public static func ==(lhs: SuggestedPostMessageAttribute, rhs: SuggestedPostMessageAttribute) -> Bool {
if lhs.currency != rhs.currency {
return false
}
if lhs.amount != rhs.amount {
return false
}
@ -69,7 +66,7 @@ extension SuggestedPostMessageAttribute {
} else if (flags & (1 << 2)) != 0 {
state = .rejected
}
self.init(currency: .stars, amount: starsAmount, timestamp: scheduleDate, state: state)
self.init(amount: starsAmount.flatMap(CurrencyAmount.init(apiAmount:)), timestamp: scheduleDate, state: state)
}
}
@ -86,7 +83,12 @@ extension SuggestedPostMessageAttribute {
if self.timestamp != nil {
flags |= 1 << 0
}
return .suggestedPost(flags: flags, starsAmount: self.amount, scheduleDate: self.timestamp)
var price: Api.StarsAmount?
if let amount = self.amount {
flags |= 1 << 3
price = amount.apiAmount
}
return .suggestedPost(flags: flags, price: price, scheduleDate: self.timestamp)
}
}

View File

@ -3,10 +3,10 @@ import Postbox
public struct SynchronizeableChatInputState: Codable, Equatable {
public struct SuggestedPost: Codable, Equatable {
public var price: Int64
public var price: CurrencyAmount?
public var timestamp: Int32?
public init(price: Int64, timestamp: Int32?) {
public init(price: CurrencyAmount?, timestamp: Int32?) {
self.price = price
self.timestamp = timestamp
}

View File

@ -114,10 +114,10 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
public enum SuggestedPostApprovalStatus: PostboxCoding, Equatable {
public enum RejectionReason: Equatable {
case generic
case lowBalance(balanceNeeded: Int64)
case lowBalance(balanceNeeded: CurrencyAmount)
}
case approved(timestamp: Int32?, amount: Int64)
case approved(timestamp: Int32?, amount: CurrencyAmount?)
case rejected(reason: RejectionReason, comment: String?)
public init(decoder: PostboxDecoder) {
@ -125,7 +125,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
case 0:
self = .approved(
timestamp: decoder.decodeOptionalInt32ForKey("ts"),
amount: decoder.decodeInt64ForKey("am", orElse: 0)
amount: decoder.decodeCodable(CurrencyAmount.self, forKey: "amt")
)
case 1:
let reason: RejectionReason
@ -133,7 +133,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
case 0:
reason = .generic
case 1:
reason = .lowBalance(balanceNeeded: decoder.decodeInt64ForKey("lowbal.val", orElse: 0))
reason = .lowBalance(balanceNeeded: decoder.decodeCodable(CurrencyAmount.self, forKey: "lowbal.val") ?? CurrencyAmount(amount: StarsAmount.zero, currency: .stars))
default:
assertionFailure()
reason = .generic
@ -154,7 +154,11 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
} else {
encoder.encodeNil(forKey: "ts")
}
encoder.encodeInt64(amount, forKey: "am")
if let amount {
encoder.encodeCodable(amount, forKey: "amt")
} else {
encoder.encodeNil(forKey: "amt")
}
case let .rejected(reason, comment):
encoder.encodeInt32(1, forKey: "_t")
switch reason {
@ -162,7 +166,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
encoder.encodeInt32(0, forKey: "rs")
case let .lowBalance(balanceNeeded):
encoder.encodeInt32(1, forKey: "rs")
encoder.encodeInt64(balanceNeeded, forKey: "lowbal.val")
encoder.encodeCodable(balanceNeeded, forKey: "lowbal.val")
}
if let comment {
encoder.encodeString(comment, forKey: "com")

View File

@ -354,34 +354,55 @@ extension StarsAmount {
}
}
public enum TelegramCurrency: Codable {
public struct CurrencyAmount: Equatable, Hashable, Codable {
private enum CodingKeys: String, CodingKey {
case discriminator = "_"
case amount = "a"
case currency = "c"
}
case stars
case ton
public enum Currency: Int32 {
case stars = 0
case ton = 1
}
public init(from decoder: Decoder) throws {
public var amount: StarsAmount
public var currency: Currency
public init(amount: StarsAmount, currency: Currency) {
self.amount = amount
self.currency = currency
}
public init(from decoder: any Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
switch try container.decode(Int32.self, forKey: .discriminator) {
case 0:
self = .stars
case 1:
self = .ton
default:
assertionFailure()
self = .stars
}
self.amount = try container.decode(StarsAmount.self, forKey: .amount)
self.currency = Currency(rawValue: try container.decode(Int32.self, forKey: .currency)) ?? .stars
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
switch self {
try container.encode(self.amount, forKey: .amount)
try container.encode(Int32(self.currency.rawValue), forKey: .currency)
}
}
extension CurrencyAmount {
init(apiAmount: Api.StarsAmount) {
switch apiAmount {
case let .starsAmount(amount, nanos):
self.init(amount: StarsAmount(value: amount, nanos: nanos), currency: .stars)
case let .starsTonAmount(amount):
self.init(amount: StarsAmount(value: amount, nanos: 0), currency: .ton)
}
}
var apiAmount: Api.StarsAmount {
switch self.currency {
case .stars:
try container.encode(0 as Int32, forKey: .discriminator)
return .starsAmount(amount: self.amount.value, nanos: self.amount.nanos)
case .ton:
try container.encode(1 as Int32, forKey: .discriminator)
assert(self.amount.nanos == 0)
return .starsTonAmount(amount: self.amount.value)
}
}
}

View File

@ -258,7 +258,17 @@ public class ChatMessageActionBubbleContentNode: ChatMessageBubbleContentNode {
}
)).string
let amountString = amount == 1 ? "\(amount) Star" : "\(amount) Stars"
let amountString: String
if let amount, amount.amount != .zero {
switch amount.currency {
case .stars:
amountString = amount.amount.value == 1 ? "\(amount.amount) Star" : "\(amount.amount) Stars"
case .ton:
amountString = "\(amount.amount) TON"
}
} else {
amountString = "0 Stars"
}
let rawString: String
if let timestamp {

View File

@ -48,13 +48,11 @@ public final class ChatMessageSuggestedPostInfoNode: ASDisplayNode {
let labelSpacing: CGFloat = 8.0
let valuesVerticalSpacing: CGFloat = 2.0
var currency: TelegramCurrency = .stars
var amount: Int64 = 0
var amount: CurrencyAmount?
var timestamp: Int32?
for attribute in item.message.attributes {
if let attribute = attribute as? SuggestedPostMessageAttribute {
currency = attribute.currency
amount = attribute.amount
timestamp = attribute.timestamp
}
@ -62,23 +60,23 @@ public final class ChatMessageSuggestedPostInfoNode: ASDisplayNode {
//TODO:localize
let amountString: String
switch currency {
case .stars:
if amount == 0 {
amountString = "Free"
} else if amount == 1 {
amountString = "1 Star"
} else {
amountString = "\(amount) Stars"
}
case .ton:
if amount == 0 {
amountString = "Free"
} else if amount == 1 {
amountString = "1 TON"
} else {
amountString = "\(amount) TON"
if let amount, amount.amount.value != 0, amount.amount.nanos != 0 {
switch amount.currency {
case .stars:
if amount.amount.value == 1 {
amountString = "1 Star"
} else {
amountString = "\(amount) Stars"
}
case .ton:
if amount.amount.value == 1 {
amountString = "1 TON"
} else {
amountString = "\(amount) TON"
}
}
} else {
amountString = "Free"
}
var timestampString: String

View File

@ -239,9 +239,9 @@ public final class SuggestPostAccessoryPanelNode: AccessoryPanelNode {
}
let textString: NSAttributedString
if let postSuggestionState = interfaceState.interfaceState.postSuggestionState, postSuggestionState.price != 0 {
if let postSuggestionState = interfaceState.interfaceState.postSuggestionState, let price = postSuggestionState.price, price.amount != .zero {
let currencySymbol: String
switch postSuggestionState.currency {
switch price.currency {
case .stars:
currencySymbol = "#"
case .ton:
@ -262,16 +262,16 @@ public final class SuggestPostAccessoryPanelNode: AccessoryPanelNode {
return PresentationStrings.FormattedString(string: interfaceState.strings.SuggestPost_SetTimeFormat_TodayAt(value).string, ranges: [])
}
)).string
textString = NSAttributedString(string: "\(currencySymbol)\(postSuggestionState.price) 📅 \(timeString)", font: textFont, textColor: self.theme.chat.inputPanel.primaryTextColor)
textString = NSAttributedString(string: "\(currencySymbol)\(price.amount) 📅 \(timeString)", font: textFont, textColor: self.theme.chat.inputPanel.primaryTextColor)
} else {
textString = NSAttributedString(string: "\(currencySymbol)\(postSuggestionState.price) for publishing anytime", font: textFont, textColor: self.theme.chat.inputPanel.primaryTextColor)
textString = NSAttributedString(string: "\(currencySymbol)\(price.amount) for publishing anytime", font: textFont, textColor: self.theme.chat.inputPanel.primaryTextColor)
}
} else {
textString = NSAttributedString(string: "Tap to offer a price for publishing", font: textFont, textColor: self.theme.chat.inputPanel.primaryTextColor)
}
let mutableTextString = NSMutableAttributedString(attributedString: textString)
for currency in [.stars, .ton] as [TelegramCurrency] {
for currency in [.stars, .ton] as [CurrencyAmount.Currency] {
let currencySymbol: String
let currencyImage: UIImage?
switch currency {

View File

@ -82,7 +82,7 @@ private final class SheetContent: CombinedComponent {
let constrainedTitleWidth = context.availableSize.width - 16.0 * 2.0
if case let .suggestedPost(mode, _, _, _, _) = component.mode {
if case let .suggestedPost(mode, _, _, _) = component.mode {
switch mode {
case .sender:
let balance = balance.update(
@ -203,7 +203,7 @@ private final class SheetContent: CombinedComponent {
minAmount = StarsAmount(value: minAmountValue, nanos: 0)
maxAmount = StarsAmount(value: resaleConfiguration.paidMessageMaxAmount, nanos: 0)
case let .suggestedPost(mode, _, _, _, _):
case let .suggestedPost(mode, _, _, _):
//TODO:localize
switch mode {
case .sender:
@ -289,7 +289,7 @@ private final class SheetContent: CombinedComponent {
)
}
if case let .suggestedPost(mode, _, _, _, _) = component.mode {
if case let .suggestedPost(mode, _, _, _) = component.mode {
//TODO:localize
let selectedId: AnyHashable = state.currency == .stars ? AnyHashable(0 as Int) : AnyHashable(1 as Int)
let starsTitle: String
@ -424,7 +424,7 @@ private final class SheetContent: CombinedComponent {
text: .plain(amountInfoString),
maximumNumberOfLines: 0
))
case let .suggestedPost(mode, _, _, _, _):
case let .suggestedPost(mode, _, _, _):
switch mode {
case let .sender(channel):
//TODO:localize
@ -515,7 +515,7 @@ private final class SheetContent: CombinedComponent {
.position(CGPoint(x: context.availableSize.width - amountAdditionalLabel.size.width / 2.0 - sideInset - 16.0, y: contentSize.height - amountAdditionalLabel.size.height / 2.0)))
}
if case let .suggestedPost(mode, _, _, _, _) = component.mode {
if case let .suggestedPost(mode, _, _, _) = component.mode {
contentSize.height += 24.0
//TODO:localize
@ -626,7 +626,7 @@ private final class SheetContent: CombinedComponent {
}
} else if case .paidMessages = component.mode {
buttonString = environment.strings.Stars_SendMessage_AdjustmentAction
} else if case let .suggestedPost(mode, _, _, _, _) = component.mode {
} else if case let .suggestedPost(mode, _, _, _) = component.mode {
//TODO:localize
switch mode {
case .sender:
@ -718,8 +718,8 @@ private final class SheetContent: CombinedComponent {
completion(amount.value)
case let .paidMessages(_, _, _, _, completion):
completion(amount.value)
case let .suggestedPost(_, _, _, _, completion):
completion(state.currency, amount.value, state.timestamp)
case let .suggestedPost(_, _, _, completion):
completion(CurrencyAmount(amount: amount, currency: state.currency), state.timestamp)
}
controller.dismissAnimated()
@ -753,7 +753,7 @@ private final class SheetContent: CombinedComponent {
fileprivate var component: SheetContent
fileprivate var amount: StarsAmount?
fileprivate var currency: TelegramCurrency
fileprivate var currency: CurrencyAmount.Currency = .stars
fileprivate var timestamp: Int32?
fileprivate var balance: StarsAmount?
@ -770,7 +770,7 @@ private final class SheetContent: CombinedComponent {
self.component = component
var amount: StarsAmount?
var currency: TelegramCurrency = .stars
var currency: CurrencyAmount.Currency = .stars
switch mode {
case let .withdraw(stats, _):
amount = StarsAmount(value: stats.balances.availableBalance.value, nanos: 0)
@ -784,11 +784,9 @@ private final class SheetContent: CombinedComponent {
amount = nil
case let .paidMessages(initialValue, _, _, _, _):
amount = StarsAmount(value: initialValue, nanos: 0)
case let .suggestedPost(_, currencyValue, initialValue, initialTimestamp, _):
currency = currencyValue
if initialValue != 0 {
amount = StarsAmount(value: initialValue, nanos: 0)
}
case let .suggestedPost(_, initialValue, initialTimestamp, _):
currency = initialValue.currency
amount = initialValue.amount
self.timestamp = initialTimestamp
}
@ -801,7 +799,7 @@ private final class SheetContent: CombinedComponent {
switch self.mode {
case .reaction:
needsBalance = true
case let .suggestedPost(mode, _, _, _, _):
case let .suggestedPost(mode, _, _, _):
switch mode {
case .sender:
needsBalance = true
@ -959,7 +957,7 @@ public final class StarsWithdrawScreen: ViewControllerComponentContainer {
case reaction(Int64?, completion: (Int64) -> Void)
case starGiftResell(StarGift.UniqueGift, Bool, completion: (Int64) -> Void)
case paidMessages(current: Int64, minValue: Int64, fractionAfterCommission: Int, kind: StarsWithdrawalScreenSubject.PaidMessageKind, completion: (Int64) -> Void)
case suggestedPost(mode: SuggestedPostMode, currency: TelegramCurrency, price: Int64, timestamp: Int32?, completion: (TelegramCurrency, Int64, Int32?) -> Void)
case suggestedPost(mode: SuggestedPostMode, price: CurrencyAmount, timestamp: Int32?, completion: (CurrencyAmount, Int32?) -> Void)
}
private let context: AccountContext
@ -1049,7 +1047,7 @@ private final class AmountFieldComponent: Component {
let maxValue: Int64?
let placeholderText: String
let labelText: String?
let currency: TelegramCurrency
let currency: CurrencyAmount.Currency
let amountUpdated: (Int64?) -> Void
let tag: AnyObject?
@ -1063,7 +1061,7 @@ private final class AmountFieldComponent: Component {
maxValue: Int64?,
placeholderText: String,
labelText: String?,
currency: TelegramCurrency,
currency: CurrencyAmount.Currency,
amountUpdated: @escaping (Int64?) -> Void,
tag: AnyObject? = nil
) {
@ -1399,7 +1397,7 @@ private final class BalanceComponent: CombinedComponent {
let context: AccountContext
let theme: PresentationTheme
let strings: PresentationStrings
let currency: TelegramCurrency
let currency: CurrencyAmount.Currency
let balance: StarsAmount?
let alignment: NSTextAlignment
@ -1407,7 +1405,7 @@ private final class BalanceComponent: CombinedComponent {
context: AccountContext,
theme: PresentationTheme,
strings: PresentationStrings,
currency: TelegramCurrency,
currency: CurrencyAmount.Currency,
balance: StarsAmount?,
alignment: NSTextAlignment
) {

View File

@ -4181,8 +4181,7 @@ extension ChatControllerImpl {
interfaceState = interfaceState.withUpdatedPostSuggestionState(ChatInterfaceState.PostSuggestionState(
editingOriginalMessageId: message.id,
currency: attribute?.currency ?? .stars,
price: attribute?.amount ?? 0,
price: attribute?.amount,
timestamp: attribute?.timestamp
))
return interfaceState
@ -4196,8 +4195,7 @@ extension ChatControllerImpl {
var interfaceState = interfaceState
interfaceState = interfaceState.withUpdatedPostSuggestionState(ChatInterfaceState.PostSuggestionState(
editingOriginalMessageId: nil,
currency: .stars,
price: 0,
price: nil,
timestamp: nil
))
return interfaceState

View File

@ -989,17 +989,19 @@ extension ChatControllerImpl {
let subject: StarsWithdrawalScreenSubject
if postSuggestionState.editingOriginalMessageId != nil {
subject = .postSuggestionModification(currency: postSuggestionState.currency, current: StarsAmount(value: postSuggestionState.price, nanos: 0), timestamp: postSuggestionState.timestamp, completion: { [weak self] currency, price, timestamp in
subject = .postSuggestionModification(current: postSuggestionState.price ?? CurrencyAmount(amount: .zero, currency: .stars), timestamp: postSuggestionState.timestamp, completion: { [weak self] price, timestamp in
guard let self else {
return
}
let price: CurrencyAmount? = price.amount == .zero ? nil : price
self.updateChatPresentationInterfaceState(interactive: true, { state in
var state = state
state = state.updatedInterfaceState { interfaceState in
var interfaceState = interfaceState
interfaceState = interfaceState.withUpdatedPostSuggestionState(ChatInterfaceState.PostSuggestionState(
editingOriginalMessageId: interfaceState.postSuggestionState?.editingOriginalMessageId,
currency: currency,
price: price,
timestamp: timestamp
))
@ -1011,20 +1013,21 @@ extension ChatControllerImpl {
} else {
subject = .postSuggestion(
channel: .channel(channel),
currency: postSuggestionState.currency,
current: StarsAmount(value: postSuggestionState.price, nanos: 0),
current: postSuggestionState.price ?? CurrencyAmount(amount: .zero, currency: .stars),
timestamp: postSuggestionState.timestamp,
completion: { [weak self] currency, price, timestamp in
completion: { [weak self] price, timestamp in
guard let self else {
return
}
let price: CurrencyAmount? = price.amount == .zero ? nil : price
self.updateChatPresentationInterfaceState(interactive: true, { state in
var state = state
state = state.updatedInterfaceState { interfaceState in
var interfaceState = interfaceState
interfaceState = interfaceState.withUpdatedPostSuggestionState(ChatInterfaceState.PostSuggestionState(
editingOriginalMessageId: interfaceState.postSuggestionState?.editingOriginalMessageId,
currency: currency,
price: price,
timestamp: timestamp
))

View File

@ -8000,7 +8000,6 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
if let postSuggestionState = self.presentationInterfaceState.interfaceState.postSuggestionState {
if attributes.first(where: { $0 is SuggestedPostMessageAttribute }) == nil {
attributes.append(SuggestedPostMessageAttribute(
currency: postSuggestionState.currency,
amount: postSuggestionState.price,
timestamp: postSuggestionState.timestamp,
state: nil

View File

@ -3734,10 +3734,10 @@ public final class SharedAccountContextImpl: SharedAccountContext {
mode = .accountWithdraw(completion: completion)
case let .enterAmount(current, minValue, fractionAfterCommission, kind, completion):
mode = .paidMessages(current: current.value, minValue: minValue.value, fractionAfterCommission: fractionAfterCommission, kind: kind, completion: completion)
case let .postSuggestion(channel, currency, current, timestamp, completion):
mode = .suggestedPost(mode: .sender(channel: channel), currency: currency, price: current.value, timestamp: timestamp, completion: completion)
case let .postSuggestionModification(currency, current, timestamp, completion):
mode = .suggestedPost(mode: .admin, currency: currency, price: current.value, timestamp: timestamp, completion: completion)
case let .postSuggestion(channel, current, timestamp, completion):
mode = .suggestedPost(mode: .sender(channel: channel), price: current, timestamp: timestamp, completion: completion)
case let .postSuggestionModification(current, timestamp, completion):
mode = .suggestedPost(mode: .admin, price: current, timestamp: timestamp, completion: completion)
}
return StarsWithdrawScreen(context: context, mode: mode)
}