Stars giveaways [skip ci]

This commit is contained in:
Ilya Laktyushin 2024-08-23 18:44:16 +04:00
parent bc33cc7e9b
commit 5941becc33
41 changed files with 1623 additions and 476 deletions

View File

@ -12264,6 +12264,7 @@ Sorry for the inconvenience.";
"Stars.Intro.Incoming" = "Incoming"; "Stars.Intro.Incoming" = "Incoming";
"Stars.Intro.Outgoing" = "Outgoing"; "Stars.Intro.Outgoing" = "Outgoing";
"Stars.Intro.Transaction.GiveawayPrize" = "Giveaway Prize";
"Stars.Intro.Transaction.MediaPurchase" = "Media Purchase"; "Stars.Intro.Transaction.MediaPurchase" = "Media Purchase";
"Stars.Intro.Transaction.AppleTopUp.Title" = "Stars Top-Up"; "Stars.Intro.Transaction.AppleTopUp.Title" = "Stars Top-Up";
"Stars.Intro.Transaction.AppleTopUp.Subtitle" = "via App Store"; "Stars.Intro.Transaction.AppleTopUp.Subtitle" = "via App Store";
@ -12823,3 +12824,16 @@ Sorry for the inconvenience.";
"Chat.ToastStarsReactionsDisabled" = "Star Reactions were disabled in %@"; "Chat.ToastStarsReactionsDisabled" = "Star Reactions were disabled in %@";
"ChatContextMenu.SingleReactionEmojiSet" = "This reaction is from #[%@]() emoji pack."; "ChatContextMenu.SingleReactionEmojiSet" = "This reaction is from #[%@]() emoji pack.";
"Channel.AdminLog.MessageParticipantSubscriptionExtended" = "%@ extended their subscription";
"Notification.StarsPrize" = "You received a gift";
"Notification.GiveawayStartedStars" = "%1$@ just started a giveaway of %2$@ Telegram Stars for its followers.";
"Notification.GiveawayStartedStarsGroup" = "%1$@ just started a giveaway of %2$@ Telegram Stars for its members.";
"Chat.Giveaway.Message.Stars.PrizeText" = "%1$@ will be distributed %2$@.";
"Chat.Giveaway.Message.Stars.Stars_1" = "**%@** Stars";
"Chat.Giveaway.Message.Stars.Stars_any" = "**%@** Stars";
"Chat.Giveaway.Message.Stars.Winners_1" = "to **%@** winner";
"Chat.Giveaway.Message.Stars.Winners_any" = "among **%@** winners";

View File

@ -413,7 +413,7 @@ public enum AvatarBackgroundColor {
case violet case violet
} }
public func generateAvatarImage(size: CGSize, icon: UIImage?, iconScale: CGFloat = 1.0, cornerRadius: CGFloat? = nil, circleCorners: Bool = false, color: AvatarBackgroundColor, customColors: [UIColor]? = nil) -> UIImage? { public func generateAvatarImage(size: CGSize, icon: UIImage?, iconScale: CGFloat = 1.0, cornerRadius: CGFloat? = nil, circleCorners: Bool = false, color: AvatarBackgroundColor, customColors: [UIColor]? = nil, diagonal: Bool = false) -> UIImage? {
return generateImage(size, rotatedContext: { size, context in return generateImage(size, rotatedContext: { size, context in
context.clear(CGRect(origin: CGPoint(), size: size)) context.clear(CGRect(origin: CGPoint(), size: size))
context.beginPath() context.beginPath()
@ -456,14 +456,21 @@ public func generateAvatarImage(size: CGSize, icon: UIImage?, iconScale: CGFloat
colorsArray = AvatarNode.gradientColors[colorIndex % AvatarNode.gradientColors.count].map(\.cgColor) as NSArray colorsArray = AvatarNode.gradientColors[colorIndex % AvatarNode.gradientColors.count].map(\.cgColor) as NSArray
} }
} }
var locations: [CGFloat] = [1.0, 0.0] var locations: [CGFloat] = []
let delta = 1.0 / CGFloat(colorsArray.count - 1)
for i in 0 ..< colorsArray.count {
locations.append(1.0 - delta * CGFloat(i))
}
let colorSpace = CGColorSpaceCreateDeviceRGB() let colorSpace = CGColorSpaceCreateDeviceRGB()
let gradient = CGGradient(colorsSpace: colorSpace, colors: colorsArray, locations: &locations)! let gradient = CGGradient(colorsSpace: colorSpace, colors: colorsArray, locations: &locations)!
context.drawLinearGradient(gradient, start: CGPoint(), end: CGPoint(x: 0.0, y: size.height), options: CGGradientDrawingOptions()) if diagonal {
context.drawLinearGradient(gradient, start: CGPoint(x: size.width, y: 0.0), end: CGPoint(x: 0.0, y: size.height), options: CGGradientDrawingOptions())
} else {
context.drawLinearGradient(gradient, start: CGPoint(), end: CGPoint(x: 0.0, y: size.height), options: CGGradientDrawingOptions())
}
context.resetClip() context.resetClip()
context.setBlendMode(.normal) context.setBlendMode(.normal)

View File

@ -622,6 +622,7 @@ private final class PendingInAppPurchaseState: Codable {
case randomId case randomId
case untilDate case untilDate
case stars case stars
case users
} }
enum PurposeType: Int32 { enum PurposeType: Int32 {
@ -633,6 +634,7 @@ private final class PendingInAppPurchaseState: Codable {
case giveaway case giveaway
case stars case stars
case starsGift case starsGift
case starsGiveaway
} }
case subscription case subscription
@ -643,6 +645,7 @@ private final class PendingInAppPurchaseState: Codable {
case giveaway(boostPeer: EnginePeer.Id, additionalPeerIds: [EnginePeer.Id], countries: [String], onlyNewSubscribers: Bool, showWinners: Bool, prizeDescription: String?, randomId: Int64, untilDate: Int32) case giveaway(boostPeer: EnginePeer.Id, additionalPeerIds: [EnginePeer.Id], countries: [String], onlyNewSubscribers: Bool, showWinners: Bool, prizeDescription: String?, randomId: Int64, untilDate: Int32)
case stars(count: Int64) case stars(count: Int64)
case starsGift(peerId: EnginePeer.Id, count: Int64) case starsGift(peerId: EnginePeer.Id, count: Int64)
case starsGiveaway(stars: Int64, boostPeer: EnginePeer.Id, additionalPeerIds: [EnginePeer.Id], countries: [String], onlyNewSubscribers: Bool, showWinners: Bool, prizeDescription: String?, randomId: Int64, untilDate: Int32, users: Int32)
public init(from decoder: Decoder) throws { public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self) let container = try decoder.container(keyedBy: CodingKeys.self)
@ -684,6 +687,19 @@ private final class PendingInAppPurchaseState: Codable {
peerId: EnginePeer.Id(try container.decode(Int64.self, forKey: .peer)), peerId: EnginePeer.Id(try container.decode(Int64.self, forKey: .peer)),
count: try container.decode(Int64.self, forKey: .stars) count: try container.decode(Int64.self, forKey: .stars)
) )
case .starsGiveaway:
self = .starsGiveaway(
stars: try container.decode(Int64.self, forKey: .stars),
boostPeer: EnginePeer.Id(try container.decode(Int64.self, forKey: .boostPeer)),
additionalPeerIds: try container.decode([Int64].self, forKey: .randomId).map { EnginePeer.Id($0) },
countries: try container.decodeIfPresent([String].self, forKey: .countries) ?? [],
onlyNewSubscribers: try container.decode(Bool.self, forKey: .onlyNewSubscribers),
showWinners: try container.decodeIfPresent(Bool.self, forKey: .showWinners) ?? false,
prizeDescription: try container.decodeIfPresent(String.self, forKey: .prizeDescription),
randomId: try container.decode(Int64.self, forKey: .randomId),
untilDate: try container.decode(Int32.self, forKey: .untilDate),
users: try container.decode(Int32.self, forKey: .users)
)
default: default:
throw DecodingError.generic throw DecodingError.generic
} }
@ -723,6 +739,18 @@ private final class PendingInAppPurchaseState: Codable {
try container.encode(PurposeType.starsGift.rawValue, forKey: .type) try container.encode(PurposeType.starsGift.rawValue, forKey: .type)
try container.encode(peerId.toInt64(), forKey: .peer) try container.encode(peerId.toInt64(), forKey: .peer)
try container.encode(count, forKey: .stars) try container.encode(count, forKey: .stars)
case let .starsGiveaway(stars, boostPeer, additionalPeerIds, countries, onlyNewSubscribers, showWinners, prizeDescription, randomId, untilDate, users):
try container.encode(PurposeType.starsGiveaway.rawValue, forKey: .type)
try container.encode(stars, forKey: .stars)
try container.encode(boostPeer.toInt64(), forKey: .boostPeer)
try container.encode(additionalPeerIds.map { $0.toInt64() }, forKey: .additionalPeerIds)
try container.encode(countries, forKey: .countries)
try container.encode(onlyNewSubscribers, forKey: .onlyNewSubscribers)
try container.encode(showWinners, forKey: .showWinners)
try container.encodeIfPresent(prizeDescription, forKey: .prizeDescription)
try container.encode(randomId, forKey: .randomId)
try container.encode(untilDate, forKey: .untilDate)
try container.encode(users, forKey: .users)
} }
} }
@ -744,6 +772,8 @@ private final class PendingInAppPurchaseState: Codable {
self = .stars(count: count) self = .stars(count: count)
case let .starsGift(peerId, count, _, _): case let .starsGift(peerId, count, _, _):
self = .starsGift(peerId: peerId, count: count) self = .starsGift(peerId: peerId, count: count)
case let .starsGiveaway(stars, boostPeer, additionalPeerIds, countries, onlyNewSubscribers, showWinners, prizeDescription, randomId, untilDate, _, _, users):
self = .starsGiveaway(stars: stars, boostPeer: boostPeer, additionalPeerIds: additionalPeerIds, countries: countries, onlyNewSubscribers: onlyNewSubscribers, showWinners: showWinners, prizeDescription: prizeDescription, randomId: randomId, untilDate: untilDate, users: users)
} }
} }
@ -766,6 +796,8 @@ private final class PendingInAppPurchaseState: Codable {
return .stars(count: count, currency: currency, amount: amount) return .stars(count: count, currency: currency, amount: amount)
case let .starsGift(peerId, count): case let .starsGift(peerId, count):
return .starsGift(peerId: peerId, count: count, currency: currency, amount: amount) return .starsGift(peerId: peerId, count: count, currency: currency, amount: amount)
case let .starsGiveaway(stars, boostPeer, additionalPeerIds, countries, onlyNewSubscribers, showWinners, prizeDescription, randomId, untilDate, users):
return .starsGiveaway(stars: stars, boostPeer: boostPeer, additionalPeerIds: additionalPeerIds, countries: countries, onlyNewSubscribers: onlyNewSubscribers, showWinners: showWinners, prizeDescription: prizeDescription, randomId: randomId, untilDate: untilDate, currency: currency, amount: amount, users: users)
} }
} }
} }

View File

@ -33,8 +33,9 @@ private final class CreateGiveawayControllerArguments {
let scrollToDescription: () -> Void let scrollToDescription: () -> Void
let setItemIdWithRevealedOptions: (EnginePeer.Id?, EnginePeer.Id?) -> Void let setItemIdWithRevealedOptions: (EnginePeer.Id?, EnginePeer.Id?) -> Void
let removeChannel: (EnginePeer.Id) -> Void let removeChannel: (EnginePeer.Id) -> Void
let expandStars: () -> Void
init(context: AccountContext, updateState: @escaping ((CreateGiveawayControllerState) -> CreateGiveawayControllerState) -> Void, dismissInput: @escaping () -> Void, openPeersSelection: @escaping () -> Void, openChannelsSelection: @escaping () -> Void, openCountriesSelection: @escaping () -> Void, openPremiumIntro: @escaping () -> Void, scrollToDate: @escaping () -> Void, scrollToDescription: @escaping () -> Void, setItemIdWithRevealedOptions: @escaping (EnginePeer.Id?, EnginePeer.Id?) -> Void, removeChannel: @escaping (EnginePeer.Id) -> Void) { init(context: AccountContext, updateState: @escaping ((CreateGiveawayControllerState) -> CreateGiveawayControllerState) -> Void, dismissInput: @escaping () -> Void, openPeersSelection: @escaping () -> Void, openChannelsSelection: @escaping () -> Void, openCountriesSelection: @escaping () -> Void, openPremiumIntro: @escaping () -> Void, scrollToDate: @escaping () -> Void, scrollToDescription: @escaping () -> Void, setItemIdWithRevealedOptions: @escaping (EnginePeer.Id?, EnginePeer.Id?) -> Void, removeChannel: @escaping (EnginePeer.Id) -> Void, expandStars: @escaping () -> Void) {
self.context = context self.context = context
self.updateState = updateState self.updateState = updateState
self.dismissInput = dismissInput self.dismissInput = dismissInput
@ -46,12 +47,14 @@ private final class CreateGiveawayControllerArguments {
self.scrollToDescription = scrollToDescription self.scrollToDescription = scrollToDescription
self.setItemIdWithRevealedOptions = setItemIdWithRevealedOptions self.setItemIdWithRevealedOptions = setItemIdWithRevealedOptions
self.removeChannel = removeChannel self.removeChannel = removeChannel
self.expandStars = expandStars
} }
} }
private enum CreateGiveawaySection: Int32 { private enum CreateGiveawaySection: Int32 {
case header case header
case mode case mode
case stars
case subscriptions case subscriptions
case channels case channels
case users case users
@ -77,14 +80,20 @@ private enum CreateGiveawayEntryTag: ItemListItemTag {
private enum CreateGiveawayEntry: ItemListNodeEntry { private enum CreateGiveawayEntry: ItemListNodeEntry {
case header(PresentationTheme, String, String) case header(PresentationTheme, String, String)
case createGiveaway(PresentationTheme, String, String, Bool) case modeHeader(PresentationTheme, String)
case awardUsers(PresentationTheme, String, String, Bool) case giftPremium(PresentationTheme, String, String, Bool)
case giftStars(PresentationTheme, String, String, Bool)
case prepaidHeader(PresentationTheme, String) case prepaidHeader(PresentationTheme, String)
case prepaid(PresentationTheme, String, String, PrepaidGiveaway) case prepaid(PresentationTheme, String, String, PrepaidGiveaway)
case starsHeader(PresentationTheme, String, String)
case stars(Int32, PresentationTheme, Int32, String, String, String, Bool)
case starsMore(PresentationTheme, String)
case starsInfo(PresentationTheme, String)
case subscriptionsHeader(PresentationTheme, String, String) case subscriptionsHeader(PresentationTheme, String, String)
case subscriptions(PresentationTheme, Int32) case subscriptions(PresentationTheme, Int32, [Int32])
case subscriptionsInfo(PresentationTheme, String) case subscriptionsInfo(PresentationTheme, String)
case channelsHeader(PresentationTheme, String) case channelsHeader(PresentationTheme, String)
@ -117,8 +126,10 @@ private enum CreateGiveawayEntry: ItemListNodeEntry {
switch self { switch self {
case .header: case .header:
return CreateGiveawaySection.header.rawValue return CreateGiveawaySection.header.rawValue
case .createGiveaway, .awardUsers, .prepaidHeader, .prepaid: case .modeHeader, .giftPremium, .giftStars, .prepaidHeader, .prepaid:
return CreateGiveawaySection.mode.rawValue return CreateGiveawaySection.mode.rawValue
case .starsHeader, .stars, .starsMore, .starsInfo:
return CreateGiveawaySection.stars.rawValue
case .subscriptionsHeader, .subscriptions, .subscriptionsInfo: case .subscriptionsHeader, .subscriptions, .subscriptionsInfo:
return CreateGiveawaySection.subscriptions.rawValue return CreateGiveawaySection.subscriptions.rawValue
case .channelsHeader, .channel, .channelAdd, .channelsInfo: case .channelsHeader, .channel, .channelAdd, .channelsInfo:
@ -139,61 +150,71 @@ private enum CreateGiveawayEntry: ItemListNodeEntry {
var stableId: Int32 { var stableId: Int32 {
switch self { switch self {
case .header: case .header:
return -2
case .modeHeader:
return -1 return -1
case .createGiveaway: case .giftPremium:
return 0 return 0
case .awardUsers: case .giftStars:
return 1 return 1
case .prepaidHeader: case .prepaidHeader:
return 2 return 2
case .prepaid: case .prepaid:
return 3 return 3
case .subscriptionsHeader: case .starsHeader:
return 4 return 4
case let .stars(_, _, stars, _, _, _, _):
return 5 + stars
case .starsMore:
return 100000
case .starsInfo:
return 100001
case .subscriptionsHeader:
return 100002
case .subscriptions: case .subscriptions:
return 5 return 100003
case .subscriptionsInfo: case .subscriptionsInfo:
return 6 return 100004
case .channelsHeader: case .channelsHeader:
return 7 return 100005
case let .channel(index, _, _, _, _): case let .channel(index, _, _, _, _):
return 8 + index return 100006 + index
case .channelAdd: case .channelAdd:
return 100 return 100200
case .channelsInfo: case .channelsInfo:
return 101 return 100201
case .usersHeader: case .usersHeader:
return 102 return 100202
case .usersAll: case .usersAll:
return 103 return 100203
case .usersNew: case .usersNew:
return 104 return 100204
case .usersInfo: case .usersInfo:
return 105 return 100205
case .durationHeader: case .durationHeader:
return 106 return 100206
case let .duration(index, _, _, _, _, _, _, _): case let .duration(index, _, _, _, _, _, _, _):
return 107 + index return 100207 + index
case .durationInfo: case .durationInfo:
return 200 return 100300
case .prizeDescription: case .prizeDescription:
return 201 return 100301
case .prizeDescriptionText: case .prizeDescriptionText:
return 202 return 100302
case .prizeDescriptionInfo: case .prizeDescriptionInfo:
return 203 return 100303
case .winners:
return 204
case .winnersInfo:
return 205
case .timeHeader: case .timeHeader:
return 206 return 100304
case .timeExpiryDate: case .timeExpiryDate:
return 207 return 100305
case .timeCustomPicker: case .timeCustomPicker:
return 208 return 100306
case .timeInfo: case .timeInfo:
return 209 return 100307
case .winners:
return 100308
case .winnersInfo:
return 100309
} }
} }
@ -205,14 +226,20 @@ private enum CreateGiveawayEntry: ItemListNodeEntry {
} else { } else {
return false return false
} }
case let .createGiveaway(lhsTheme, lhsText, lhsSubtext, lhsSelected): case let .modeHeader(lhsTheme, lhsText):
if case let .createGiveaway(rhsTheme, rhsText, rhsSubtext, rhsSelected) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsSubtext == rhsSubtext, lhsSelected == rhsSelected { if case let .modeHeader(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
return true return true
} else { } else {
return false return false
} }
case let .awardUsers(lhsTheme, lhsText, lhsSubtext, lhsSelected): case let .giftPremium(lhsTheme, lhsText, lhsSubtext, lhsSelected):
if case let .awardUsers(rhsTheme, rhsText, rhsSubtext, rhsSelected) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsSubtext == rhsSubtext, lhsSelected == rhsSelected { if case let .giftPremium(rhsTheme, rhsText, rhsSubtext, rhsSelected) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsSubtext == rhsSubtext, lhsSelected == rhsSelected {
return true
} else {
return false
}
case let .giftStars(lhsTheme, lhsText, lhsSubtext, lhsSelected):
if case let .giftStars(rhsTheme, rhsText, rhsSubtext, rhsSelected) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsSubtext == rhsSubtext, lhsSelected == rhsSelected {
return true return true
} else { } else {
return false return false
@ -229,14 +256,38 @@ private enum CreateGiveawayEntry: ItemListNodeEntry {
} else { } else {
return false return false
} }
case let .starsHeader(lhsTheme, lhsText, lhsAdditionalText):
if case let .starsHeader(rhsTheme, rhsText, rhsAdditionalText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsAdditionalText == rhsAdditionalText {
return true
} else {
return false
}
case let .stars(lhsIndex, lhsTheme, lhsStars, lhsTitle, lhsSubtitle, lhsLabel, lhsIsSelected):
if case let .stars(rhsIndex, rhsTheme, rhsStars, rhsTitle, rhsSubtitle, rhsLabel, rhsIsSelected) = rhs, lhsIndex == rhsIndex, lhsTheme === rhsTheme, lhsStars == rhsStars, lhsTitle == rhsTitle, lhsSubtitle == rhsSubtitle, lhsLabel == rhsLabel, lhsIsSelected == rhsIsSelected {
return true
} else {
return false
}
case let .starsMore(lhsTheme, lhsText):
if case let .starsMore(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
return true
} else {
return false
}
case let .starsInfo(lhsTheme, lhsText):
if case let .starsInfo(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
return true
} else {
return false
}
case let .subscriptionsHeader(lhsTheme, lhsText, lhsAdditionalText): case let .subscriptionsHeader(lhsTheme, lhsText, lhsAdditionalText):
if case let .subscriptionsHeader(rhsTheme, rhsText, rhsAdditionalText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsAdditionalText == rhsAdditionalText { if case let .subscriptionsHeader(rhsTheme, rhsText, rhsAdditionalText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsAdditionalText == rhsAdditionalText {
return true return true
} else { } else {
return false return false
} }
case let .subscriptions(lhsTheme, lhsValue): case let .subscriptions(lhsTheme, lhsValue, lhsValues):
if case let .subscriptions(rhsTheme, rhsValue) = rhs, lhsTheme === rhsTheme, lhsValue == rhsValue { if case let .subscriptions(rhsTheme, rhsValue, rhsValues) = rhs, lhsTheme === rhsTheme, lhsValue == rhsValue, lhsValues == rhsValues {
return true return true
} else { } else {
return false return false
@ -379,29 +430,31 @@ private enum CreateGiveawayEntry: ItemListNodeEntry {
switch self { switch self {
case let .header(_, title, text): case let .header(_, title, text):
return ItemListTextItem(presentationData: presentationData, text: .plain(title + text), sectionId: self.section) return ItemListTextItem(presentationData: presentationData, text: .plain(title + text), sectionId: self.section)
case let .createGiveaway(_, title, subtitle, isSelected): case let .modeHeader(_, text):
return GiftOptionItem(presentationData: presentationData, context: arguments.context, icon: .image(color: .blue, name: "Premium/Giveaway"), title: title, subtitle: subtitle, isSelected: isSelected, sectionId: self.section, action: { return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
arguments.updateState { state in case let .giftPremium(_, title, subtitle, isSelected):
var updatedState = state return GiftOptionItem(presentationData: presentationData, context: arguments.context, icon: .image(color: .premium, name: "Peer Info/PremiumIcon"), title: title, subtitle: subtitle, subtitleActive: true, isSelected: isSelected, sectionId: self.section, action: {
updatedState.mode = .giveaway
return updatedState
}
})
case let .awardUsers(_, title, subtitle, isSelected):
return GiftOptionItem(presentationData: presentationData, context: arguments.context, icon: .image(color: .violet, name: "Media Editor/Privacy/SelectedUsers"), title: title, subtitle: subtitle, subtitleActive: true, isSelected: isSelected, sectionId: self.section, action: {
var openSelection = false var openSelection = false
arguments.updateState { state in arguments.updateState { state in
var updatedState = state var updatedState = state
if state.mode == .gift || state.peers.isEmpty { if (state.mode == .giveaway && state.peers.isEmpty) {
openSelection = true openSelection = true
} }
updatedState.mode = .gift updatedState.mode = .giveaway
return updatedState return updatedState
} }
if openSelection { if openSelection {
arguments.openPeersSelection() arguments.openPeersSelection()
} }
}) })
case let .giftStars(_, title, subtitle, isSelected):
return GiftOptionItem(presentationData: presentationData, context: arguments.context, icon: .image(color: .stars, name: "Peer Info/PremiumIcon"), title: title, subtitle: subtitle, subtitleActive: false, isSelected: isSelected, sectionId: self.section, action: {
arguments.updateState { state in
var updatedState = state
updatedState.mode = .starsGiveaway
return updatedState
}
})
case let .prepaidHeader(_, text): case let .prepaidHeader(_, text):
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section) return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
case let .prepaid(_, title, subtitle, prepaidGiveaway): case let .prepaid(_, title, subtitle, prepaidGiveaway):
@ -417,13 +470,33 @@ private enum CreateGiveawayEntry: ItemListNodeEntry {
color = .blue color = .blue
} }
return GiftOptionItem(presentationData: presentationData, context: arguments.context, icon: .image(color: color, name: "Premium/Giveaway"), title: title, titleFont: .bold, titleBadge: "\(prepaidGiveaway.quantity * 4)", subtitle: subtitle, sectionId: self.section, action: nil) return GiftOptionItem(presentationData: presentationData, context: arguments.context, icon: .image(color: color, name: "Premium/Giveaway"), title: title, titleFont: .bold, titleBadge: "\(prepaidGiveaway.quantity * 4)", subtitle: subtitle, sectionId: self.section, action: nil)
case let .subscriptionsHeader(_, text, additionalText): case let .starsHeader(_, text, additionalText):
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, accessoryText: ItemListSectionHeaderAccessoryText(value: additionalText, color: .generic), sectionId: self.section) return ItemListSectionHeaderItem(presentationData: presentationData, text: text, accessoryText: ItemListSectionHeaderAccessoryText(value: additionalText, color: .generic), sectionId: self.section)
case let .subscriptions(_, value): case let .stars(_, _, stars, title, subtitle, label, isSelected):
return SubscriptionsCountItem(theme: presentationData.theme, strings: presentationData.strings, value: value, sectionId: self.section, updated: { value in return GiftOptionItem(presentationData: presentationData, context: arguments.context, title: title, subtitle: subtitle, subtitleFont: .small, label: .generic(label), badge: nil, isSelected: isSelected, stars: Int64(stars), sectionId: self.section, action: {
arguments.updateState { state in arguments.updateState { state in
var updatedState = state var updatedState = state
updatedState.subscriptions = value updatedState.stars = Int64(stars)
return updatedState
}
})
case let .starsMore(theme, title):
return ItemListPeerActionItem(presentationData: presentationData, icon: PresentationResourcesItemList.downArrowImage(theme), title: title, sectionId: self.section, editing: false, action: {
arguments.expandStars()
})
case let .starsInfo(_, text):
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section)
case let .subscriptionsHeader(_, text, additionalText):
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, accessoryText: ItemListSectionHeaderAccessoryText(value: additionalText, color: .generic), sectionId: self.section)
case let .subscriptions(_, value, values):
return SubscriptionsCountItem(theme: presentationData.theme, strings: presentationData.strings, value: value, values: values, sectionId: self.section, updated: { value in
arguments.updateState { state in
var updatedState = state
if state.mode == .giveaway {
updatedState.subscriptions = value
} else if state.mode == .starsGiveaway {
updatedState.winners = value
}
return updatedState return updatedState
} }
}) })
@ -626,6 +699,19 @@ private struct PremiumGiftProduct: Equatable {
} }
} }
private struct StarsGiveawayProduct: Equatable {
let giveawayOption: StarsGiveawayOption
let storeProduct: InAppPurchaseManager.Product
var id: String {
return self.storeProduct.id
}
var price: String {
return self.storeProduct.price
}
}
private func createGiveawayControllerEntries( private func createGiveawayControllerEntries(
peerId: EnginePeer.Id, peerId: EnginePeer.Id,
subject: CreateGiveawaySubject, subject: CreateGiveawaySubject,
@ -635,6 +721,7 @@ private func createGiveawayControllerEntries(
peers: [EnginePeer.Id: EnginePeer], peers: [EnginePeer.Id: EnginePeer],
products: [PremiumGiftProduct], products: [PremiumGiftProduct],
defaultPrice: (Int64, NSDecimalNumber), defaultPrice: (Int64, NSDecimalNumber),
starsGiveawayOptions: [StarsGiveawayProduct],
minDate: Int32, minDate: Int32,
maxDate: Int32 maxDate: Int32
) -> [CreateGiveawayEntry] { ) -> [CreateGiveawayEntry] {
@ -647,10 +734,8 @@ private func createGiveawayControllerEntries(
switch subject { switch subject {
case .generic: case .generic:
entries.append(.createGiveaway(presentationData.theme, presentationData.strings.BoostGift_CreateGiveaway, presentationData.strings.BoostGift_CreateGiveawayInfo, state.mode == .giveaway))
let recipientsText: String let recipientsText: String
if !state.peers.isEmpty { if !state.peers.isEmpty && state.mode == .gift {
var peerNamesArray: [String] = [] var peerNamesArray: [String] = []
let peersCount = state.peers.count let peersCount = state.peers.count
for peerId in state.peers.prefix(2) { for peerId in state.peers.prefix(2) {
@ -665,14 +750,47 @@ private func createGiveawayControllerEntries(
recipientsText = presentationData.strings.PremiumGift_LabelRecipients(Int32(peersCount)) recipientsText = presentationData.strings.PremiumGift_LabelRecipients(Int32(peersCount))
} }
} else { } else {
recipientsText = presentationData.strings.BoostGift_SelectRecipients recipientsText = presentationData.strings.BoostGift_CreateGiveawayInfo //presentationData.strings.BoostGift_SelectRecipients
} }
entries.append(.awardUsers(presentationData.theme, presentationData.strings.BoostGift_AwardSpecificUsers, recipientsText, state.mode == .gift))
//TODO:localize
entries.append(.modeHeader(presentationData.theme, "PRIZE"))
entries.append(.giftPremium(presentationData.theme, "Telegram Premium", recipientsText, state.mode == .giveaway || state.mode == .gift))
entries.append(.giftStars(presentationData.theme, "Telegram Stars", presentationData.strings.BoostGift_CreateGiveawayInfo, state.mode == .starsGiveaway))
case let .prepaid(prepaidGiveaway): case let .prepaid(prepaidGiveaway):
entries.append(.prepaidHeader(presentationData.theme, presentationData.strings.BoostGift_PrepaidGiveawayTitle)) entries.append(.prepaidHeader(presentationData.theme, presentationData.strings.BoostGift_PrepaidGiveawayTitle))
entries.append(.prepaid(presentationData.theme, presentationData.strings.BoostGift_PrepaidGiveawayCount(prepaidGiveaway.quantity), presentationData.strings.BoostGift_PrepaidGiveawayMonths("\(prepaidGiveaway.months)").string, prepaidGiveaway)) entries.append(.prepaid(presentationData.theme, presentationData.strings.BoostGift_PrepaidGiveawayCount(prepaidGiveaway.quantity), presentationData.strings.BoostGift_PrepaidGiveawayMonths("\(prepaidGiveaway.months)").string, prepaidGiveaway))
} }
if case .starsGiveaway = state.mode, !starsGiveawayOptions.isEmpty {
let selectedOption = starsGiveawayOptions.first(where: { $0.giveawayOption.count == state.stars })!
entries.append(.starsHeader(presentationData.theme, "STARS TO DISTRIBUTE".uppercased(), "\(selectedOption.giveawayOption.yearlyBoosts) BOOSTS"))
var i: Int32 = 0
for product in starsGiveawayOptions {
if !state.starsExpanded && product.giveawayOption.isExtended {
continue
}
let giftTitle: String = "\(product.giveawayOption.count) Stars"
let winners = product.giveawayOption.winners.first(where: { $0.users == state.winners }) ?? product.giveawayOption.winners.first!
let subtitle = "\(winners.starsPerUser) per user"
let label = product.storeProduct.price
let isSelected = product.giveawayOption.count == state.stars
entries.append(.stars(i, presentationData.theme, Int32(product.giveawayOption.count), giftTitle, subtitle, label, isSelected))
i += 1
}
if !state.starsExpanded {
entries.append(.starsMore(presentationData.theme, "Show More Options"))
}
entries.append(.starsInfo(presentationData.theme, "Choose how many stars to give away and how many boosts to receive for 1 year."))
}
let appendDurationEntries = { let appendDurationEntries = {
entries.append(.durationHeader(presentationData.theme, presentationData.strings.BoostGift_DurationTitle.uppercased())) entries.append(.durationHeader(presentationData.theme, presentationData.strings.BoostGift_DurationTitle.uppercased()))
@ -682,6 +800,8 @@ private func createGiveawayControllerEntries(
recipientCount = Int(state.subscriptions) recipientCount = Int(state.subscriptions)
case .gift: case .gift:
recipientCount = state.peers.count recipientCount = state.peers.count
case .starsGiveaway:
recipientCount = Int(state.subscriptions)
} }
var i: Int32 = 0 var i: Int32 = 0
@ -721,11 +841,21 @@ private func createGiveawayControllerEntries(
} }
switch state.mode { switch state.mode {
case .giveaway: case .giveaway, .starsGiveaway:
if case .generic = subject { if case .starsGiveaway = state.mode {
entries.append(.subscriptionsHeader(presentationData.theme, presentationData.strings.BoostGift_QuantityTitle.uppercased(), presentationData.strings.BoostGift_QuantityBoosts(state.subscriptions * 4))) var values: [Int32] = [1]
entries.append(.subscriptions(presentationData.theme, state.subscriptions)) if let selectedOption = starsGiveawayOptions.first(where: { $0.giveawayOption.count == state.stars }) {
entries.append(.subscriptionsInfo(presentationData.theme, presentationData.strings.BoostGift_QuantityInfo)) values = selectedOption.giveawayOption.winners.map { $0.users }
}
entries.append(.subscriptionsHeader(presentationData.theme, "NUMBER OF WINNERS", ""))
entries.append(.subscriptions(presentationData.theme, state.winners, values))
entries.append(.subscriptionsInfo(presentationData.theme, "Choose how many winners you want to distribute stars among."))
} else {
if case .generic = subject {
entries.append(.subscriptionsHeader(presentationData.theme, presentationData.strings.BoostGift_QuantityTitle.uppercased(), presentationData.strings.BoostGift_QuantityBoosts(state.subscriptions * 4)))
entries.append(.subscriptions(presentationData.theme, state.subscriptions, [1, 3, 5, 7, 10, 25, 50]))
entries.append(.subscriptionsInfo(presentationData.theme, presentationData.strings.BoostGift_QuantityInfo))
}
} }
entries.append(.channelsHeader(presentationData.theme, isGroup ? presentationData.strings.BoostGift_GroupsAndChannelsTitle.uppercased() : presentationData.strings.BoostGift_ChannelsAndGroupsTitle.uppercased())) entries.append(.channelsHeader(presentationData.theme, isGroup ? presentationData.strings.BoostGift_GroupsAndChannelsTitle.uppercased() : presentationData.strings.BoostGift_ChannelsAndGroupsTitle.uppercased()))
@ -765,12 +895,16 @@ private func createGiveawayControllerEntries(
entries.append(.usersNew(presentationData.theme, isGroup ? presentationData.strings.BoostGift_Group_OnlyNewMembers : presentationData.strings.BoostGift_OnlyNewSubscribers, countriesText, state.onlyNewEligible)) entries.append(.usersNew(presentationData.theme, isGroup ? presentationData.strings.BoostGift_Group_OnlyNewMembers : presentationData.strings.BoostGift_OnlyNewSubscribers, countriesText, state.onlyNewEligible))
entries.append(.usersInfo(presentationData.theme, isGroup ? presentationData.strings.BoostGift_Group_LimitMembersInfo : presentationData.strings.BoostGift_LimitSubscribersInfo)) entries.append(.usersInfo(presentationData.theme, isGroup ? presentationData.strings.BoostGift_Group_LimitMembersInfo : presentationData.strings.BoostGift_LimitSubscribersInfo))
if case .generic = subject { if case .starsGiveaway = state.mode {
appendDurationEntries()
} else {
if case .generic = subject {
appendDurationEntries()
}
} }
entries.append(.prizeDescription(presentationData.theme, presentationData.strings.BoostGift_AdditionalPrizes, state.showPrizeDescription)) entries.append(.prizeDescription(presentationData.theme, presentationData.strings.BoostGift_AdditionalPrizes, state.showPrizeDescription))
var prizeDescriptionInfoText = presentationData.strings.BoostGift_AdditionalPrizesInfoOff var prizeDescriptionInfoText = state.mode == .starsGiveaway ? "Turn this on if you want to give the winners your own prizes in addition to Stars." : presentationData.strings.BoostGift_AdditionalPrizesInfoOff
if state.showPrizeDescription { if state.showPrizeDescription {
entries.append(.prizeDescriptionText(presentationData.theme, presentationData.strings.BoostGift_AdditionalPrizesPlaceholder, state.prizeDescription, state.subscriptions)) entries.append(.prizeDescriptionText(presentationData.theme, presentationData.strings.BoostGift_AdditionalPrizesPlaceholder, state.prizeDescription, state.subscriptions))
@ -785,18 +919,28 @@ private func createGiveawayControllerEntries(
} }
} }
entries.append(.prizeDescriptionInfo(presentationData.theme, prizeDescriptionInfoText)) entries.append(.prizeDescriptionInfo(presentationData.theme, prizeDescriptionInfoText))
entries.append(.winners(presentationData.theme, presentationData.strings.BoostGift_Winners, state.showWinners))
entries.append(.winnersInfo(presentationData.theme, presentationData.strings.BoostGift_WinnersInfo))
entries.append(.timeHeader(presentationData.theme, presentationData.strings.BoostGift_DateTitle.uppercased())) entries.append(.timeHeader(presentationData.theme, presentationData.strings.BoostGift_DateTitle.uppercased()))
entries.append(.timeCustomPicker(presentationData.theme, presentationData.dateTimeFormat, state.time, minDate, maxDate, state.pickingExpiryDate, state.pickingExpiryTime)) entries.append(.timeCustomPicker(presentationData.theme, presentationData.dateTimeFormat, state.time, minDate, maxDate, state.pickingExpiryDate, state.pickingExpiryTime))
let timeInfoText: String
if isGroup { if isGroup {
entries.append(.timeInfo(presentationData.theme, presentationData.strings.BoostGift_Group_DateInfo(presentationData.strings.BoostGift_Group_DateInfoMembers(Int32(state.subscriptions))).string)) if case .starsGiveaway = state.mode {
timeInfoText = "Choose when \(presentationData.strings.BoostGift_Group_DateInfoMembers(Int32(state.winners))) of your group will be randomly selected to receive Stars."
} else {
timeInfoText = presentationData.strings.BoostGift_Group_DateInfo(presentationData.strings.BoostGift_Group_DateInfoMembers(Int32(state.subscriptions))).string
}
} else { } else {
entries.append(.timeInfo(presentationData.theme, presentationData.strings.BoostGift_DateInfo(presentationData.strings.BoostGift_DateInfoSubscribers(Int32(state.subscriptions))).string)) if case .starsGiveaway = state.mode {
timeInfoText = "Choose when \(presentationData.strings.BoostGift_DateInfoSubscribers(Int32(state.winners))) of your channel will be randomly selected to receive Stars."
} else {
timeInfoText = presentationData.strings.BoostGift_DateInfo(presentationData.strings.BoostGift_DateInfoSubscribers(Int32(state.subscriptions))).string
}
} }
entries.append(.timeInfo(presentationData.theme, timeInfoText))
entries.append(.winners(presentationData.theme, presentationData.strings.BoostGift_Winners, state.showWinners))
entries.append(.winnersInfo(presentationData.theme, presentationData.strings.BoostGift_WinnersInfo))
case .gift: case .gift:
appendDurationEntries() appendDurationEntries()
} }
@ -808,10 +952,13 @@ private struct CreateGiveawayControllerState: Equatable {
enum Mode { enum Mode {
case giveaway case giveaway
case gift case gift
case starsGiveaway
} }
var mode: Mode var mode: Mode
var subscriptions: Int32 var subscriptions: Int32
var stars: Int64
var winners: Int32
var channels: [EnginePeer.Id] = [] var channels: [EnginePeer.Id] = []
var peers: [EnginePeer.Id] = [] var peers: [EnginePeer.Id] = []
var selectedMonths: Int32? var selectedMonths: Int32?
@ -825,6 +972,7 @@ private struct CreateGiveawayControllerState: Equatable {
var pickingExpiryDate = false var pickingExpiryDate = false
var revealedItemId: EnginePeer.Id? = nil var revealedItemId: EnginePeer.Id? = nil
var updating = false var updating = false
var starsExpanded = false
} }
public enum CreateGiveawaySubject { public enum CreateGiveawaySubject {
@ -857,7 +1005,7 @@ public func createGiveawayController(context: AccountContext, updatedPresentatio
let minDate = currentTime + 60 * 1 let minDate = currentTime + 60 * 1
let maxDate = currentTime + context.userLimits.maxGiveawayPeriodSeconds let maxDate = currentTime + context.userLimits.maxGiveawayPeriodSeconds
let initialState: CreateGiveawayControllerState = CreateGiveawayControllerState(mode: .giveaway, subscriptions: initialSubscriptions, time: expiryTime) let initialState: CreateGiveawayControllerState = CreateGiveawayControllerState(mode: .giveaway, subscriptions: initialSubscriptions, stars: 500, winners: 5, time: expiryTime)
let statePromise = ValuePromise(initialState, ignoreRepeated: true) let statePromise = ValuePromise(initialState, ignoreRepeated: true)
let stateValue = Atomic(value: initialState) let stateValue = Atomic(value: initialState)
@ -868,6 +1016,7 @@ public func createGiveawayController(context: AccountContext, updatedPresentatio
let isGroupValue = Atomic<Bool>(value: false) let isGroupValue = Atomic<Bool>(value: false)
let productsValue = Atomic<[PremiumGiftProduct]?>(value: nil) let productsValue = Atomic<[PremiumGiftProduct]?>(value: nil)
let starsValue = Atomic<[StarsGiveawayProduct]?>(value: nil)
var buyActionImpl: (() -> Void)? var buyActionImpl: (() -> Void)?
var openPeersSelectionImpl: (() -> Void)? var openPeersSelectionImpl: (() -> Void)?
@ -912,6 +1061,13 @@ public func createGiveawayController(context: AccountContext, updatedPresentatio
updatedState.channels = updatedState.channels.filter { $0 != id } updatedState.channels = updatedState.channels.filter { $0 != id }
return updatedState return updatedState
} }
},
expandStars: {
updateState { state in
var updatedState = state
updatedState.starsExpanded = true
return updatedState
}
}) })
let presentationData = updatedPresentationData?.signal ?? context.sharedContext.presentationData let presentationData = updatedPresentationData?.signal ?? context.sharedContext.presentationData
@ -938,6 +1094,20 @@ public func createGiveawayController(context: AccountContext, updatedPresentatio
return (gifts, defaultPrice) return (gifts, defaultPrice)
} }
let starsGiveawayOptions: Signal<[StarsGiveawayProduct], NoError> = combineLatest(
.single([]) |> then(context.engine.payments.starsGiveawayOptions()),
context.inAppPurchaseManager?.availableProducts ?? .single([])
)
|> map { options, products in
var result: [StarsGiveawayProduct] = []
for option in options {
if let product = products.first(where: { $0.id == option.storeProductId }), !product.isSubscription {
result.append(StarsGiveawayProduct(giveawayOption: option, storeProduct: product))
}
}
return result
}
let previousState = Atomic<CreateGiveawayControllerState?>(value: nil) let previousState = Atomic<CreateGiveawayControllerState?>(value: nil)
let signal = combineLatest( let signal = combineLatest(
presentationData, presentationData,
@ -952,10 +1122,11 @@ public func createGiveawayController(context: AccountContext, updatedPresentatio
return (state, peers) return (state, peers)
} }
}, },
productsAndDefaultPrice productsAndDefaultPrice,
starsGiveawayOptions
) )
|> deliverOnMainQueue |> deliverOnMainQueue
|> map { presentationData, stateAndPeersMap, productsAndDefaultPrice -> (ItemListControllerState, (ItemListNodeState, Any)) in |> map { presentationData, stateAndPeersMap, productsAndDefaultPrice, starsGiveawayOptions -> (ItemListControllerState, (ItemListNodeState, Any)) in
var presentationData = presentationData var presentationData = presentationData
let (products, defaultPrice) = productsAndDefaultPrice let (products, defaultPrice) = productsAndDefaultPrice
@ -971,7 +1142,9 @@ public func createGiveawayController(context: AccountContext, updatedPresentatio
} }
let _ = isGroupValue.swap(isGroup) let _ = isGroupValue.swap(isGroup)
let headerItem = CreateGiveawayHeaderItem(theme: presentationData.theme, strings: presentationData.strings, title: presentationData.strings.BoostGift_Title, text: isGroup ? presentationData.strings.BoostGift_Group_Description : presentationData.strings.BoostGift_Description, cancel: { //TODO:localize
let headerText = isGroup ? "Get more boosts and members for\nyour group by giving away prizes." : "Get more boosts and subscribers for\nyour channel by giving away prizes."
let headerItem = CreateGiveawayHeaderItem(theme: presentationData.theme, strings: presentationData.strings, title: presentationData.strings.BoostGift_Title, text: headerText, cancel: {
dismissImpl?() dismissImpl?()
}) })
@ -981,6 +1154,8 @@ public func createGiveawayController(context: AccountContext, updatedPresentatio
badgeCount = state.subscriptions * 4 badgeCount = state.subscriptions * 4
case .gift: case .gift:
badgeCount = Int32(state.peers.count) * 4 badgeCount = Int32(state.peers.count) * 4
case .starsGiveaway:
badgeCount = Int32(state.stars) / 500
} }
let footerItem = CreateGiveawayFooterItem(theme: presentationData.theme, title: state.mode == .gift ? presentationData.strings.BoostGift_GiftPremium : presentationData.strings.BoostGift_StartGiveaway, badgeCount: badgeCount, isLoading: state.updating, action: { let footerItem = CreateGiveawayFooterItem(theme: presentationData.theme, title: state.mode == .gift ? presentationData.strings.BoostGift_GiftPremium : presentationData.strings.BoostGift_StartGiveaway, badgeCount: badgeCount, isLoading: state.updating, action: {
if case .prepaid = subject { if case .prepaid = subject {
@ -995,6 +1170,10 @@ public func createGiveawayController(context: AccountContext, updatedPresentatio
let leftNavigationButton = ItemListNavigationButton(content: .none, style: .regular, enabled: false, action: {}) let leftNavigationButton = ItemListNavigationButton(content: .none, style: .regular, enabled: false, action: {})
let _ = productsValue.swap(products) let _ = productsValue.swap(products)
let previousStars = starsValue.swap(starsGiveawayOptions)
if (previousStars ?? []).isEmpty && !starsGiveawayOptions.isEmpty {
}
let previousState = previousState.swap(state) let previousState = previousState.swap(state)
var animateChanges = false var animateChanges = false
@ -1014,6 +1193,9 @@ public func createGiveawayController(context: AccountContext, updatedPresentatio
if previousState.showPrizeDescription != state.showPrizeDescription { if previousState.showPrizeDescription != state.showPrizeDescription {
animateChanges = true animateChanges = true
} }
if previousState.starsExpanded != state.starsExpanded {
animateChanges = true
}
} }
var peers: [EnginePeer.Id: EnginePeer] = [:] var peers: [EnginePeer.Id: EnginePeer] = [:]
@ -1024,7 +1206,7 @@ public func createGiveawayController(context: AccountContext, updatedPresentatio
} }
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(""), leftNavigationButton: leftNavigationButton, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true) let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(""), leftNavigationButton: leftNavigationButton, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true)
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: createGiveawayControllerEntries(peerId: peerId, subject: subject, state: state, presentationData: presentationData, locale: locale, peers: peers, products: products, defaultPrice: defaultPrice, minDate: minDate, maxDate: maxDate), style: .blocks, emptyStateItem: nil, headerItem: headerItem, footerItem: footerItem, crossfadeState: false, animateChanges: animateChanges) let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: createGiveawayControllerEntries(peerId: peerId, subject: subject, state: state, presentationData: presentationData, locale: locale, peers: peers, products: products, defaultPrice: defaultPrice, starsGiveawayOptions: starsGiveawayOptions, minDate: minDate, maxDate: maxDate), style: .blocks, emptyStateItem: nil, headerItem: headerItem, footerItem: footerItem, crossfadeState: false, animateChanges: animateChanges)
return (controllerState, (listState, arguments)) return (controllerState, (listState, arguments))
} }
@ -1063,7 +1245,9 @@ public func createGiveawayController(context: AccountContext, updatedPresentatio
return return
} }
var selectedProduct: PremiumGiftProduct? var selectedProduct: PremiumGiftProduct?
var selectedStarsProduct: StarsGiveawayProduct?
let selectedMonths = state.selectedMonths ?? 12 let selectedMonths = state.selectedMonths ?? 12
let selectedStars = state.stars
switch state.mode { switch state.mode {
case .giveaway: case .giveaway:
if let product = products.first(where: { $0.months == selectedMonths && $0.giftOption.users == state.subscriptions }) { if let product = products.first(where: { $0.months == selectedMonths && $0.giftOption.users == state.subscriptions }) {
@ -1073,18 +1257,27 @@ public func createGiveawayController(context: AccountContext, updatedPresentatio
if let product = products.first(where: { $0.months == selectedMonths && $0.giftOption.users == 1 }) { if let product = products.first(where: { $0.months == selectedMonths && $0.giftOption.users == 1 }) {
selectedProduct = product selectedProduct = product
} }
case .starsGiveaway:
guard let starsOptions = starsValue.with({ $0 }), !starsOptions.isEmpty else {
return
}
if let product = starsOptions.first(where: { $0.giveawayOption.count == selectedStars }) {
selectedStarsProduct = product
}
} }
guard let selectedProduct else { if [.gift, .giveaway].contains(state.mode) {
let alertController = textAlertController(context: context, title: presentationData.strings.BoostGift_ReduceQuantity_Title, text: presentationData.strings.BoostGift_ReduceQuantity_Text("\(state.subscriptions)", "\(selectedMonths)", "\(25)").string, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .defaultAction, title: presentationData.strings.BoostGift_ReduceQuantity_Reduce, action: { guard let _ = selectedProduct else {
updateState { state in let alertController = textAlertController(context: context, title: presentationData.strings.BoostGift_ReduceQuantity_Title, text: presentationData.strings.BoostGift_ReduceQuantity_Text("\(state.subscriptions)", "\(selectedMonths)", "\(25)").string, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .defaultAction, title: presentationData.strings.BoostGift_ReduceQuantity_Reduce, action: {
var updatedState = state updateState { state in
updatedState.subscriptions = 25 var updatedState = state
return updatedState updatedState.subscriptions = 25
} return updatedState
})], parseMarkdown: true) }
presentControllerImpl?(alertController) })], parseMarkdown: true)
return presentControllerImpl?(alertController)
return
}
} }
updateState { state in updateState { state in
@ -1093,25 +1286,48 @@ public func createGiveawayController(context: AccountContext, updatedPresentatio
return updatedState return updatedState
} }
let (currency, amount) = selectedProduct.storeProduct.priceCurrencyAndAmount
let purpose: AppStoreTransactionPurpose let purpose: AppStoreTransactionPurpose
let quantity: Int32 let quantity: Int32
var storeProduct: InAppPurchaseManager.Product?
switch state.mode { switch state.mode {
case .giveaway: case .giveaway:
guard let selectedProduct else {
return
}
let (currency, amount) = selectedProduct.storeProduct.priceCurrencyAndAmount
let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970) let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
let untilDate = max(state.time, currentTime + 60) let untilDate = max(state.time, currentTime + 60)
purpose = .giveaway(boostPeer: peerId, additionalPeerIds: state.channels.filter { $0 != peerId }, countries: state.countries, onlyNewSubscribers: state.onlyNewEligible, showWinners: state.showWinners, prizeDescription: state.prizeDescription.isEmpty ? nil : state.prizeDescription, randomId: Int64.random(in: .min ..< .max), untilDate: untilDate, currency: currency, amount: amount) purpose = .giveaway(boostPeer: peerId, additionalPeerIds: state.channels.filter { $0 != peerId }, countries: state.countries, onlyNewSubscribers: state.onlyNewEligible, showWinners: state.showWinners, prizeDescription: state.prizeDescription.isEmpty ? nil : state.prizeDescription, randomId: Int64.random(in: .min ..< .max), untilDate: untilDate, currency: currency, amount: amount)
quantity = selectedProduct.giftOption.storeQuantity quantity = selectedProduct.giftOption.storeQuantity
storeProduct = selectedProduct.storeProduct
case .gift: case .gift:
guard let selectedProduct else {
return
}
let (currency, amount) = selectedProduct.storeProduct.priceCurrencyAndAmount
purpose = .giftCode(peerIds: state.peers, boostPeer: peerId, currency: currency, amount: amount) purpose = .giftCode(peerIds: state.peers, boostPeer: peerId, currency: currency, amount: amount)
quantity = Int32(state.peers.count) quantity = Int32(state.peers.count)
storeProduct = selectedProduct.storeProduct
case .starsGiveaway:
guard let selectedStarsProduct else {
return
}
let (currency, amount) = selectedStarsProduct.storeProduct.priceCurrencyAndAmount
let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
let untilDate = max(state.time, currentTime + 60)
purpose = .starsGiveaway(stars: selectedStarsProduct.giveawayOption.count, boostPeer: peerId, additionalPeerIds: state.channels.filter { $0 != peerId }, countries: state.countries, onlyNewSubscribers: state.onlyNewEligible, showWinners: state.showWinners, prizeDescription: state.prizeDescription.isEmpty ? nil : state.prizeDescription, randomId: Int64.random(in: .min ..< .max), untilDate: untilDate, currency: currency, amount: amount, users: state.winners)
quantity = 1
storeProduct = selectedStarsProduct.storeProduct
}
guard let storeProduct else {
return
} }
let _ = (context.engine.payments.canPurchasePremium(purpose: purpose) let _ = (context.engine.payments.canPurchasePremium(purpose: purpose)
|> deliverOnMainQueue).startStandalone(next: { [weak controller] available in |> deliverOnMainQueue).startStandalone(next: { [weak controller] available in
if available, let inAppPurchaseManager = context.inAppPurchaseManager { if available, let inAppPurchaseManager = context.inAppPurchaseManager {
let _ = (inAppPurchaseManager.buyProduct(selectedProduct.storeProduct, quantity: quantity, purpose: purpose) let _ = (inAppPurchaseManager.buyProduct(storeProduct, quantity: quantity, purpose: purpose)
|> deliverOnMainQueue).startStandalone(next: { [weak controller] status in |> deliverOnMainQueue).startStandalone(next: { [weak controller] status in
if case .purchased = status { if case .purchased = status {
if let controller, let navigationController = controller.navigationController as? NavigationController { if let controller, let navigationController = controller.navigationController as? NavigationController {
@ -1133,7 +1349,7 @@ public func createGiveawayController(context: AccountContext, updatedPresentatio
let title: String let title: String
let text: String let text: String
switch state.mode { switch state.mode {
case .giveaway: case .giveaway, .starsGiveaway:
title = presentationData.strings.BoostGift_GiveawayCreated_Title title = presentationData.strings.BoostGift_GiveawayCreated_Title
text = isGroup ? presentationData.strings.BoostGift_Group_GiveawayCreated_Text : presentationData.strings.BoostGift_GiveawayCreated_Text text = isGroup ? presentationData.strings.BoostGift_Group_GiveawayCreated_Text : presentationData.strings.BoostGift_GiveawayCreated_Text
case .gift: case .gift:
@ -1248,6 +1464,8 @@ public func createGiveawayController(context: AccountContext, updatedPresentatio
updatedState.peers = privacy.additionallyIncludePeers updatedState.peers = privacy.additionallyIncludePeers
if updatedState.peers.isEmpty { if updatedState.peers.isEmpty {
updatedState.mode = .giveaway updatedState.mode = .giveaway
} else {
updatedState.mode = .gift
} }
return updatedState return updatedState
} }

View File

@ -19,6 +19,8 @@ public final class GiftOptionItem: ListViewItem, ItemListItem {
case green case green
case red case red
case violet case violet
case premium
case stars
} }
case peer(EnginePeer) case peer(EnginePeer)
@ -62,10 +64,11 @@ public final class GiftOptionItem: ListViewItem, ItemListItem {
let label: Label? let label: Label?
let badge: String? let badge: String?
let isSelected: Bool? let isSelected: Bool?
let stars: Int64?
public let sectionId: ItemListSectionId public let sectionId: ItemListSectionId
let action: (() -> Void)? let action: (() -> Void)?
public init(presentationData: ItemListPresentationData, context: AccountContext, icon: Icon? = nil, title: String, titleFont: Font = .regular, titleBadge: String? = nil, subtitle: String?, subtitleFont: SubtitleFont = .regular, subtitleActive: Bool = false, label: Label? = nil, badge: String? = nil, isSelected: Bool? = nil, sectionId: ItemListSectionId, action: (() -> Void)?) { public init(presentationData: ItemListPresentationData, context: AccountContext, icon: Icon? = nil, title: String, titleFont: Font = .regular, titleBadge: String? = nil, subtitle: String?, subtitleFont: SubtitleFont = .regular, subtitleActive: Bool = false, label: Label? = nil, badge: String? = nil, isSelected: Bool? = nil, stars: Int64? = nil, sectionId: ItemListSectionId, action: (() -> Void)?) {
self.presentationData = presentationData self.presentationData = presentationData
self.icon = icon self.icon = icon
self.context = context self.context = context
@ -78,6 +81,7 @@ public final class GiftOptionItem: ListViewItem, ItemListItem {
self.label = label self.label = label
self.badge = badge self.badge = badge
self.isSelected = isSelected self.isSelected = isSelected
self.stars = stars
self.sectionId = sectionId self.sectionId = sectionId
self.action = action self.action = action
} }
@ -148,6 +152,7 @@ class GiftOptionItemNode: ItemListRevealOptionsItemNode {
private let titleBadge = ComponentView<Empty>() private let titleBadge = ComponentView<Empty>()
private let statusNode: TextNode private let statusNode: TextNode
private var statusArrowNode: ASImageNode? private var statusArrowNode: ASImageNode?
private var starsIconNode: ASImageNode?
private var labelBackgroundNode: ASImageNode? private var labelBackgroundNode: ASImageNode?
private let labelNode: TextNode private let labelNode: TextNode
@ -387,6 +392,7 @@ class GiftOptionItemNode: ItemListRevealOptionsItemNode {
} }
let colors: [UIColor] let colors: [UIColor]
var diagonal = false
switch color { switch color {
case .blue: case .blue:
colors = [UIColor(rgb: 0x2a9ef1), UIColor(rgb: 0x71d4fc)] colors = [UIColor(rgb: 0x2a9ef1), UIColor(rgb: 0x71d4fc)]
@ -396,9 +402,21 @@ class GiftOptionItemNode: ItemListRevealOptionsItemNode {
colors = [UIColor(rgb: 0xff516a), UIColor(rgb: 0xff885e)] colors = [UIColor(rgb: 0xff516a), UIColor(rgb: 0xff885e)]
case .violet: case .violet:
colors = [UIColor(rgb: 0xd569ec), UIColor(rgb: 0xe0a2f3)] colors = [UIColor(rgb: 0xd569ec), UIColor(rgb: 0xe0a2f3)]
case .premium:
colors = [
UIColor(rgb: 0x6b93ff),
UIColor(rgb: 0x6b93ff),
UIColor(rgb: 0x8d77ff),
UIColor(rgb: 0xb56eec),
UIColor(rgb: 0xb56eec)
]
diagonal = true
case .stars:
colors = [UIColor(rgb: 0xdd6f12), UIColor(rgb: 0xfec80f)]
diagonal = true
} }
if iconNode.image == nil || iconUpdated { if iconNode.image == nil || iconUpdated {
iconNode.image = generateAvatarImage(size: iconSize, icon: generateTintedImage(image: UIImage(bundleImageName: name), color: .white), iconScale: 1.0, cornerRadius: 20.0, color: .blue, customColors: colors) iconNode.image = generateAvatarImage(size: iconSize, icon: generateTintedImage(image: UIImage(bundleImageName: name), color: .white), iconScale: 1.0, cornerRadius: 20.0, color: .blue, customColors: colors, diagonal: diagonal)
} }
iconNode.frame = iconFrame iconNode.frame = iconFrame
} }
@ -437,6 +455,26 @@ class GiftOptionItemNode: ItemListRevealOptionsItemNode {
selectableControlNode?.removeFromSupernode() selectableControlNode?.removeFromSupernode()
}) })
} }
var titleOffset: CGFloat = 0.0
if let stars = item.stars {
let starsIconNode: ASImageNode
if let current = strongSelf.starsIconNode {
starsIconNode = current
} else {
starsIconNode = ASImageNode()
starsIconNode.displaysAsynchronously = false
strongSelf.addSubnode(starsIconNode)
strongSelf.starsIconNode = starsIconNode
starsIconNode.image = generateStarsIcon(amount: stars)
}
if let icon = starsIconNode.image {
starsIconNode.frame = CGRect(origin: CGPoint(x: leftInset + editingOffset + avatarInset, y: 10.0), size: icon.size)
titleOffset += icon.size.width + 3.0
}
}
let _ = titleApply() let _ = titleApply()
let _ = statusApply() let _ = statusApply()
@ -494,7 +532,7 @@ class GiftOptionItemNode: ItemListRevealOptionsItemNode {
} else { } else {
titleVerticalOriginY = floorToScreenPixels((contentSize.height - titleLayout.size.height) / 2.0) titleVerticalOriginY = floorToScreenPixels((contentSize.height - titleLayout.size.height) / 2.0)
} }
let titleFrame = CGRect(origin: CGPoint(x: leftInset + editingOffset + avatarInset, y: titleVerticalOriginY), size: titleLayout.size) let titleFrame = CGRect(origin: CGPoint(x: leftInset + editingOffset + avatarInset + titleOffset, y: titleVerticalOriginY), size: titleLayout.size)
transition.updateFrame(node: strongSelf.titleNode, frame: titleFrame) transition.updateFrame(node: strongSelf.titleNode, frame: titleFrame)
var badgeOffset: CGFloat = 0.0 var badgeOffset: CGFloat = 0.0
@ -678,3 +716,77 @@ class GiftOptionItemNode: ItemListRevealOptionsItemNode {
self.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, removeOnCompletion: false) self.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, removeOnCompletion: false)
} }
} }
private func generateStarsIcon(amount: Int64) -> UIImage {
let stars: [Int64: Int] = [
15: 1,
75: 2,
250: 3,
500: 4,
1000: 5,
2500: 6,
25: 1,
50: 1,
100: 2,
150: 2,
350: 3,
750: 4,
1500: 5,
5000: 6,
10000: 6,
25000: 7,
35000: 7
]
let count = stars[amount] ?? 1
let image = generateGradientTintedImage(
image: UIImage(bundleImageName: "Peer Info/PremiumIcon"),
colors: [
UIColor(rgb: 0xfed219),
UIColor(rgb: 0xf3a103),
UIColor(rgb: 0xe78104)
],
direction: .diagonal
)!
let imageSize = CGSize(width: 20.0, height: 20.0)
let partImage = generateImage(imageSize, contextGenerator: { size, context in
context.clear(CGRect(origin: .zero, size: size))
if let cgImage = image.cgImage {
context.draw(cgImage, in: CGRect(origin: .zero, size: size), byTiling: false)
context.saveGState()
context.clip(to: CGRect(origin: .zero, size: size).insetBy(dx: -1.0, dy: -1.0).offsetBy(dx: -2.0, dy: 0.0), mask: cgImage)
context.setBlendMode(.clear)
context.setFillColor(UIColor.clear.cgColor)
context.fill(CGRect(origin: .zero, size: size))
context.restoreGState()
context.setBlendMode(.clear)
context.setFillColor(UIColor.clear.cgColor)
context.fill(CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: size.width / 2.0, height: size.height - 4.0)))
}
})!
let spacing: CGFloat = (3.0 - UIScreenPixel)
let totalWidth = 20.0 + spacing * CGFloat(count - 1)
return generateImage(CGSize(width: ceil(totalWidth), height: 20.0), contextGenerator: { size, context in
context.clear(CGRect(origin: .zero, size: size))
var originX = floorToScreenPixels((size.width - totalWidth) / 2.0)
let mainImage = UIImage(bundleImageName: "Premium/Stars/StarLarge")
if let cgImage = mainImage?.cgImage, let partCGImage = partImage.cgImage {
context.draw(cgImage, in: CGRect(origin: CGPoint(x: originX, y: 0.0), size: imageSize).insetBy(dx: -1.5, dy: -1.5), byTiling: false)
originX += spacing + UIScreenPixel
for _ in 0 ..< count - 1 {
context.draw(partCGImage, in: CGRect(origin: CGPoint(x: originX, y: -UIScreenPixel), size: imageSize).insetBy(dx: -1.0 + UIScreenPixel, dy: -1.0 + UIScreenPixel), byTiling: false)
originX += spacing
}
}
})!
}

View File

@ -43,11 +43,23 @@ public func presentGiveawayInfoController(
} }
var months: Int32 = 0 var months: Int32 = 0
var stars: Int64 = 0
if let giveaway { if let giveaway {
months = giveaway.months switch giveaway.prize {
case let .premium(monthsValue):
months = monthsValue
case let .stars(amount):
stars = amount
}
} else if let giveawayResults { } else if let giveawayResults {
months = giveawayResults.months switch giveawayResults.prize {
case let .premium(monthsValue):
months = monthsValue
case let .stars(amount):
stars = amount
}
} }
let _ = stars
var prizeDescription: String? var prizeDescription: String?
if let giveaway { if let giveaway {
@ -265,7 +277,7 @@ public func presentGiveawayInfoController(
} }
} }
if activatedCount > 0 { if let activatedCount, activatedCount > 0 {
ending += " " + presentationData.strings.Chat_Giveaway_Info_ActivatedLinks(activatedCount) ending += " " + presentationData.strings.Chat_Giveaway_Info_ActivatedLinks(activatedCount)
} }
@ -279,7 +291,7 @@ public func presentGiveawayInfoController(
})] })]
case .notWon: case .notWon:
result = "**\(presentationData.strings.Chat_Giveaway_Info_DidntWin)**\n\n" result = "**\(presentationData.strings.Chat_Giveaway_Info_DidntWin)**\n\n"
case let .won(slug): case let .wonPremium(slug):
result = "**\(presentationData.strings.Chat_Giveaway_Info_Won("").string)**\n\n" result = "**\(presentationData.strings.Chat_Giveaway_Info_Won("").string)**\n\n"
actions = [TextAlertAction(type: .defaultAction, title: presentationData.strings.Chat_Giveaway_Info_ViewPrize, action: { actions = [TextAlertAction(type: .defaultAction, title: presentationData.strings.Chat_Giveaway_Info_ViewPrize, action: {
dismissImpl?() dismissImpl?()
@ -287,6 +299,15 @@ public func presentGiveawayInfoController(
}), TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: { }), TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {
dismissImpl?() dismissImpl?()
})] })]
case let .wonStars(stars):
let _ = stars
result = "**\(presentationData.strings.Chat_Giveaway_Info_Won("").string)**\n\n"
actions = [TextAlertAction(type: .defaultAction, title: presentationData.strings.Chat_Giveaway_Info_ViewPrize, action: {
dismissImpl?()
openLink("")
}), TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {
dismissImpl?()
})]
} }
text = "\(result)\(intro)\(additionalPrizes)\n\n\(ending)" text = "\(result)\(intro)\(additionalPrizes)\n\n\(ending)"

View File

@ -879,7 +879,7 @@ private final class PremiumGiftScreenComponent: CombinedComponent {
price = nil price = nil
} }
let buttonText = presentationData.strings.Premium_Gift_GiftSubscription(price ?? "").string let buttonText = presentationData.strings.Premium_Gift_GiftSubscription(price ?? "").string
self.buttonStatePromise.set(.single(AttachmentMainButtonState(text: buttonText, font: .bold, background: .premium, textColor: .white, isVisible: true, progress: self.inProgress ? .center : .none, isEnabled: true))) self.buttonStatePromise.set(.single(AttachmentMainButtonState(text: buttonText, font: .bold, background: .premium, textColor: .white, isVisible: true, progress: self.inProgress ? .center : .none, isEnabled: true, hasShimmer: false)))
} }
func buy() { func buy() {

View File

@ -13,13 +13,15 @@ final class SubscriptionsCountItem: ListViewItem, ItemListItem {
let theme: PresentationTheme let theme: PresentationTheme
let strings: PresentationStrings let strings: PresentationStrings
let value: Int32 let value: Int32
let values: [Int32]
let sectionId: ItemListSectionId let sectionId: ItemListSectionId
let updated: (Int32) -> Void let updated: (Int32) -> Void
init(theme: PresentationTheme, strings: PresentationStrings, value: Int32, sectionId: ItemListSectionId, updated: @escaping (Int32) -> Void) { init(theme: PresentationTheme, strings: PresentationStrings, value: Int32, values: [Int32], sectionId: ItemListSectionId, updated: @escaping (Int32) -> Void) {
self.theme = theme self.theme = theme
self.strings = strings self.strings = strings
self.value = value self.value = value
self.values = values
self.sectionId = sectionId self.sectionId = sectionId
self.updated = updated self.updated = updated
} }
@ -64,13 +66,7 @@ private final class SubscriptionsCountItemNode: ListViewItemNode {
private let bottomStripeNode: ASDisplayNode private let bottomStripeNode: ASDisplayNode
private let maskNode: ASImageNode private let maskNode: ASImageNode
private let label1TextNode: TextNode private let textNodes: [TextNode]
private let label3TextNode: TextNode
private let label5TextNode: TextNode
private let label7TextNode: TextNode
private let label10TextNode: TextNode
private let label25TextNode: TextNode
private let label50TextNode: TextNode
private var sliderView: TGPhotoEditorSliderView? private var sliderView: TGPhotoEditorSliderView?
private var item: SubscriptionsCountItem? private var item: SubscriptionsCountItem?
@ -88,43 +84,36 @@ private final class SubscriptionsCountItemNode: ListViewItemNode {
self.maskNode = ASImageNode() self.maskNode = ASImageNode()
self.label1TextNode = TextNode() self.textNodes = (0 ..< 10).map { _ -> TextNode in
self.label1TextNode.isUserInteractionEnabled = false let textNode = TextNode()
self.label1TextNode.displaysAsynchronously = false textNode.isUserInteractionEnabled = false
textNode.displaysAsynchronously = false
self.label3TextNode = TextNode() return textNode
self.label3TextNode.isUserInteractionEnabled = false }
self.label3TextNode.displaysAsynchronously = false
self.label5TextNode = TextNode()
self.label5TextNode.isUserInteractionEnabled = false
self.label5TextNode.displaysAsynchronously = false
self.label7TextNode = TextNode()
self.label7TextNode.isUserInteractionEnabled = false
self.label7TextNode.displaysAsynchronously = false
self.label10TextNode = TextNode()
self.label10TextNode.isUserInteractionEnabled = false
self.label10TextNode.displaysAsynchronously = false
self.label25TextNode = TextNode()
self.label25TextNode.isUserInteractionEnabled = false
self.label25TextNode.displaysAsynchronously = false
self.label50TextNode = TextNode()
self.label50TextNode.isUserInteractionEnabled = false
self.label50TextNode.displaysAsynchronously = false
super.init(layerBacked: false, dynamicBounce: false) super.init(layerBacked: false, dynamicBounce: false)
self.addSubnode(self.label1TextNode) self.textNodes.forEach(self.addSubnode)
self.addSubnode(self.label3TextNode) }
self.addSubnode(self.label5TextNode)
self.addSubnode(self.label7TextNode) func updateSliderView() {
self.addSubnode(self.label10TextNode) if let sliderView = self.sliderView, let item = self.item {
self.addSubnode(self.label25TextNode) sliderView.maximumValue = CGFloat(item.values.count - 1)
self.addSubnode(self.label50TextNode) sliderView.positionsCount = item.values.count
var value: Int32 = 0
for i in 0 ..< item.values.count {
if item.values[i] >= item.value {
value = Int32(i)
break
}
}
sliderView.value = CGFloat(value)
sliderView.isUserInteractionEnabled = true
sliderView.alpha = 1.0
sliderView.layer.allowsGroupOpacity = false
}
} }
override func didLoad() { override func didLoad() {
@ -142,26 +131,14 @@ private final class SubscriptionsCountItemNode: ListViewItemNode {
sliderView.useLinesForPositions = true sliderView.useLinesForPositions = true
sliderView.disablesInteractiveTransitionGestureRecognizer = true sliderView.disablesInteractiveTransitionGestureRecognizer = true
if let item = self.item, let params = self.layoutParams { if let item = self.item, let params = self.layoutParams {
var mappedValue: Int32 = 0 var value: Int32 = 0
switch Int(item.value) { for i in 0 ..< item.values.count {
case 1: if item.values[i] >= item.value {
mappedValue = 0 value = Int32(i)
case 3: break
mappedValue = 1 }
case 5:
mappedValue = 2
case 7:
mappedValue = 3
case 10:
mappedValue = 4
case 25:
mappedValue = 5
case 50:
mappedValue = 6
default:
mappedValue = 0
} }
sliderView.value = CGFloat(mappedValue) sliderView.value = CGFloat(value)
sliderView.backgroundColor = item.theme.list.itemBlocksBackgroundColor sliderView.backgroundColor = item.theme.list.itemBlocksBackgroundColor
sliderView.backColor = item.theme.list.itemSwitchColors.frameColor sliderView.backColor = item.theme.list.itemSwitchColors.frameColor
sliderView.startColor = item.theme.list.itemSwitchColors.frameColor sliderView.startColor = item.theme.list.itemSwitchColors.frameColor
@ -178,13 +155,7 @@ private final class SubscriptionsCountItemNode: ListViewItemNode {
func asyncLayout() -> (_ item: SubscriptionsCountItem, _ params: ListViewItemLayoutParams, _ neighbors: ItemListNeighbors) -> (ListViewItemNodeLayout, () -> Void) { func asyncLayout() -> (_ item: SubscriptionsCountItem, _ params: ListViewItemLayoutParams, _ neighbors: ItemListNeighbors) -> (ListViewItemNodeLayout, () -> Void) {
let currentItem = self.item let currentItem = self.item
let makeLabel1TextLayout = TextNode.asyncLayout(self.label1TextNode) let makeTextLayouts = self.textNodes.map(TextNode.asyncLayout)
let makeLabel3TextLayout = TextNode.asyncLayout(self.label3TextNode)
let makeLabel5TextLayout = TextNode.asyncLayout(self.label5TextNode)
let makeLabel7TextLayout = TextNode.asyncLayout(self.label7TextNode)
let makeLabel10TextLayout = TextNode.asyncLayout(self.label10TextNode)
let makeLabel25TextLayout = TextNode.asyncLayout(self.label25TextNode)
let makeLabel50TextLayout = TextNode.asyncLayout(self.label50TextNode)
return { item, params, neighbors in return { item, params, neighbors in
var themeUpdated = false var themeUpdated = false
@ -196,20 +167,16 @@ private final class SubscriptionsCountItemNode: ListViewItemNode {
let insets: UIEdgeInsets let insets: UIEdgeInsets
let separatorHeight = UIScreenPixel let separatorHeight = UIScreenPixel
let (label1TextLayout, label1TextApply) = makeLabel1TextLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: "1", font: Font.regular(13.0), textColor: item.theme.list.itemSecondaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width, height: CGFloat.greatestFiniteMagnitude), alignment: .center, lineSpacing: 0.0, cutout: nil, insets: UIEdgeInsets())) var textLayoutAndApply: [(TextNodeLayout, () -> TextNode)] = []
let (label3TextLayout, label3TextApply) = makeLabel3TextLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: "3", font: Font.regular(13.0), textColor: item.theme.list.itemSecondaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width, height: CGFloat.greatestFiniteMagnitude), alignment: .center, lineSpacing: 0.0, cutout: nil, insets: UIEdgeInsets()))
let (label5TextLayout, label5TextApply) = makeLabel5TextLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: "5", font: Font.regular(13.0), textColor: item.theme.list.itemSecondaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width, height: CGFloat.greatestFiniteMagnitude), alignment: .center, lineSpacing: 0.0, cutout: nil, insets: UIEdgeInsets()))
let (label7TextLayout, label7TextApply) = makeLabel7TextLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: "7", font: Font.regular(13.0), textColor: item.theme.list.itemSecondaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width, height: CGFloat.greatestFiniteMagnitude), alignment: .center, lineSpacing: 0.0, cutout: nil, insets: UIEdgeInsets()))
let (label10TextLayout, label10TextApply) = makeLabel10TextLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: "10", font: Font.regular(13.0), textColor: item.theme.list.itemSecondaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width, height: CGFloat.greatestFiniteMagnitude), alignment: .center, lineSpacing: 0.0, cutout: nil, insets: UIEdgeInsets()))
let (label25TextLayout, label25TextApply) = makeLabel25TextLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: "25", font: Font.regular(13.0), textColor: item.theme.list.itemSecondaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width, height: CGFloat.greatestFiniteMagnitude), alignment: .center, lineSpacing: 0.0, cutout: nil, insets: UIEdgeInsets()))
let (label50TextLayout, label50TextApply) = makeLabel50TextLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: "50", font: Font.regular(13.0), textColor: item.theme.list.itemSecondaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width, height: CGFloat.greatestFiniteMagnitude), alignment: .center, lineSpacing: 0.0, cutout: nil, insets: UIEdgeInsets()))
for i in 0 ..< item.values.count {
let value = item.values[i]
let valueString: String = "\(value)"
let (textLayout, textApply) = makeTextLayouts[i](TextNodeLayoutArguments(attributedString: NSAttributedString(string: valueString, font: Font.regular(13.0), textColor: item.theme.list.itemSecondaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width, height: CGFloat.greatestFiniteMagnitude), alignment: .center, lineSpacing: 0.0, cutout: nil, insets: UIEdgeInsets()))
textLayoutAndApply.append((textLayout, textApply))
}
contentSize = CGSize(width: params.width, height: 88.0) contentSize = CGSize(width: params.width, height: 88.0)
insets = itemListNeighborsGroupedInsets(neighbors, params) insets = itemListNeighborsGroupedInsets(neighbors, params)
@ -269,30 +236,31 @@ private final class SubscriptionsCountItemNode: ListViewItemNode {
strongSelf.topStripeNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: layoutSize.width, height: separatorHeight)) strongSelf.topStripeNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: layoutSize.width, height: separatorHeight))
strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height + bottomStripeOffset), size: CGSize(width: layoutSize.width - bottomStripeInset, height: separatorHeight)) strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height + bottomStripeOffset), size: CGSize(width: layoutSize.width - bottomStripeInset, height: separatorHeight))
let _ = label1TextApply() for (_, apply) in textLayoutAndApply {
let _ = label3TextApply() let _ = apply()
let _ = label5TextApply() }
let _ = label7TextApply()
let _ = label10TextApply()
let _ = label25TextApply()
let _ = label50TextApply()
let textNodes: [(TextNode, CGSize)] = [ let textNodes: [(TextNode, CGSize)] = textLayoutAndApply.map { layout, apply -> (TextNode, CGSize) in
(strongSelf.label1TextNode, label1TextLayout.size), let node = apply()
(strongSelf.label3TextNode, label3TextLayout.size), return (node, layout.size)
(strongSelf.label5TextNode, label5TextLayout.size), }
(strongSelf.label7TextNode, label7TextLayout.size),
(strongSelf.label10TextNode, label10TextLayout.size),
(strongSelf.label25TextNode, label25TextLayout.size),
(strongSelf.label50TextNode, label50TextLayout.size)
]
let delta = (params.width - params.leftInset - params.rightInset - 20.0 * 2.0) / CGFloat(textNodes.count - 1) let delta = (params.width - params.leftInset - params.rightInset - 18.0 * 2.0) / CGFloat(max(item.values.count - 1, 1))
for i in 0 ..< textNodes.count { for i in 0 ..< strongSelf.textNodes.count {
guard i < item.values.count else {
strongSelf.textNodes[i].isHidden = true
continue
}
let (textNode, textSize) = textNodes[i] let (textNode, textSize) = textNodes[i]
textNode.isHidden = false
var position = params.leftInset + 18.0 + delta * CGFloat(i)
if i == textNodes.count - 1 {
position -= textSize.width
} else if i > 0 {
position -= textSize.width / 2.0
}
let position = params.leftInset + 20.0 + delta * CGFloat(i) textNode.frame = CGRect(origin: CGPoint(x: position, y: 15.0), size: textSize)
textNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels(position - textSize.width / 2.0), y: 15.0), size: textSize)
} }
if let sliderView = strongSelf.sliderView { if let sliderView = strongSelf.sliderView {
@ -306,28 +274,7 @@ private final class SubscriptionsCountItemNode: ListViewItemNode {
sliderView.frame = CGRect(origin: CGPoint(x: params.leftInset + 15.0, y: 37.0), size: CGSize(width: params.width - params.leftInset - params.rightInset - 15.0 * 2.0, height: 44.0)) sliderView.frame = CGRect(origin: CGPoint(x: params.leftInset + 15.0, y: 37.0), size: CGSize(width: params.width - params.leftInset - params.rightInset - 15.0 * 2.0, height: 44.0))
sliderView.hitTestEdgeInsets = UIEdgeInsets(top: -sliderView.frame.minX, left: 0.0, bottom: 0.0, right: -sliderView.frame.minX) sliderView.hitTestEdgeInsets = UIEdgeInsets(top: -sliderView.frame.minX, left: 0.0, bottom: 0.0, right: -sliderView.frame.minX)
var mappedValue: Int32 = 0 strongSelf.updateSliderView()
switch Int(item.value) {
case 1:
mappedValue = 0
case 3:
mappedValue = 1
case 5:
mappedValue = 2
case 7:
mappedValue = 3
case 10:
mappedValue = 4
case 25:
mappedValue = 5
case 50:
mappedValue = 6
default:
mappedValue = 0
}
if Int32(sliderView.value) != mappedValue {
sliderView.value = CGFloat(mappedValue)
}
} }
} }
}) })

View File

@ -156,6 +156,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-1347021750] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionParticipantJoinByRequest($0) } dict[-1347021750] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionParticipantJoinByRequest($0) }
dict[-124291086] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionParticipantLeave($0) } dict[-124291086] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionParticipantLeave($0) }
dict[-115071790] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionParticipantMute($0) } dict[-115071790] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionParticipantMute($0) }
dict[1684286899] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionParticipantSubExtend($0) }
dict[-714643696] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionParticipantToggleAdmin($0) } dict[-714643696] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionParticipantToggleAdmin($0) }
dict[-422036098] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionParticipantToggleBan($0) } dict[-422036098] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionParticipantToggleBan($0) }
dict[-431740480] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionParticipantUnmute($0) } dict[-431740480] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionParticipantUnmute($0) }
@ -387,7 +388,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-1759532989] = { return Api.InputMedia.parse_inputMediaGeoLive($0) } dict[-1759532989] = { return Api.InputMedia.parse_inputMediaGeoLive($0) }
dict[-104578748] = { return Api.InputMedia.parse_inputMediaGeoPoint($0) } dict[-104578748] = { return Api.InputMedia.parse_inputMediaGeoPoint($0) }
dict[1080028941] = { return Api.InputMedia.parse_inputMediaInvoice($0) } dict[1080028941] = { return Api.InputMedia.parse_inputMediaInvoice($0) }
dict[-1436147773] = { return Api.InputMedia.parse_inputMediaPaidMedia($0) } dict[-1005571194] = { return Api.InputMedia.parse_inputMediaPaidMedia($0) }
dict[-1279654347] = { return Api.InputMedia.parse_inputMediaPhoto($0) } dict[-1279654347] = { return Api.InputMedia.parse_inputMediaPhoto($0) }
dict[-440664550] = { return Api.InputMedia.parse_inputMediaPhotoExternal($0) } dict[-440664550] = { return Api.InputMedia.parse_inputMediaPhotoExternal($0) }
dict[261416433] = { return Api.InputMedia.parse_inputMediaPoll($0) } dict[261416433] = { return Api.InputMedia.parse_inputMediaPoll($0) }
@ -469,6 +470,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[369444042] = { return Api.InputStorePaymentPurpose.parse_inputStorePaymentPremiumGiveaway($0) } dict[369444042] = { return Api.InputStorePaymentPurpose.parse_inputStorePaymentPremiumGiveaway($0) }
dict[-1502273946] = { return Api.InputStorePaymentPurpose.parse_inputStorePaymentPremiumSubscription($0) } dict[-1502273946] = { return Api.InputStorePaymentPurpose.parse_inputStorePaymentPremiumSubscription($0) }
dict[494149367] = { return Api.InputStorePaymentPurpose.parse_inputStorePaymentStarsGift($0) } dict[494149367] = { return Api.InputStorePaymentPurpose.parse_inputStorePaymentStarsGift($0) }
dict[1964968186] = { return Api.InputStorePaymentPurpose.parse_inputStorePaymentStarsGiveaway($0) }
dict[-572715178] = { return Api.InputStorePaymentPurpose.parse_inputStorePaymentStarsTopup($0) } dict[-572715178] = { return Api.InputStorePaymentPurpose.parse_inputStorePaymentStarsTopup($0) }
dict[1012306921] = { return Api.InputTheme.parse_inputTheme($0) } dict[1012306921] = { return Api.InputTheme.parse_inputTheme($0) }
dict[-175567375] = { return Api.InputTheme.parse_inputThemeSlug($0) } dict[-175567375] = { return Api.InputTheme.parse_inputThemeSlug($0) }
@ -550,7 +552,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[1737240073] = { return Api.MessageAction.parse_messageActionGiftCode($0) } dict[1737240073] = { return Api.MessageAction.parse_messageActionGiftCode($0) }
dict[-935499028] = { return Api.MessageAction.parse_messageActionGiftPremium($0) } dict[-935499028] = { return Api.MessageAction.parse_messageActionGiftPremium($0) }
dict[1171632161] = { return Api.MessageAction.parse_messageActionGiftStars($0) } dict[1171632161] = { return Api.MessageAction.parse_messageActionGiftStars($0) }
dict[858499565] = { return Api.MessageAction.parse_messageActionGiveawayLaunch($0) } dict[-1475391004] = { return Api.MessageAction.parse_messageActionGiveawayLaunch($0) }
dict[715107781] = { return Api.MessageAction.parse_messageActionGiveawayResults($0) } dict[715107781] = { return Api.MessageAction.parse_messageActionGiveawayResults($0) }
dict[2047704898] = { return Api.MessageAction.parse_messageActionGroupCall($0) } dict[2047704898] = { return Api.MessageAction.parse_messageActionGroupCall($0) }
dict[-1281329567] = { return Api.MessageAction.parse_messageActionGroupCallScheduled($0) } dict[-1281329567] = { return Api.MessageAction.parse_messageActionGroupCallScheduled($0) }
@ -561,6 +563,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
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) }
dict[-1341372510] = { return Api.MessageAction.parse_messageActionPrizeStars($0) }
dict[827428507] = { return Api.MessageAction.parse_messageActionRequestedPeer($0) } dict[827428507] = { return Api.MessageAction.parse_messageActionRequestedPeer($0) }
dict[-1816979384] = { return Api.MessageAction.parse_messageActionRequestedPeerSentMe($0) } dict[-1816979384] = { return Api.MessageAction.parse_messageActionRequestedPeerSentMe($0) }
dict[1200788123] = { return Api.MessageAction.parse_messageActionScreenshotTaken($0) } dict[1200788123] = { return Api.MessageAction.parse_messageActionScreenshotTaken($0) }
@ -605,8 +608,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-38694904] = { return Api.MessageMedia.parse_messageMediaGame($0) } dict[-38694904] = { return Api.MessageMedia.parse_messageMediaGame($0) }
dict[1457575028] = { return Api.MessageMedia.parse_messageMediaGeo($0) } dict[1457575028] = { return Api.MessageMedia.parse_messageMediaGeo($0) }
dict[-1186937242] = { return Api.MessageMedia.parse_messageMediaGeoLive($0) } dict[-1186937242] = { return Api.MessageMedia.parse_messageMediaGeoLive($0) }
dict[-626162256] = { return Api.MessageMedia.parse_messageMediaGiveaway($0) } dict[-1442366485] = { return Api.MessageMedia.parse_messageMediaGiveaway($0) }
dict[-963047320] = { return Api.MessageMedia.parse_messageMediaGiveawayResults($0) } dict[-827703647] = { return Api.MessageMedia.parse_messageMediaGiveawayResults($0) }
dict[-156940077] = { return Api.MessageMedia.parse_messageMediaInvoice($0) } dict[-156940077] = { return Api.MessageMedia.parse_messageMediaInvoice($0) }
dict[-1467669359] = { return Api.MessageMedia.parse_messageMediaPaidMedia($0) } dict[-1467669359] = { return Api.MessageMedia.parse_messageMediaPaidMedia($0) }
dict[1766936791] = { return Api.MessageMedia.parse_messageMediaPhoto($0) } dict[1766936791] = { return Api.MessageMedia.parse_messageMediaPhoto($0) }
@ -884,11 +887,13 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[1301522832] = { return Api.SponsoredMessage.parse_sponsoredMessage($0) } dict[1301522832] = { return Api.SponsoredMessage.parse_sponsoredMessage($0) }
dict[1124938064] = { return Api.SponsoredMessageReportOption.parse_sponsoredMessageReportOption($0) } dict[1124938064] = { return Api.SponsoredMessageReportOption.parse_sponsoredMessageReportOption($0) }
dict[1577421297] = { return Api.StarsGiftOption.parse_starsGiftOption($0) } dict[1577421297] = { return Api.StarsGiftOption.parse_starsGiftOption($0) }
dict[-1798404822] = { return Api.StarsGiveawayOption.parse_starsGiveawayOption($0) }
dict[1411605001] = { return Api.StarsGiveawayWinnersOption.parse_starsGiveawayWinnersOption($0) }
dict[2033461574] = { return Api.StarsRevenueStatus.parse_starsRevenueStatus($0) } dict[2033461574] = { return Api.StarsRevenueStatus.parse_starsRevenueStatus($0) }
dict[1401868056] = { return Api.StarsSubscription.parse_starsSubscription($0) } dict[1401868056] = { return Api.StarsSubscription.parse_starsSubscription($0) }
dict[88173912] = { return Api.StarsSubscriptionPricing.parse_starsSubscriptionPricing($0) } dict[88173912] = { return Api.StarsSubscriptionPricing.parse_starsSubscriptionPricing($0) }
dict[198776256] = { return Api.StarsTopupOption.parse_starsTopupOption($0) } dict[198776256] = { return Api.StarsTopupOption.parse_starsTopupOption($0) }
dict[1127934763] = { return Api.StarsTransaction.parse_starsTransaction($0) } dict[-294313259] = { return Api.StarsTransaction.parse_starsTransaction($0) }
dict[-670195363] = { return Api.StarsTransactionPeer.parse_starsTransactionPeer($0) } dict[-670195363] = { return Api.StarsTransactionPeer.parse_starsTransactionPeer($0) }
dict[1617438738] = { return Api.StarsTransactionPeer.parse_starsTransactionPeerAds($0) } dict[1617438738] = { return Api.StarsTransactionPeer.parse_starsTransactionPeerAds($0) }
dict[-1269320843] = { return Api.StarsTransactionPeer.parse_starsTransactionPeerAppStore($0) } dict[-1269320843] = { return Api.StarsTransactionPeer.parse_starsTransactionPeerAppStore($0) }
@ -956,6 +961,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[164329305] = { return Api.Update.parse_updateBotMessageReactions($0) } dict[164329305] = { return Api.Update.parse_updateBotMessageReactions($0) }
dict[-1646578564] = { return Api.Update.parse_updateBotNewBusinessMessage($0) } dict[-1646578564] = { return Api.Update.parse_updateBotNewBusinessMessage($0) }
dict[-1934976362] = { return Api.Update.parse_updateBotPrecheckoutQuery($0) } dict[-1934976362] = { return Api.Update.parse_updateBotPrecheckoutQuery($0) }
dict[675009298] = { return Api.Update.parse_updateBotPurchasedPaidMedia($0) }
dict[-1246823043] = { return Api.Update.parse_updateBotShippingQuery($0) } dict[-1246823043] = { return Api.Update.parse_updateBotShippingQuery($0) }
dict[-997782967] = { return Api.Update.parse_updateBotStopped($0) } dict[-997782967] = { return Api.Update.parse_updateBotStopped($0) }
dict[-2095595325] = { return Api.Update.parse_updateBotWebhookJSON($0) } dict[-2095595325] = { return Api.Update.parse_updateBotWebhookJSON($0) }
@ -1026,6 +1032,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[1753886890] = { return Api.Update.parse_updateNewStickerSet($0) } dict[1753886890] = { return Api.Update.parse_updateNewStickerSet($0) }
dict[405070859] = { return Api.Update.parse_updateNewStoryReaction($0) } dict[405070859] = { return Api.Update.parse_updateNewStoryReaction($0) }
dict[-1094555409] = { return Api.Update.parse_updateNotifySettings($0) } dict[-1094555409] = { return Api.Update.parse_updateNotifySettings($0) }
dict[1372224236] = { return Api.Update.parse_updatePaidReactionPrivacy($0) }
dict[-337610926] = { return Api.Update.parse_updatePeerBlocked($0) } dict[-337610926] = { return Api.Update.parse_updatePeerBlocked($0) }
dict[-1147422299] = { return Api.Update.parse_updatePeerHistoryTTL($0) } dict[-1147422299] = { return Api.Update.parse_updatePeerHistoryTTL($0) }
dict[-1263546448] = { return Api.Update.parse_updatePeerLocated($0) } dict[-1263546448] = { return Api.Update.parse_updatePeerLocated($0) }
@ -1322,7 +1329,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[675942550] = { return Api.payments.CheckedGiftCode.parse_checkedGiftCode($0) } dict[675942550] = { return Api.payments.CheckedGiftCode.parse_checkedGiftCode($0) }
dict[-1362048039] = { return Api.payments.ExportedInvoice.parse_exportedInvoice($0) } dict[-1362048039] = { return Api.payments.ExportedInvoice.parse_exportedInvoice($0) }
dict[1130879648] = { return Api.payments.GiveawayInfo.parse_giveawayInfo($0) } dict[1130879648] = { return Api.payments.GiveawayInfo.parse_giveawayInfo($0) }
dict[13456752] = { return Api.payments.GiveawayInfo.parse_giveawayInfoResults($0) } dict[-512366993] = { return Api.payments.GiveawayInfo.parse_giveawayInfoResults($0) }
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) }
@ -1408,7 +1415,7 @@ public extension Api {
return parser(reader) return parser(reader)
} }
else { else {
telegramApiLog("Type constructor \(String(signature, radix: 16, uppercase: false)) not found") telegramApiLog("Type constructor \(String(UInt32(bitPattern: signature), radix: 16, uppercase: false)) not found")
return nil return nil
} }
} }
@ -2006,6 +2013,10 @@ public extension Api {
_1.serialize(buffer, boxed) _1.serialize(buffer, boxed)
case let _1 as Api.StarsGiftOption: case let _1 as Api.StarsGiftOption:
_1.serialize(buffer, boxed) _1.serialize(buffer, boxed)
case let _1 as Api.StarsGiveawayOption:
_1.serialize(buffer, boxed)
case let _1 as Api.StarsGiveawayWinnersOption:
_1.serialize(buffer, boxed)
case let _1 as Api.StarsRevenueStatus: case let _1 as Api.StarsRevenueStatus:
_1.serialize(buffer, boxed) _1.serialize(buffer, boxed)
case let _1 as Api.StarsSubscription: case let _1 as Api.StarsSubscription:

View File

@ -141,7 +141,7 @@ public extension Api {
case inputMediaGeoLive(flags: Int32, geoPoint: Api.InputGeoPoint, heading: Int32?, period: Int32?, proximityNotificationRadius: Int32?) case inputMediaGeoLive(flags: Int32, geoPoint: Api.InputGeoPoint, heading: Int32?, period: Int32?, proximityNotificationRadius: Int32?)
case inputMediaGeoPoint(geoPoint: Api.InputGeoPoint) case inputMediaGeoPoint(geoPoint: Api.InputGeoPoint)
case inputMediaInvoice(flags: Int32, title: String, description: String, photo: Api.InputWebDocument?, invoice: Api.Invoice, payload: Buffer, provider: String?, providerData: Api.DataJSON, startParam: String?, extendedMedia: Api.InputMedia?) case inputMediaInvoice(flags: Int32, title: String, description: String, photo: Api.InputWebDocument?, invoice: Api.Invoice, payload: Buffer, provider: String?, providerData: Api.DataJSON, startParam: String?, extendedMedia: Api.InputMedia?)
case inputMediaPaidMedia(starsAmount: Int64, extendedMedia: [Api.InputMedia]) case inputMediaPaidMedia(flags: Int32, starsAmount: Int64, extendedMedia: [Api.InputMedia], payload: String?)
case inputMediaPhoto(flags: Int32, id: Api.InputPhoto, ttlSeconds: Int32?) case inputMediaPhoto(flags: Int32, id: Api.InputPhoto, ttlSeconds: Int32?)
case inputMediaPhotoExternal(flags: Int32, url: String, ttlSeconds: Int32?) case inputMediaPhotoExternal(flags: Int32, url: String, ttlSeconds: Int32?)
case inputMediaPoll(flags: Int32, poll: Api.Poll, correctAnswers: [Buffer]?, solution: String?, solutionEntities: [Api.MessageEntity]?) case inputMediaPoll(flags: Int32, poll: Api.Poll, correctAnswers: [Buffer]?, solution: String?, solutionEntities: [Api.MessageEntity]?)
@ -228,16 +228,18 @@ public extension Api {
if Int(flags) & Int(1 << 1) != 0 {serializeString(startParam!, buffer: buffer, boxed: false)} if Int(flags) & Int(1 << 1) != 0 {serializeString(startParam!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 2) != 0 {extendedMedia!.serialize(buffer, true)} if Int(flags) & Int(1 << 2) != 0 {extendedMedia!.serialize(buffer, true)}
break break
case .inputMediaPaidMedia(let starsAmount, let extendedMedia): case .inputMediaPaidMedia(let flags, let starsAmount, let extendedMedia, let payload):
if boxed { if boxed {
buffer.appendInt32(-1436147773) buffer.appendInt32(-1005571194)
} }
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt64(starsAmount, buffer: buffer, boxed: false) serializeInt64(starsAmount, buffer: buffer, boxed: false)
buffer.appendInt32(481674261) buffer.appendInt32(481674261)
buffer.appendInt32(Int32(extendedMedia.count)) buffer.appendInt32(Int32(extendedMedia.count))
for item in extendedMedia { for item in extendedMedia {
item.serialize(buffer, true) item.serialize(buffer, true)
} }
if Int(flags) & Int(1 << 0) != 0 {serializeString(payload!, buffer: buffer, boxed: false)}
break break
case .inputMediaPhoto(let flags, let id, let ttlSeconds): case .inputMediaPhoto(let flags, let id, let ttlSeconds):
if boxed { if boxed {
@ -354,8 +356,8 @@ public extension Api {
return ("inputMediaGeoPoint", [("geoPoint", geoPoint as Any)]) return ("inputMediaGeoPoint", [("geoPoint", geoPoint as Any)])
case .inputMediaInvoice(let flags, let title, let description, let photo, let invoice, let payload, let provider, let providerData, let startParam, let extendedMedia): case .inputMediaInvoice(let flags, let title, let description, let photo, let invoice, let payload, let provider, let providerData, let startParam, let extendedMedia):
return ("inputMediaInvoice", [("flags", flags as Any), ("title", title as Any), ("description", description as Any), ("photo", photo as Any), ("invoice", invoice as Any), ("payload", payload as Any), ("provider", provider as Any), ("providerData", providerData as Any), ("startParam", startParam as Any), ("extendedMedia", extendedMedia as Any)]) return ("inputMediaInvoice", [("flags", flags as Any), ("title", title as Any), ("description", description as Any), ("photo", photo as Any), ("invoice", invoice as Any), ("payload", payload as Any), ("provider", provider as Any), ("providerData", providerData as Any), ("startParam", startParam as Any), ("extendedMedia", extendedMedia as Any)])
case .inputMediaPaidMedia(let starsAmount, let extendedMedia): case .inputMediaPaidMedia(let flags, let starsAmount, let extendedMedia, let payload):
return ("inputMediaPaidMedia", [("starsAmount", starsAmount as Any), ("extendedMedia", extendedMedia as Any)]) return ("inputMediaPaidMedia", [("flags", flags as Any), ("starsAmount", starsAmount as Any), ("extendedMedia", extendedMedia as Any), ("payload", payload as Any)])
case .inputMediaPhoto(let flags, let id, let ttlSeconds): case .inputMediaPhoto(let flags, let id, let ttlSeconds):
return ("inputMediaPhoto", [("flags", flags as Any), ("id", id as Any), ("ttlSeconds", ttlSeconds as Any)]) return ("inputMediaPhoto", [("flags", flags as Any), ("id", id as Any), ("ttlSeconds", ttlSeconds as Any)])
case .inputMediaPhotoExternal(let flags, let url, let ttlSeconds): case .inputMediaPhotoExternal(let flags, let url, let ttlSeconds):
@ -546,16 +548,22 @@ public extension Api {
} }
} }
public static func parse_inputMediaPaidMedia(_ reader: BufferReader) -> InputMedia? { public static func parse_inputMediaPaidMedia(_ reader: BufferReader) -> InputMedia? {
var _1: Int64? var _1: Int32?
_1 = reader.readInt64() _1 = reader.readInt32()
var _2: [Api.InputMedia]? var _2: Int64?
_2 = reader.readInt64()
var _3: [Api.InputMedia]?
if let _ = reader.readInt32() { if let _ = reader.readInt32() {
_2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.InputMedia.self) _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.InputMedia.self)
} }
var _4: String?
if Int(_1!) & Int(1 << 0) != 0 {_4 = parseString(reader) }
let _c1 = _1 != nil let _c1 = _1 != nil
let _c2 = _2 != nil let _c2 = _2 != nil
if _c1 && _c2 { let _c3 = _3 != nil
return Api.InputMedia.inputMediaPaidMedia(starsAmount: _1!, extendedMedia: _2!) let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil
if _c1 && _c2 && _c3 && _c4 {
return Api.InputMedia.inputMediaPaidMedia(flags: _1!, starsAmount: _2!, extendedMedia: _3!, payload: _4)
} }
else { else {
return nil return nil

View File

@ -715,6 +715,7 @@ public extension Api {
case inputStorePaymentPremiumGiveaway(flags: Int32, boostPeer: Api.InputPeer, additionalPeers: [Api.InputPeer]?, countriesIso2: [String]?, prizeDescription: String?, randomId: Int64, untilDate: Int32, currency: String, amount: Int64) case inputStorePaymentPremiumGiveaway(flags: Int32, boostPeer: Api.InputPeer, additionalPeers: [Api.InputPeer]?, countriesIso2: [String]?, prizeDescription: String?, randomId: Int64, untilDate: Int32, currency: String, amount: Int64)
case inputStorePaymentPremiumSubscription(flags: Int32) case inputStorePaymentPremiumSubscription(flags: Int32)
case inputStorePaymentStarsGift(userId: Api.InputUser, stars: Int64, currency: String, amount: Int64) case inputStorePaymentStarsGift(userId: Api.InputUser, stars: Int64, currency: String, amount: Int64)
case inputStorePaymentStarsGiveaway(flags: Int32, stars: Int64, boostPeer: Api.InputPeer, additionalPeers: [Api.InputPeer]?, countriesIso2: [String]?, prizeDescription: String?, randomId: Int64, untilDate: Int32, currency: String, amount: Int64, users: Int32)
case inputStorePaymentStarsTopup(stars: Int64, currency: String, amount: Int64) case inputStorePaymentStarsTopup(stars: Int64, currency: String, amount: Int64)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
@ -778,6 +779,30 @@ public extension Api {
serializeString(currency, buffer: buffer, boxed: false) serializeString(currency, buffer: buffer, boxed: false)
serializeInt64(amount, buffer: buffer, boxed: false) serializeInt64(amount, buffer: buffer, boxed: false)
break break
case .inputStorePaymentStarsGiveaway(let flags, let stars, let boostPeer, let additionalPeers, let countriesIso2, let prizeDescription, let randomId, let untilDate, let currency, let amount, let users):
if boxed {
buffer.appendInt32(1964968186)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt64(stars, buffer: buffer, boxed: false)
boostPeer.serialize(buffer, true)
if Int(flags) & Int(1 << 1) != 0 {buffer.appendInt32(481674261)
buffer.appendInt32(Int32(additionalPeers!.count))
for item in additionalPeers! {
item.serialize(buffer, true)
}}
if Int(flags) & Int(1 << 2) != 0 {buffer.appendInt32(481674261)
buffer.appendInt32(Int32(countriesIso2!.count))
for item in countriesIso2! {
serializeString(item, buffer: buffer, boxed: false)
}}
if Int(flags) & Int(1 << 4) != 0 {serializeString(prizeDescription!, buffer: buffer, boxed: false)}
serializeInt64(randomId, buffer: buffer, boxed: false)
serializeInt32(untilDate, buffer: buffer, boxed: false)
serializeString(currency, buffer: buffer, boxed: false)
serializeInt64(amount, buffer: buffer, boxed: false)
serializeInt32(users, buffer: buffer, boxed: false)
break
case .inputStorePaymentStarsTopup(let stars, let currency, let amount): case .inputStorePaymentStarsTopup(let stars, let currency, let amount):
if boxed { if boxed {
buffer.appendInt32(-572715178) buffer.appendInt32(-572715178)
@ -801,6 +826,8 @@ public extension Api {
return ("inputStorePaymentPremiumSubscription", [("flags", flags as Any)]) return ("inputStorePaymentPremiumSubscription", [("flags", flags as Any)])
case .inputStorePaymentStarsGift(let userId, let stars, let currency, let amount): case .inputStorePaymentStarsGift(let userId, let stars, let currency, let amount):
return ("inputStorePaymentStarsGift", [("userId", userId as Any), ("stars", stars as Any), ("currency", currency as Any), ("amount", amount as Any)]) return ("inputStorePaymentStarsGift", [("userId", userId as Any), ("stars", stars as Any), ("currency", currency as Any), ("amount", amount as Any)])
case .inputStorePaymentStarsGiveaway(let flags, let stars, let boostPeer, let additionalPeers, let countriesIso2, let prizeDescription, let randomId, let untilDate, let currency, let amount, let users):
return ("inputStorePaymentStarsGiveaway", [("flags", flags as Any), ("stars", stars as Any), ("boostPeer", boostPeer as Any), ("additionalPeers", additionalPeers as Any), ("countriesIso2", countriesIso2 as Any), ("prizeDescription", prizeDescription as Any), ("randomId", randomId as Any), ("untilDate", untilDate as Any), ("currency", currency as Any), ("amount", amount as Any), ("users", users as Any)])
case .inputStorePaymentStarsTopup(let stars, let currency, let amount): case .inputStorePaymentStarsTopup(let stars, let currency, let amount):
return ("inputStorePaymentStarsTopup", [("stars", stars as Any), ("currency", currency as Any), ("amount", amount as Any)]) return ("inputStorePaymentStarsTopup", [("stars", stars as Any), ("currency", currency as Any), ("amount", amount as Any)])
} }
@ -926,6 +953,53 @@ public extension Api {
return nil return nil
} }
} }
public static func parse_inputStorePaymentStarsGiveaway(_ reader: BufferReader) -> InputStorePaymentPurpose? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Int64?
_2 = reader.readInt64()
var _3: Api.InputPeer?
if let signature = reader.readInt32() {
_3 = Api.parse(reader, signature: signature) as? Api.InputPeer
}
var _4: [Api.InputPeer]?
if Int(_1!) & Int(1 << 1) != 0 {if let _ = reader.readInt32() {
_4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.InputPeer.self)
} }
var _5: [String]?
if Int(_1!) & Int(1 << 2) != 0 {if let _ = reader.readInt32() {
_5 = Api.parseVector(reader, elementSignature: -1255641564, elementType: String.self)
} }
var _6: String?
if Int(_1!) & Int(1 << 4) != 0 {_6 = parseString(reader) }
var _7: Int64?
_7 = reader.readInt64()
var _8: Int32?
_8 = reader.readInt32()
var _9: String?
_9 = parseString(reader)
var _10: Int64?
_10 = reader.readInt64()
var _11: Int32?
_11 = reader.readInt32()
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil
let _c5 = (Int(_1!) & Int(1 << 2) == 0) || _5 != nil
let _c6 = (Int(_1!) & Int(1 << 4) == 0) || _6 != nil
let _c7 = _7 != nil
let _c8 = _8 != nil
let _c9 = _9 != nil
let _c10 = _10 != nil
let _c11 = _11 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 {
return Api.InputStorePaymentPurpose.inputStorePaymentStarsGiveaway(flags: _1!, stars: _2!, boostPeer: _3!, additionalPeers: _4, countriesIso2: _5, prizeDescription: _6, randomId: _7!, untilDate: _8!, currency: _9!, amount: _10!, users: _11!)
}
else {
return nil
}
}
public static func parse_inputStorePaymentStarsTopup(_ reader: BufferReader) -> InputStorePaymentPurpose? { public static func parse_inputStorePaymentStarsTopup(_ reader: BufferReader) -> InputStorePaymentPurpose? {
var _1: Int64? var _1: Int64?
_1 = reader.readInt64() _1 = reader.readInt64()
@ -1006,75 +1080,3 @@ public extension Api {
} }
} }
public extension Api {
enum InputThemeSettings: TypeConstructorDescription {
case inputThemeSettings(flags: Int32, baseTheme: Api.BaseTheme, accentColor: Int32, outboxAccentColor: Int32?, messageColors: [Int32]?, wallpaper: Api.InputWallPaper?, wallpaperSettings: Api.WallPaperSettings?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .inputThemeSettings(let flags, let baseTheme, let accentColor, let outboxAccentColor, let messageColors, let wallpaper, let wallpaperSettings):
if boxed {
buffer.appendInt32(-1881255857)
}
serializeInt32(flags, buffer: buffer, boxed: false)
baseTheme.serialize(buffer, true)
serializeInt32(accentColor, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 3) != 0 {serializeInt32(outboxAccentColor!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 0) != 0 {buffer.appendInt32(481674261)
buffer.appendInt32(Int32(messageColors!.count))
for item in messageColors! {
serializeInt32(item, buffer: buffer, boxed: false)
}}
if Int(flags) & Int(1 << 1) != 0 {wallpaper!.serialize(buffer, true)}
if Int(flags) & Int(1 << 1) != 0 {wallpaperSettings!.serialize(buffer, true)}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .inputThemeSettings(let flags, let baseTheme, let accentColor, let outboxAccentColor, let messageColors, let wallpaper, let wallpaperSettings):
return ("inputThemeSettings", [("flags", flags as Any), ("baseTheme", baseTheme as Any), ("accentColor", accentColor as Any), ("outboxAccentColor", outboxAccentColor as Any), ("messageColors", messageColors as Any), ("wallpaper", wallpaper as Any), ("wallpaperSettings", wallpaperSettings as Any)])
}
}
public static func parse_inputThemeSettings(_ reader: BufferReader) -> InputThemeSettings? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Api.BaseTheme?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.BaseTheme
}
var _3: Int32?
_3 = reader.readInt32()
var _4: Int32?
if Int(_1!) & Int(1 << 3) != 0 {_4 = reader.readInt32() }
var _5: [Int32]?
if Int(_1!) & Int(1 << 0) != 0 {if let _ = reader.readInt32() {
_5 = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self)
} }
var _6: Api.InputWallPaper?
if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() {
_6 = Api.parse(reader, signature: signature) as? Api.InputWallPaper
} }
var _7: Api.WallPaperSettings?
if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() {
_7 = Api.parse(reader, signature: signature) as? Api.WallPaperSettings
} }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = (Int(_1!) & Int(1 << 3) == 0) || _4 != nil
let _c5 = (Int(_1!) & Int(1 << 0) == 0) || _5 != nil
let _c6 = (Int(_1!) & Int(1 << 1) == 0) || _6 != nil
let _c7 = (Int(_1!) & Int(1 << 1) == 0) || _7 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 {
return Api.InputThemeSettings.inputThemeSettings(flags: _1!, baseTheme: _2!, accentColor: _3!, outboxAccentColor: _4, messageColors: _5, wallpaper: _6, wallpaperSettings: _7)
}
else {
return nil
}
}
}
}

View File

@ -1,3 +1,75 @@
public extension Api {
enum InputThemeSettings: TypeConstructorDescription {
case inputThemeSettings(flags: Int32, baseTheme: Api.BaseTheme, accentColor: Int32, outboxAccentColor: Int32?, messageColors: [Int32]?, wallpaper: Api.InputWallPaper?, wallpaperSettings: Api.WallPaperSettings?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .inputThemeSettings(let flags, let baseTheme, let accentColor, let outboxAccentColor, let messageColors, let wallpaper, let wallpaperSettings):
if boxed {
buffer.appendInt32(-1881255857)
}
serializeInt32(flags, buffer: buffer, boxed: false)
baseTheme.serialize(buffer, true)
serializeInt32(accentColor, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 3) != 0 {serializeInt32(outboxAccentColor!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 0) != 0 {buffer.appendInt32(481674261)
buffer.appendInt32(Int32(messageColors!.count))
for item in messageColors! {
serializeInt32(item, buffer: buffer, boxed: false)
}}
if Int(flags) & Int(1 << 1) != 0 {wallpaper!.serialize(buffer, true)}
if Int(flags) & Int(1 << 1) != 0 {wallpaperSettings!.serialize(buffer, true)}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .inputThemeSettings(let flags, let baseTheme, let accentColor, let outboxAccentColor, let messageColors, let wallpaper, let wallpaperSettings):
return ("inputThemeSettings", [("flags", flags as Any), ("baseTheme", baseTheme as Any), ("accentColor", accentColor as Any), ("outboxAccentColor", outboxAccentColor as Any), ("messageColors", messageColors as Any), ("wallpaper", wallpaper as Any), ("wallpaperSettings", wallpaperSettings as Any)])
}
}
public static func parse_inputThemeSettings(_ reader: BufferReader) -> InputThemeSettings? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Api.BaseTheme?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.BaseTheme
}
var _3: Int32?
_3 = reader.readInt32()
var _4: Int32?
if Int(_1!) & Int(1 << 3) != 0 {_4 = reader.readInt32() }
var _5: [Int32]?
if Int(_1!) & Int(1 << 0) != 0 {if let _ = reader.readInt32() {
_5 = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self)
} }
var _6: Api.InputWallPaper?
if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() {
_6 = Api.parse(reader, signature: signature) as? Api.InputWallPaper
} }
var _7: Api.WallPaperSettings?
if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() {
_7 = Api.parse(reader, signature: signature) as? Api.WallPaperSettings
} }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = (Int(_1!) & Int(1 << 3) == 0) || _4 != nil
let _c5 = (Int(_1!) & Int(1 << 0) == 0) || _5 != nil
let _c6 = (Int(_1!) & Int(1 << 1) == 0) || _6 != nil
let _c7 = (Int(_1!) & Int(1 << 1) == 0) || _7 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 {
return Api.InputThemeSettings.inputThemeSettings(flags: _1!, baseTheme: _2!, accentColor: _3!, outboxAccentColor: _4, messageColors: _5, wallpaper: _6, wallpaperSettings: _7)
}
else {
return nil
}
}
}
}
public extension Api { public extension Api {
indirect enum InputUser: TypeConstructorDescription { indirect enum InputUser: TypeConstructorDescription {
case inputUser(userId: Int64, accessHash: Int64) case inputUser(userId: Int64, accessHash: Int64)

View File

@ -989,7 +989,7 @@ public extension Api {
case messageActionGiftCode(flags: Int32, boostPeer: Api.Peer?, months: Int32, slug: String, currency: String?, amount: Int64?, cryptoCurrency: String?, cryptoAmount: Int64?) case messageActionGiftCode(flags: Int32, boostPeer: Api.Peer?, months: Int32, slug: String, currency: String?, amount: Int64?, cryptoCurrency: String?, cryptoAmount: Int64?)
case messageActionGiftPremium(flags: Int32, currency: String, amount: Int64, months: Int32, cryptoCurrency: String?, cryptoAmount: Int64?) case messageActionGiftPremium(flags: Int32, currency: String, amount: Int64, months: Int32, cryptoCurrency: String?, cryptoAmount: Int64?)
case messageActionGiftStars(flags: Int32, currency: String, amount: Int64, stars: Int64, cryptoCurrency: String?, cryptoAmount: Int64?, transactionId: String?) case messageActionGiftStars(flags: Int32, currency: String, amount: Int64, stars: Int64, cryptoCurrency: String?, cryptoAmount: Int64?, transactionId: String?)
case messageActionGiveawayLaunch case messageActionGiveawayLaunch(flags: Int32, stars: Int64?)
case messageActionGiveawayResults(winnersCount: Int32, unclaimedCount: Int32) case messageActionGiveawayResults(winnersCount: Int32, unclaimedCount: Int32)
case messageActionGroupCall(flags: Int32, call: Api.InputGroupCall, duration: Int32?) case messageActionGroupCall(flags: Int32, call: Api.InputGroupCall, duration: Int32?)
case messageActionGroupCallScheduled(call: Api.InputGroupCall, scheduleDate: Int32) case messageActionGroupCallScheduled(call: Api.InputGroupCall, scheduleDate: Int32)
@ -1000,6 +1000,7 @@ public extension Api {
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
case messageActionPrizeStars(flags: Int32, stars: Int64, transactionId: String, boostPeer: Api.Peer, giveawayMsgId: Int32)
case messageActionRequestedPeer(buttonId: Int32, peers: [Api.Peer]) case messageActionRequestedPeer(buttonId: Int32, peers: [Api.Peer])
case messageActionRequestedPeerSentMe(buttonId: Int32, peers: [Api.RequestedPeer]) case messageActionRequestedPeerSentMe(buttonId: Int32, peers: [Api.RequestedPeer])
case messageActionScreenshotTaken case messageActionScreenshotTaken
@ -1175,11 +1176,12 @@ public extension Api {
if Int(flags) & Int(1 << 0) != 0 {serializeInt64(cryptoAmount!, buffer: buffer, boxed: false)} if Int(flags) & Int(1 << 0) != 0 {serializeInt64(cryptoAmount!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 1) != 0 {serializeString(transactionId!, buffer: buffer, boxed: false)} if Int(flags) & Int(1 << 1) != 0 {serializeString(transactionId!, buffer: buffer, boxed: false)}
break break
case .messageActionGiveawayLaunch: case .messageActionGiveawayLaunch(let flags, let stars):
if boxed { if boxed {
buffer.appendInt32(858499565) buffer.appendInt32(-1475391004)
} }
serializeInt32(flags, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {serializeInt64(stars!, buffer: buffer, boxed: false)}
break break
case .messageActionGiveawayResults(let winnersCount, let unclaimedCount): case .messageActionGiveawayResults(let winnersCount, let unclaimedCount):
if boxed { if boxed {
@ -1266,6 +1268,16 @@ public extension Api {
buffer.appendInt32(-1799538451) buffer.appendInt32(-1799538451)
} }
break
case .messageActionPrizeStars(let flags, let stars, let transactionId, let boostPeer, let giveawayMsgId):
if boxed {
buffer.appendInt32(-1341372510)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt64(stars, buffer: buffer, boxed: false)
serializeString(transactionId, buffer: buffer, boxed: false)
boostPeer.serialize(buffer, true)
serializeInt32(giveawayMsgId, buffer: buffer, boxed: false)
break break
case .messageActionRequestedPeer(let buttonId, let peers): case .messageActionRequestedPeer(let buttonId, let peers):
if boxed { if boxed {
@ -1422,8 +1434,8 @@ public extension Api {
return ("messageActionGiftPremium", [("flags", flags as Any), ("currency", currency as Any), ("amount", amount as Any), ("months", months as Any), ("cryptoCurrency", cryptoCurrency as Any), ("cryptoAmount", cryptoAmount as Any)]) return ("messageActionGiftPremium", [("flags", flags as Any), ("currency", currency as Any), ("amount", amount as Any), ("months", months as Any), ("cryptoCurrency", cryptoCurrency as Any), ("cryptoAmount", cryptoAmount as Any)])
case .messageActionGiftStars(let flags, let currency, let amount, let stars, let cryptoCurrency, let cryptoAmount, let transactionId): case .messageActionGiftStars(let flags, let currency, let amount, let stars, let cryptoCurrency, let cryptoAmount, let transactionId):
return ("messageActionGiftStars", [("flags", flags as Any), ("currency", currency as Any), ("amount", amount as Any), ("stars", stars as Any), ("cryptoCurrency", cryptoCurrency as Any), ("cryptoAmount", cryptoAmount as Any), ("transactionId", transactionId as Any)]) return ("messageActionGiftStars", [("flags", flags as Any), ("currency", currency as Any), ("amount", amount as Any), ("stars", stars as Any), ("cryptoCurrency", cryptoCurrency as Any), ("cryptoAmount", cryptoAmount as Any), ("transactionId", transactionId as Any)])
case .messageActionGiveawayLaunch: case .messageActionGiveawayLaunch(let flags, let stars):
return ("messageActionGiveawayLaunch", []) return ("messageActionGiveawayLaunch", [("flags", flags as Any), ("stars", stars as Any)])
case .messageActionGiveawayResults(let winnersCount, let unclaimedCount): case .messageActionGiveawayResults(let winnersCount, let unclaimedCount):
return ("messageActionGiveawayResults", [("winnersCount", winnersCount as Any), ("unclaimedCount", unclaimedCount as Any)]) return ("messageActionGiveawayResults", [("winnersCount", winnersCount as Any), ("unclaimedCount", unclaimedCount as Any)])
case .messageActionGroupCall(let flags, let call, let duration): case .messageActionGroupCall(let flags, let call, let duration):
@ -1444,6 +1456,8 @@ public extension Api {
return ("messageActionPhoneCall", [("flags", flags as Any), ("callId", callId as Any), ("reason", reason as Any), ("duration", duration as Any)]) return ("messageActionPhoneCall", [("flags", flags as Any), ("callId", callId as Any), ("reason", reason as Any), ("duration", duration as Any)])
case .messageActionPinMessage: case .messageActionPinMessage:
return ("messageActionPinMessage", []) return ("messageActionPinMessage", [])
case .messageActionPrizeStars(let flags, let stars, let transactionId, let boostPeer, let giveawayMsgId):
return ("messageActionPrizeStars", [("flags", flags as Any), ("stars", stars as Any), ("transactionId", transactionId as Any), ("boostPeer", boostPeer as Any), ("giveawayMsgId", giveawayMsgId as Any)])
case .messageActionRequestedPeer(let buttonId, let peers): case .messageActionRequestedPeer(let buttonId, let peers):
return ("messageActionRequestedPeer", [("buttonId", buttonId as Any), ("peers", peers as Any)]) return ("messageActionRequestedPeer", [("buttonId", buttonId as Any), ("peers", peers as Any)])
case .messageActionRequestedPeerSentMe(let buttonId, let peers): case .messageActionRequestedPeerSentMe(let buttonId, let peers):
@ -1762,7 +1776,18 @@ public extension Api {
} }
} }
public static func parse_messageActionGiveawayLaunch(_ reader: BufferReader) -> MessageAction? { public static func parse_messageActionGiveawayLaunch(_ reader: BufferReader) -> MessageAction? {
return Api.MessageAction.messageActionGiveawayLaunch var _1: Int32?
_1 = reader.readInt32()
var _2: Int64?
if Int(_1!) & Int(1 << 0) != 0 {_2 = reader.readInt64() }
let _c1 = _1 != nil
let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil
if _c1 && _c2 {
return Api.MessageAction.messageActionGiveawayLaunch(flags: _1!, stars: _2)
}
else {
return nil
}
} }
public static func parse_messageActionGiveawayResults(_ reader: BufferReader) -> MessageAction? { public static func parse_messageActionGiveawayResults(_ reader: BufferReader) -> MessageAction? {
var _1: Int32? var _1: Int32?
@ -1942,6 +1967,31 @@ public extension Api {
public static func parse_messageActionPinMessage(_ reader: BufferReader) -> MessageAction? { public static func parse_messageActionPinMessage(_ reader: BufferReader) -> MessageAction? {
return Api.MessageAction.messageActionPinMessage return Api.MessageAction.messageActionPinMessage
} }
public static func parse_messageActionPrizeStars(_ reader: BufferReader) -> MessageAction? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Int64?
_2 = reader.readInt64()
var _3: String?
_3 = parseString(reader)
var _4: Api.Peer?
if let signature = reader.readInt32() {
_4 = Api.parse(reader, signature: signature) as? Api.Peer
}
var _5: Int32?
_5 = reader.readInt32()
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
let _c5 = _5 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 {
return Api.MessageAction.messageActionPrizeStars(flags: _1!, stars: _2!, transactionId: _3!, boostPeer: _4!, giveawayMsgId: _5!)
}
else {
return nil
}
}
public static func parse_messageActionRequestedPeer(_ reader: BufferReader) -> MessageAction? { public static func parse_messageActionRequestedPeer(_ reader: BufferReader) -> MessageAction? {
var _1: Int32? var _1: Int32?
_1 = reader.readInt32() _1 = reader.readInt32()

View File

@ -715,8 +715,8 @@ public extension Api {
case messageMediaGame(game: Api.Game) case messageMediaGame(game: Api.Game)
case messageMediaGeo(geo: Api.GeoPoint) case messageMediaGeo(geo: Api.GeoPoint)
case messageMediaGeoLive(flags: Int32, geo: Api.GeoPoint, heading: Int32?, period: Int32, proximityNotificationRadius: Int32?) case messageMediaGeoLive(flags: Int32, geo: Api.GeoPoint, heading: Int32?, period: Int32, proximityNotificationRadius: Int32?)
case messageMediaGiveaway(flags: Int32, channels: [Int64], countriesIso2: [String]?, prizeDescription: String?, quantity: Int32, months: Int32, untilDate: Int32) case messageMediaGiveaway(flags: Int32, channels: [Int64], countriesIso2: [String]?, prizeDescription: String?, quantity: Int32, months: Int32?, stars: Int64?, untilDate: Int32)
case messageMediaGiveawayResults(flags: Int32, channelId: Int64, additionalPeersCount: Int32?, launchMsgId: Int32, winnersCount: Int32, unclaimedCount: Int32, winners: [Int64], months: Int32, prizeDescription: String?, untilDate: Int32) case messageMediaGiveawayResults(flags: Int32, channelId: Int64, additionalPeersCount: Int32?, launchMsgId: Int32, winnersCount: Int32, unclaimedCount: Int32, winners: [Int64], months: Int32?, stars: Int64?, prizeDescription: String?, untilDate: Int32)
case messageMediaInvoice(flags: Int32, title: String, description: String, photo: Api.WebDocument?, receiptMsgId: Int32?, currency: String, totalAmount: Int64, startParam: String, extendedMedia: Api.MessageExtendedMedia?) case messageMediaInvoice(flags: Int32, title: String, description: String, photo: Api.WebDocument?, receiptMsgId: Int32?, currency: String, totalAmount: Int64, startParam: String, extendedMedia: Api.MessageExtendedMedia?)
case messageMediaPaidMedia(starsAmount: Int64, extendedMedia: [Api.MessageExtendedMedia]) case messageMediaPaidMedia(starsAmount: Int64, extendedMedia: [Api.MessageExtendedMedia])
case messageMediaPhoto(flags: Int32, photo: Api.Photo?, ttlSeconds: Int32?) case messageMediaPhoto(flags: Int32, photo: Api.Photo?, ttlSeconds: Int32?)
@ -782,9 +782,9 @@ public extension Api {
serializeInt32(period, buffer: buffer, boxed: false) serializeInt32(period, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(proximityNotificationRadius!, buffer: buffer, boxed: false)} if Int(flags) & Int(1 << 1) != 0 {serializeInt32(proximityNotificationRadius!, buffer: buffer, boxed: false)}
break break
case .messageMediaGiveaway(let flags, let channels, let countriesIso2, let prizeDescription, let quantity, let months, let untilDate): case .messageMediaGiveaway(let flags, let channels, let countriesIso2, let prizeDescription, let quantity, let months, let stars, let untilDate):
if boxed { if boxed {
buffer.appendInt32(-626162256) buffer.appendInt32(-1442366485)
} }
serializeInt32(flags, buffer: buffer, boxed: false) serializeInt32(flags, buffer: buffer, boxed: false)
buffer.appendInt32(481674261) buffer.appendInt32(481674261)
@ -799,12 +799,13 @@ public extension Api {
}} }}
if Int(flags) & Int(1 << 3) != 0 {serializeString(prizeDescription!, buffer: buffer, boxed: false)} if Int(flags) & Int(1 << 3) != 0 {serializeString(prizeDescription!, buffer: buffer, boxed: false)}
serializeInt32(quantity, buffer: buffer, boxed: false) serializeInt32(quantity, buffer: buffer, boxed: false)
serializeInt32(months, buffer: buffer, boxed: false) if Int(flags) & Int(1 << 4) != 0 {serializeInt32(months!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 5) != 0 {serializeInt64(stars!, buffer: buffer, boxed: false)}
serializeInt32(untilDate, buffer: buffer, boxed: false) serializeInt32(untilDate, buffer: buffer, boxed: false)
break break
case .messageMediaGiveawayResults(let flags, let channelId, let additionalPeersCount, let launchMsgId, let winnersCount, let unclaimedCount, let winners, let months, let prizeDescription, let untilDate): case .messageMediaGiveawayResults(let flags, let channelId, let additionalPeersCount, let launchMsgId, let winnersCount, let unclaimedCount, let winners, let months, let stars, let prizeDescription, let untilDate):
if boxed { if boxed {
buffer.appendInt32(-963047320) buffer.appendInt32(-827703647)
} }
serializeInt32(flags, buffer: buffer, boxed: false) serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt64(channelId, buffer: buffer, boxed: false) serializeInt64(channelId, buffer: buffer, boxed: false)
@ -817,7 +818,8 @@ public extension Api {
for item in winners { for item in winners {
serializeInt64(item, buffer: buffer, boxed: false) serializeInt64(item, buffer: buffer, boxed: false)
} }
serializeInt32(months, buffer: buffer, boxed: false) if Int(flags) & Int(1 << 4) != 0 {serializeInt32(months!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 5) != 0 {serializeInt64(stars!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 1) != 0 {serializeString(prizeDescription!, buffer: buffer, boxed: false)} if Int(flags) & Int(1 << 1) != 0 {serializeString(prizeDescription!, buffer: buffer, boxed: false)}
serializeInt32(untilDate, buffer: buffer, boxed: false) serializeInt32(untilDate, buffer: buffer, boxed: false)
break break
@ -913,10 +915,10 @@ public extension Api {
return ("messageMediaGeo", [("geo", geo as Any)]) return ("messageMediaGeo", [("geo", geo as Any)])
case .messageMediaGeoLive(let flags, let geo, let heading, let period, let proximityNotificationRadius): case .messageMediaGeoLive(let flags, let geo, let heading, let period, let proximityNotificationRadius):
return ("messageMediaGeoLive", [("flags", flags as Any), ("geo", geo as Any), ("heading", heading as Any), ("period", period as Any), ("proximityNotificationRadius", proximityNotificationRadius as Any)]) return ("messageMediaGeoLive", [("flags", flags as Any), ("geo", geo as Any), ("heading", heading as Any), ("period", period as Any), ("proximityNotificationRadius", proximityNotificationRadius as Any)])
case .messageMediaGiveaway(let flags, let channels, let countriesIso2, let prizeDescription, let quantity, let months, let untilDate): case .messageMediaGiveaway(let flags, let channels, let countriesIso2, let prizeDescription, let quantity, let months, let stars, let untilDate):
return ("messageMediaGiveaway", [("flags", flags as Any), ("channels", channels as Any), ("countriesIso2", countriesIso2 as Any), ("prizeDescription", prizeDescription as Any), ("quantity", quantity as Any), ("months", months as Any), ("untilDate", untilDate as Any)]) return ("messageMediaGiveaway", [("flags", flags as Any), ("channels", channels as Any), ("countriesIso2", countriesIso2 as Any), ("prizeDescription", prizeDescription as Any), ("quantity", quantity as Any), ("months", months as Any), ("stars", stars as Any), ("untilDate", untilDate as Any)])
case .messageMediaGiveawayResults(let flags, let channelId, let additionalPeersCount, let launchMsgId, let winnersCount, let unclaimedCount, let winners, let months, let prizeDescription, let untilDate): case .messageMediaGiveawayResults(let flags, let channelId, let additionalPeersCount, let launchMsgId, let winnersCount, let unclaimedCount, let winners, let months, let stars, let prizeDescription, let untilDate):
return ("messageMediaGiveawayResults", [("flags", flags as Any), ("channelId", channelId as Any), ("additionalPeersCount", additionalPeersCount as Any), ("launchMsgId", launchMsgId as Any), ("winnersCount", winnersCount as Any), ("unclaimedCount", unclaimedCount as Any), ("winners", winners as Any), ("months", months as Any), ("prizeDescription", prizeDescription as Any), ("untilDate", untilDate as Any)]) return ("messageMediaGiveawayResults", [("flags", flags as Any), ("channelId", channelId as Any), ("additionalPeersCount", additionalPeersCount as Any), ("launchMsgId", launchMsgId as Any), ("winnersCount", winnersCount as Any), ("unclaimedCount", unclaimedCount as Any), ("winners", winners as Any), ("months", months as Any), ("stars", stars as Any), ("prizeDescription", prizeDescription as Any), ("untilDate", untilDate as Any)])
case .messageMediaInvoice(let flags, let title, let description, let photo, let receiptMsgId, let currency, let totalAmount, let startParam, let extendedMedia): case .messageMediaInvoice(let flags, let title, let description, let photo, let receiptMsgId, let currency, let totalAmount, let startParam, let extendedMedia):
return ("messageMediaInvoice", [("flags", flags as Any), ("title", title as Any), ("description", description as Any), ("photo", photo as Any), ("receiptMsgId", receiptMsgId as Any), ("currency", currency as Any), ("totalAmount", totalAmount as Any), ("startParam", startParam as Any), ("extendedMedia", extendedMedia as Any)]) return ("messageMediaInvoice", [("flags", flags as Any), ("title", title as Any), ("description", description as Any), ("photo", photo as Any), ("receiptMsgId", receiptMsgId as Any), ("currency", currency as Any), ("totalAmount", totalAmount as Any), ("startParam", startParam as Any), ("extendedMedia", extendedMedia as Any)])
case .messageMediaPaidMedia(let starsAmount, let extendedMedia): case .messageMediaPaidMedia(let starsAmount, let extendedMedia):
@ -1067,18 +1069,21 @@ public extension Api {
var _5: Int32? var _5: Int32?
_5 = reader.readInt32() _5 = reader.readInt32()
var _6: Int32? var _6: Int32?
_6 = reader.readInt32() if Int(_1!) & Int(1 << 4) != 0 {_6 = reader.readInt32() }
var _7: Int32? var _7: Int64?
_7 = reader.readInt32() if Int(_1!) & Int(1 << 5) != 0 {_7 = reader.readInt64() }
var _8: Int32?
_8 = reader.readInt32()
let _c1 = _1 != nil let _c1 = _1 != nil
let _c2 = _2 != nil let _c2 = _2 != nil
let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil
let _c4 = (Int(_1!) & Int(1 << 3) == 0) || _4 != nil let _c4 = (Int(_1!) & Int(1 << 3) == 0) || _4 != nil
let _c5 = _5 != nil let _c5 = _5 != nil
let _c6 = _6 != nil let _c6 = (Int(_1!) & Int(1 << 4) == 0) || _6 != nil
let _c7 = _7 != nil let _c7 = (Int(_1!) & Int(1 << 5) == 0) || _7 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 { let _c8 = _8 != nil
return Api.MessageMedia.messageMediaGiveaway(flags: _1!, channels: _2!, countriesIso2: _3, prizeDescription: _4, quantity: _5!, months: _6!, untilDate: _7!) if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 {
return Api.MessageMedia.messageMediaGiveaway(flags: _1!, channels: _2!, countriesIso2: _3, prizeDescription: _4, quantity: _5!, months: _6, stars: _7, untilDate: _8!)
} }
else { else {
return nil return nil
@ -1102,11 +1107,13 @@ public extension Api {
_7 = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self) _7 = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self)
} }
var _8: Int32? var _8: Int32?
_8 = reader.readInt32() if Int(_1!) & Int(1 << 4) != 0 {_8 = reader.readInt32() }
var _9: String? var _9: Int64?
if Int(_1!) & Int(1 << 1) != 0 {_9 = parseString(reader) } if Int(_1!) & Int(1 << 5) != 0 {_9 = reader.readInt64() }
var _10: Int32? var _10: String?
_10 = reader.readInt32() if Int(_1!) & Int(1 << 1) != 0 {_10 = parseString(reader) }
var _11: Int32?
_11 = reader.readInt32()
let _c1 = _1 != nil let _c1 = _1 != nil
let _c2 = _2 != nil let _c2 = _2 != nil
let _c3 = (Int(_1!) & Int(1 << 3) == 0) || _3 != nil let _c3 = (Int(_1!) & Int(1 << 3) == 0) || _3 != nil
@ -1114,11 +1121,12 @@ public extension Api {
let _c5 = _5 != nil let _c5 = _5 != nil
let _c6 = _6 != nil let _c6 = _6 != nil
let _c7 = _7 != nil let _c7 = _7 != nil
let _c8 = _8 != nil let _c8 = (Int(_1!) & Int(1 << 4) == 0) || _8 != nil
let _c9 = (Int(_1!) & Int(1 << 1) == 0) || _9 != nil let _c9 = (Int(_1!) & Int(1 << 5) == 0) || _9 != nil
let _c10 = _10 != nil let _c10 = (Int(_1!) & Int(1 << 1) == 0) || _10 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 { let _c11 = _11 != nil
return Api.MessageMedia.messageMediaGiveawayResults(flags: _1!, channelId: _2!, additionalPeersCount: _3, launchMsgId: _4!, winnersCount: _5!, unclaimedCount: _6!, winners: _7!, months: _8!, prizeDescription: _9, untilDate: _10!) if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 {
return Api.MessageMedia.messageMediaGiveawayResults(flags: _1!, channelId: _2!, additionalPeersCount: _3, launchMsgId: _4!, winnersCount: _5!, unclaimedCount: _6!, winners: _7!, months: _8, stars: _9, prizeDescription: _10, untilDate: _11!)
} }
else { else {
return nil return nil

View File

@ -624,6 +624,116 @@ public extension Api {
} }
} }
public extension Api {
enum StarsGiveawayOption: TypeConstructorDescription {
case starsGiveawayOption(flags: Int32, stars: Int64, yearlyBoosts: Int32, storeProduct: String?, currency: String, amount: Int64, winners: [Api.StarsGiveawayWinnersOption])
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .starsGiveawayOption(let flags, let stars, let yearlyBoosts, let storeProduct, let currency, let amount, let winners):
if boxed {
buffer.appendInt32(-1798404822)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt64(stars, buffer: buffer, boxed: false)
serializeInt32(yearlyBoosts, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 2) != 0 {serializeString(storeProduct!, buffer: buffer, boxed: false)}
serializeString(currency, buffer: buffer, boxed: false)
serializeInt64(amount, buffer: buffer, boxed: false)
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(winners.count))
for item in winners {
item.serialize(buffer, true)
}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .starsGiveawayOption(let flags, let stars, let yearlyBoosts, let storeProduct, let currency, let amount, let winners):
return ("starsGiveawayOption", [("flags", flags as Any), ("stars", stars as Any), ("yearlyBoosts", yearlyBoosts as Any), ("storeProduct", storeProduct as Any), ("currency", currency as Any), ("amount", amount as Any), ("winners", winners as Any)])
}
}
public static func parse_starsGiveawayOption(_ reader: BufferReader) -> StarsGiveawayOption? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Int64?
_2 = reader.readInt64()
var _3: Int32?
_3 = reader.readInt32()
var _4: String?
if Int(_1!) & Int(1 << 2) != 0 {_4 = parseString(reader) }
var _5: String?
_5 = parseString(reader)
var _6: Int64?
_6 = reader.readInt64()
var _7: [Api.StarsGiveawayWinnersOption]?
if let _ = reader.readInt32() {
_7 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StarsGiveawayWinnersOption.self)
}
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = (Int(_1!) & Int(1 << 2) == 0) || _4 != nil
let _c5 = _5 != nil
let _c6 = _6 != nil
let _c7 = _7 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 {
return Api.StarsGiveawayOption.starsGiveawayOption(flags: _1!, stars: _2!, yearlyBoosts: _3!, storeProduct: _4, currency: _5!, amount: _6!, winners: _7!)
}
else {
return nil
}
}
}
}
public extension Api {
enum StarsGiveawayWinnersOption: TypeConstructorDescription {
case starsGiveawayWinnersOption(flags: Int32, users: Int32, perUserStars: Int64)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .starsGiveawayWinnersOption(let flags, let users, let perUserStars):
if boxed {
buffer.appendInt32(1411605001)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt32(users, buffer: buffer, boxed: false)
serializeInt64(perUserStars, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .starsGiveawayWinnersOption(let flags, let users, let perUserStars):
return ("starsGiveawayWinnersOption", [("flags", flags as Any), ("users", users as Any), ("perUserStars", perUserStars as Any)])
}
}
public static func parse_starsGiveawayWinnersOption(_ reader: BufferReader) -> StarsGiveawayWinnersOption? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Int32?
_2 = reader.readInt32()
var _3: Int64?
_3 = reader.readInt64()
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
if _c1 && _c2 && _c3 {
return Api.StarsGiveawayWinnersOption.starsGiveawayWinnersOption(flags: _1!, users: _2!, perUserStars: _3!)
}
else {
return nil
}
}
}
}
public extension Api { public extension Api {
enum StarsRevenueStatus: TypeConstructorDescription { enum StarsRevenueStatus: TypeConstructorDescription {
case starsRevenueStatus(flags: Int32, currentBalance: Int64, availableBalance: Int64, overallRevenue: Int64, nextWithdrawalAt: Int32?) case starsRevenueStatus(flags: Int32, currentBalance: Int64, availableBalance: Int64, overallRevenue: Int64, nextWithdrawalAt: Int32?)
@ -830,13 +940,13 @@ public extension Api {
} }
public extension Api { public extension Api {
enum StarsTransaction: TypeConstructorDescription { enum StarsTransaction: TypeConstructorDescription {
case starsTransaction(flags: Int32, id: String, stars: Int64, date: Int32, peer: Api.StarsTransactionPeer, title: String?, description: String?, photo: Api.WebDocument?, transactionDate: Int32?, transactionUrl: String?, botPayload: Buffer?, msgId: Int32?, extendedMedia: [Api.MessageMedia]?, subscriptionPeriod: Int32?) case starsTransaction(flags: Int32, id: String, stars: Int64, date: Int32, peer: Api.StarsTransactionPeer, title: String?, description: String?, photo: Api.WebDocument?, transactionDate: Int32?, transactionUrl: String?, botPayload: Buffer?, msgId: Int32?, extendedMedia: [Api.MessageMedia]?, subscriptionPeriod: Int32?, giveawayPostId: Int32?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self { switch self {
case .starsTransaction(let flags, let id, let stars, let date, let peer, let title, let description, let photo, let transactionDate, let transactionUrl, let botPayload, let msgId, let extendedMedia, let subscriptionPeriod): case .starsTransaction(let flags, let id, let stars, let date, let peer, let title, let description, let photo, let transactionDate, let transactionUrl, let botPayload, let msgId, let extendedMedia, let subscriptionPeriod, let giveawayPostId):
if boxed { if boxed {
buffer.appendInt32(1127934763) buffer.appendInt32(-294313259)
} }
serializeInt32(flags, buffer: buffer, boxed: false) serializeInt32(flags, buffer: buffer, boxed: false)
serializeString(id, buffer: buffer, boxed: false) serializeString(id, buffer: buffer, boxed: false)
@ -856,14 +966,15 @@ public extension Api {
item.serialize(buffer, true) item.serialize(buffer, true)
}} }}
if Int(flags) & Int(1 << 12) != 0 {serializeInt32(subscriptionPeriod!, buffer: buffer, boxed: false)} if Int(flags) & Int(1 << 12) != 0 {serializeInt32(subscriptionPeriod!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 13) != 0 {serializeInt32(giveawayPostId!, buffer: buffer, boxed: false)}
break break
} }
} }
public func descriptionFields() -> (String, [(String, Any)]) { public func descriptionFields() -> (String, [(String, Any)]) {
switch self { switch self {
case .starsTransaction(let flags, let id, let stars, let date, let peer, let title, let description, let photo, let transactionDate, let transactionUrl, let botPayload, let msgId, let extendedMedia, let subscriptionPeriod): case .starsTransaction(let flags, let id, let stars, let date, let peer, let title, let description, let photo, let transactionDate, let transactionUrl, let botPayload, let msgId, let extendedMedia, let subscriptionPeriod, let giveawayPostId):
return ("starsTransaction", [("flags", flags as Any), ("id", id as Any), ("stars", stars as Any), ("date", date as Any), ("peer", peer as Any), ("title", title as Any), ("description", description as Any), ("photo", photo as Any), ("transactionDate", transactionDate as Any), ("transactionUrl", transactionUrl as Any), ("botPayload", botPayload as Any), ("msgId", msgId as Any), ("extendedMedia", extendedMedia as Any), ("subscriptionPeriod", subscriptionPeriod as Any)]) return ("starsTransaction", [("flags", flags as Any), ("id", id as Any), ("stars", stars as Any), ("date", date as Any), ("peer", peer as Any), ("title", title as Any), ("description", description as Any), ("photo", photo as Any), ("transactionDate", transactionDate as Any), ("transactionUrl", transactionUrl as Any), ("botPayload", botPayload as Any), ("msgId", msgId as Any), ("extendedMedia", extendedMedia as Any), ("subscriptionPeriod", subscriptionPeriod as Any), ("giveawayPostId", giveawayPostId as Any)])
} }
} }
@ -902,6 +1013,8 @@ public extension Api {
} } } }
var _14: Int32? var _14: Int32?
if Int(_1!) & Int(1 << 12) != 0 {_14 = reader.readInt32() } if Int(_1!) & Int(1 << 12) != 0 {_14 = reader.readInt32() }
var _15: Int32?
if Int(_1!) & Int(1 << 13) != 0 {_15 = reader.readInt32() }
let _c1 = _1 != nil let _c1 = _1 != nil
let _c2 = _2 != nil let _c2 = _2 != nil
let _c3 = _3 != nil let _c3 = _3 != nil
@ -916,8 +1029,9 @@ public extension Api {
let _c12 = (Int(_1!) & Int(1 << 8) == 0) || _12 != nil let _c12 = (Int(_1!) & Int(1 << 8) == 0) || _12 != nil
let _c13 = (Int(_1!) & Int(1 << 9) == 0) || _13 != nil let _c13 = (Int(_1!) & Int(1 << 9) == 0) || _13 != nil
let _c14 = (Int(_1!) & Int(1 << 12) == 0) || _14 != nil let _c14 = (Int(_1!) & Int(1 << 12) == 0) || _14 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 { let _c15 = (Int(_1!) & Int(1 << 13) == 0) || _15 != nil
return Api.StarsTransaction.starsTransaction(flags: _1!, id: _2!, stars: _3!, date: _4!, peer: _5!, title: _6, description: _7, photo: _8, transactionDate: _9, transactionUrl: _10, botPayload: _11, msgId: _12, extendedMedia: _13, subscriptionPeriod: _14) if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 {
return Api.StarsTransaction.starsTransaction(flags: _1!, id: _2!, stars: _3!, date: _4!, peer: _5!, title: _6, description: _7, photo: _8, transactionDate: _9, transactionUrl: _10, botPayload: _11, msgId: _12, extendedMedia: _13, subscriptionPeriod: _14, giveawayPostId: _15)
} }
else { else {
return nil return nil

View File

@ -278,6 +278,7 @@ public extension Api {
case updateBotMessageReactions(peer: Api.Peer, msgId: Int32, date: Int32, reactions: [Api.ReactionCount], qts: Int32) case updateBotMessageReactions(peer: Api.Peer, msgId: Int32, date: Int32, reactions: [Api.ReactionCount], qts: Int32)
case updateBotNewBusinessMessage(flags: Int32, connectionId: String, message: Api.Message, replyToMessage: Api.Message?, qts: Int32) case updateBotNewBusinessMessage(flags: Int32, connectionId: String, message: Api.Message, replyToMessage: Api.Message?, qts: Int32)
case updateBotPrecheckoutQuery(flags: Int32, queryId: Int64, userId: Int64, payload: Buffer, info: Api.PaymentRequestedInfo?, shippingOptionId: String?, currency: String, totalAmount: Int64) case updateBotPrecheckoutQuery(flags: Int32, queryId: Int64, userId: Int64, payload: Buffer, info: Api.PaymentRequestedInfo?, shippingOptionId: String?, currency: String, totalAmount: Int64)
case updateBotPurchasedPaidMedia(userId: Int64, payload: String, qts: Int32)
case updateBotShippingQuery(queryId: Int64, userId: Int64, payload: Buffer, shippingAddress: Api.PostAddress) case updateBotShippingQuery(queryId: Int64, userId: Int64, payload: Buffer, shippingAddress: Api.PostAddress)
case updateBotStopped(userId: Int64, date: Int32, stopped: Api.Bool, qts: Int32) case updateBotStopped(userId: Int64, date: Int32, stopped: Api.Bool, qts: Int32)
case updateBotWebhookJSON(data: Api.DataJSON) case updateBotWebhookJSON(data: Api.DataJSON)
@ -348,6 +349,7 @@ public extension Api {
case updateNewStickerSet(stickerset: Api.messages.StickerSet) case updateNewStickerSet(stickerset: Api.messages.StickerSet)
case updateNewStoryReaction(storyId: Int32, peer: Api.Peer, reaction: Api.Reaction) case updateNewStoryReaction(storyId: Int32, peer: Api.Peer, reaction: Api.Reaction)
case updateNotifySettings(peer: Api.NotifyPeer, notifySettings: Api.PeerNotifySettings) case updateNotifySettings(peer: Api.NotifyPeer, notifySettings: Api.PeerNotifySettings)
case updatePaidReactionPrivacy(private: Api.Bool)
case updatePeerBlocked(flags: Int32, peerId: Api.Peer) case updatePeerBlocked(flags: Int32, peerId: Api.Peer)
case updatePeerHistoryTTL(flags: Int32, peer: Api.Peer, ttlPeriod: Int32?) case updatePeerHistoryTTL(flags: Int32, peer: Api.Peer, ttlPeriod: Int32?)
case updatePeerLocated(peers: [Api.PeerLocated]) case updatePeerLocated(peers: [Api.PeerLocated])
@ -577,6 +579,14 @@ public extension Api {
serializeString(currency, buffer: buffer, boxed: false) serializeString(currency, buffer: buffer, boxed: false)
serializeInt64(totalAmount, buffer: buffer, boxed: false) serializeInt64(totalAmount, buffer: buffer, boxed: false)
break break
case .updateBotPurchasedPaidMedia(let userId, let payload, let qts):
if boxed {
buffer.appendInt32(675009298)
}
serializeInt64(userId, buffer: buffer, boxed: false)
serializeString(payload, buffer: buffer, boxed: false)
serializeInt32(qts, buffer: buffer, boxed: false)
break
case .updateBotShippingQuery(let queryId, let userId, let payload, let shippingAddress): case .updateBotShippingQuery(let queryId, let userId, let payload, let shippingAddress):
if boxed { if boxed {
buffer.appendInt32(-1246823043) buffer.appendInt32(-1246823043)
@ -1173,6 +1183,12 @@ public extension Api {
peer.serialize(buffer, true) peer.serialize(buffer, true)
notifySettings.serialize(buffer, true) notifySettings.serialize(buffer, true)
break break
case .updatePaidReactionPrivacy(let `private`):
if boxed {
buffer.appendInt32(1372224236)
}
`private`.serialize(buffer, true)
break
case .updatePeerBlocked(let flags, let peerId): case .updatePeerBlocked(let flags, let peerId):
if boxed { if boxed {
buffer.appendInt32(-337610926) buffer.appendInt32(-337610926)
@ -1649,6 +1665,8 @@ public extension Api {
return ("updateBotNewBusinessMessage", [("flags", flags as Any), ("connectionId", connectionId as Any), ("message", message as Any), ("replyToMessage", replyToMessage as Any), ("qts", qts as Any)]) return ("updateBotNewBusinessMessage", [("flags", flags as Any), ("connectionId", connectionId as Any), ("message", message as Any), ("replyToMessage", replyToMessage as Any), ("qts", qts as Any)])
case .updateBotPrecheckoutQuery(let flags, let queryId, let userId, let payload, let info, let shippingOptionId, let currency, let totalAmount): case .updateBotPrecheckoutQuery(let flags, let queryId, let userId, let payload, let info, let shippingOptionId, let currency, let totalAmount):
return ("updateBotPrecheckoutQuery", [("flags", flags as Any), ("queryId", queryId as Any), ("userId", userId as Any), ("payload", payload as Any), ("info", info as Any), ("shippingOptionId", shippingOptionId as Any), ("currency", currency as Any), ("totalAmount", totalAmount as Any)]) return ("updateBotPrecheckoutQuery", [("flags", flags as Any), ("queryId", queryId as Any), ("userId", userId as Any), ("payload", payload as Any), ("info", info as Any), ("shippingOptionId", shippingOptionId as Any), ("currency", currency as Any), ("totalAmount", totalAmount as Any)])
case .updateBotPurchasedPaidMedia(let userId, let payload, let qts):
return ("updateBotPurchasedPaidMedia", [("userId", userId as Any), ("payload", payload as Any), ("qts", qts as Any)])
case .updateBotShippingQuery(let queryId, let userId, let payload, let shippingAddress): case .updateBotShippingQuery(let queryId, let userId, let payload, let shippingAddress):
return ("updateBotShippingQuery", [("queryId", queryId as Any), ("userId", userId as Any), ("payload", payload as Any), ("shippingAddress", shippingAddress as Any)]) return ("updateBotShippingQuery", [("queryId", queryId as Any), ("userId", userId as Any), ("payload", payload as Any), ("shippingAddress", shippingAddress as Any)])
case .updateBotStopped(let userId, let date, let stopped, let qts): case .updateBotStopped(let userId, let date, let stopped, let qts):
@ -1789,6 +1807,8 @@ public extension Api {
return ("updateNewStoryReaction", [("storyId", storyId as Any), ("peer", peer as Any), ("reaction", reaction as Any)]) return ("updateNewStoryReaction", [("storyId", storyId as Any), ("peer", peer as Any), ("reaction", reaction as Any)])
case .updateNotifySettings(let peer, let notifySettings): case .updateNotifySettings(let peer, let notifySettings):
return ("updateNotifySettings", [("peer", peer as Any), ("notifySettings", notifySettings as Any)]) return ("updateNotifySettings", [("peer", peer as Any), ("notifySettings", notifySettings as Any)])
case .updatePaidReactionPrivacy(let `private`):
return ("updatePaidReactionPrivacy", [("`private`", `private` as Any)])
case .updatePeerBlocked(let flags, let peerId): case .updatePeerBlocked(let flags, let peerId):
return ("updatePeerBlocked", [("flags", flags as Any), ("peerId", peerId as Any)]) return ("updatePeerBlocked", [("flags", flags as Any), ("peerId", peerId as Any)])
case .updatePeerHistoryTTL(let flags, let peer, let ttlPeriod): case .updatePeerHistoryTTL(let flags, let peer, let ttlPeriod):
@ -2281,6 +2301,23 @@ public extension Api {
return nil return nil
} }
} }
public static func parse_updateBotPurchasedPaidMedia(_ reader: BufferReader) -> Update? {
var _1: Int64?
_1 = reader.readInt64()
var _2: String?
_2 = parseString(reader)
var _3: Int32?
_3 = reader.readInt32()
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
if _c1 && _c2 && _c3 {
return Api.Update.updateBotPurchasedPaidMedia(userId: _1!, payload: _2!, qts: _3!)
}
else {
return nil
}
}
public static func parse_updateBotShippingQuery(_ reader: BufferReader) -> Update? { public static func parse_updateBotShippingQuery(_ reader: BufferReader) -> Update? {
var _1: Int64? var _1: Int64?
_1 = reader.readInt64() _1 = reader.readInt64()
@ -3529,6 +3566,19 @@ public extension Api {
return nil return nil
} }
} }
public static func parse_updatePaidReactionPrivacy(_ reader: BufferReader) -> Update? {
var _1: Api.Bool?
if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.Bool
}
let _c1 = _1 != nil
if _c1 {
return Api.Update.updatePaidReactionPrivacy(private: _1!)
}
else {
return nil
}
}
public static func parse_updatePeerBlocked(_ reader: BufferReader) -> Update? { public static func parse_updatePeerBlocked(_ reader: BufferReader) -> Update? {
var _1: Int32? var _1: Int32?
_1 = reader.readInt32() _1 = reader.readInt32()

View File

@ -395,6 +395,7 @@ public extension Api {
case channelAdminLogEventActionParticipantJoinByRequest(invite: Api.ExportedChatInvite, approvedBy: Int64) case channelAdminLogEventActionParticipantJoinByRequest(invite: Api.ExportedChatInvite, approvedBy: Int64)
case channelAdminLogEventActionParticipantLeave case channelAdminLogEventActionParticipantLeave
case channelAdminLogEventActionParticipantMute(participant: Api.GroupCallParticipant) case channelAdminLogEventActionParticipantMute(participant: Api.GroupCallParticipant)
case channelAdminLogEventActionParticipantSubExtend(prevParticipant: Api.ChannelParticipant, newParticipant: Api.ChannelParticipant)
case channelAdminLogEventActionParticipantToggleAdmin(prevParticipant: Api.ChannelParticipant, newParticipant: Api.ChannelParticipant) case channelAdminLogEventActionParticipantToggleAdmin(prevParticipant: Api.ChannelParticipant, newParticipant: Api.ChannelParticipant)
case channelAdminLogEventActionParticipantToggleBan(prevParticipant: Api.ChannelParticipant, newParticipant: Api.ChannelParticipant) case channelAdminLogEventActionParticipantToggleBan(prevParticipant: Api.ChannelParticipant, newParticipant: Api.ChannelParticipant)
case channelAdminLogEventActionParticipantUnmute(participant: Api.GroupCallParticipant) case channelAdminLogEventActionParticipantUnmute(participant: Api.GroupCallParticipant)
@ -631,6 +632,13 @@ public extension Api {
} }
participant.serialize(buffer, true) participant.serialize(buffer, true)
break break
case .channelAdminLogEventActionParticipantSubExtend(let prevParticipant, let newParticipant):
if boxed {
buffer.appendInt32(1684286899)
}
prevParticipant.serialize(buffer, true)
newParticipant.serialize(buffer, true)
break
case .channelAdminLogEventActionParticipantToggleAdmin(let prevParticipant, let newParticipant): case .channelAdminLogEventActionParticipantToggleAdmin(let prevParticipant, let newParticipant):
if boxed { if boxed {
buffer.appendInt32(-714643696) buffer.appendInt32(-714643696)
@ -811,6 +819,8 @@ public extension Api {
return ("channelAdminLogEventActionParticipantLeave", []) return ("channelAdminLogEventActionParticipantLeave", [])
case .channelAdminLogEventActionParticipantMute(let participant): case .channelAdminLogEventActionParticipantMute(let participant):
return ("channelAdminLogEventActionParticipantMute", [("participant", participant as Any)]) return ("channelAdminLogEventActionParticipantMute", [("participant", participant as Any)])
case .channelAdminLogEventActionParticipantSubExtend(let prevParticipant, let newParticipant):
return ("channelAdminLogEventActionParticipantSubExtend", [("prevParticipant", prevParticipant as Any), ("newParticipant", newParticipant as Any)])
case .channelAdminLogEventActionParticipantToggleAdmin(let prevParticipant, let newParticipant): case .channelAdminLogEventActionParticipantToggleAdmin(let prevParticipant, let newParticipant):
return ("channelAdminLogEventActionParticipantToggleAdmin", [("prevParticipant", prevParticipant as Any), ("newParticipant", newParticipant as Any)]) return ("channelAdminLogEventActionParticipantToggleAdmin", [("prevParticipant", prevParticipant as Any), ("newParticipant", newParticipant as Any)])
case .channelAdminLogEventActionParticipantToggleBan(let prevParticipant, let newParticipant): case .channelAdminLogEventActionParticipantToggleBan(let prevParticipant, let newParticipant):
@ -1314,6 +1324,24 @@ public extension Api {
return nil return nil
} }
} }
public static func parse_channelAdminLogEventActionParticipantSubExtend(_ reader: BufferReader) -> ChannelAdminLogEventAction? {
var _1: Api.ChannelParticipant?
if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.ChannelParticipant
}
var _2: Api.ChannelParticipant?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.ChannelParticipant
}
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.ChannelAdminLogEventAction.channelAdminLogEventActionParticipantSubExtend(prevParticipant: _1!, newParticipant: _2!)
}
else {
return nil
}
}
public static func parse_channelAdminLogEventActionParticipantToggleAdmin(_ reader: BufferReader) -> ChannelAdminLogEventAction? { public static func parse_channelAdminLogEventActionParticipantToggleAdmin(_ reader: BufferReader) -> ChannelAdminLogEventAction? {
var _1: Api.ChannelParticipant? var _1: Api.ChannelParticipant?
if let signature = reader.readInt32() { if let signature = reader.readInt32() {

View File

@ -583,7 +583,7 @@ public extension Api.payments {
public extension Api.payments { public extension Api.payments {
enum GiveawayInfo: TypeConstructorDescription { enum GiveawayInfo: TypeConstructorDescription {
case giveawayInfo(flags: Int32, startDate: Int32, joinedTooEarlyDate: Int32?, adminDisallowedChatId: Int64?, disallowedCountry: String?) case giveawayInfo(flags: Int32, startDate: Int32, joinedTooEarlyDate: Int32?, adminDisallowedChatId: Int64?, disallowedCountry: String?)
case giveawayInfoResults(flags: Int32, startDate: Int32, giftCodeSlug: String?, finishDate: Int32, winnersCount: Int32, activatedCount: Int32) case giveawayInfoResults(flags: Int32, startDate: Int32, giftCodeSlug: String?, starsPrize: Int64?, finishDate: Int32, winnersCount: Int32, activatedCount: Int32?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self { switch self {
@ -597,16 +597,17 @@ public extension Api.payments {
if Int(flags) & Int(1 << 2) != 0 {serializeInt64(adminDisallowedChatId!, buffer: buffer, boxed: false)} if Int(flags) & Int(1 << 2) != 0 {serializeInt64(adminDisallowedChatId!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 4) != 0 {serializeString(disallowedCountry!, buffer: buffer, boxed: false)} if Int(flags) & Int(1 << 4) != 0 {serializeString(disallowedCountry!, buffer: buffer, boxed: false)}
break break
case .giveawayInfoResults(let flags, let startDate, let giftCodeSlug, let finishDate, let winnersCount, let activatedCount): case .giveawayInfoResults(let flags, let startDate, let giftCodeSlug, let starsPrize, let finishDate, let winnersCount, let activatedCount):
if boxed { if boxed {
buffer.appendInt32(13456752) buffer.appendInt32(-512366993)
} }
serializeInt32(flags, buffer: buffer, boxed: false) serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt32(startDate, buffer: buffer, boxed: false) serializeInt32(startDate, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {serializeString(giftCodeSlug!, buffer: buffer, boxed: false)} if Int(flags) & Int(1 << 3) != 0 {serializeString(giftCodeSlug!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 4) != 0 {serializeInt64(starsPrize!, buffer: buffer, boxed: false)}
serializeInt32(finishDate, buffer: buffer, boxed: false) serializeInt32(finishDate, buffer: buffer, boxed: false)
serializeInt32(winnersCount, buffer: buffer, boxed: false) serializeInt32(winnersCount, buffer: buffer, boxed: false)
serializeInt32(activatedCount, buffer: buffer, boxed: false) if Int(flags) & Int(1 << 2) != 0 {serializeInt32(activatedCount!, buffer: buffer, boxed: false)}
break break
} }
} }
@ -615,8 +616,8 @@ public extension Api.payments {
switch self { switch self {
case .giveawayInfo(let flags, let startDate, let joinedTooEarlyDate, let adminDisallowedChatId, let disallowedCountry): case .giveawayInfo(let flags, let startDate, let joinedTooEarlyDate, let adminDisallowedChatId, let disallowedCountry):
return ("giveawayInfo", [("flags", flags as Any), ("startDate", startDate as Any), ("joinedTooEarlyDate", joinedTooEarlyDate as Any), ("adminDisallowedChatId", adminDisallowedChatId as Any), ("disallowedCountry", disallowedCountry as Any)]) return ("giveawayInfo", [("flags", flags as Any), ("startDate", startDate as Any), ("joinedTooEarlyDate", joinedTooEarlyDate as Any), ("adminDisallowedChatId", adminDisallowedChatId as Any), ("disallowedCountry", disallowedCountry as Any)])
case .giveawayInfoResults(let flags, let startDate, let giftCodeSlug, let finishDate, let winnersCount, let activatedCount): case .giveawayInfoResults(let flags, let startDate, let giftCodeSlug, let starsPrize, let finishDate, let winnersCount, let activatedCount):
return ("giveawayInfoResults", [("flags", flags as Any), ("startDate", startDate as Any), ("giftCodeSlug", giftCodeSlug as Any), ("finishDate", finishDate as Any), ("winnersCount", winnersCount as Any), ("activatedCount", activatedCount as Any)]) return ("giveawayInfoResults", [("flags", flags as Any), ("startDate", startDate as Any), ("giftCodeSlug", giftCodeSlug as Any), ("starsPrize", starsPrize as Any), ("finishDate", finishDate as Any), ("winnersCount", winnersCount as Any), ("activatedCount", activatedCount as Any)])
} }
} }
@ -649,21 +650,24 @@ public extension Api.payments {
var _2: Int32? var _2: Int32?
_2 = reader.readInt32() _2 = reader.readInt32()
var _3: String? var _3: String?
if Int(_1!) & Int(1 << 0) != 0 {_3 = parseString(reader) } if Int(_1!) & Int(1 << 3) != 0 {_3 = parseString(reader) }
var _4: Int32? var _4: Int64?
_4 = reader.readInt32() if Int(_1!) & Int(1 << 4) != 0 {_4 = reader.readInt64() }
var _5: Int32? var _5: Int32?
_5 = reader.readInt32() _5 = reader.readInt32()
var _6: Int32? var _6: Int32?
_6 = reader.readInt32() _6 = reader.readInt32()
var _7: Int32?
if Int(_1!) & Int(1 << 2) != 0 {_7 = reader.readInt32() }
let _c1 = _1 != nil let _c1 = _1 != nil
let _c2 = _2 != nil let _c2 = _2 != nil
let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil let _c3 = (Int(_1!) & Int(1 << 3) == 0) || _3 != nil
let _c4 = _4 != nil let _c4 = (Int(_1!) & Int(1 << 4) == 0) || _4 != nil
let _c5 = _5 != nil let _c5 = _5 != nil
let _c6 = _6 != nil let _c6 = _6 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { let _c7 = (Int(_1!) & Int(1 << 2) == 0) || _7 != nil
return Api.payments.GiveawayInfo.giveawayInfoResults(flags: _1!, startDate: _2!, giftCodeSlug: _3, finishDate: _4!, winnersCount: _5!, activatedCount: _6!) if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 {
return Api.payments.GiveawayInfo.giveawayInfoResults(flags: _1!, startDate: _2!, giftCodeSlug: _3, starsPrize: _4, finishDate: _5!, winnersCount: _6!, activatedCount: _7)
} }
else { else {
return nil return nil

View File

@ -6425,6 +6425,21 @@ public extension Api.functions.messages {
}) })
} }
} }
public extension Api.functions.messages {
static func getPaidReactionPrivacy() -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
let buffer = Buffer()
buffer.appendInt32(1193563562)
return (FunctionDescription(name: "messages.getPaidReactionPrivacy", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
let reader = BufferReader(buffer)
var result: Api.Updates?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.Updates
}
return result
})
}
}
public extension Api.functions.messages { public extension Api.functions.messages {
static func getPeerDialogs(peers: [Api.InputDialogPeer]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.PeerDialogs>) { static func getPeerDialogs(peers: [Api.InputDialogPeer]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.PeerDialogs>) {
let buffer = Buffer() let buffer = Buffer()
@ -7935,15 +7950,16 @@ public extension Api.functions.messages {
} }
} }
public extension Api.functions.messages { public extension Api.functions.messages {
static func sendPaidReaction(flags: Int32, peer: Api.InputPeer, msgId: Int32, count: Int32, randomId: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) { static func sendPaidReaction(flags: Int32, peer: Api.InputPeer, msgId: Int32, count: Int32, randomId: Int64, `private`: Api.Bool?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
let buffer = Buffer() let buffer = Buffer()
buffer.appendInt32(633929278) buffer.appendInt32(-1646877061)
serializeInt32(flags, buffer: buffer, boxed: false) serializeInt32(flags, buffer: buffer, boxed: false)
peer.serialize(buffer, true) peer.serialize(buffer, true)
serializeInt32(msgId, buffer: buffer, boxed: false) serializeInt32(msgId, buffer: buffer, boxed: false)
serializeInt32(count, buffer: buffer, boxed: false) serializeInt32(count, buffer: buffer, boxed: false)
serializeInt64(randomId, buffer: buffer, boxed: false) serializeInt64(randomId, buffer: buffer, boxed: false)
return (FunctionDescription(name: "messages.sendPaidReaction", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("msgId", String(describing: msgId)), ("count", String(describing: count)), ("randomId", String(describing: randomId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in if Int(flags) & Int(1 << 0) != 0 {`private`!.serialize(buffer, true)}
return (FunctionDescription(name: "messages.sendPaidReaction", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("msgId", String(describing: msgId)), ("count", String(describing: count)), ("randomId", String(describing: randomId)), ("`private`", String(describing: `private`))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
let reader = BufferReader(buffer) let reader = BufferReader(buffer)
var result: Api.Updates? var result: Api.Updates?
if let signature = reader.readInt32() { if let signature = reader.readInt32() {
@ -8963,6 +8979,21 @@ public extension Api.functions.payments {
}) })
} }
} }
public extension Api.functions.payments {
static func getStarsGiveawayOptions() -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.StarsGiveawayOption]>) {
let buffer = Buffer()
buffer.appendInt32(-1122042562)
return (FunctionDescription(name: "payments.getStarsGiveawayOptions", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.StarsGiveawayOption]? in
let reader = BufferReader(buffer)
var result: [Api.StarsGiveawayOption]?
if let _ = reader.readInt32() {
result = Api.parseVector(reader, elementSignature: 0, elementType: Api.StarsGiveawayOption.self)
}
return result
})
}
}
public extension Api.functions.payments { public extension Api.functions.payments {
static func getStarsRevenueAdsAccountUrl(peer: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.payments.StarsRevenueAdsAccountUrl>) { static func getStarsRevenueAdsAccountUrl(peer: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.payments.StarsRevenueAdsAccountUrl>) {
let buffer = Buffer() let buffer = Buffer()

View File

@ -258,6 +258,8 @@ func apiMessagePeerIds(_ message: Api.Message) -> [PeerId] {
if let boostPeer = boostPeer { if let boostPeer = boostPeer {
result.append(boostPeer.peerId) result.append(boostPeer.peerId)
} }
case let .messageActionPrizeStars(_, _, _, boostPeer, _):
result.append(boostPeer.peerId)
case let .messageActionPaymentRefunded(_, peer, _, _, _, _): case let .messageActionPaymentRefunded(_, peer, _, _, _, _):
result.append(peer.peerId) result.append(peer.peerId)
} }
@ -425,13 +427,21 @@ func textMediaAndExpirationTimerFromApiMedia(_ media: Api.MessageMedia?, _ peerI
case let .messageMediaStory(flags, peerId, id, _): case let .messageMediaStory(flags, peerId, id, _):
let isMention = (flags & (1 << 1)) != 0 let isMention = (flags & (1 << 1)) != 0
return (TelegramMediaStory(storyId: StoryId(peerId: peerId.peerId, id: id), isMention: isMention), nil, nil, nil, nil) return (TelegramMediaStory(storyId: StoryId(peerId: peerId.peerId, id: id), isMention: isMention), nil, nil, nil, nil)
case let .messageMediaGiveaway(apiFlags, channels, countries, prizeDescription, quantity, months, untilDate): case let .messageMediaGiveaway(apiFlags, channels, countries, prizeDescription, quantity, months, stars, untilDate):
var flags: TelegramMediaGiveaway.Flags = [] var flags: TelegramMediaGiveaway.Flags = []
if (apiFlags & (1 << 0)) != 0 { if (apiFlags & (1 << 0)) != 0 {
flags.insert(.onlyNewSubscribers) flags.insert(.onlyNewSubscribers)
} }
return (TelegramMediaGiveaway(flags: flags, channelPeerIds: channels.map { PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value($0)) }, countries: countries ?? [], quantity: quantity, months: months, untilDate: untilDate, prizeDescription: prizeDescription), nil, nil, nil, nil) let prize: TelegramMediaGiveaway.Prize
case let .messageMediaGiveawayResults(apiFlags, channelId, additionalPeersCount, launchMsgId, winnersCount, unclaimedCount, winners, months, prizeDescription, untilDate): if let months {
prize = .premium(months: months)
} else if let stars {
prize = .stars(amount: stars)
} else {
return (nil, nil, nil, nil, nil)
}
return (TelegramMediaGiveaway(flags: flags, channelPeerIds: channels.map { PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value($0)) }, countries: countries ?? [], quantity: quantity, prize: prize, untilDate: untilDate, prizeDescription: prizeDescription), nil, nil, nil, nil)
case let .messageMediaGiveawayResults(apiFlags, channelId, additionalPeersCount, launchMsgId, winnersCount, unclaimedCount, winners, months, stars, prizeDescription, untilDate):
var flags: TelegramMediaGiveawayResults.Flags = [] var flags: TelegramMediaGiveawayResults.Flags = []
if (apiFlags & (1 << 0)) != 0 { if (apiFlags & (1 << 0)) != 0 {
flags.insert(.onlyNewSubscribers) flags.insert(.onlyNewSubscribers)
@ -439,7 +449,15 @@ func textMediaAndExpirationTimerFromApiMedia(_ media: Api.MessageMedia?, _ peerI
if (apiFlags & (1 << 2)) != 0 { if (apiFlags & (1 << 2)) != 0 {
flags.insert(.refunded) flags.insert(.refunded)
} }
return (TelegramMediaGiveawayResults(flags: flags, launchMessageId: MessageId(peerId: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(channelId)), namespace: Namespaces.Message.Cloud, id: launchMsgId), additionalChannelsCount: additionalPeersCount ?? 0, winnersPeerIds: winners.map { PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value($0)) }, winnersCount: winnersCount, unclaimedCount: unclaimedCount, months: months, untilDate: untilDate, prizeDescription: prizeDescription), nil, nil, nil, nil) let prize: TelegramMediaGiveawayResults.Prize
if let months {
prize = .premium(months: months)
} else if let stars {
prize = .stars(amount: stars)
} else {
return (nil, nil, nil, nil, nil)
}
return (TelegramMediaGiveawayResults(flags: flags, launchMessageId: MessageId(peerId: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(channelId)), namespace: Namespaces.Message.Cloud, id: launchMsgId), additionalChannelsCount: additionalPeersCount ?? 0, winnersPeerIds: winners.map { PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value($0)) }, winnersCount: winnersCount, unclaimedCount: unclaimedCount, prize: prize, untilDate: untilDate, prizeDescription: prizeDescription), nil, nil, nil, nil)
case let .messageMediaPaidMedia(starsAmount, apiExtendedMedia): case let .messageMediaPaidMedia(starsAmount, apiExtendedMedia):
return (TelegramMediaPaidContent(amount: starsAmount, extendedMedia: apiExtendedMedia.compactMap({ TelegramExtendedMedia(apiExtendedMedia: $0, peerId: peerId) })), nil, nil, nil, nil) return (TelegramMediaPaidContent(amount: starsAmount, extendedMedia: apiExtendedMedia.compactMap({ TelegramExtendedMedia(apiExtendedMedia: $0, peerId: peerId) })), nil, nil, nil, nil)
} }

View File

@ -135,8 +135,8 @@ func telegramMediaActionFromApiAction(_ action: Api.MessageAction) -> TelegramMe
} }
case let .messageActionGiftCode(flags, boostPeer, months, slug, currency, amount, cryptoCurrency, cryptoAmount): case let .messageActionGiftCode(flags, boostPeer, months, slug, currency, amount, cryptoCurrency, cryptoAmount):
return TelegramMediaAction(action: .giftCode(slug: slug, fromGiveaway: (flags & (1 << 0)) != 0, isUnclaimed: (flags & (1 << 2)) != 0, boostPeerId: boostPeer?.peerId, months: months, currency: currency, amount: amount, cryptoCurrency: cryptoCurrency, cryptoAmount: cryptoAmount)) return TelegramMediaAction(action: .giftCode(slug: slug, fromGiveaway: (flags & (1 << 0)) != 0, isUnclaimed: (flags & (1 << 2)) != 0, boostPeerId: boostPeer?.peerId, months: months, currency: currency, amount: amount, cryptoCurrency: cryptoCurrency, cryptoAmount: cryptoAmount))
case .messageActionGiveawayLaunch: case let .messageActionGiveawayLaunch(_, stars):
return TelegramMediaAction(action: .giveawayLaunched) return TelegramMediaAction(action: .giveawayLaunched(stars: stars))
case let .messageActionGiveawayResults(winners, unclaimed): case let .messageActionGiveawayResults(winners, unclaimed):
return TelegramMediaAction(action: .giveawayResults(winners: winners, unclaimed: unclaimed)) return TelegramMediaAction(action: .giveawayResults(winners: winners, unclaimed: unclaimed))
case let .messageActionBoostApply(boosts): case let .messageActionBoostApply(boosts):
@ -148,6 +148,8 @@ func telegramMediaActionFromApiAction(_ action: Api.MessageAction) -> TelegramMe
transactionId = id transactionId = id
} }
return TelegramMediaAction(action: .paymentRefunded(peerId: peer.peerId, currency: currency, totalAmount: totalAmount, payload: payload?.makeData(), transactionId: transactionId)) return TelegramMediaAction(action: .paymentRefunded(peerId: peer.peerId, currency: currency, totalAmount: totalAmount, payload: payload?.makeData(), transactionId: transactionId))
case let .messageActionPrizeStars(flags, stars, transactionId, boostPeer, giveawayMsgId):
return TelegramMediaAction(action: .prizeStars(amount: stars, isUnclaimed: (flags & (1 << 2)) != 0, boostPeerId: boostPeer.peerId, transactionId: transactionId, giveawayMessageId: MessageId(peerId: boostPeer.peerId, namespace: Namespaces.Message.Cloud, id: giveawayMsgId)))
} }
} }

View File

@ -165,8 +165,10 @@ func mediaContentToUpload(accountPeerId: PeerId, network: Network, postbox: Post
if media.count == results.count { if media.count == results.count {
return .content(PendingMessageUploadedContentAndReuploadInfo( return .content(PendingMessageUploadedContentAndReuploadInfo(
content: .media(.inputMediaPaidMedia( content: .media(.inputMediaPaidMedia(
flags: 0,
starsAmount: paidContent.amount, starsAmount: paidContent.amount,
extendedMedia: media extendedMedia: media,
payload: nil
), text), ), text),
reuploadInfo: nil, reuploadInfo: nil,
cacheReferenceKey: nil cacheReferenceKey: nil

View File

@ -409,7 +409,7 @@ private func requestSendStarsReaction(postbox: Postbox, network: Network, stateM
flags |= 1 << 0 flags |= 1 << 0
} }
let signal: Signal<Never, RequestUpdateMessageReactionError> = network.request(Api.functions.messages.sendPaidReaction(flags: flags, peer: inputPeer, msgId: messageId.id, count: count, randomId: Int64(bitPattern: randomId))) let signal: Signal<Never, RequestUpdateMessageReactionError> = network.request(Api.functions.messages.sendPaidReaction(flags: flags, peer: inputPeer, msgId: messageId.id, count: count, randomId: Int64(bitPattern: randomId), private: nil))
|> mapError { _ -> RequestUpdateMessageReactionError in |> mapError { _ -> RequestUpdateMessageReactionError in
return .generic return .generic
} }

View File

@ -210,7 +210,7 @@ public class BoxedMessage: NSObject {
public class Serialization: NSObject, MTSerialization { public class Serialization: NSObject, MTSerialization {
public func currentLayer() -> UInt { public func currentLayer() -> UInt {
return 186 return 187
} }
public func parseMessage(_ data: Data!) -> Any! { public func parseMessage(_ data: Data!) -> Any! {

View File

@ -123,12 +123,13 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
case setChatWallpaper(wallpaper: TelegramWallpaper, forBoth: Bool) case setChatWallpaper(wallpaper: TelegramWallpaper, forBoth: Bool)
case setSameChatWallpaper(wallpaper: TelegramWallpaper) case setSameChatWallpaper(wallpaper: TelegramWallpaper)
case giftCode(slug: String, fromGiveaway: Bool, isUnclaimed: Bool, boostPeerId: PeerId?, months: Int32, currency: String?, amount: Int64?, cryptoCurrency: String?, cryptoAmount: Int64?) case giftCode(slug: String, fromGiveaway: Bool, isUnclaimed: Bool, boostPeerId: PeerId?, months: Int32, currency: String?, amount: Int64?, cryptoCurrency: String?, cryptoAmount: Int64?)
case giveawayLaunched case giveawayLaunched(stars: Int64?)
case joinedChannel case joinedChannel
case giveawayResults(winners: Int32, unclaimed: Int32) case giveawayResults(winners: Int32, unclaimed: Int32)
case boostsApplied(boosts: Int32) case boostsApplied(boosts: Int32)
case paymentRefunded(peerId: PeerId, currency: String, totalAmount: Int64, payload: Data?, transactionId: String) case paymentRefunded(peerId: PeerId, currency: String, totalAmount: Int64, payload: Data?, transactionId: String)
case giftStars(currency: String, amount: Int64, count: Int64, cryptoCurrency: String?, cryptoAmount: Int64?, transactionId: String?) case giftStars(currency: String, amount: Int64, count: Int64, cryptoCurrency: String?, cryptoAmount: Int64?, transactionId: String?)
case prizeStars(amount: Int64, isUnclaimed: Bool, boostPeerId: PeerId?, transactionId: String?, giveawayMessageId: MessageId?)
public init(decoder: PostboxDecoder) { public init(decoder: PostboxDecoder) {
let rawValue: Int32 = decoder.decodeInt32ForKey("_rawValue", orElse: 0) let rawValue: Int32 = decoder.decodeInt32ForKey("_rawValue", orElse: 0)
@ -230,7 +231,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
case 36: case 36:
self = .giftCode(slug: decoder.decodeStringForKey("slug", orElse: ""), fromGiveaway: decoder.decodeBoolForKey("give", orElse: false), isUnclaimed: decoder.decodeBoolForKey("unclaimed", orElse: false), boostPeerId: decoder.decodeOptionalInt64ForKey("pi").flatMap { PeerId($0) }, months: decoder.decodeInt32ForKey("months", orElse: 0), currency: decoder.decodeOptionalStringForKey("currency"), amount: decoder.decodeOptionalInt64ForKey("amount"), cryptoCurrency: decoder.decodeOptionalStringForKey("cryptoCurrency"), cryptoAmount: decoder.decodeOptionalInt64ForKey("cryptoAmount")) self = .giftCode(slug: decoder.decodeStringForKey("slug", orElse: ""), fromGiveaway: decoder.decodeBoolForKey("give", orElse: false), isUnclaimed: decoder.decodeBoolForKey("unclaimed", orElse: false), boostPeerId: decoder.decodeOptionalInt64ForKey("pi").flatMap { PeerId($0) }, months: decoder.decodeInt32ForKey("months", orElse: 0), currency: decoder.decodeOptionalStringForKey("currency"), amount: decoder.decodeOptionalInt64ForKey("amount"), cryptoCurrency: decoder.decodeOptionalStringForKey("cryptoCurrency"), cryptoAmount: decoder.decodeOptionalInt64ForKey("cryptoAmount"))
case 37: case 37:
self = .giveawayLaunched self = .giveawayLaunched(stars: decoder.decodeOptionalInt64ForKey("stars"))
case 38: case 38:
self = .joinedChannel self = .joinedChannel
case 39: case 39:
@ -241,6 +242,14 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
self = .paymentRefunded(peerId: PeerId(decoder.decodeInt64ForKey("pi", orElse: 0)), currency: decoder.decodeStringForKey("currency", orElse: ""), totalAmount: decoder.decodeInt64ForKey("amount", orElse: 0), payload: decoder.decodeDataForKey("payload"), transactionId: decoder.decodeStringForKey("transactionId", orElse: "")) self = .paymentRefunded(peerId: PeerId(decoder.decodeInt64ForKey("pi", orElse: 0)), currency: decoder.decodeStringForKey("currency", orElse: ""), totalAmount: decoder.decodeInt64ForKey("amount", orElse: 0), payload: decoder.decodeDataForKey("payload"), transactionId: decoder.decodeStringForKey("transactionId", orElse: ""))
case 42: case 42:
self = .giftStars(currency: decoder.decodeStringForKey("currency", orElse: ""), amount: decoder.decodeInt64ForKey("amount", orElse: 0), count: decoder.decodeInt64ForKey("count", orElse: 0), cryptoCurrency: decoder.decodeOptionalStringForKey("cryptoCurrency"), cryptoAmount: decoder.decodeOptionalInt64ForKey("cryptoAmount"), transactionId: decoder.decodeOptionalStringForKey("transactionId")) self = .giftStars(currency: decoder.decodeStringForKey("currency", orElse: ""), amount: decoder.decodeInt64ForKey("amount", orElse: 0), count: decoder.decodeInt64ForKey("count", orElse: 0), cryptoCurrency: decoder.decodeOptionalStringForKey("cryptoCurrency"), cryptoAmount: decoder.decodeOptionalInt64ForKey("cryptoAmount"), transactionId: decoder.decodeOptionalStringForKey("transactionId"))
case 43:
let boostPeerId = decoder.decodeOptionalInt64ForKey("pi").flatMap { PeerId($0) }
let giveawayMsgId = decoder.decodeOptionalInt32ForKey("giveawayMsgId")
var giveawayMessageId: MessageId?
if let boostPeerId, let giveawayMsgId {
giveawayMessageId = MessageId(peerId: boostPeerId, namespace: Namespaces.Message.Cloud, id: giveawayMsgId)
}
self = .prizeStars(amount: decoder.decodeInt64ForKey("amount", orElse: 0), isUnclaimed: decoder.decodeBoolForKey("unclaimed", orElse: false), boostPeerId: boostPeerId, transactionId: decoder.decodeOptionalStringForKey("transactionId"), giveawayMessageId: giveawayMessageId)
default: default:
self = .unknown self = .unknown
} }
@ -452,8 +461,13 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
} else { } else {
encoder.encodeNil(forKey: "cryptoAmount") encoder.encodeNil(forKey: "cryptoAmount")
} }
case .giveawayLaunched: case let .giveawayLaunched(stars):
encoder.encodeInt32(37, forKey: "_rawValue") encoder.encodeInt32(37, forKey: "_rawValue")
if let stars = stars {
encoder.encodeInt64(stars, forKey: "stars")
} else {
encoder.encodeNil(forKey: "stars")
}
case .joinedChannel: case .joinedChannel:
encoder.encodeInt32(38, forKey: "_rawValue") encoder.encodeInt32(38, forKey: "_rawValue")
case let .giveawayResults(winners, unclaimed): case let .giveawayResults(winners, unclaimed):
@ -491,6 +505,25 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
} else { } else {
encoder.encodeNil(forKey: "transactionId") encoder.encodeNil(forKey: "transactionId")
} }
case let .prizeStars(amount, isUnclaimed, boostPeerId, transactionId, giveawayMessageId):
encoder.encodeInt32(43, forKey: "_rawValue")
encoder.encodeInt64(amount, forKey: "amount")
encoder.encodeBool(isUnclaimed, forKey: "unclaimed")
if let boostPeerId = boostPeerId {
encoder.encodeInt64(boostPeerId.toInt64(), forKey: "pi")
} else {
encoder.encodeNil(forKey: "pi")
}
if let transactionId {
encoder.encodeString(transactionId, forKey: "transactionId")
} else {
encoder.encodeNil(forKey: "transactionId")
}
if let giveawayMessageId {
encoder.encodeInt32(giveawayMessageId.id, forKey: "giveawayMsgId")
} else {
encoder.encodeNil(forKey: "giveawayMsgId")
}
} }
} }
@ -516,6 +549,8 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
return boostPeerId.flatMap { [$0] } ?? [] return boostPeerId.flatMap { [$0] } ?? []
case let .paymentRefunded(peerId, _, _, _, _): case let .paymentRefunded(peerId, _, _, _, _):
return [peerId] return [peerId]
case let .prizeStars(_, _, boostPeerId, _, _):
return boostPeerId.flatMap { [$0] } ?? []
default: default:
return [] return []
} }

View File

@ -12,6 +12,11 @@ public final class TelegramMediaGiveaway: Media, Equatable {
public static let showWinners = Flags(rawValue: 1 << 1) public static let showWinners = Flags(rawValue: 1 << 1)
} }
public enum Prize: Equatable {
case premium(months: Int32)
case stars(amount: Int64)
}
public var id: MediaId? { public var id: MediaId? {
return nil return nil
} }
@ -23,16 +28,16 @@ public final class TelegramMediaGiveaway: Media, Equatable {
public let channelPeerIds: [PeerId] public let channelPeerIds: [PeerId]
public let countries: [String] public let countries: [String]
public let quantity: Int32 public let quantity: Int32
public let months: Int32 public let prize: Prize
public let untilDate: Int32 public let untilDate: Int32
public let prizeDescription: String? public let prizeDescription: String?
public init(flags: Flags, channelPeerIds: [PeerId], countries: [String], quantity: Int32, months: Int32, untilDate: Int32, prizeDescription: String?) { public init(flags: Flags, channelPeerIds: [PeerId], countries: [String], quantity: Int32, prize: Prize, untilDate: Int32, prizeDescription: String?) {
self.flags = flags self.flags = flags
self.channelPeerIds = channelPeerIds self.channelPeerIds = channelPeerIds
self.countries = countries self.countries = countries
self.quantity = quantity self.quantity = quantity
self.months = months self.prize = prize
self.untilDate = untilDate self.untilDate = untilDate
self.prizeDescription = prizeDescription self.prizeDescription = prizeDescription
} }
@ -42,7 +47,13 @@ public final class TelegramMediaGiveaway: Media, Equatable {
self.channelPeerIds = decoder.decodeInt64ArrayForKey("cns").map { PeerId($0) } self.channelPeerIds = decoder.decodeInt64ArrayForKey("cns").map { PeerId($0) }
self.countries = decoder.decodeStringArrayForKey("cnt") self.countries = decoder.decodeStringArrayForKey("cnt")
self.quantity = decoder.decodeInt32ForKey("qty", orElse: 0) self.quantity = decoder.decodeInt32ForKey("qty", orElse: 0)
self.months = decoder.decodeInt32ForKey("mts", orElse: 0) if let months = decoder.decodeOptionalInt32ForKey("mts") {
self.prize = .premium(months: months)
} else if let stars = decoder.decodeOptionalInt64ForKey("str") {
self.prize = .stars(amount: stars)
} else {
self.prize = .premium(months: 0)
}
self.untilDate = decoder.decodeInt32ForKey("unt", orElse: 0) self.untilDate = decoder.decodeInt32ForKey("unt", orElse: 0)
self.prizeDescription = decoder.decodeOptionalStringForKey("des") self.prizeDescription = decoder.decodeOptionalStringForKey("des")
} }
@ -52,7 +63,12 @@ public final class TelegramMediaGiveaway: Media, Equatable {
encoder.encodeInt64Array(self.channelPeerIds.map { $0.toInt64() }, forKey: "cns") encoder.encodeInt64Array(self.channelPeerIds.map { $0.toInt64() }, forKey: "cns")
encoder.encodeStringArray(self.countries, forKey: "cnt") encoder.encodeStringArray(self.countries, forKey: "cnt")
encoder.encodeInt32(self.quantity, forKey: "qty") encoder.encodeInt32(self.quantity, forKey: "qty")
encoder.encodeInt32(self.months, forKey: "mts") switch self.prize {
case let .premium(months):
encoder.encodeInt32(months, forKey: "mts")
case let .stars(amount):
encoder.encodeInt64(amount, forKey: "str")
}
encoder.encodeInt32(self.untilDate, forKey: "unt") encoder.encodeInt32(self.untilDate, forKey: "unt")
if let prizeDescription = self.prizeDescription { if let prizeDescription = self.prizeDescription {
encoder.encodeString(prizeDescription, forKey: "des") encoder.encodeString(prizeDescription, forKey: "des")
@ -81,7 +97,7 @@ public final class TelegramMediaGiveaway: Media, Equatable {
if self.quantity != other.quantity { if self.quantity != other.quantity {
return false return false
} }
if self.months != other.months { if self.prize != other.prize {
return false return false
} }
if self.untilDate != other.untilDate { if self.untilDate != other.untilDate {

View File

@ -12,6 +12,11 @@ public final class TelegramMediaGiveawayResults: Media, Equatable {
public static let onlyNewSubscribers = Flags(rawValue: 1 << 1) public static let onlyNewSubscribers = Flags(rawValue: 1 << 1)
} }
public enum Prize: Equatable {
case premium(months: Int32)
case stars(amount: Int64)
}
public var id: MediaId? { public var id: MediaId? {
return nil return nil
} }
@ -25,18 +30,18 @@ public final class TelegramMediaGiveawayResults: Media, Equatable {
public let winnersPeerIds: [PeerId] public let winnersPeerIds: [PeerId]
public let winnersCount: Int32 public let winnersCount: Int32
public let unclaimedCount: Int32 public let unclaimedCount: Int32
public let months: Int32 public let prize: Prize
public let untilDate: Int32 public let untilDate: Int32
public let prizeDescription: String? public let prizeDescription: String?
public init(flags: Flags, launchMessageId: MessageId, additionalChannelsCount: Int32, winnersPeerIds: [PeerId], winnersCount: Int32, unclaimedCount: Int32, months: Int32, untilDate: Int32, prizeDescription: String?) { public init(flags: Flags, launchMessageId: MessageId, additionalChannelsCount: Int32, winnersPeerIds: [PeerId], winnersCount: Int32, unclaimedCount: Int32, prize: Prize, untilDate: Int32, prizeDescription: String?) {
self.flags = flags self.flags = flags
self.launchMessageId = launchMessageId self.launchMessageId = launchMessageId
self.additionalChannelsCount = additionalChannelsCount self.additionalChannelsCount = additionalChannelsCount
self.winnersPeerIds = winnersPeerIds self.winnersPeerIds = winnersPeerIds
self.winnersCount = winnersCount self.winnersCount = winnersCount
self.unclaimedCount = unclaimedCount self.unclaimedCount = unclaimedCount
self.months = months self.prize = prize
self.untilDate = untilDate self.untilDate = untilDate
self.prizeDescription = prizeDescription self.prizeDescription = prizeDescription
} }
@ -48,7 +53,13 @@ public final class TelegramMediaGiveawayResults: Media, Equatable {
self.winnersPeerIds = decoder.decodeInt64ArrayForKey("wnr").map { PeerId($0) } self.winnersPeerIds = decoder.decodeInt64ArrayForKey("wnr").map { PeerId($0) }
self.winnersCount = decoder.decodeInt32ForKey("wnc", orElse: 0) self.winnersCount = decoder.decodeInt32ForKey("wnc", orElse: 0)
self.unclaimedCount = decoder.decodeInt32ForKey("unc", orElse: 0) self.unclaimedCount = decoder.decodeInt32ForKey("unc", orElse: 0)
self.months = decoder.decodeInt32ForKey("mts", orElse: 0) if let months = decoder.decodeOptionalInt32ForKey("mts") {
self.prize = .premium(months: months)
} else if let stars = decoder.decodeOptionalInt64ForKey("str") {
self.prize = .stars(amount: stars)
} else {
self.prize = .premium(months: 0)
}
self.untilDate = decoder.decodeInt32ForKey("unt", orElse: 0) self.untilDate = decoder.decodeInt32ForKey("unt", orElse: 0)
self.prizeDescription = decoder.decodeOptionalStringForKey("des") self.prizeDescription = decoder.decodeOptionalStringForKey("des")
} }
@ -61,7 +72,12 @@ public final class TelegramMediaGiveawayResults: Media, Equatable {
encoder.encodeInt64Array(self.winnersPeerIds.map { $0.toInt64() }, forKey: "wnr") encoder.encodeInt64Array(self.winnersPeerIds.map { $0.toInt64() }, forKey: "wnr")
encoder.encodeInt32(self.winnersCount, forKey: "wnc") encoder.encodeInt32(self.winnersCount, forKey: "wnc")
encoder.encodeInt32(self.unclaimedCount, forKey: "unc") encoder.encodeInt32(self.unclaimedCount, forKey: "unc")
encoder.encodeInt32(self.months, forKey: "mts") switch self.prize {
case let .premium(months):
encoder.encodeInt32(months, forKey: "mts")
case let .stars(amount):
encoder.encodeInt64(amount, forKey: "str")
}
encoder.encodeInt32(self.untilDate, forKey: "unt") encoder.encodeInt32(self.untilDate, forKey: "unt")
if let prizeDescription = self.prizeDescription { if let prizeDescription = self.prizeDescription {
encoder.encodeString(prizeDescription, forKey: "des") encoder.encodeString(prizeDescription, forKey: "des")
@ -96,7 +112,7 @@ public final class TelegramMediaGiveawayResults: Media, Equatable {
if self.unclaimedCount != other.unclaimedCount { if self.unclaimedCount != other.unclaimedCount {
return false return false
} }
if self.months != other.months { if self.prize != other.prize {
return false return false
} }
if self.untilDate != other.untilDate { if self.untilDate != other.untilDate {

View File

@ -19,6 +19,7 @@ public enum AppStoreTransactionPurpose {
case giveaway(boostPeer: EnginePeer.Id, additionalPeerIds: [EnginePeer.Id], countries: [String], onlyNewSubscribers: Bool, showWinners: Bool, prizeDescription: String?, randomId: Int64, untilDate: Int32, currency: String, amount: Int64) case giveaway(boostPeer: EnginePeer.Id, additionalPeerIds: [EnginePeer.Id], countries: [String], onlyNewSubscribers: Bool, showWinners: Bool, prizeDescription: String?, randomId: Int64, untilDate: Int32, currency: String, amount: Int64)
case stars(count: Int64, currency: String, amount: Int64) case stars(count: Int64, currency: String, amount: Int64)
case starsGift(peerId: EnginePeer.Id, count: Int64, currency: String, amount: Int64) case starsGift(peerId: EnginePeer.Id, count: Int64, currency: String, amount: Int64)
case starsGiveaway(stars: Int64, boostPeer: EnginePeer.Id, additionalPeerIds: [EnginePeer.Id], countries: [String], onlyNewSubscribers: Bool, showWinners: Bool, prizeDescription: String?, randomId: Int64, untilDate: Int32, currency: String, amount: Int64, users: Int32)
} }
private func apiInputStorePaymentPurpose(account: Account, purpose: AppStoreTransactionPurpose) -> Signal<Api.InputStorePaymentPurpose, NoError> { private func apiInputStorePaymentPurpose(account: Account, purpose: AppStoreTransactionPurpose) -> Signal<Api.InputStorePaymentPurpose, NoError> {
@ -101,6 +102,36 @@ private func apiInputStorePaymentPurpose(account: Account, purpose: AppStoreTran
} }
return .single(.inputStorePaymentStarsGift(userId: inputUser, stars: count, currency: currency, amount: amount)) return .single(.inputStorePaymentStarsGift(userId: inputUser, stars: count, currency: currency, amount: amount))
} }
case let .starsGiveaway(stars, boostPeerId, additionalPeerIds, countries, onlyNewSubscribers, showWinners, prizeDescription, randomId, untilDate, currency, amount, users):
return account.postbox.transaction { transaction -> Signal<Api.InputStorePaymentPurpose, NoError> in
guard let peer = transaction.getPeer(boostPeerId), let apiBoostPeer = apiInputPeer(peer) else {
return .complete()
}
var flags: Int32 = 0
if onlyNewSubscribers {
flags |= (1 << 0)
}
if showWinners {
flags |= (1 << 3)
}
var additionalPeers: [Api.InputPeer] = []
if !additionalPeerIds.isEmpty {
flags |= (1 << 1)
for peerId in additionalPeerIds {
if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) {
additionalPeers.append(inputPeer)
}
}
}
if !countries.isEmpty {
flags |= (1 << 2)
}
if let _ = prizeDescription {
flags |= (1 << 4)
}
return .single(.inputStorePaymentStarsGiveaway(flags: flags, stars: stars, boostPeer: apiBoostPeer, additionalPeers: additionalPeers, countriesIso2: countries, prizeDescription: prizeDescription, randomId: randomId, untilDate: untilDate, currency: currency, amount: amount, users: users))
}
|> switchToLatest
} }
} }

View File

@ -79,12 +79,13 @@ public enum PremiumGiveawayInfo: Equatable {
public enum ResultStatus: Equatable { public enum ResultStatus: Equatable {
case notWon case notWon
case won(slug: String) case wonPremium(slug: String)
case wonStars(stars: Int64)
case refunded case refunded
} }
case ongoing(startDate: Int32, status: OngoingStatus) case ongoing(startDate: Int32, status: OngoingStatus)
case finished(status: ResultStatus, startDate: Int32, finishDate: Int32, winnersCount: Int32, activatedCount: Int32) case finished(status: ResultStatus, startDate: Int32, finishDate: Int32, winnersCount: Int32, activatedCount: Int32?)
} }
public struct PrepaidGiveaway: Equatable { public struct PrepaidGiveaway: Equatable {
@ -122,12 +123,14 @@ func _internal_getPremiumGiveawayInfo(account: Account, peerId: EnginePeer.Id, m
} else { } else {
return .ongoing(startDate: startDate, status: .notQualified) return .ongoing(startDate: startDate, status: .notQualified)
} }
case let .giveawayInfoResults(flags, startDate, giftCodeSlug, finishDate, winnersCount, activatedCount): case let .giveawayInfoResults(flags, startDate, giftCodeSlug, stars, finishDate, winnersCount, activatedCount):
let status: PremiumGiveawayInfo.ResultStatus let status: PremiumGiveawayInfo.ResultStatus
if (flags & (1 << 1)) != 0 { if (flags & (1 << 1)) != 0 {
status = .refunded status = .refunded
} else if let stars {
status = .wonStars(stars: stars)
} else if let giftCodeSlug = giftCodeSlug { } else if let giftCodeSlug = giftCodeSlug {
status = .won(slug: giftCodeSlug) status = .wonPremium(slug: giftCodeSlug)
} else { } else {
status = .notWon status = .notWon
} }

View File

@ -145,6 +145,130 @@ func _internal_starsGiftOptions(account: Account, peerId: EnginePeer.Id?) -> Sig
} }
} }
public struct StarsGiveawayOption: Equatable, Codable {
enum CodingKeys: String, CodingKey {
case count
case currency
case amount
case yearlyBoosts
case storeProductId
case winners
case isExtended
case isDefault
}
public struct Winners: Equatable, Codable {
enum CodingKeys: String, CodingKey {
case users
case starsPerUser
case isDefault
}
public let users: Int32
public let starsPerUser: Int64
public let isDefault: Bool
public init(users: Int32, starsPerUser: Int64, isDefault: Bool) {
self.users = users
self.starsPerUser = starsPerUser
self.isDefault = isDefault
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.users = try container.decode(Int32.self, forKey: .users)
self.starsPerUser = try container.decode(Int64.self, forKey: .starsPerUser)
self.isDefault = try container.decodeIfPresent(Bool.self, forKey: .isDefault) ?? false
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(self.users, forKey: .users)
try container.encode(self.starsPerUser, forKey: .starsPerUser)
try container.encode(self.isDefault, forKey: .isDefault)
}
}
public let count: Int64
public let yearlyBoosts: Int32
public let currency: String
public let amount: Int64
public let storeProductId: String?
public let winners: [Winners]
public let isExtended: Bool
public let isDefault: Bool
public init(count: Int64, yearlyBoosts: Int32, storeProductId: String?, currency: String, amount: Int64, winners: [Winners], isExtended: Bool, isDefault: Bool) {
self.count = count
self.yearlyBoosts = yearlyBoosts
self.currency = currency
self.amount = amount
self.storeProductId = storeProductId
self.winners = winners
self.isExtended = isExtended
self.isDefault = isDefault
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.count = try container.decode(Int64.self, forKey: .count)
self.yearlyBoosts = try container.decode(Int32.self, forKey: .yearlyBoosts)
self.storeProductId = try container.decodeIfPresent(String.self, forKey: .storeProductId)
self.currency = try container.decode(String.self, forKey: .currency)
self.amount = try container.decode(Int64.self, forKey: .amount)
self.winners = try container.decode([StarsGiveawayOption.Winners].self, forKey: .winners)
self.isExtended = try container.decodeIfPresent(Bool.self, forKey: .isExtended) ?? false
self.isDefault = try container.decodeIfPresent(Bool.self, forKey: .isDefault) ?? false
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(self.count, forKey: .count)
try container.encode(self.yearlyBoosts, forKey: .yearlyBoosts)
try container.encodeIfPresent(self.storeProductId, forKey: .storeProductId)
try container.encode(self.currency, forKey: .currency)
try container.encode(self.amount, forKey: .amount)
try container.encode(self.winners, forKey: .winners)
try container.encode(self.isExtended, forKey: .isExtended)
try container.encode(self.isDefault, forKey: .isDefault)
}
}
extension StarsGiveawayOption.Winners {
init(apiStarsGiveawayWinnersOption: Api.StarsGiveawayWinnersOption) {
switch apiStarsGiveawayWinnersOption {
case let .starsGiveawayWinnersOption(flags, users, starsPerUser):
self.init(users: users, starsPerUser: starsPerUser, isDefault: (flags & (1 << 0)) != 0)
}
}
}
extension StarsGiveawayOption {
init(apiStarsGiveawayOption: Api.StarsGiveawayOption) {
switch apiStarsGiveawayOption {
case let .starsGiveawayOption(flags, stars, yearlyBoosts, storeProduct, currency, amount, winners):
self.init(count: stars, yearlyBoosts: yearlyBoosts, storeProductId: storeProduct, currency: currency, amount: amount, winners: winners.map { StarsGiveawayOption.Winners(apiStarsGiveawayWinnersOption: $0) }, isExtended: (flags & (1 << 0)) != 0, isDefault: (flags & (1 << 1)) != 0)
}
}
}
func _internal_starsGiveawayOptions(account: Account) -> Signal<[StarsGiveawayOption], NoError> {
return account.network.request(Api.functions.payments.getStarsGiveawayOptions())
|> map(Optional.init)
|> `catch` { _ -> Signal<[Api.StarsGiveawayOption]?, NoError> in
return .single(nil)
}
|> mapToSignal { results -> Signal<[StarsGiveawayOption], NoError> in
if let results = results {
return .single(results.map { StarsGiveawayOption(apiStarsGiveawayOption: $0) })
} else {
return .single([])
}
}
}
struct InternalStarsStatus { struct InternalStarsStatus {
let balance: Int64 let balance: Int64
let subscriptionsMissingBalance: Int64? let subscriptionsMissingBalance: Int64?
@ -344,7 +468,7 @@ private final class StarsContextImpl {
} }
var transactions = state.transactions var transactions = state.transactions
if addTransaction { if addTransaction {
transactions.insert(.init(flags: [.isLocal], id: "\(arc4random())", count: balance, date: Int32(Date().timeIntervalSince1970), peer: .appStore, title: nil, description: nil, photo: nil, transactionDate: nil, transactionUrl: nil, paidMessageId: nil, media: [], subscriptionPeriod: nil), at: 0) transactions.insert(.init(flags: [.isLocal], id: "\(arc4random())", count: balance, date: Int32(Date().timeIntervalSince1970), peer: .appStore, title: nil, description: nil, photo: nil, transactionDate: nil, transactionUrl: nil, paidMessageId: nil, giveawayMessageId: nil, media: [], subscriptionPeriod: nil), at: 0)
} }
self.updateState(StarsContext.State(flags: [.isPendingBalance], balance: max(0, state.balance + balance), subscriptions: state.subscriptions, canLoadMoreSubscriptions: state.canLoadMoreSubscriptions, transactions: transactions, canLoadMoreTransactions: state.canLoadMoreTransactions, isLoading: state.isLoading)) self.updateState(StarsContext.State(flags: [.isPendingBalance], balance: max(0, state.balance + balance), subscriptions: state.subscriptions, canLoadMoreSubscriptions: state.canLoadMoreSubscriptions, transactions: transactions, canLoadMoreTransactions: state.canLoadMoreTransactions, isLoading: state.isLoading))
@ -366,9 +490,11 @@ private final class StarsContextImpl {
private extension StarsContext.State.Transaction { private extension StarsContext.State.Transaction {
init?(apiTransaction: Api.StarsTransaction, peerId: EnginePeer.Id?, transaction: Transaction) { init?(apiTransaction: Api.StarsTransaction, peerId: EnginePeer.Id?, transaction: Transaction) {
switch apiTransaction { switch apiTransaction {
case let .starsTransaction(apiFlags, id, stars, date, transactionPeer, title, description, photo, transactionDate, transactionUrl, _, messageId, extendedMedia, subscriptionPeriod): case let .starsTransaction(apiFlags, id, stars, date, transactionPeer, title, description, photo, transactionDate, transactionUrl, _, messageId, extendedMedia, subscriptionPeriod, giveawayPostId):
let parsedPeer: StarsContext.State.Transaction.Peer let parsedPeer: StarsContext.State.Transaction.Peer
var paidMessageId: MessageId? var paidMessageId: MessageId?
var giveawayMessageId: MessageId?
switch transactionPeer { switch transactionPeer {
case .starsTransactionPeerAppStore: case .starsTransactionPeerAppStore:
parsedPeer = .appStore parsedPeer = .appStore
@ -394,6 +520,9 @@ private extension StarsContext.State.Transaction {
paidMessageId = MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: messageId) paidMessageId = MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: messageId)
} }
} }
if let giveawayPostId {
giveawayMessageId = MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: giveawayPostId)
}
} }
var flags: Flags = [] var flags: Flags = []
@ -415,7 +544,7 @@ private extension StarsContext.State.Transaction {
let media = extendedMedia.flatMap({ $0.compactMap { textMediaAndExpirationTimerFromApiMedia($0, PeerId(0)).media } }) ?? [] let media = extendedMedia.flatMap({ $0.compactMap { textMediaAndExpirationTimerFromApiMedia($0, PeerId(0)).media } }) ?? []
let _ = subscriptionPeriod let _ = subscriptionPeriod
self.init(flags: flags, id: id, count: stars, date: date, peer: parsedPeer, title: title, description: description, photo: photo.flatMap(TelegramMediaWebFile.init), transactionDate: transactionDate, transactionUrl: transactionUrl, paidMessageId: paidMessageId, media: media, subscriptionPeriod: subscriptionPeriod) self.init(flags: flags, id: id, count: stars, date: date, peer: parsedPeer, title: title, description: description, photo: photo.flatMap(TelegramMediaWebFile.init), transactionDate: transactionDate, transactionUrl: transactionUrl, paidMessageId: paidMessageId, giveawayMessageId: giveawayMessageId, media: media, subscriptionPeriod: subscriptionPeriod)
} }
} }
} }
@ -481,6 +610,7 @@ public final class StarsContext {
public let transactionDate: Int32? public let transactionDate: Int32?
public let transactionUrl: String? public let transactionUrl: String?
public let paidMessageId: MessageId? public let paidMessageId: MessageId?
public let giveawayMessageId: MessageId?
public let media: [Media] public let media: [Media]
public let subscriptionPeriod: Int32? public let subscriptionPeriod: Int32?
@ -496,6 +626,7 @@ public final class StarsContext {
transactionDate: Int32?, transactionDate: Int32?,
transactionUrl: String?, transactionUrl: String?,
paidMessageId: MessageId?, paidMessageId: MessageId?,
giveawayMessageId: MessageId?,
media: [Media], media: [Media],
subscriptionPeriod: Int32? subscriptionPeriod: Int32?
) { ) {
@ -510,6 +641,7 @@ public final class StarsContext {
self.transactionDate = transactionDate self.transactionDate = transactionDate
self.transactionUrl = transactionUrl self.transactionUrl = transactionUrl
self.paidMessageId = paidMessageId self.paidMessageId = paidMessageId
self.giveawayMessageId = giveawayMessageId
self.media = media self.media = media
self.subscriptionPeriod = subscriptionPeriod self.subscriptionPeriod = subscriptionPeriod
} }
@ -548,6 +680,9 @@ public final class StarsContext {
if lhs.paidMessageId != rhs.paidMessageId { if lhs.paidMessageId != rhs.paidMessageId {
return false return false
} }
if lhs.giveawayMessageId != rhs.giveawayMessageId {
return false
}
if !areMediaArraysEqual(lhs.media, rhs.media) { if !areMediaArraysEqual(lhs.media, rhs.media) {
return false return false
} }

View File

@ -74,6 +74,10 @@ public extension TelegramEngine {
return _internal_starsGiftOptions(account: self.account, peerId: peerId) return _internal_starsGiftOptions(account: self.account, peerId: peerId)
} }
public func starsGiveawayOptions() -> Signal<[StarsGiveawayOption], NoError> {
return _internal_starsGiveawayOptions(account: self.account)
}
public func peerStarsContext() -> StarsContext { public func peerStarsContext() -> StarsContext {
return StarsContext(account: self.account) return StarsContext(account: self.account)
} }

View File

@ -93,6 +93,7 @@ public enum AdminLogEventAction {
case changeWallpaper(prev: TelegramWallpaper?, new: TelegramWallpaper?) case changeWallpaper(prev: TelegramWallpaper?, new: TelegramWallpaper?)
case changeStatus(prev: PeerEmojiStatus?, new: PeerEmojiStatus?) case changeStatus(prev: PeerEmojiStatus?, new: PeerEmojiStatus?)
case changeEmojiPack(prev: StickerPackReference?, new: StickerPackReference?) case changeEmojiPack(prev: StickerPackReference?, new: StickerPackReference?)
case participantSubscriptionExtended(prev: RenderedChannelParticipant, new: RenderedChannelParticipant)
} }
public enum ChannelAdminLogEventError { public enum ChannelAdminLogEventError {
@ -449,6 +450,13 @@ func channelAdminLogEvents(accountPeerId: PeerId, postbox: Postbox, network: Net
action = .changeEmojiPack(prev: StickerPackReference(apiInputSet: prevStickerset), new: StickerPackReference(apiInputSet: newStickerset)) action = .changeEmojiPack(prev: StickerPackReference(apiInputSet: prevStickerset), new: StickerPackReference(apiInputSet: newStickerset))
case let .channelAdminLogEventActionToggleSignatureProfiles(newValue): case let .channelAdminLogEventActionToggleSignatureProfiles(newValue):
action = .toggleSignatureProfiles(boolFromApiValue(newValue)) action = .toggleSignatureProfiles(boolFromApiValue(newValue))
case let .channelAdminLogEventActionParticipantSubExtend(prev, new):
let prevParticipant = ChannelParticipant(apiParticipant: prev)
let newParticipant = ChannelParticipant(apiParticipant: new)
if let prevPeer = peers[prevParticipant.peerId], let newPeer = peers[newParticipant.peerId] {
action = .participantSubscriptionExtended(prev: RenderedChannelParticipant(participant: prevParticipant, peer: prevPeer), new: RenderedChannelParticipant(participant: newParticipant, peer: newPeer))
}
} }
let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId)) let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId))
if let action = action { if let action = action {

View File

@ -966,13 +966,18 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
} else { } else {
attributedString = NSAttributedString(string: strings.Notification_GiftLink, font: titleFont, textColor: primaryTextColor) attributedString = NSAttributedString(string: strings.Notification_GiftLink, font: titleFont, textColor: primaryTextColor)
} }
case .giveawayLaunched: case let .giveawayLaunched(stars):
var isGroup = false var isGroup = false
let messagePeer = message.peers[message.id.peerId] let messagePeer = message.peers[message.id.peerId]
if let channel = messagePeer as? TelegramChannel, case .group = channel.info { if let channel = messagePeer as? TelegramChannel, case .group = channel.info {
isGroup = true isGroup = true
} }
let resultTitleString = isGroup ? strings.Notification_GiveawayStartedGroup(compactAuthorName) : strings.Notification_GiveawayStarted(compactAuthorName) let resultTitleString: PresentationStrings.FormattedString
if let stars {
resultTitleString = isGroup ? strings.Notification_GiveawayStartedStarsGroup(compactAuthorName, "\(stars)") : strings.Notification_GiveawayStartedStars(compactAuthorName, "\(stars)")
} else {
resultTitleString = isGroup ? strings.Notification_GiveawayStartedGroup(compactAuthorName) : strings.Notification_GiveawayStarted(compactAuthorName)
}
attributedString = addAttributesToStringWithRanges(resultTitleString._tuple, body: bodyAttributes, argumentAttributes: [0: boldAttributes]) attributedString = addAttributesToStringWithRanges(resultTitleString._tuple, body: bodyAttributes, argumentAttributes: [0: boldAttributes])
case .joinedChannel: case .joinedChannel:
attributedString = NSAttributedString(string: strings.Notification_ChannelJoinedByYou, font: titleBoldFont, textColor: primaryTextColor) attributedString = NSAttributedString(string: strings.Notification_ChannelJoinedByYou, font: titleBoldFont, textColor: primaryTextColor)
@ -1035,6 +1040,8 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
mutableString.addAttribute(NSAttributedString.Key(TelegramTextAttributes.PeerMention), value: TelegramPeerMention(peerId: peerId, mention: ""), range: NSMakeRange(range.location, (peerName as NSString).length)) mutableString.addAttribute(NSAttributedString.Key(TelegramTextAttributes.PeerMention), value: TelegramPeerMention(peerId: peerId, mention: ""), range: NSMakeRange(range.location, (peerName as NSString).length))
} }
attributedString = mutableString attributedString = mutableString
case .prizeStars:
attributedString = NSAttributedString(string: strings.Notification_StarsPrize, font: titleFont, textColor: primaryTextColor)
case .unknown: case .unknown:
attributedString = nil attributedString = nil
} }

View File

@ -211,6 +211,8 @@ private func contentNodeMessagesAndClassesForItem(_ item: ChatMessageItem) -> ([
result.append((message, ChatMessageWallpaperBubbleContentNode.self, itemAttributes, BubbleItemAttributes(isAttachment: false, neighborType: .text, neighborSpacing: .default))) result.append((message, ChatMessageWallpaperBubbleContentNode.self, itemAttributes, BubbleItemAttributes(isAttachment: false, neighborType: .text, neighborSpacing: .default)))
} else if case .giftCode = action.action { } else if case .giftCode = action.action {
result.append((message, ChatMessageGiftBubbleContentNode.self, itemAttributes, BubbleItemAttributes(isAttachment: false, neighborType: .text, neighborSpacing: .default))) result.append((message, ChatMessageGiftBubbleContentNode.self, itemAttributes, BubbleItemAttributes(isAttachment: false, neighborType: .text, neighborSpacing: .default)))
} else if case .prizeStars = action.action {
result.append((message, ChatMessageGiftBubbleContentNode.self, itemAttributes, BubbleItemAttributes(isAttachment: false, neighborType: .text, neighborSpacing: .default)))
} else if case .joinedChannel = action.action { } else if case .joinedChannel = action.action {
result.append((message, ChatMessageJoinedChannelBubbleContentNode.self, itemAttributes, BubbleItemAttributes(isAttachment: false, neighborType: .text, neighborSpacing: .default))) result.append((message, ChatMessageJoinedChannelBubbleContentNode.self, itemAttributes, BubbleItemAttributes(isAttachment: false, neighborType: .text, neighborSpacing: .default)))
} else { } else {

View File

@ -268,6 +268,20 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
} }
title = item.presentationData.strings.Notification_StarsGift_Title(Int32(count)) title = item.presentationData.strings.Notification_StarsGift_Title(Int32(count))
text = incoming ? item.presentationData.strings.Notification_StarsGift_Subtitle : item.presentationData.strings.Notification_StarsGift_SubtitleYou(peerName).string text = incoming ? item.presentationData.strings.Notification_StarsGift_Subtitle : item.presentationData.strings.Notification_StarsGift_SubtitleYou(peerName).string
case let .prizeStars(count, _, channelId, _, _):
if count <= 1000 {
months = 3
} else if count < 2500 {
months = 6
} else {
months = 12
}
var peerName = ""
if let channelId, let channel = item.message.peers[channelId] {
peerName = EnginePeer(channel).compactDisplayTitle
}
title = "Congratulations!" //""item.presentationData.strings.Notification_StarsGift_Title(Int32(count))
text = "You won a prize in a giveaway organized by **\(peerName)**.\n\nYour prize is **\(count) Stars**." //item.presentationData.strings.Notification_StarsGift_Subtitle
case let .giftCode(_, fromGiveaway, unclaimed, channelId, monthsValue, _, _, _, _): case let .giftCode(_, fromGiveaway, unclaimed, channelId, monthsValue, _, _, _, _):
if channelId == nil { if channelId == nil {
months = monthsValue months = monthsValue

View File

@ -259,22 +259,35 @@ public class ChatMessageGiveawayBubbleContentNode: ChatMessageBubbleContentNode,
if badgeTextColor.distance(to: accentColor) < 1 { if badgeTextColor.distance(to: accentColor) < 1 {
badgeTextColor = incoming ? item.presentationData.theme.theme.chat.message.incoming.bubble.withoutWallpaper.fill.first! : item.presentationData.theme.theme.chat.message.outgoing.bubble.withoutWallpaper.fill.first! badgeTextColor = incoming ? item.presentationData.theme.theme.chat.message.incoming.bubble.withoutWallpaper.fill.first! : item.presentationData.theme.theme.chat.message.outgoing.bubble.withoutWallpaper.fill.first!
} }
var updatedBadgeImage: UIImage? var isStars = false
if themeUpdated {
updatedBadgeImage = generateStretchableFilledCircleImage(diameter: 21.0, color: accentColor, strokeColor: backgroundColor, strokeWidth: 1.0 + UIScreenPixel, backgroundColor: nil)
}
let badgeText: String let badgeText: String
if let giveaway { if let giveaway {
badgeText = "X\(giveaway.quantity)" switch giveaway.prize {
case .premium:
badgeText = "X\(giveaway.quantity)"
case let .stars(amount):
badgeText = "\(amount)"
isStars = true
}
} else if let giveawayResults { } else if let giveawayResults {
badgeText = "X\(giveawayResults.winnersCount)" switch giveawayResults.prize {
case .premium:
badgeText = "X\(giveawayResults.winnersCount)"
case let .stars(amount):
badgeText = "\(amount)"
isStars = true
}
} else { } else {
badgeText = "" badgeText = ""
} }
let badgeString = NSAttributedString(string: badgeText, font: Font.with(size: 10.0, design: .round , weight: .bold, traits: .monospacedNumbers), textColor: badgeTextColor) let badgeString = NSAttributedString(string: badgeText, font: Font.with(size: 10.0, design: .round , weight: .bold, traits: .monospacedNumbers), textColor: badgeTextColor)
var updatedBadgeImage: UIImage?
if themeUpdated {
updatedBadgeImage = generateStretchableFilledCircleImage(diameter: 21.0, color: isStars ? UIColor(rgb: 0xffaf0a) : accentColor, strokeColor: backgroundColor, strokeWidth: 1.0 + UIScreenPixel, backgroundColor: nil)
}
let prizeTitleText: String let prizeTitleText: String
if let giveawayResults { if let giveawayResults {
if giveawayResults.winnersCount > 1 { if giveawayResults.winnersCount > 1 {
@ -316,17 +329,33 @@ public class ChatMessageGiveawayBubbleContentNode: ChatMessageBubbleContentNode,
subscriptionsString = subscriptionsString.replacingOccurrences(of: "**\(giveaway.quantity)** ", with: "") subscriptionsString = subscriptionsString.replacingOccurrences(of: "**\(giveaway.quantity)** ", with: "")
} }
prizeTextString = parseMarkdownIntoAttributedString(item.presentationData.strings.Chat_Giveaway_Message_PrizeText( switch giveaway.prize {
subscriptionsString, case let .premium(months):
item.presentationData.strings.Chat_Giveaway_Message_Months(giveaway.months) prizeTextString = parseMarkdownIntoAttributedString(item.presentationData.strings.Chat_Giveaway_Message_PrizeText(
).string, attributes: MarkdownAttributes( subscriptionsString,
body: MarkdownAttributeSet(font: textFont, textColor: textColor), item.presentationData.strings.Chat_Giveaway_Message_Months(months)
bold: MarkdownAttributeSet(font: boldTextFont, textColor: textColor), ).string, attributes: MarkdownAttributes(
link: MarkdownAttributeSet(font: textFont, textColor: textColor), body: MarkdownAttributeSet(font: textFont, textColor: textColor),
linkAttribute: { url in bold: MarkdownAttributeSet(font: boldTextFont, textColor: textColor),
return ("URL", url) link: MarkdownAttributeSet(font: textFont, textColor: textColor),
} linkAttribute: { url in
), textAlignment: .center) return ("URL", url)
}
), textAlignment: .center)
case let .stars(amount):
let starsString = item.presentationData.strings.Chat_Giveaway_Message_Stars_Stars(Int32(amount))
prizeTextString = parseMarkdownIntoAttributedString(item.presentationData.strings.Chat_Giveaway_Message_Stars_PrizeText(
starsString,
item.presentationData.strings.Chat_Giveaway_Message_Stars_Winners(giveaway.quantity)
).string, attributes: MarkdownAttributes(
body: MarkdownAttributeSet(font: textFont, textColor: textColor),
bold: MarkdownAttributeSet(font: boldTextFont, textColor: textColor),
link: MarkdownAttributeSet(font: textFont, textColor: textColor),
linkAttribute: { url in
return ("URL", url)
}
), textAlignment: .center)
}
} else if let giveawayResults { } else if let giveawayResults {
prizeTextString = parseMarkdownIntoAttributedString(item.presentationData.strings.Chat_Giveaway_Message_WinnersSelectedText(giveawayResults.winnersCount), attributes: MarkdownAttributes( prizeTextString = parseMarkdownIntoAttributedString(item.presentationData.strings.Chat_Giveaway_Message_WinnersSelectedText(giveawayResults.winnersCount), attributes: MarkdownAttributes(
body: MarkdownAttributeSet(font: textFont, textColor: textColor), body: MarkdownAttributeSet(font: textFont, textColor: textColor),
@ -548,7 +577,21 @@ public class ChatMessageGiveawayBubbleContentNode: ChatMessageBubbleContentNode,
let (buttonWidth, continueLayout) = makeButtonLayout(constrainedSize.width, nil, nil, false, item.presentationData.strings.Chat_Giveaway_Message_LearnMore.uppercased(), titleColor, false, true) let (buttonWidth, continueLayout) = makeButtonLayout(constrainedSize.width, nil, nil, false, item.presentationData.strings.Chat_Giveaway_Message_LearnMore.uppercased(), titleColor, false, true)
let animationName: String let animationName: String
let months = giveaway?.months ?? 0 var months: Int32 = 0
if let giveaway {
switch giveaway.prize {
case let .premium(monthsValue):
months = monthsValue
case let .stars(amount):
if amount <= 1000 {
months = 3
} else if amount < 2500 {
months = 6
} else {
months = 12
}
}
}
if let _ = giveaway { if let _ = giveaway {
switch months { switch months {
case 12: case 12:

View File

@ -2254,6 +2254,32 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
} }
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil) let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: availableReactions, availableMessageEffects: availableMessageEffects, savedMessageTags: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .participantSubscriptionExtended(_, new):
var peers = SimpleDictionary<PeerId, Peer>()
var author: Peer?
if let peer = self.entry.peers[self.entry.event.peerId] {
author = peer
peers[peer.id] = peer
}
peers[peer.id] = peer
for (_, peer) in new.peers {
peers[peer.id] = peer
}
peers[new.peer.id] = new.peer
var text: String = ""
var entities: [MessageTextEntity] = []
appendAttributedText(text: self.presentationData.strings.Channel_AdminLog_MessageParticipantSubscriptionExtended(author.flatMap(EnginePeer.init)?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) ?? ""), generateEntities: { index in
if index == 0, let author = author {
return [.TextMention(peerId: author.id)]
}
return []
}, to: &text, entities: &entities)
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: availableReactions, availableMessageEffects: availableMessageEffects, savedMessageTags: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil)) return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: availableReactions, availableMessageEffects: availableMessageEffects, savedMessageTags: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
} }

View File

@ -284,28 +284,6 @@ private final class StarsPurchaseScreenContentComponent: CombinedComponent {
size.height += 21.0 size.height += 21.0
context.component.externalState.descriptionHeight = text.size.height context.component.externalState.descriptionHeight = text.size.height
let stars: [Int64: Int] = [
15: 1,
75: 2,
250: 3,
500: 4,
1000: 5,
2500: 6,
25: 1,
50: 1,
100: 2,
150: 2,
350: 3,
750: 4,
1500: 5,
5000: 6,
10000: 6,
25000: 7,
35000: 7
]
let externalStateUpdated = context.component.stateUpdated let externalStateUpdated = context.component.stateUpdated
@ -369,7 +347,7 @@ private final class StarsPurchaseScreenContentComponent: CombinedComponent {
title: titleComponent, title: titleComponent,
contentInsets: UIEdgeInsets(top: 12.0, left: -6.0, bottom: 12.0, right: 0.0), contentInsets: UIEdgeInsets(top: 12.0, left: -6.0, bottom: 12.0, right: 0.0),
leftIcon: .custom(AnyComponentWithIdentity(id: 0, component: AnyComponent(StarsIconComponent( leftIcon: .custom(AnyComponentWithIdentity(id: 0, component: AnyComponent(StarsIconComponent(
count: stars[product.count] ?? 1 amount: product.count
))), true), ))), true),
accessory: .custom(ListActionItemComponent.CustomAccessory(component: AnyComponentWithIdentity(id: 0, component: AnyComponent(MultilineTextComponent( accessory: .custom(ListActionItemComponent.CustomAccessory(component: AnyComponentWithIdentity(id: 0, component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString( text: .plain(NSAttributedString(
@ -1131,7 +1109,30 @@ public final class StarsPurchaseScreen: ViewControllerComponentContainer {
} }
} }
func generateStarsIcon(count: Int) -> UIImage { func generateStarsIcon(amount: Int64) -> UIImage {
let stars: [Int64: Int] = [
15: 1,
75: 2,
250: 3,
500: 4,
1000: 5,
2500: 6,
25: 1,
50: 1,
100: 2,
150: 2,
350: 3,
750: 4,
1500: 5,
5000: 6,
10000: 6,
25000: 7,
35000: 7
]
let count = stars[amount] ?? 1
let image = generateGradientTintedImage( let image = generateGradientTintedImage(
image: UIImage(bundleImageName: "Peer Info/PremiumIcon"), image: UIImage(bundleImageName: "Peer Info/PremiumIcon"),
colors: [ colors: [
@ -1183,16 +1184,16 @@ func generateStarsIcon(count: Int) -> UIImage {
} }
final class StarsIconComponent: CombinedComponent { final class StarsIconComponent: CombinedComponent {
let count: Int let amount: Int64
init( init(
count: Int amount: Int64
) { ) {
self.count = count self.amount = amount
} }
static func ==(lhs: StarsIconComponent, rhs: StarsIconComponent) -> Bool { static func ==(lhs: StarsIconComponent, rhs: StarsIconComponent) -> Bool {
if lhs.count != rhs.count { if lhs.amount != rhs.amount {
return false return false
} }
return true return true
@ -1201,11 +1202,11 @@ final class StarsIconComponent: CombinedComponent {
static var body: Body { static var body: Body {
let icon = Child(Image.self) let icon = Child(Image.self)
var image: (UIImage, Int)? var image: (UIImage, Int64)?
return { context in return { context in
if image == nil || image?.1 != context.component.count { if image == nil || image?.1 != context.component.amount {
image = (generateStarsIcon(count: context.component.count), context.component.count) image = (generateStarsIcon(amount: context.component.amount), context.component.amount)
} }
let iconSize = CGSize(width: image!.0.size.width, height: 20.0) let iconSize = CGSize(width: image!.0.size.width, height: 20.0)

View File

@ -97,6 +97,9 @@ private final class StarsTransactionSheetContent: CombinedComponent {
peerIds.append(receipt.botPaymentId) peerIds.append(receipt.botPaymentId)
case let .gift(message): case let .gift(message):
peerIds.append(message.id.peerId) peerIds.append(message.id.peerId)
if let action = message.media.first(where: { $0 is TelegramMediaAction }) as? TelegramMediaAction, case let .prizeStars(_, _, boostPeerId, _, _) = action.action, let boostPeerId {
peerIds.append(boostPeerId)
}
case let .subscription(subscription): case let .subscription(subscription):
peerIds.append(subscription.peer.id) peerIds.append(subscription.peer.id)
case let .importer(_, _, importer, _): case let .importer(_, _, importer, _):
@ -213,6 +216,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
var isSubscriptionFee = false var isSubscriptionFee = false
var isCancelled = false var isCancelled = false
var isReaction = false var isReaction = false
var giveawayMessageId: MessageId?
var delayedCloseOnOpenPeer = true var delayedCloseOnOpenPeer = true
switch subject { switch subject {
@ -424,25 +428,41 @@ private final class StarsTransactionSheetContent: CombinedComponent {
delayedCloseOnOpenPeer = false delayedCloseOnOpenPeer = false
case let .gift(message): case let .gift(message):
let incoming = message.flags.contains(.Incoming) let incoming = message.flags.contains(.Incoming)
titleText = incoming ? strings.Stars_Gift_Received_Title : strings.Stars_Gift_Sent_Title
let peerName = state.peerMap[message.id.peerId]?.compactDisplayTitle ?? "" let peerName = state.peerMap[message.id.peerId]?.compactDisplayTitle ?? ""
descriptionText = incoming ? strings.Stars_Gift_Received_Text : strings.Stars_Gift_Sent_Text(peerName).string descriptionText = incoming ? strings.Stars_Gift_Received_Text : strings.Stars_Gift_Sent_Text(peerName).string
if let action = message.media.first(where: { $0 is TelegramMediaAction }) as? TelegramMediaAction, case let .giftStars(_, _, countValue, _, _, _) = action.action { if let action = message.media.first(where: { $0 is TelegramMediaAction }) as? TelegramMediaAction {
count = countValue if case let .giftStars(_, _, countValue, _, _, _) = action.action {
if !incoming { titleText = incoming ? strings.Stars_Gift_Received_Title : strings.Stars_Gift_Sent_Title
countIsGeneric = true
count = countValue
if !incoming {
countIsGeneric = true
}
countOnTop = true
transactionId = nil
if message.id.peerId.id._internalGetInt64Value() == 777000 {
toPeer = nil
} else {
toPeer = state.peerMap[message.id.peerId]
}
} else if case let .prizeStars(countValue, _, boostPeerId, _, giveawayMessageIdValue) = action.action {
titleText = "Received Prize"
count = countValue
countOnTop = true
transactionId = nil//transactionIdValue
giveawayMessageId = giveawayMessageIdValue
if let boostPeerId {
toPeer = state.peerMap[boostPeerId]
}
} else {
fatalError()
} }
countOnTop = true
transactionId = nil
} else { } else {
fatalError() fatalError()
} }
date = message.timestamp date = message.timestamp
if message.id.peerId.id._internalGetInt64Value() == 777000 {
toPeer = nil
} else {
toPeer = state.peerMap[message.id.peerId]
}
isGift = true isGift = true
delayedCloseOnOpenPeer = false delayedCloseOnOpenPeer = false
} }
@ -623,6 +643,34 @@ private final class StarsTransactionSheetContent: CombinedComponent {
)) ))
} }
if let giveawayMessageId {
tableItems.append(.init(
id: "gift",
title: "Gift",
component: AnyComponent(
MultilineTextComponent(text: .plain(NSAttributedString(string: "\(count) Stars", font: tableFont, textColor: tableTextColor)))
)
))
tableItems.append(.init(
id: "reason",
title: "Reason",
component: AnyComponent(
Button(
content: AnyComponent(
MultilineTextComponent(text: .plain(NSAttributedString(string: "Giveaway", font: tableFont, textColor: tableLinkColor)))
),
action: {
component.openMessage(giveawayMessageId)
Queue.mainQueue().after(1.0, {
component.cancel(false)
})
}
)
)
))
}
if let messageId { if let messageId {
let peerName: String let peerName: String
if case let .transaction(_, parentPeer) = component.subject { if case let .transaction(_, parentPeer) = component.subject {

View File

@ -209,7 +209,10 @@ final class StarsTransactionsListPanelComponent: Component {
var itemPeer = item.peer var itemPeer = item.peer
switch item.peer { switch item.peer {
case let .peer(peer): case let .peer(peer):
if !item.media.isEmpty { if let _ = item.giveawayMessageId {
itemTitle = peer.displayTitle(strings: environment.strings, displayOrder: .firstLast)
itemSubtitle = environment.strings.Stars_Intro_Transaction_GiveawayPrize
} else if !item.media.isEmpty {
itemTitle = environment.strings.Stars_Intro_Transaction_MediaPurchase itemTitle = environment.strings.Stars_Intro_Transaction_MediaPurchase
itemSubtitle = peer.displayTitle(strings: environment.strings, displayOrder: .firstLast) itemSubtitle = peer.displayTitle(strings: environment.strings, displayOrder: .firstLast)
} else if let title = item.title { } else if let title = item.title {

View File

@ -1189,6 +1189,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
case let .giftCode(slug, _, _, _, _, _, _, _, _): case let .giftCode(slug, _, _, _, _, _, _, _, _):
strongSelf.openResolved(result: .premiumGiftCode(slug: slug), sourceMessageId: message.id, progress: params.progress) strongSelf.openResolved(result: .premiumGiftCode(slug: slug), sourceMessageId: message.id, progress: params.progress)
return true return true
case .prizeStars:
let controller = strongSelf.context.sharedContext.makeStarsGiftScreen(context: strongSelf.context, message: EngineMessage(message))
strongSelf.push(controller)
return true
case let .suggestedProfilePhoto(image): case let .suggestedProfilePhoto(image):
strongSelf.chatDisplayNode.dismissInput() strongSelf.chatDisplayNode.dismissInput()
if let image = image { if let image = image {