Update API

This commit is contained in:
Ilya Laktyushin 2025-01-16 02:16:28 +04:00
parent b6f8cce7ea
commit f137e27944
52 changed files with 1523 additions and 593 deletions

View File

@ -13067,6 +13067,7 @@ Sorry for the inconvenience.";
"Notification.StarGift.Title" = "Gift from %@";
"Notification.StarGift.Subtitle" = "Display this gift on your page or convert it to %@.";
"Notification.StarGift.Subtitle.Channel" = "Display this gift in channel's Gifts or convert it to %@.";
"Notification.StarGift.Subtitle.Stars_1" = "%@ Star";
"Notification.StarGift.Subtitle.Stars_any" = "%@ Stars";
"Notification.StarGift.Subtitle.Other" = "%1$@ can keep this gift on their page or convert it to %2$@.";
@ -13672,13 +13673,23 @@ Sorry for the inconvenience.";
"SharedMedia.SimilarChannelCount_1" = "%@ channel";
"SharedMedia.SimilarChannelCount_any" = "%@ channels";
"SharedMedia.SimilarChannel.Subscribers_1" = "%@ subscriber";
"SharedMedia.SimilarChannel.Subscribers_any" = "%@ subscribers";
"SharedMedia.SimilarBotCount_1" = "%@ bot";
"SharedMedia.SimilarBotCount_any" = "%@ bots";
"SharedMedia.SimilarBot.Users_1" = "%@ monthly user";
"SharedMedia.SimilarBot.Users_any" = "%@ monthly users";
"PeerInfo.SimilarBots.ShowMore" = "Show More Bots";
"PeerInfo.SimilarBots.ShowMoreInfo" = "Subscribe to [Telegram Premium]()\nto unlock up to **100** similar bots.";
"PeerInfo.VerifyAccounts" = "Verify Accounts";
"Gift.View.Context.Share" = "Share";
"Gift.View.Context.CopyLink" = "Copy Link";
"Gift.View.Context.Transfer" = "Transfer";
"Gift.Withdraw.Title" = "Manage with Fragment";
"Gift.Withdraw.Text" = "You can use Fragment, a third-party service, to transfer **%@** to your TON account. After that, you can manage it as an NFT with any TON wallet outside Telegram.\n\nYou can also move such NFTs back to your Telegram account via Fragment.";
"Gift.Withdraw.Proceed" = "Open Fragment";

View File

@ -1101,7 +1101,7 @@ public protocol SharedAccountContext: AnyObject {
func makeStarsGiveawayBoostScreen(context: AccountContext, peerId: EnginePeer.Id, boost: ChannelBoostersContext.State.Boost) -> ViewController
func makeStarsIntroScreen(context: AccountContext) -> ViewController
func makeGiftViewScreen(context: AccountContext, message: EngineMessage, shareStory: (() -> Void)?) -> ViewController
func makeGiftViewScreen(context: AccountContext, gift: StarGift.UniqueGift, shareStory: (() -> Void)?) -> ViewController
func makeGiftViewScreen(context: AccountContext, gift: StarGift.UniqueGift, shareStory: (() -> Void)?, dismissed: (() -> Void)?) -> ViewController
func makeStorySharingScreen(context: AccountContext, subject: StorySharingSubject, parentController: ViewController) -> ViewController

View File

@ -50,7 +50,7 @@ public enum PremiumGiftSource: Equatable {
case settings([EnginePeer.Id: TelegramBirthday]?)
case chatList([EnginePeer.Id: TelegramBirthday]?)
case stars([EnginePeer.Id: TelegramBirthday]?)
case starGiftTransfer([EnginePeer.Id: TelegramBirthday]?, EngineMessage.Id, StarGift.UniqueGift, Int64, Int32?)
case starGiftTransfer([EnginePeer.Id: TelegramBirthday]?, StarGiftReference, StarGift.UniqueGift, Int64, Int32?)
case channelBoost
case deeplink(String?)
}

View File

@ -3103,8 +3103,8 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
currentCredibilityIconContent = .text(color: item.presentationData.theme.chat.message.incoming.scamColor, string: item.presentationData.strings.Message_FakeAccount.uppercased())
} else if let emojiStatus = peer.emojiStatus, !premiumConfiguration.isPremiumDisabled {
currentStatusIconContent = .animation(content: .customEmoji(fileId: emojiStatus.fileId), size: CGSize(width: 32.0, height: 32.0), placeholderColor: item.presentationData.theme.list.mediaPlaceholderColor, themeColor: item.presentationData.theme.list.itemAccentColor, loopMode: .count(2))
if case let .starGift(_, _, _, _, _, innerColor, _, _, _) = emojiStatus.content {
currentStatusIconParticleColor = UIColor(rgb: UInt32(bitPattern: innerColor))
if let color = emojiStatus.color {
currentStatusIconParticleColor = UIColor(rgb: UInt32(bitPattern: color))
}
} else if peer.isPremium && !premiumConfiguration.isPremiumDisabled {
currentCredibilityIconContent = .premium(color: item.presentationData.theme.list.itemAccentColor)
@ -3134,8 +3134,8 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
currentCredibilityIconContent = .text(color: item.presentationData.theme.chat.message.incoming.scamColor, string: item.presentationData.strings.Message_FakeAccount.uppercased())
} else if let emojiStatus = peer.emojiStatus, !premiumConfiguration.isPremiumDisabled {
currentStatusIconContent = .animation(content: .customEmoji(fileId: emojiStatus.fileId), size: CGSize(width: 32.0, height: 32.0), placeholderColor: item.presentationData.theme.list.mediaPlaceholderColor, themeColor: item.presentationData.theme.list.itemAccentColor, loopMode: .count(2))
if case let .starGift(_, _, _, _, _, innerColor, _, _, _) = emojiStatus.content {
currentStatusIconParticleColor = UIColor(rgb: UInt32(bitPattern: innerColor))
if let color = emojiStatus.color {
currentStatusIconParticleColor = UIColor(rgb: UInt32(bitPattern: color))
}
} else if peer.isPremium && !premiumConfiguration.isPremiumDisabled {
currentCredibilityIconContent = .premium(color: item.presentationData.theme.list.itemAccentColor)

View File

@ -1508,7 +1508,7 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
transition: .immediate,
component: AnyComponent(credibilityIconComponent),
environment: {},
containerSize: CGSize(width: 20.0, height: 20.0)
containerSize: CGSize(width: 16.0, height: 16.0)
)
nextIconX += 4.0

View File

@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "more.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,79 @@
%PDF-1.7
1 0 obj
<< >>
endobj
2 0 obj
<< /Length 3 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 1.500000 1.335754 cm
0.000000 0.000000 0.000000 scn
5.252930 4.662109 m
5.252930 4.527832 5.199219 4.409668 5.097168 4.307617 c
0.843262 0.145020 l
0.746582 0.048340 0.628418 0.000000 0.488770 0.000000 c
0.214844 0.000000 0.000000 0.209473 0.000000 0.488770 c
0.000000 0.628418 0.053711 0.746582 0.139648 0.837891 c
4.049805 4.662109 l
0.139648 8.486328 l
0.053711 8.577637 0.000000 8.701172 0.000000 8.835449 c
0.000000 9.114746 0.214844 9.324219 0.488770 9.324219 c
0.628418 9.324219 0.746582 9.275879 0.843262 9.184570 c
5.097168 5.016602 l
5.199219 4.919922 5.252930 4.796387 5.252930 4.662109 c
h
f
n
Q
endstream
endobj
3 0 obj
675
endobj
4 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 8.000000 12.000000 ]
/Resources 1 0 R
/Contents 2 0 R
/Parent 5 0 R
>>
endobj
5 0 obj
<< /Kids [ 4 0 R ]
/Count 1
/Type /Pages
>>
endobj
6 0 obj
<< /Pages 5 0 R
/Type /Catalog
>>
endobj
xref
0 7
0000000000 65535 f
0000000010 00000 n
0000000034 00000 n
0000000765 00000 n
0000000787 00000 n
0000000959 00000 n
0000001033 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 6 0 R
/Size 7
>>
startxref
1092
%%EOF

View File

@ -2785,7 +2785,7 @@ static CGPoint TGCameraControllerClampPointToScreenSize(__unused id self, __unus
else if (widescreenWidth == 896.0f)
return CGRectMake(0, 121, screenSize.width, screenSize.height - 121 - 223);
else if (widescreenWidth == 874.0f)
return CGRectMake(0, 121, screenSize.width, screenSize.height - 135 - 202);
return CGRectMake(0, 136, screenSize.width, screenSize.height - 136 - 202);
else if (widescreenWidth == 852.0f)
return CGRectMake(0, 136, screenSize.width, screenSize.height - 136 - 192);
else if (widescreenWidth == 844.0f)

View File

@ -157,6 +157,17 @@
_counterOffset = 7.0f;
shutterButtonWidth = 72.0f;
}
else if (widescreenWidth == 874.0f)
{
_topPanelOffset = 48.0f;
_topPanelHeight = 44.0f;
_bottomPanelOffset = 63.0f;
_bottomPanelHeight = 128.0f;
_modeControlOffset = -1.0f;
_modeControlHeight = 51.0f;
_counterOffset = 7.0f;
shutterButtonWidth = 72.0f;
}
else if (widescreenWidth == 852.0f)
{
_topPanelOffset = 48.0f;

View File

@ -281,11 +281,10 @@ const CGFloat TGCameraTabletPanelViewWidth = 102.0f;
_shutterButton.frame.origin.y + _shutterButton.frame.size.height + 20.0,
_flipButton.frame.size.width, _flipButton.frame.size.height);
CGFloat flipButtonPosition = 0.0f;
CGFloat cancelButtonPosition = _panelView.frame.size.height - _cancelButton.frame.size.height - 7;
if (!_doneButton.hidden)
{
flipButtonPosition = _panelView.frame.size.height / 8.0f - _flipButton.frame.size.height / 2.0f;
cancelButtonPosition = 7.0f;
}

View File

@ -70,7 +70,7 @@
@dynamic thumbnailSignalForItem;
@dynamic editingContext;
- (instancetype)initWithFrame:(CGRect)frame avatar:(bool)avatar hasUltrawideCamera:(bool)hasUltrawideCamera hasTelephotoCamera:(bool)hasTelephotoCamera {
- (instancetype)initWithFrame:(CGRect)frame avatar:(bool)avatar hasUltrawideCamera:(bool)hasUltrawideCamera hasTelephotoCamera:(bool)hasTelephotoCamera camera:(PGCamera *)camera {
self = [super init];
if (self != nil) {
}

View File

@ -890,12 +890,22 @@ private func createGiveawayControllerEntries(
}
}
let boostCount: Int32
switch state.mode {
case .giveaway:
boostCount = state.subscriptions * 4
case .gift:
boostCount = Int32(state.peers.count) * 4
case .starsGiveaway:
boostCount = Int32(state.stars) / 500
}
entries.append(.channelsHeader(presentationData.theme, isGroup ? presentationData.strings.BoostGift_GroupsAndChannelsTitle.uppercased() : presentationData.strings.BoostGift_ChannelsAndGroupsTitle.uppercased()))
var index: Int32 = 0
let channels = [peerId] + state.channels
for channelId in channels {
if let channel = peers[channelId] {
entries.append(.channel(index, presentationData.theme, channel, channel.id == peerId ? state.subscriptions * 4 : nil, false))
entries.append(.channel(index, presentationData.theme, channel, channel.id == peerId ? boostCount : nil, false))
}
index += 1
}

View File

@ -205,7 +205,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[1605510357] = { return Api.ChatAdminRights.parse_chatAdminRights($0) }
dict[-219353309] = { return Api.ChatAdminWithInvites.parse_chatAdminWithInvites($0) }
dict[-1626209256] = { return Api.ChatBannedRights.parse_chatBannedRights($0) }
dict[-1611417512] = { return Api.ChatFull.parse_channelFull($0) }
dict[1389789291] = { return Api.ChatFull.parse_channelFull($0) }
dict[640893467] = { return Api.ChatFull.parse_chatFull($0) }
dict[1553807106] = { return Api.ChatInvite.parse_chatInvite($0) }
dict[1516793212] = { return Api.ChatInvite.parse_chatInviteAlready($0) }
@ -383,9 +383,9 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-977967015] = { return Api.InputInvoice.parse_inputInvoiceMessage($0) }
dict[-1734841331] = { return Api.InputInvoice.parse_inputInvoicePremiumGiftCode($0) }
dict[-1020867857] = { return Api.InputInvoice.parse_inputInvoiceSlug($0) }
dict[634962392] = { return Api.InputInvoice.parse_inputInvoiceStarGift($0) }
dict[-1371821587] = { return Api.InputInvoice.parse_inputInvoiceStarGiftTransfer($0) }
dict[1589539426] = { return Api.InputInvoice.parse_inputInvoiceStarGiftUpgrade($0) }
dict[-396206446] = { return Api.InputInvoice.parse_inputInvoiceStarGift($0) }
dict[1247763417] = { return Api.InputInvoice.parse_inputInvoiceStarGiftTransfer($0) }
dict[1300335965] = { return Api.InputInvoice.parse_inputInvoiceStarGiftUpgrade($0) }
dict[1710230755] = { return Api.InputInvoice.parse_inputInvoiceStars($0) }
dict[-122978821] = { return Api.InputMedia.parse_inputMediaContact($0) }
dict[-428884101] = { return Api.InputMedia.parse_inputMediaDice($0) }
@ -457,6 +457,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[18418929] = { return Api.InputQuickReplyShortcut.parse_inputQuickReplyShortcutId($0) }
dict[583071445] = { return Api.InputReplyTo.parse_inputReplyToMessage($0) }
dict[1484862010] = { return Api.InputReplyTo.parse_inputReplyToStory($0) }
dict[-251549057] = { return Api.InputSavedStarGift.parse_inputSavedStarGiftChat($0) }
dict[1764202389] = { return Api.InputSavedStarGift.parse_inputSavedStarGiftUser($0) }
dict[1399317950] = { return Api.InputSecureFile.parse_inputSecureFile($0) }
dict[859091184] = { return Api.InputSecureFile.parse_inputSecureFileUploaded($0) }
dict[-618540889] = { return Api.InputSecureValue.parse_inputSecureValue($0) }
@ -585,7 +587,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-1434950843] = { return Api.MessageAction.parse_messageActionSetChatTheme($0) }
dict[1348510708] = { return Api.MessageAction.parse_messageActionSetChatWallPaper($0) }
dict[1007897979] = { return Api.MessageAction.parse_messageActionSetMessagesTTL($0) }
dict[-655036249] = { return Api.MessageAction.parse_messageActionStarGift($0) }
dict[178478442] = { return Api.MessageAction.parse_messageActionStarGift($0) }
dict[638024601] = { return Api.MessageAction.parse_messageActionStarGiftUnique($0) }
dict[1474192222] = { return Api.MessageAction.parse_messageActionSuggestProfilePhoto($0) }
dict[228168278] = { return Api.MessageAction.parse_messageActionTopicCreate($0) }
@ -618,7 +620,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[1313731771] = { return Api.MessageFwdHeader.parse_messageFwdHeader($0) }
dict[1882335561] = { return Api.MessageMedia.parse_messageMediaContact($0) }
dict[1065280907] = { return Api.MessageMedia.parse_messageMediaDice($0) }
dict[1838230743] = { return Api.MessageMedia.parse_messageMediaDocument($0) }
dict[-608307692] = { return Api.MessageMedia.parse_messageMediaDocument($0) }
dict[1038967584] = { return Api.MessageMedia.parse_messageMediaEmpty($0) }
dict[-38694904] = { return Api.MessageMedia.parse_messageMediaGame($0) }
dict[1457575028] = { return Api.MessageMedia.parse_messageMediaGeo($0) }
@ -849,6 +851,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[289586518] = { return Api.SavedContact.parse_savedPhoneContact($0) }
dict[-1115174036] = { return Api.SavedDialog.parse_savedDialog($0) }
dict[-881854424] = { return Api.SavedReactionTag.parse_savedReactionTag($0) }
dict[1002989455] = { return Api.SavedStarGift.parse_savedStarGift($0) }
dict[-911191137] = { return Api.SearchResultsCalendarPeriod.parse_searchResultsCalendarPeriod($0) }
dict[2137295719] = { return Api.SearchResultsPosition.parse_searchResultPosition($0) }
dict[871426631] = { return Api.SecureCredentialsEncrypted.parse_secureCredentialsEncrypted($0) }
@ -1379,6 +1382,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[1314881805] = { return Api.payments.PaymentResult.parse_paymentResult($0) }
dict[-666824391] = { return Api.payments.PaymentResult.parse_paymentVerificationNeeded($0) }
dict[-74456004] = { return Api.payments.SavedInfo.parse_savedInfo($0) }
dict[1154859627] = { return Api.payments.SavedStarGifts.parse_savedStarGifts($0) }
dict[377215243] = { return Api.payments.StarGiftUpgradePreview.parse_starGiftUpgradePreview($0) }
dict[-1877571094] = { return Api.payments.StarGifts.parse_starGifts($0) }
dict[-1551326360] = { return Api.payments.StarGifts.parse_starGiftsNotModified($0) }
@ -1388,7 +1392,6 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[1822222573] = { return Api.payments.StarsStatus.parse_starsStatus($0) }
dict[-1261053863] = { return Api.payments.SuggestedStarRefBots.parse_suggestedStarRefBots($0) }
dict[-895289845] = { return Api.payments.UniqueStarGift.parse_uniqueStarGift($0) }
dict[1801827607] = { return Api.payments.UserStarGifts.parse_userStarGifts($0) }
dict[-784000893] = { return Api.payments.ValidatedRequestedInfo.parse_validatedRequestedInfo($0) }
dict[541839704] = { return Api.phone.ExportedGroupCallInvite.parse_exportedGroupCallInvite($0) }
dict[-1636664659] = { return Api.phone.GroupCall.parse_groupCall($0) }
@ -1823,6 +1826,8 @@ public extension Api {
_1.serialize(buffer, boxed)
case let _1 as Api.InputReplyTo:
_1.serialize(buffer, boxed)
case let _1 as Api.InputSavedStarGift:
_1.serialize(buffer, boxed)
case let _1 as Api.InputSecureFile:
_1.serialize(buffer, boxed)
case let _1 as Api.InputSecureValue:
@ -2035,6 +2040,8 @@ public extension Api {
_1.serialize(buffer, boxed)
case let _1 as Api.SavedReactionTag:
_1.serialize(buffer, boxed)
case let _1 as Api.SavedStarGift:
_1.serialize(buffer, boxed)
case let _1 as Api.SearchResultsCalendarPeriod:
_1.serialize(buffer, boxed)
case let _1 as Api.SearchResultsPosition:
@ -2465,6 +2472,8 @@ public extension Api {
_1.serialize(buffer, boxed)
case let _1 as Api.payments.SavedInfo:
_1.serialize(buffer, boxed)
case let _1 as Api.payments.SavedStarGifts:
_1.serialize(buffer, boxed)
case let _1 as Api.payments.StarGiftUpgradePreview:
_1.serialize(buffer, boxed)
case let _1 as Api.payments.StarGifts:
@ -2481,8 +2490,6 @@ public extension Api {
_1.serialize(buffer, boxed)
case let _1 as Api.payments.UniqueStarGift:
_1.serialize(buffer, boxed)
case let _1 as Api.payments.UserStarGifts:
_1.serialize(buffer, boxed)
case let _1 as Api.payments.ValidatedRequestedInfo:
_1.serialize(buffer, boxed)
case let _1 as Api.phone.ExportedGroupCallInvite:

View File

@ -212,9 +212,9 @@ public extension Api {
case inputInvoiceMessage(peer: Api.InputPeer, msgId: Int32)
case inputInvoicePremiumGiftCode(purpose: Api.InputStorePaymentPurpose, option: Api.PremiumGiftCodeOption)
case inputInvoiceSlug(slug: String)
case inputInvoiceStarGift(flags: Int32, userId: Api.InputUser, giftId: Int64, message: Api.TextWithEntities?)
case inputInvoiceStarGiftTransfer(msgId: Int32, toId: Api.InputUser)
case inputInvoiceStarGiftUpgrade(flags: Int32, msgId: Int32)
case inputInvoiceStarGift(flags: Int32, peer: Api.InputPeer, giftId: Int64, message: Api.TextWithEntities?)
case inputInvoiceStarGiftTransfer(stargift: Api.InputSavedStarGift, toId: Api.InputPeer)
case inputInvoiceStarGiftUpgrade(flags: Int32, stargift: Api.InputSavedStarGift)
case inputInvoiceStars(purpose: Api.InputStorePaymentPurpose)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
@ -245,28 +245,28 @@ public extension Api {
}
serializeString(slug, buffer: buffer, boxed: false)
break
case .inputInvoiceStarGift(let flags, let userId, let giftId, let message):
case .inputInvoiceStarGift(let flags, let peer, let giftId, let message):
if boxed {
buffer.appendInt32(634962392)
buffer.appendInt32(-396206446)
}
serializeInt32(flags, buffer: buffer, boxed: false)
userId.serialize(buffer, true)
peer.serialize(buffer, true)
serializeInt64(giftId, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 1) != 0 {message!.serialize(buffer, true)}
break
case .inputInvoiceStarGiftTransfer(let msgId, let toId):
case .inputInvoiceStarGiftTransfer(let stargift, let toId):
if boxed {
buffer.appendInt32(-1371821587)
buffer.appendInt32(1247763417)
}
serializeInt32(msgId, buffer: buffer, boxed: false)
stargift.serialize(buffer, true)
toId.serialize(buffer, true)
break
case .inputInvoiceStarGiftUpgrade(let flags, let msgId):
case .inputInvoiceStarGiftUpgrade(let flags, let stargift):
if boxed {
buffer.appendInt32(1589539426)
buffer.appendInt32(1300335965)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt32(msgId, buffer: buffer, boxed: false)
stargift.serialize(buffer, true)
break
case .inputInvoiceStars(let purpose):
if boxed {
@ -287,12 +287,12 @@ public extension Api {
return ("inputInvoicePremiumGiftCode", [("purpose", purpose as Any), ("option", option as Any)])
case .inputInvoiceSlug(let slug):
return ("inputInvoiceSlug", [("slug", slug as Any)])
case .inputInvoiceStarGift(let flags, let userId, let giftId, let message):
return ("inputInvoiceStarGift", [("flags", flags as Any), ("userId", userId as Any), ("giftId", giftId as Any), ("message", message as Any)])
case .inputInvoiceStarGiftTransfer(let msgId, let toId):
return ("inputInvoiceStarGiftTransfer", [("msgId", msgId as Any), ("toId", toId as Any)])
case .inputInvoiceStarGiftUpgrade(let flags, let msgId):
return ("inputInvoiceStarGiftUpgrade", [("flags", flags as Any), ("msgId", msgId as Any)])
case .inputInvoiceStarGift(let flags, let peer, let giftId, let message):
return ("inputInvoiceStarGift", [("flags", flags as Any), ("peer", peer as Any), ("giftId", giftId as Any), ("message", message as Any)])
case .inputInvoiceStarGiftTransfer(let stargift, let toId):
return ("inputInvoiceStarGiftTransfer", [("stargift", stargift as Any), ("toId", toId as Any)])
case .inputInvoiceStarGiftUpgrade(let flags, let stargift):
return ("inputInvoiceStarGiftUpgrade", [("flags", flags as Any), ("stargift", stargift as Any)])
case .inputInvoiceStars(let purpose):
return ("inputInvoiceStars", [("purpose", purpose as Any)])
}
@ -357,9 +357,9 @@ public extension Api {
public static func parse_inputInvoiceStarGift(_ reader: BufferReader) -> InputInvoice? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Api.InputUser?
var _2: Api.InputPeer?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.InputUser
_2 = Api.parse(reader, signature: signature) as? Api.InputPeer
}
var _3: Int64?
_3 = reader.readInt64()
@ -372,23 +372,25 @@ public extension Api {
let _c3 = _3 != nil
let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil
if _c1 && _c2 && _c3 && _c4 {
return Api.InputInvoice.inputInvoiceStarGift(flags: _1!, userId: _2!, giftId: _3!, message: _4)
return Api.InputInvoice.inputInvoiceStarGift(flags: _1!, peer: _2!, giftId: _3!, message: _4)
}
else {
return nil
}
}
public static func parse_inputInvoiceStarGiftTransfer(_ reader: BufferReader) -> InputInvoice? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Api.InputUser?
var _1: Api.InputSavedStarGift?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.InputUser
_1 = Api.parse(reader, signature: signature) as? Api.InputSavedStarGift
}
var _2: Api.InputPeer?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.InputPeer
}
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.InputInvoice.inputInvoiceStarGiftTransfer(msgId: _1!, toId: _2!)
return Api.InputInvoice.inputInvoiceStarGiftTransfer(stargift: _1!, toId: _2!)
}
else {
return nil
@ -397,12 +399,14 @@ public extension Api {
public static func parse_inputInvoiceStarGiftUpgrade(_ reader: BufferReader) -> InputInvoice? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Int32?
_2 = reader.readInt32()
var _2: Api.InputSavedStarGift?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.InputSavedStarGift
}
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.InputInvoice.inputInvoiceStarGiftUpgrade(flags: _1!, msgId: _2!)
return Api.InputInvoice.inputInvoiceStarGiftUpgrade(flags: _1!, stargift: _2!)
}
else {
return nil

View File

@ -364,6 +364,68 @@ public extension Api {
}
}
public extension Api {
indirect enum InputSavedStarGift: TypeConstructorDescription {
case inputSavedStarGiftChat(peer: Api.InputPeer, savedId: Int64)
case inputSavedStarGiftUser(msgId: Int32)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .inputSavedStarGiftChat(let peer, let savedId):
if boxed {
buffer.appendInt32(-251549057)
}
peer.serialize(buffer, true)
serializeInt64(savedId, buffer: buffer, boxed: false)
break
case .inputSavedStarGiftUser(let msgId):
if boxed {
buffer.appendInt32(1764202389)
}
serializeInt32(msgId, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .inputSavedStarGiftChat(let peer, let savedId):
return ("inputSavedStarGiftChat", [("peer", peer as Any), ("savedId", savedId as Any)])
case .inputSavedStarGiftUser(let msgId):
return ("inputSavedStarGiftUser", [("msgId", msgId as Any)])
}
}
public static func parse_inputSavedStarGiftChat(_ reader: BufferReader) -> InputSavedStarGift? {
var _1: Api.InputPeer?
if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.InputPeer
}
var _2: Int64?
_2 = reader.readInt64()
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.InputSavedStarGift.inputSavedStarGiftChat(peer: _1!, savedId: _2!)
}
else {
return nil
}
}
public static func parse_inputSavedStarGiftUser(_ reader: BufferReader) -> InputSavedStarGift? {
var _1: Int32?
_1 = reader.readInt32()
let _c1 = _1 != nil
if _c1 {
return Api.InputSavedStarGift.inputSavedStarGiftUser(msgId: _1!)
}
else {
return nil
}
}
}
}
public extension Api {
enum InputSecureFile: TypeConstructorDescription {
case inputSecureFile(id: Int64, accessHash: Int64)

View File

@ -373,7 +373,7 @@ public extension Api {
case messageActionSetChatTheme(emoticon: String)
case messageActionSetChatWallPaper(flags: Int32, wallpaper: Api.WallPaper)
case messageActionSetMessagesTTL(flags: Int32, period: Int32, autoSettingFrom: Int64?)
case messageActionStarGift(flags: Int32, gift: Api.StarGift, message: Api.TextWithEntities?, convertStars: Int64?, upgradeMsgId: Int32?, upgradeStars: Int64?)
case messageActionStarGift(flags: Int32, gift: Api.StarGift, message: Api.TextWithEntities?, convertStars: Int64?, upgradeMsgId: Int32?, upgradeStars: Int64?, fromId: Int64?, peer: Api.Peer?)
case messageActionStarGiftUnique(flags: Int32, gift: Api.StarGift, canExportAt: Int32?, transferStars: Int64?)
case messageActionSuggestProfilePhoto(photo: Api.Photo)
case messageActionTopicCreate(flags: Int32, title: String, iconColor: Int32, iconEmojiId: Int64?)
@ -720,9 +720,9 @@ public extension Api {
serializeInt32(period, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {serializeInt64(autoSettingFrom!, buffer: buffer, boxed: false)}
break
case .messageActionStarGift(let flags, let gift, let message, let convertStars, let upgradeMsgId, let upgradeStars):
case .messageActionStarGift(let flags, let gift, let message, let convertStars, let upgradeMsgId, let upgradeStars, let fromId, let peer):
if boxed {
buffer.appendInt32(-655036249)
buffer.appendInt32(178478442)
}
serializeInt32(flags, buffer: buffer, boxed: false)
gift.serialize(buffer, true)
@ -730,6 +730,8 @@ public extension Api {
if Int(flags) & Int(1 << 4) != 0 {serializeInt64(convertStars!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 5) != 0 {serializeInt32(upgradeMsgId!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 8) != 0 {serializeInt64(upgradeStars!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 11) != 0 {serializeInt64(fromId!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 11) != 0 {peer!.serialize(buffer, true)}
break
case .messageActionStarGiftUnique(let flags, let gift, let canExportAt, let transferStars):
if boxed {
@ -865,8 +867,8 @@ public extension Api {
return ("messageActionSetChatWallPaper", [("flags", flags as Any), ("wallpaper", wallpaper as Any)])
case .messageActionSetMessagesTTL(let flags, let period, let autoSettingFrom):
return ("messageActionSetMessagesTTL", [("flags", flags as Any), ("period", period as Any), ("autoSettingFrom", autoSettingFrom as Any)])
case .messageActionStarGift(let flags, let gift, let message, let convertStars, let upgradeMsgId, let upgradeStars):
return ("messageActionStarGift", [("flags", flags as Any), ("gift", gift as Any), ("message", message as Any), ("convertStars", convertStars as Any), ("upgradeMsgId", upgradeMsgId as Any), ("upgradeStars", upgradeStars as Any)])
case .messageActionStarGift(let flags, let gift, let message, let convertStars, let upgradeMsgId, let upgradeStars, let fromId, let peer):
return ("messageActionStarGift", [("flags", flags as Any), ("gift", gift as Any), ("message", message as Any), ("convertStars", convertStars as Any), ("upgradeMsgId", upgradeMsgId as Any), ("upgradeStars", upgradeStars as Any), ("fromId", fromId as Any), ("peer", peer as Any)])
case .messageActionStarGiftUnique(let flags, let gift, let canExportAt, let transferStars):
return ("messageActionStarGiftUnique", [("flags", flags as Any), ("gift", gift as Any), ("canExportAt", canExportAt as Any), ("transferStars", transferStars as Any)])
case .messageActionSuggestProfilePhoto(let photo):
@ -1533,14 +1535,22 @@ public extension Api {
if Int(_1!) & Int(1 << 5) != 0 {_5 = reader.readInt32() }
var _6: Int64?
if Int(_1!) & Int(1 << 8) != 0 {_6 = reader.readInt64() }
var _7: Int64?
if Int(_1!) & Int(1 << 11) != 0 {_7 = reader.readInt64() }
var _8: Api.Peer?
if Int(_1!) & Int(1 << 11) != 0 {if let signature = reader.readInt32() {
_8 = Api.parse(reader, signature: signature) as? Api.Peer
} }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil
let _c4 = (Int(_1!) & Int(1 << 4) == 0) || _4 != nil
let _c5 = (Int(_1!) & Int(1 << 5) == 0) || _5 != nil
let _c6 = (Int(_1!) & Int(1 << 8) == 0) || _6 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 {
return Api.MessageAction.messageActionStarGift(flags: _1!, gift: _2!, message: _3, convertStars: _4, upgradeMsgId: _5, upgradeStars: _6)
let _c7 = (Int(_1!) & Int(1 << 11) == 0) || _7 != nil
let _c8 = (Int(_1!) & Int(1 << 11) == 0) || _8 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 {
return Api.MessageAction.messageActionStarGift(flags: _1!, gift: _2!, message: _3, convertStars: _4, upgradeMsgId: _5, upgradeStars: _6, fromId: _7, peer: _8)
}
else {
return nil

View File

@ -710,7 +710,7 @@ public extension Api {
indirect enum MessageMedia: TypeConstructorDescription {
case messageMediaContact(phoneNumber: String, firstName: String, lastName: String, vcard: String, userId: Int64)
case messageMediaDice(value: Int32, emoticon: String)
case messageMediaDocument(flags: Int32, document: Api.Document?, altDocuments: [Api.Document]?, coverPhoto: Api.Photo?, ttlSeconds: Int32?)
case messageMediaDocument(flags: Int32, document: Api.Document?, altDocuments: [Api.Document]?, videoCover: Api.Photo?, ttlSeconds: Int32?)
case messageMediaEmpty
case messageMediaGame(game: Api.Game)
case messageMediaGeo(geo: Api.GeoPoint)
@ -745,9 +745,9 @@ public extension Api {
serializeInt32(value, buffer: buffer, boxed: false)
serializeString(emoticon, buffer: buffer, boxed: false)
break
case .messageMediaDocument(let flags, let document, let altDocuments, let coverPhoto, let ttlSeconds):
case .messageMediaDocument(let flags, let document, let altDocuments, let videoCover, let ttlSeconds):
if boxed {
buffer.appendInt32(1838230743)
buffer.appendInt32(-608307692)
}
serializeInt32(flags, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {document!.serialize(buffer, true)}
@ -756,7 +756,7 @@ public extension Api {
for item in altDocuments! {
item.serialize(buffer, true)
}}
if Int(flags) & Int(1 << 9) != 0 {coverPhoto!.serialize(buffer, true)}
if Int(flags) & Int(1 << 9) != 0 {videoCover!.serialize(buffer, true)}
if Int(flags) & Int(1 << 2) != 0 {serializeInt32(ttlSeconds!, buffer: buffer, boxed: false)}
break
case .messageMediaEmpty:
@ -910,8 +910,8 @@ public extension Api {
return ("messageMediaContact", [("phoneNumber", phoneNumber as Any), ("firstName", firstName as Any), ("lastName", lastName as Any), ("vcard", vcard as Any), ("userId", userId as Any)])
case .messageMediaDice(let value, let emoticon):
return ("messageMediaDice", [("value", value as Any), ("emoticon", emoticon as Any)])
case .messageMediaDocument(let flags, let document, let altDocuments, let coverPhoto, let ttlSeconds):
return ("messageMediaDocument", [("flags", flags as Any), ("document", document as Any), ("altDocuments", altDocuments as Any), ("coverPhoto", coverPhoto as Any), ("ttlSeconds", ttlSeconds as Any)])
case .messageMediaDocument(let flags, let document, let altDocuments, let videoCover, let ttlSeconds):
return ("messageMediaDocument", [("flags", flags as Any), ("document", document as Any), ("altDocuments", altDocuments as Any), ("videoCover", videoCover as Any), ("ttlSeconds", ttlSeconds as Any)])
case .messageMediaEmpty:
return ("messageMediaEmpty", [])
case .messageMediaGame(let game):
@ -1003,7 +1003,7 @@ public extension Api {
let _c4 = (Int(_1!) & Int(1 << 9) == 0) || _4 != nil
let _c5 = (Int(_1!) & Int(1 << 2) == 0) || _5 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 {
return Api.MessageMedia.messageMediaDocument(flags: _1!, document: _2, altDocuments: _3, coverPhoto: _4, ttlSeconds: _5)
return Api.MessageMedia.messageMediaDocument(flags: _1!, document: _2, altDocuments: _3, videoCover: _4, ttlSeconds: _5)
}
else {
return nil

View File

@ -142,6 +142,86 @@ public extension Api {
}
}
public extension Api {
enum SavedStarGift: TypeConstructorDescription {
case savedStarGift(flags: Int32, fromId: Int64?, date: Int32, gift: Api.StarGift, message: Api.TextWithEntities?, msgId: Int32?, savedId: Int64?, convertStars: Int64?, upgradeStars: Int64?, canExportAt: Int32?, transferStars: Int64?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .savedStarGift(let flags, let fromId, let date, let gift, let message, let msgId, let savedId, let convertStars, let upgradeStars, let canExportAt, let transferStars):
if boxed {
buffer.appendInt32(1002989455)
}
serializeInt32(flags, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 1) != 0 {serializeInt64(fromId!, buffer: buffer, boxed: false)}
serializeInt32(date, buffer: buffer, boxed: false)
gift.serialize(buffer, true)
if Int(flags) & Int(1 << 2) != 0 {message!.serialize(buffer, true)}
if Int(flags) & Int(1 << 3) != 0 {serializeInt32(msgId!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 11) != 0 {serializeInt64(savedId!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 4) != 0 {serializeInt64(convertStars!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 6) != 0 {serializeInt64(upgradeStars!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 7) != 0 {serializeInt32(canExportAt!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 8) != 0 {serializeInt64(transferStars!, buffer: buffer, boxed: false)}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .savedStarGift(let flags, let fromId, let date, let gift, let message, let msgId, let savedId, let convertStars, let upgradeStars, let canExportAt, let transferStars):
return ("savedStarGift", [("flags", flags as Any), ("fromId", fromId as Any), ("date", date as Any), ("gift", gift as Any), ("message", message as Any), ("msgId", msgId as Any), ("savedId", savedId as Any), ("convertStars", convertStars as Any), ("upgradeStars", upgradeStars as Any), ("canExportAt", canExportAt as Any), ("transferStars", transferStars as Any)])
}
}
public static func parse_savedStarGift(_ reader: BufferReader) -> SavedStarGift? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Int64?
if Int(_1!) & Int(1 << 1) != 0 {_2 = reader.readInt64() }
var _3: Int32?
_3 = reader.readInt32()
var _4: Api.StarGift?
if let signature = reader.readInt32() {
_4 = Api.parse(reader, signature: signature) as? Api.StarGift
}
var _5: Api.TextWithEntities?
if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() {
_5 = Api.parse(reader, signature: signature) as? Api.TextWithEntities
} }
var _6: Int32?
if Int(_1!) & Int(1 << 3) != 0 {_6 = reader.readInt32() }
var _7: Int64?
if Int(_1!) & Int(1 << 11) != 0 {_7 = reader.readInt64() }
var _8: Int64?
if Int(_1!) & Int(1 << 4) != 0 {_8 = reader.readInt64() }
var _9: Int64?
if Int(_1!) & Int(1 << 6) != 0 {_9 = reader.readInt64() }
var _10: Int32?
if Int(_1!) & Int(1 << 7) != 0 {_10 = reader.readInt32() }
var _11: Int64?
if Int(_1!) & Int(1 << 8) != 0 {_11 = reader.readInt64() }
let _c1 = _1 != nil
let _c2 = (Int(_1!) & Int(1 << 1) == 0) || _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
let _c5 = (Int(_1!) & Int(1 << 2) == 0) || _5 != nil
let _c6 = (Int(_1!) & Int(1 << 3) == 0) || _6 != nil
let _c7 = (Int(_1!) & Int(1 << 11) == 0) || _7 != nil
let _c8 = (Int(_1!) & Int(1 << 4) == 0) || _8 != nil
let _c9 = (Int(_1!) & Int(1 << 6) == 0) || _9 != nil
let _c10 = (Int(_1!) & Int(1 << 7) == 0) || _10 != nil
let _c11 = (Int(_1!) & Int(1 << 8) == 0) || _11 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 {
return Api.SavedStarGift.savedStarGift(flags: _1!, fromId: _2, date: _3!, gift: _4!, message: _5, msgId: _6, savedId: _7, convertStars: _8, upgradeStars: _9, canExportAt: _10, transferStars: _11)
}
else {
return nil
}
}
}
}
public extension Api {
enum SearchResultsCalendarPeriod: TypeConstructorDescription {
case searchResultsCalendarPeriod(date: Int32, minMsgId: Int32, maxMsgId: Int32, count: Int32)

View File

@ -1,3 +1,77 @@
public extension Api.payments {
enum SavedStarGifts: TypeConstructorDescription {
case savedStarGifts(flags: Int32, count: Int32, gifts: [Api.SavedStarGift], nextOffset: String?, chats: [Api.Chat], users: [Api.User])
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .savedStarGifts(let flags, let count, let gifts, let nextOffset, let chats, let users):
if boxed {
buffer.appendInt32(1154859627)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt32(count, buffer: buffer, boxed: false)
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(gifts.count))
for item in gifts {
item.serialize(buffer, true)
}
if Int(flags) & Int(1 << 0) != 0 {serializeString(nextOffset!, buffer: buffer, boxed: false)}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(chats.count))
for item in chats {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(users.count))
for item in users {
item.serialize(buffer, true)
}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .savedStarGifts(let flags, let count, let gifts, let nextOffset, let chats, let users):
return ("savedStarGifts", [("flags", flags as Any), ("count", count as Any), ("gifts", gifts as Any), ("nextOffset", nextOffset as Any), ("chats", chats as Any), ("users", users as Any)])
}
}
public static func parse_savedStarGifts(_ reader: BufferReader) -> SavedStarGifts? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Int32?
_2 = reader.readInt32()
var _3: [Api.SavedStarGift]?
if let _ = reader.readInt32() {
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.SavedStarGift.self)
}
var _4: String?
if Int(_1!) & Int(1 << 0) != 0 {_4 = parseString(reader) }
var _5: [Api.Chat]?
if let _ = reader.readInt32() {
_5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self)
}
var _6: [Api.User]?
if let _ = reader.readInt32() {
_6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
}
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil
let _c5 = _5 != nil
let _c6 = _6 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 {
return Api.payments.SavedStarGifts.savedStarGifts(flags: _1!, count: _2!, gifts: _3!, nextOffset: _4, chats: _5!, users: _6!)
}
else {
return nil
}
}
}
}
public extension Api.payments {
enum StarGiftUpgradePreview: TypeConstructorDescription {
case starGiftUpgradePreview(sampleAttributes: [Api.StarGiftAttribute])
@ -424,70 +498,6 @@ public extension Api.payments {
}
}
public extension Api.payments {
enum UserStarGifts: TypeConstructorDescription {
case userStarGifts(flags: Int32, count: Int32, gifts: [Api.UserStarGift], nextOffset: String?, users: [Api.User])
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .userStarGifts(let flags, let count, let gifts, let nextOffset, let users):
if boxed {
buffer.appendInt32(1801827607)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt32(count, buffer: buffer, boxed: false)
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(gifts.count))
for item in gifts {
item.serialize(buffer, true)
}
if Int(flags) & Int(1 << 0) != 0 {serializeString(nextOffset!, buffer: buffer, boxed: false)}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(users.count))
for item in users {
item.serialize(buffer, true)
}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .userStarGifts(let flags, let count, let gifts, let nextOffset, let users):
return ("userStarGifts", [("flags", flags as Any), ("count", count as Any), ("gifts", gifts as Any), ("nextOffset", nextOffset as Any), ("users", users as Any)])
}
}
public static func parse_userStarGifts(_ reader: BufferReader) -> UserStarGifts? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Int32?
_2 = reader.readInt32()
var _3: [Api.UserStarGift]?
if let _ = reader.readInt32() {
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.UserStarGift.self)
}
var _4: String?
if Int(_1!) & Int(1 << 0) != 0 {_4 = parseString(reader) }
var _5: [Api.User]?
if let _ = reader.readInt32() {
_5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
}
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil
let _c5 = _5 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 {
return Api.payments.UserStarGifts.userStarGifts(flags: _1!, count: _2!, gifts: _3!, nextOffset: _4, users: _5!)
}
else {
return nil
}
}
}
}
public extension Api.payments {
enum ValidatedRequestedInfo: TypeConstructorDescription {
case validatedRequestedInfo(flags: Int32, id: String?, shippingOptions: [Api.ShippingOption]?)

View File

@ -9088,11 +9088,11 @@ public extension Api.functions.payments {
}
}
public extension Api.functions.payments {
static func convertStarGift(msgId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
static func convertStarGift(stargift: Api.InputSavedStarGift) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
let buffer = Buffer()
buffer.appendInt32(1920404611)
serializeInt32(msgId, buffer: buffer, boxed: false)
return (FunctionDescription(name: "payments.convertStarGift", parameters: [("msgId", String(describing: msgId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in
buffer.appendInt32(1958676331)
stargift.serialize(buffer, true)
return (FunctionDescription(name: "payments.convertStarGift", parameters: [("stargift", String(describing: stargift))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in
let reader = BufferReader(buffer)
var result: Api.Bool?
if let signature = reader.readInt32() {
@ -9280,6 +9280,43 @@ public extension Api.functions.payments {
})
}
}
public extension Api.functions.payments {
static func getSavedStarGift(stargift: [Api.InputSavedStarGift]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.payments.SavedStarGifts>) {
let buffer = Buffer()
buffer.appendInt32(-1269456634)
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(stargift.count))
for item in stargift {
item.serialize(buffer, true)
}
return (FunctionDescription(name: "payments.getSavedStarGift", parameters: [("stargift", String(describing: stargift))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.payments.SavedStarGifts? in
let reader = BufferReader(buffer)
var result: Api.payments.SavedStarGifts?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.payments.SavedStarGifts
}
return result
})
}
}
public extension Api.functions.payments {
static func getSavedStarGifts(flags: Int32, peer: Api.InputPeer, offset: String, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.payments.SavedStarGifts>) {
let buffer = Buffer()
buffer.appendInt32(595791337)
serializeInt32(flags, buffer: buffer, boxed: false)
peer.serialize(buffer, true)
serializeString(offset, buffer: buffer, boxed: false)
serializeInt32(limit, buffer: buffer, boxed: false)
return (FunctionDescription(name: "payments.getSavedStarGifts", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("offset", String(describing: offset)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.payments.SavedStarGifts? in
let reader = BufferReader(buffer)
var result: Api.payments.SavedStarGifts?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.payments.SavedStarGifts
}
return result
})
}
}
public extension Api.functions.payments {
static func getStarGiftUpgradePreview(giftId: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.payments.StarGiftUpgradePreview>) {
let buffer = Buffer()
@ -9508,42 +9545,6 @@ public extension Api.functions.payments {
})
}
}
public extension Api.functions.payments {
static func getUserStarGift(msgId: [Int32]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.payments.UserStarGifts>) {
let buffer = Buffer()
buffer.appendInt32(-1258101595)
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(msgId.count))
for item in msgId {
serializeInt32(item, buffer: buffer, boxed: false)
}
return (FunctionDescription(name: "payments.getUserStarGift", parameters: [("msgId", String(describing: msgId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.payments.UserStarGifts? in
let reader = BufferReader(buffer)
var result: Api.payments.UserStarGifts?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.payments.UserStarGifts
}
return result
})
}
}
public extension Api.functions.payments {
static func getUserStarGifts(userId: Api.InputUser, offset: String, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.payments.UserStarGifts>) {
let buffer = Buffer()
buffer.appendInt32(1584580577)
userId.serialize(buffer, true)
serializeString(offset, buffer: buffer, boxed: false)
serializeInt32(limit, buffer: buffer, boxed: false)
return (FunctionDescription(name: "payments.getUserStarGifts", parameters: [("userId", String(describing: userId)), ("offset", String(describing: offset)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.payments.UserStarGifts? in
let reader = BufferReader(buffer)
var result: Api.payments.UserStarGifts?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.payments.UserStarGifts
}
return result
})
}
}
public extension Api.functions.payments {
static func launchPrepaidGiveaway(peer: Api.InputPeer, giveawayId: Int64, purpose: Api.InputStorePaymentPurpose) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
let buffer = Buffer()
@ -9578,12 +9579,12 @@ public extension Api.functions.payments {
}
}
public extension Api.functions.payments {
static func saveStarGift(flags: Int32, msgId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
static func saveStarGift(flags: Int32, stargift: Api.InputSavedStarGift) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
let buffer = Buffer()
buffer.appendInt32(-1828902226)
buffer.appendInt32(707422588)
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt32(msgId, buffer: buffer, boxed: false)
return (FunctionDescription(name: "payments.saveStarGift", parameters: [("flags", String(describing: flags)), ("msgId", String(describing: msgId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in
stargift.serialize(buffer, true)
return (FunctionDescription(name: "payments.saveStarGift", parameters: [("flags", String(describing: flags)), ("stargift", String(describing: stargift))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in
let reader = BufferReader(buffer)
var result: Api.Bool?
if let signature = reader.readInt32() {
@ -9631,12 +9632,12 @@ public extension Api.functions.payments {
}
}
public extension Api.functions.payments {
static func transferStarGift(msgId: Int32, toId: Api.InputUser) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
static func transferStarGift(stargift: Api.InputSavedStarGift, toId: Api.InputUser) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
let buffer = Buffer()
buffer.appendInt32(859813158)
serializeInt32(msgId, buffer: buffer, boxed: false)
buffer.appendInt32(-279379968)
stargift.serialize(buffer, true)
toId.serialize(buffer, true)
return (FunctionDescription(name: "payments.transferStarGift", parameters: [("msgId", String(describing: msgId)), ("toId", String(describing: toId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
return (FunctionDescription(name: "payments.transferStarGift", parameters: [("stargift", String(describing: stargift)), ("toId", String(describing: toId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
let reader = BufferReader(buffer)
var result: Api.Updates?
if let signature = reader.readInt32() {
@ -9647,12 +9648,12 @@ public extension Api.functions.payments {
}
}
public extension Api.functions.payments {
static func upgradeStarGift(flags: Int32, msgId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
static func upgradeStarGift(flags: Int32, stargift: Api.InputSavedStarGift) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
let buffer = Buffer()
buffer.appendInt32(-816904319)
buffer.appendInt32(-1361648395)
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt32(msgId, buffer: buffer, boxed: false)
return (FunctionDescription(name: "payments.upgradeStarGift", parameters: [("flags", String(describing: flags)), ("msgId", String(describing: msgId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
stargift.serialize(buffer, true)
return (FunctionDescription(name: "payments.upgradeStarGift", parameters: [("flags", String(describing: flags)), ("stargift", String(describing: stargift))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
let reader = BufferReader(buffer)
var result: Api.Updates?
if let signature = reader.readInt32() {

View File

@ -940,14 +940,14 @@ public extension Api {
}
public extension Api {
enum ChatFull: TypeConstructorDescription {
case channelFull(flags: Int32, flags2: Int32, id: Int64, about: String, participantsCount: Int32?, adminsCount: Int32?, kickedCount: Int32?, bannedCount: Int32?, onlineCount: Int32?, readInboxMaxId: Int32, readOutboxMaxId: Int32, unreadCount: Int32, chatPhoto: Api.Photo, notifySettings: Api.PeerNotifySettings, exportedInvite: Api.ExportedChatInvite?, botInfo: [Api.BotInfo], migratedFromChatId: Int64?, migratedFromMaxId: Int32?, pinnedMsgId: Int32?, stickerset: Api.StickerSet?, availableMinId: Int32?, folderId: Int32?, linkedChatId: Int64?, location: Api.ChannelLocation?, slowmodeSeconds: Int32?, slowmodeNextSendDate: Int32?, statsDc: Int32?, pts: Int32, call: Api.InputGroupCall?, ttlPeriod: Int32?, pendingSuggestions: [String]?, groupcallDefaultJoinAs: Api.Peer?, themeEmoticon: String?, requestsPending: Int32?, recentRequesters: [Int64]?, defaultSendAs: Api.Peer?, availableReactions: Api.ChatReactions?, reactionsLimit: Int32?, stories: Api.PeerStories?, wallpaper: Api.WallPaper?, boostsApplied: Int32?, boostsUnrestrict: Int32?, emojiset: Api.StickerSet?, botVerification: Api.BotVerification?)
case channelFull(flags: Int32, flags2: Int32, id: Int64, about: String, participantsCount: Int32?, adminsCount: Int32?, kickedCount: Int32?, bannedCount: Int32?, onlineCount: Int32?, readInboxMaxId: Int32, readOutboxMaxId: Int32, unreadCount: Int32, chatPhoto: Api.Photo, notifySettings: Api.PeerNotifySettings, exportedInvite: Api.ExportedChatInvite?, botInfo: [Api.BotInfo], migratedFromChatId: Int64?, migratedFromMaxId: Int32?, pinnedMsgId: Int32?, stickerset: Api.StickerSet?, availableMinId: Int32?, folderId: Int32?, linkedChatId: Int64?, location: Api.ChannelLocation?, slowmodeSeconds: Int32?, slowmodeNextSendDate: Int32?, statsDc: Int32?, pts: Int32, call: Api.InputGroupCall?, ttlPeriod: Int32?, pendingSuggestions: [String]?, groupcallDefaultJoinAs: Api.Peer?, themeEmoticon: String?, requestsPending: Int32?, recentRequesters: [Int64]?, defaultSendAs: Api.Peer?, availableReactions: Api.ChatReactions?, reactionsLimit: Int32?, stories: Api.PeerStories?, wallpaper: Api.WallPaper?, boostsApplied: Int32?, boostsUnrestrict: Int32?, emojiset: Api.StickerSet?, botVerification: Api.BotVerification?, stargiftsCount: Int32?)
case chatFull(flags: Int32, id: Int64, about: String, participants: Api.ChatParticipants, chatPhoto: Api.Photo?, notifySettings: Api.PeerNotifySettings, exportedInvite: Api.ExportedChatInvite?, botInfo: [Api.BotInfo]?, pinnedMsgId: Int32?, folderId: Int32?, call: Api.InputGroupCall?, ttlPeriod: Int32?, groupcallDefaultJoinAs: Api.Peer?, themeEmoticon: String?, requestsPending: Int32?, recentRequesters: [Int64]?, availableReactions: Api.ChatReactions?, reactionsLimit: Int32?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .channelFull(let flags, let flags2, let id, let about, let participantsCount, let adminsCount, let kickedCount, let bannedCount, let onlineCount, let readInboxMaxId, let readOutboxMaxId, let unreadCount, let chatPhoto, let notifySettings, let exportedInvite, let botInfo, let migratedFromChatId, let migratedFromMaxId, let pinnedMsgId, let stickerset, let availableMinId, let folderId, let linkedChatId, let location, let slowmodeSeconds, let slowmodeNextSendDate, let statsDc, let pts, let call, let ttlPeriod, let pendingSuggestions, let groupcallDefaultJoinAs, let themeEmoticon, let requestsPending, let recentRequesters, let defaultSendAs, let availableReactions, let reactionsLimit, let stories, let wallpaper, let boostsApplied, let boostsUnrestrict, let emojiset, let botVerification):
case .channelFull(let flags, let flags2, let id, let about, let participantsCount, let adminsCount, let kickedCount, let bannedCount, let onlineCount, let readInboxMaxId, let readOutboxMaxId, let unreadCount, let chatPhoto, let notifySettings, let exportedInvite, let botInfo, let migratedFromChatId, let migratedFromMaxId, let pinnedMsgId, let stickerset, let availableMinId, let folderId, let linkedChatId, let location, let slowmodeSeconds, let slowmodeNextSendDate, let statsDc, let pts, let call, let ttlPeriod, let pendingSuggestions, let groupcallDefaultJoinAs, let themeEmoticon, let requestsPending, let recentRequesters, let defaultSendAs, let availableReactions, let reactionsLimit, let stories, let wallpaper, let boostsApplied, let boostsUnrestrict, let emojiset, let botVerification, let stargiftsCount):
if boxed {
buffer.appendInt32(-1611417512)
buffer.appendInt32(1389789291)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt32(flags2, buffer: buffer, boxed: false)
@ -1005,6 +1005,7 @@ public extension Api {
if Int(flags2) & Int(1 << 9) != 0 {serializeInt32(boostsUnrestrict!, buffer: buffer, boxed: false)}
if Int(flags2) & Int(1 << 10) != 0 {emojiset!.serialize(buffer, true)}
if Int(flags2) & Int(1 << 17) != 0 {botVerification!.serialize(buffer, true)}
if Int(flags2) & Int(1 << 18) != 0 {serializeInt32(stargiftsCount!, buffer: buffer, boxed: false)}
break
case .chatFull(let flags, let id, let about, let participants, let chatPhoto, let notifySettings, let exportedInvite, let botInfo, let pinnedMsgId, let folderId, let call, let ttlPeriod, let groupcallDefaultJoinAs, let themeEmoticon, let requestsPending, let recentRequesters, let availableReactions, let reactionsLimit):
if boxed {
@ -1042,8 +1043,8 @@ public extension Api {
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .channelFull(let flags, let flags2, let id, let about, let participantsCount, let adminsCount, let kickedCount, let bannedCount, let onlineCount, let readInboxMaxId, let readOutboxMaxId, let unreadCount, let chatPhoto, let notifySettings, let exportedInvite, let botInfo, let migratedFromChatId, let migratedFromMaxId, let pinnedMsgId, let stickerset, let availableMinId, let folderId, let linkedChatId, let location, let slowmodeSeconds, let slowmodeNextSendDate, let statsDc, let pts, let call, let ttlPeriod, let pendingSuggestions, let groupcallDefaultJoinAs, let themeEmoticon, let requestsPending, let recentRequesters, let defaultSendAs, let availableReactions, let reactionsLimit, let stories, let wallpaper, let boostsApplied, let boostsUnrestrict, let emojiset, let botVerification):
return ("channelFull", [("flags", flags as Any), ("flags2", flags2 as Any), ("id", id as Any), ("about", about as Any), ("participantsCount", participantsCount as Any), ("adminsCount", adminsCount as Any), ("kickedCount", kickedCount as Any), ("bannedCount", bannedCount as Any), ("onlineCount", onlineCount as Any), ("readInboxMaxId", readInboxMaxId as Any), ("readOutboxMaxId", readOutboxMaxId as Any), ("unreadCount", unreadCount as Any), ("chatPhoto", chatPhoto as Any), ("notifySettings", notifySettings as Any), ("exportedInvite", exportedInvite as Any), ("botInfo", botInfo as Any), ("migratedFromChatId", migratedFromChatId as Any), ("migratedFromMaxId", migratedFromMaxId as Any), ("pinnedMsgId", pinnedMsgId as Any), ("stickerset", stickerset as Any), ("availableMinId", availableMinId as Any), ("folderId", folderId as Any), ("linkedChatId", linkedChatId as Any), ("location", location as Any), ("slowmodeSeconds", slowmodeSeconds as Any), ("slowmodeNextSendDate", slowmodeNextSendDate as Any), ("statsDc", statsDc as Any), ("pts", pts as Any), ("call", call as Any), ("ttlPeriod", ttlPeriod as Any), ("pendingSuggestions", pendingSuggestions as Any), ("groupcallDefaultJoinAs", groupcallDefaultJoinAs as Any), ("themeEmoticon", themeEmoticon as Any), ("requestsPending", requestsPending as Any), ("recentRequesters", recentRequesters as Any), ("defaultSendAs", defaultSendAs as Any), ("availableReactions", availableReactions as Any), ("reactionsLimit", reactionsLimit as Any), ("stories", stories as Any), ("wallpaper", wallpaper as Any), ("boostsApplied", boostsApplied as Any), ("boostsUnrestrict", boostsUnrestrict as Any), ("emojiset", emojiset as Any), ("botVerification", botVerification as Any)])
case .channelFull(let flags, let flags2, let id, let about, let participantsCount, let adminsCount, let kickedCount, let bannedCount, let onlineCount, let readInboxMaxId, let readOutboxMaxId, let unreadCount, let chatPhoto, let notifySettings, let exportedInvite, let botInfo, let migratedFromChatId, let migratedFromMaxId, let pinnedMsgId, let stickerset, let availableMinId, let folderId, let linkedChatId, let location, let slowmodeSeconds, let slowmodeNextSendDate, let statsDc, let pts, let call, let ttlPeriod, let pendingSuggestions, let groupcallDefaultJoinAs, let themeEmoticon, let requestsPending, let recentRequesters, let defaultSendAs, let availableReactions, let reactionsLimit, let stories, let wallpaper, let boostsApplied, let boostsUnrestrict, let emojiset, let botVerification, let stargiftsCount):
return ("channelFull", [("flags", flags as Any), ("flags2", flags2 as Any), ("id", id as Any), ("about", about as Any), ("participantsCount", participantsCount as Any), ("adminsCount", adminsCount as Any), ("kickedCount", kickedCount as Any), ("bannedCount", bannedCount as Any), ("onlineCount", onlineCount as Any), ("readInboxMaxId", readInboxMaxId as Any), ("readOutboxMaxId", readOutboxMaxId as Any), ("unreadCount", unreadCount as Any), ("chatPhoto", chatPhoto as Any), ("notifySettings", notifySettings as Any), ("exportedInvite", exportedInvite as Any), ("botInfo", botInfo as Any), ("migratedFromChatId", migratedFromChatId as Any), ("migratedFromMaxId", migratedFromMaxId as Any), ("pinnedMsgId", pinnedMsgId as Any), ("stickerset", stickerset as Any), ("availableMinId", availableMinId as Any), ("folderId", folderId as Any), ("linkedChatId", linkedChatId as Any), ("location", location as Any), ("slowmodeSeconds", slowmodeSeconds as Any), ("slowmodeNextSendDate", slowmodeNextSendDate as Any), ("statsDc", statsDc as Any), ("pts", pts as Any), ("call", call as Any), ("ttlPeriod", ttlPeriod as Any), ("pendingSuggestions", pendingSuggestions as Any), ("groupcallDefaultJoinAs", groupcallDefaultJoinAs as Any), ("themeEmoticon", themeEmoticon as Any), ("requestsPending", requestsPending as Any), ("recentRequesters", recentRequesters as Any), ("defaultSendAs", defaultSendAs as Any), ("availableReactions", availableReactions as Any), ("reactionsLimit", reactionsLimit as Any), ("stories", stories as Any), ("wallpaper", wallpaper as Any), ("boostsApplied", boostsApplied as Any), ("boostsUnrestrict", boostsUnrestrict as Any), ("emojiset", emojiset as Any), ("botVerification", botVerification as Any), ("stargiftsCount", stargiftsCount as Any)])
case .chatFull(let flags, let id, let about, let participants, let chatPhoto, let notifySettings, let exportedInvite, let botInfo, let pinnedMsgId, let folderId, let call, let ttlPeriod, let groupcallDefaultJoinAs, let themeEmoticon, let requestsPending, let recentRequesters, let availableReactions, let reactionsLimit):
return ("chatFull", [("flags", flags as Any), ("id", id as Any), ("about", about as Any), ("participants", participants as Any), ("chatPhoto", chatPhoto as Any), ("notifySettings", notifySettings as Any), ("exportedInvite", exportedInvite as Any), ("botInfo", botInfo as Any), ("pinnedMsgId", pinnedMsgId as Any), ("folderId", folderId as Any), ("call", call as Any), ("ttlPeriod", ttlPeriod as Any), ("groupcallDefaultJoinAs", groupcallDefaultJoinAs as Any), ("themeEmoticon", themeEmoticon as Any), ("requestsPending", requestsPending as Any), ("recentRequesters", recentRequesters as Any), ("availableReactions", availableReactions as Any), ("reactionsLimit", reactionsLimit as Any)])
}
@ -1170,6 +1171,8 @@ public extension Api {
if Int(_2!) & Int(1 << 17) != 0 {if let signature = reader.readInt32() {
_44 = Api.parse(reader, signature: signature) as? Api.BotVerification
} }
var _45: Int32?
if Int(_2!) & Int(1 << 18) != 0 {_45 = reader.readInt32() }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
@ -1214,8 +1217,9 @@ public extension Api {
let _c42 = (Int(_2!) & Int(1 << 9) == 0) || _42 != nil
let _c43 = (Int(_2!) & Int(1 << 10) == 0) || _43 != nil
let _c44 = (Int(_2!) & Int(1 << 17) == 0) || _44 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 && _c20 && _c21 && _c22 && _c23 && _c24 && _c25 && _c26 && _c27 && _c28 && _c29 && _c30 && _c31 && _c32 && _c33 && _c34 && _c35 && _c36 && _c37 && _c38 && _c39 && _c40 && _c41 && _c42 && _c43 && _c44 {
return Api.ChatFull.channelFull(flags: _1!, flags2: _2!, id: _3!, about: _4!, participantsCount: _5, adminsCount: _6, kickedCount: _7, bannedCount: _8, onlineCount: _9, readInboxMaxId: _10!, readOutboxMaxId: _11!, unreadCount: _12!, chatPhoto: _13!, notifySettings: _14!, exportedInvite: _15, botInfo: _16!, migratedFromChatId: _17, migratedFromMaxId: _18, pinnedMsgId: _19, stickerset: _20, availableMinId: _21, folderId: _22, linkedChatId: _23, location: _24, slowmodeSeconds: _25, slowmodeNextSendDate: _26, statsDc: _27, pts: _28!, call: _29, ttlPeriod: _30, pendingSuggestions: _31, groupcallDefaultJoinAs: _32, themeEmoticon: _33, requestsPending: _34, recentRequesters: _35, defaultSendAs: _36, availableReactions: _37, reactionsLimit: _38, stories: _39, wallpaper: _40, boostsApplied: _41, boostsUnrestrict: _42, emojiset: _43, botVerification: _44)
let _c45 = (Int(_2!) & Int(1 << 18) == 0) || _45 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 && _c20 && _c21 && _c22 && _c23 && _c24 && _c25 && _c26 && _c27 && _c28 && _c29 && _c30 && _c31 && _c32 && _c33 && _c34 && _c35 && _c36 && _c37 && _c38 && _c39 && _c40 && _c41 && _c42 && _c43 && _c44 && _c45 {
return Api.ChatFull.channelFull(flags: _1!, flags2: _2!, id: _3!, about: _4!, participantsCount: _5, adminsCount: _6, kickedCount: _7, bannedCount: _8, onlineCount: _9, readInboxMaxId: _10!, readOutboxMaxId: _11!, unreadCount: _12!, chatPhoto: _13!, notifySettings: _14!, exportedInvite: _15, botInfo: _16!, migratedFromChatId: _17, migratedFromMaxId: _18, pinnedMsgId: _19, stickerset: _20, availableMinId: _21, folderId: _22, linkedChatId: _23, location: _24, slowmodeSeconds: _25, slowmodeNextSendDate: _26, statsDc: _27, pts: _28!, call: _29, ttlPeriod: _30, pendingSuggestions: _31, groupcallDefaultJoinAs: _32, themeEmoticon: _33, requestsPending: _34, recentRequesters: _35, defaultSendAs: _36, availableReactions: _37, reactionsLimit: _38, stories: _39, wallpaper: _40, boostsApplied: _41, boostsUnrestrict: _42, emojiset: _43, botVerification: _44, stargiftsCount: _45)
}
else {
return nil

View File

@ -171,7 +171,7 @@ func telegramMediaActionFromApiAction(_ action: Api.MessageAction) -> TelegramMe
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)))
case let .messageActionStarGift(flags, apiGift, message, convertStars, upgradeMessageId, upgradeStars):
case let .messageActionStarGift(flags, apiGift, message, convertStars, upgradeMessageId, upgradeStars, fromId, peer):
let text: String?
let entities: [MessageTextEntity]?
switch message {
@ -185,7 +185,7 @@ func telegramMediaActionFromApiAction(_ action: Api.MessageAction) -> TelegramMe
guard let gift = StarGift(apiStarGift: apiGift) else {
return nil
}
return TelegramMediaAction(action: .starGift(gift: gift, convertStars: convertStars, text: text, entities: entities, nameHidden: (flags & (1 << 0)) != 0, savedToProfile: (flags & (1 << 2)) != 0, converted: (flags & (1 << 3)) != 0, upgraded: (flags & (1 << 5)) != 0, canUpgrade: (flags & (1 << 10)) != 0, upgradeStars: upgradeStars, isRefunded: (flags & (1 << 9)) != 0, upgradeMessageId: upgradeMessageId))
return TelegramMediaAction(action: .starGift(gift: gift, convertStars: convertStars, text: text, entities: entities, nameHidden: (flags & (1 << 0)) != 0, savedToProfile: (flags & (1 << 2)) != 0, converted: (flags & (1 << 3)) != 0, upgraded: (flags & (1 << 5)) != 0, canUpgrade: (flags & (1 << 10)) != 0, upgradeStars: upgradeStars, isRefunded: (flags & (1 << 9)) != 0, upgradeMessageId: upgradeMessageId, peerId: peer?.peerId, senderId: fromId.flatMap { EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value($0)) }))
case let .messageActionStarGiftUnique(flags, apiGift, canExportAt, transferStars):
guard let gift = StarGift(apiStarGift: apiGift) else {
return nil

View File

@ -260,6 +260,12 @@ public enum PeerNameColor: Hashable {
}
public struct PeerEmojiStatus: Equatable, Codable {
private enum CodingKeys: String, CodingKey {
case fileId
case content
case expirationDate
}
public enum Content: Equatable, Codable {
private enum CodingKeys: String, CodingKey {
case discriminator
@ -318,6 +324,26 @@ public struct PeerEmojiStatus: Equatable, Codable {
self.content = content
self.expirationDate = expirationDate
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
if let content = try container.decodeIfPresent(Content.self, forKey: .content) {
self.content = content
} else if let fileId = try container.decodeIfPresent(Int64.self, forKey: .fileId) {
self.content = .emoji(fileId: fileId)
} else {
self.content = .emoji(fileId: 0)
}
self.expirationDate = try container.decodeIfPresent(Int32.self, forKey: .expirationDate)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(self.content, forKey: .content)
try container.encodeIfPresent(self.expirationDate, forKey: .expirationDate)
}
}
extension PeerEmojiStatus {

View File

@ -130,7 +130,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
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 prizeStars(amount: Int64, isUnclaimed: Bool, boostPeerId: PeerId?, transactionId: String?, giveawayMessageId: MessageId?)
case starGift(gift: StarGift, convertStars: Int64?, text: String?, entities: [MessageTextEntity]?, nameHidden: Bool, savedToProfile: Bool, converted: Bool, upgraded: Bool, canUpgrade: Bool, upgradeStars: Int64?, isRefunded: Bool, upgradeMessageId: Int32?)
case starGift(gift: StarGift, convertStars: Int64?, text: String?, entities: [MessageTextEntity]?, nameHidden: Bool, savedToProfile: Bool, converted: Bool, upgraded: Bool, canUpgrade: Bool, upgradeStars: Int64?, isRefunded: Bool, upgradeMessageId: Int32?, peerId: EnginePeer.Id?, senderId: EnginePeer.Id?)
case starGiftUnique(gift: StarGift, isUpgrade: Bool, isTransferred: Bool, savedToProfile: Bool, canExportDate: Int32?, transferStars: Int64?, isRefunded: Bool)
public init(decoder: PostboxDecoder) {
@ -253,7 +253,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
}
self = .prizeStars(amount: decoder.decodeInt64ForKey("amount", orElse: 0), isUnclaimed: decoder.decodeBoolForKey("unclaimed", orElse: false), boostPeerId: boostPeerId, transactionId: decoder.decodeOptionalStringForKey("transactionId"), giveawayMessageId: giveawayMessageId)
case 44:
self = .starGift(gift: decoder.decodeObjectForKey("gift", decoder: { StarGift(decoder: $0) }) as! StarGift, convertStars: decoder.decodeOptionalInt64ForKey("convertStars"), text: decoder.decodeOptionalStringForKey("text"), entities: decoder.decodeOptionalObjectArrayWithDecoderForKey("entities"), nameHidden: decoder.decodeBoolForKey("nameHidden", orElse: false), savedToProfile: decoder.decodeBoolForKey("savedToProfile", orElse: false), converted: decoder.decodeBoolForKey("converted", orElse: false), upgraded: decoder.decodeBoolForKey("upgraded", orElse: false), canUpgrade: decoder.decodeBoolForKey("canUpgrade", orElse: false), upgradeStars: decoder.decodeOptionalInt64ForKey("upgradeStars"), isRefunded: decoder.decodeBoolForKey("isRefunded", orElse: false), upgradeMessageId: decoder.decodeOptionalInt32ForKey("upgradeMessageId"))
self = .starGift(gift: decoder.decodeObjectForKey("gift", decoder: { StarGift(decoder: $0) }) as! StarGift, convertStars: decoder.decodeOptionalInt64ForKey("convertStars"), text: decoder.decodeOptionalStringForKey("text"), entities: decoder.decodeOptionalObjectArrayWithDecoderForKey("entities"), nameHidden: decoder.decodeBoolForKey("nameHidden", orElse: false), savedToProfile: decoder.decodeBoolForKey("savedToProfile", orElse: false), converted: decoder.decodeBoolForKey("converted", orElse: false), upgraded: decoder.decodeBoolForKey("upgraded", orElse: false), canUpgrade: decoder.decodeBoolForKey("canUpgrade", orElse: false), upgradeStars: decoder.decodeOptionalInt64ForKey("upgradeStars"), isRefunded: decoder.decodeBoolForKey("isRefunded", orElse: false), upgradeMessageId: decoder.decodeOptionalInt32ForKey("upgradeMessageId"), peerId: decoder.decodeOptionalInt64ForKey("peerId").flatMap { EnginePeer.Id($0) }, senderId: decoder.decodeOptionalInt64ForKey("senderId").flatMap { EnginePeer.Id($0) })
case 45:
self = .starGiftUnique(gift: decoder.decodeObjectForKey("gift", decoder: { StarGift(decoder: $0) }) as! StarGift, isUpgrade: decoder.decodeBoolForKey("isUpgrade", orElse: false), isTransferred: decoder.decodeBoolForKey("isTransferred", orElse: false), savedToProfile: decoder.decodeBoolForKey("savedToProfile", orElse: false), canExportDate: decoder.decodeOptionalInt32ForKey("canExportDate"), transferStars: decoder.decodeOptionalInt64ForKey("transferStars"), isRefunded: decoder.decodeBoolForKey("isRefunded", orElse: false))
default:
@ -548,7 +548,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
} else {
encoder.encodeNil(forKey: "giveawayMsgId")
}
case let .starGift(gift, convertStars, text, entities, nameHidden, savedToProfile, converted, upgraded, canUpgrade, upgradeStars, isRefunded, upgradeMessageId):
case let .starGift(gift, convertStars, text, entities, nameHidden, savedToProfile, converted, upgraded, canUpgrade, upgradeStars, isRefunded, upgradeMessageId, peerId, senderId):
encoder.encodeInt32(44, forKey: "_rawValue")
encoder.encodeObject(gift, forKey: "gift")
if let convertStars {
@ -579,6 +579,16 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
} else {
encoder.encodeNil(forKey: "upgradeMessageId")
}
if let peerId {
encoder.encodeInt64(peerId.toInt64(), forKey: "peerId")
} else {
encoder.encodeNil(forKey: "peerId")
}
if let senderId {
encoder.encodeInt64(senderId.toInt64(), forKey: "senderId")
} else {
encoder.encodeNil(forKey: "senderId")
}
case let .starGiftUnique(gift, isUpgrade, isTransferred, savedToProfile, canExportDate, transferStars, isRefunded):
encoder.encodeInt32(45, forKey: "_rawValue")
encoder.encodeObject(gift, forKey: "gift")

View File

@ -14,8 +14,8 @@ public enum BotPaymentInvoiceSource {
case starsChatSubscription(hash: String)
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)
case starGift(hideName: Bool, includeUpgrade: Bool, peerId: EnginePeer.Id, giftId: Int64, text: String?, entities: [MessageTextEntity]?)
case starGiftUpgrade(keepOriginalInfo: Bool, messageId: EngineMessage.Id)
case starGiftTransfer(messageId: EngineMessage.Id, toPeerId: EnginePeer.Id)
case starGiftUpgrade(keepOriginalInfo: Bool, reference: StarGiftReference)
case starGiftTransfer(reference: StarGiftReference, toPeerId: EnginePeer.Id)
}
public struct BotPaymentInvoiceFields: OptionSet {
@ -360,7 +360,7 @@ func _internal_parseInputInvoice(transaction: Transaction, source: BotPaymentInv
}
return .inputInvoiceStars(purpose: .inputStorePaymentStarsGiveaway(flags: flags, stars: stars, boostPeer: apiBoostPeer, additionalPeers: additionalPeers, countriesIso2: countries, prizeDescription: prizeDescription, randomId: randomId, untilDate: untilDate, currency: currency, amount: amount, users: users))
case let .starGift(hideName, includeUpgrade, peerId, giftId, text, entities):
guard let peer = transaction.getPeer(peerId), let inputUser = apiInputUser(peer) else {
guard let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) else {
return nil
}
var flags: Int32 = 0
@ -375,18 +375,18 @@ func _internal_parseInputInvoice(transaction: Transaction, source: BotPaymentInv
flags |= (1 << 1)
message = .textWithEntities(text: text, entities: entities.flatMap { apiEntitiesFromMessageTextEntities($0, associatedPeers: SimpleDictionary()) } ?? [])
}
return .inputInvoiceStarGift(flags: flags, userId: inputUser, giftId: giftId, message: message)
case let .starGiftUpgrade(keepOriginalInfo, messageId):
return .inputInvoiceStarGift(flags: flags, peer: inputPeer, giftId: giftId, message: message)
case let .starGiftUpgrade(keepOriginalInfo, reference):
var flags: Int32 = 0
if keepOriginalInfo {
flags |= (1 << 0)
}
return .inputInvoiceStarGiftUpgrade(flags: flags, msgId: messageId.id)
case let .starGiftTransfer(messageId, toPeerId):
guard let peer = transaction.getPeer(toPeerId), let inputUser = apiInputUser(peer) else {
return reference.apiStarGiftReference(transaction: transaction).flatMap { .inputInvoiceStarGiftUpgrade(flags: flags, stargift: $0) }
case let .starGiftTransfer(reference, toPeerId):
guard let peer = transaction.getPeer(toPeerId), let inputPeer = apiInputPeer(peer) else {
return nil
}
return .inputInvoiceStarGiftTransfer(msgId: messageId.id, toId: inputUser)
return reference.apiStarGiftReference(transaction: transaction).flatMap { .inputInvoiceStarGiftTransfer(stargift: $0, toId: inputPeer) }
}
}

View File

@ -668,59 +668,78 @@ func managedStarGiftsUpdates(postbox: Postbox, network: Network) -> Signal<Never
return (poll |> then(.complete() |> suspendAwareDelay(1.0 * 60.0 * 60.0, queue: Queue.concurrentDefaultQueue()))) |> restart
}
func _internal_convertStarGift(account: Account, messageId: EngineMessage.Id) -> Signal<Never, NoError> {
return account.network.request(Api.functions.payments.convertStarGift(msgId: messageId.id))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.Bool?, NoError> in
return .single(nil)
func _internal_convertStarGift(account: Account, reference: StarGiftReference) -> Signal<Never, NoError> {
return account.postbox.transaction { transaction in
return reference.apiStarGiftReference(transaction: transaction)
}
|> mapToSignal { result in
if let result, case .boolTrue = result {
return account.postbox.transaction { transaction -> Void in
transaction.updatePeerCachedData(peerIds: Set([account.peerId]), update: { _, cachedData -> CachedPeerData? in
if let cachedData = cachedData as? CachedUserData, let starGiftsCount = cachedData.starGiftsCount {
var updatedData = cachedData
updatedData = updatedData.withUpdatedStarGiftsCount(max(0, starGiftsCount - 1))
return updatedData
} else {
return cachedData
}
})
}
|> mapToSignal { starGift in
guard let starGift else {
return .complete()
}
return .complete()
return account.network.request(Api.functions.payments.convertStarGift(stargift: starGift))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.Bool?, NoError> in
return .single(nil)
}
|> mapToSignal { result in
if let result, case .boolTrue = result {
return account.postbox.transaction { transaction -> Void in
transaction.updatePeerCachedData(peerIds: Set([account.peerId]), update: { _, cachedData -> CachedPeerData? in
if let cachedData = cachedData as? CachedUserData, let starGiftsCount = cachedData.starGiftsCount {
var updatedData = cachedData
updatedData = updatedData.withUpdatedStarGiftsCount(max(0, starGiftsCount - 1))
return updatedData
} else {
return cachedData
}
})
}
}
return .complete()
}
|> ignoreValues
}
|> ignoreValues
}
func _internal_updateStarGiftAddedToProfile(account: Account, messageId: EngineMessage.Id, added: Bool) -> Signal<Never, NoError> {
func _internal_updateStarGiftAddedToProfile(account: Account, reference: StarGiftReference, added: Bool) -> Signal<Never, NoError> {
var flags: Int32 = 0
if !added {
flags |= (1 << 0)
}
return account.network.request(Api.functions.payments.saveStarGift(flags: flags, msgId: messageId.id))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.Bool?, NoError> in
return .single(nil)
return account.postbox.transaction { transaction in
return reference.apiStarGiftReference(transaction: transaction)
}
|> mapToSignal { starGift in
guard let starGift else {
return .complete()
}
return account.network.request(Api.functions.payments.saveStarGift(flags: flags, stargift: starGift))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.Bool?, NoError> in
return .single(nil)
}
|> ignoreValues
}
|> ignoreValues
}
public enum TransferStarGiftError {
case generic
}
func _internal_transferStarGift(account: Account, prepaid: Bool, messageId: EngineMessage.Id, peerId: EnginePeer.Id) -> Signal<Never, TransferStarGiftError> {
return account.postbox.transaction { transaction -> Api.InputUser? in
return transaction.getPeer(peerId).flatMap(apiInputUser)
func _internal_transferStarGift(account: Account, prepaid: Bool, reference: StarGiftReference, peerId: EnginePeer.Id) -> Signal<Never, TransferStarGiftError> {
return account.postbox.transaction { transaction -> (Api.InputUser, Api.InputSavedStarGift)? in
guard let inputUser = transaction.getPeer(peerId).flatMap(apiInputUser), let starGift = reference.apiStarGiftReference(transaction: transaction) else {
return nil
}
return (inputUser, starGift)
}
|> castError(TransferStarGiftError.self)
|> mapToSignal { inputUser -> Signal<Never, TransferStarGiftError> in
guard let inputUser else {
|> mapToSignal { inputUserAndStarGift -> Signal<Never, TransferStarGiftError> in
guard let (inputUser, starGift) = inputUserAndStarGift else {
return .complete()
}
if prepaid {
return account.network.request(Api.functions.payments.transferStarGift(msgId: messageId.id, toId: inputUser))
return account.network.request(Api.functions.payments.transferStarGift(stargift: starGift, toId: inputUser))
|> mapError { _ -> TransferStarGiftError in
return .generic
}
@ -730,7 +749,7 @@ func _internal_transferStarGift(account: Account, prepaid: Bool, messageId: Engi
}
|> ignoreValues
} else {
let source: BotPaymentInvoiceSource = .starGiftTransfer(messageId: messageId, toPeerId: peerId)
let source: BotPaymentInvoiceSource = .starGiftTransfer(reference: reference, toPeerId: peerId)
return _internal_fetchBotPaymentForm(accountPeerId: account.peerId, postbox: account.postbox, network: account.network, source: source, themeParams: nil)
|> map(Optional.init)
|> `catch` { error -> Signal<BotPaymentForm?, TransferStarGiftError> in
@ -747,7 +766,7 @@ func _internal_transferStarGift(account: Account, prepaid: Bool, messageId: Engi
}
|> ignoreValues
} else {
return _internal_transferStarGift(account: account, prepaid: true, messageId: messageId, peerId: peerId)
return _internal_transferStarGift(account: account, prepaid: true, reference: reference, peerId: peerId)
}
}
}
@ -758,9 +777,9 @@ public enum UpgradeStarGiftError {
case generic
}
func _internal_upgradeStarGift(account: Account, formId: Int64?, messageId: EngineMessage.Id, keepOriginalInfo: Bool) -> Signal<ProfileGiftsContext.State.StarGift, UpgradeStarGiftError> {
func _internal_upgradeStarGift(account: Account, formId: Int64?, reference: StarGiftReference, keepOriginalInfo: Bool) -> Signal<ProfileGiftsContext.State.StarGift, UpgradeStarGiftError> {
if let formId {
let source: BotPaymentInvoiceSource = .starGiftUpgrade(keepOriginalInfo: keepOriginalInfo, messageId: messageId)
let source: BotPaymentInvoiceSource = .starGiftUpgrade(keepOriginalInfo: keepOriginalInfo, reference: reference)
return _internal_sendStarsPaymentForm(account: account, formId: formId, source: source)
|> mapError { _ -> UpgradeStarGiftError in
return .generic
@ -777,41 +796,51 @@ func _internal_upgradeStarGift(account: Account, formId: Int64?, messageId: Engi
if keepOriginalInfo {
flags |= (1 << 0)
}
return account.network.request(Api.functions.payments.upgradeStarGift(flags: flags, msgId: messageId.id))
|> mapError { _ -> UpgradeStarGiftError in
return .generic
return account.postbox.transaction { transaction in
return reference.apiStarGiftReference(transaction: transaction)
}
|> mapToSignal { updates in
account.stateManager.addUpdates(updates)
for update in updates.allUpdates {
switch update {
case let .updateNewMessage(message, _, _):
if let message = StoreMessage(apiMessage: message, accountPeerId: account.peerId, peerIsForum: false) {
for media in message.media {
if let action = media as? TelegramMediaAction, case let .starGiftUnique(gift, _, _, savedToProfile, canExportDate, transferStars, _) = action.action, case let .Id(messageId) = message.id {
return .single(ProfileGiftsContext.State.StarGift(
gift: gift,
fromPeer: nil,
date: message.timestamp,
text: nil,
entities: nil,
messageId: messageId,
nameHidden: false,
savedToProfile: savedToProfile,
convertStars: nil,
canUpgrade: false,
canExportDate: canExportDate,
upgradeStars: nil,
transferStars: transferStars
))
|> castError(UpgradeStarGiftError.self)
|> mapToSignal { starGift in
guard let starGift else {
return .fail(.generic)
}
return account.network.request(Api.functions.payments.upgradeStarGift(flags: flags, stargift: starGift))
|> mapError { _ -> UpgradeStarGiftError in
return .generic
}
|> mapToSignal { updates in
account.stateManager.addUpdates(updates)
for update in updates.allUpdates {
switch update {
case let .updateNewMessage(message, _, _):
if let message = StoreMessage(apiMessage: message, accountPeerId: account.peerId, peerIsForum: false) {
for media in message.media {
if let action = media as? TelegramMediaAction, case let .starGiftUnique(gift, _, _, savedToProfile, canExportDate, transferStars, _) = action.action, case let .Id(messageId) = message.id {
let _ = messageId
return .single(ProfileGiftsContext.State.StarGift(
gift: gift,
reference: reference,
fromPeer: nil,
date: message.timestamp,
text: nil,
entities: nil,
nameHidden: false,
savedToProfile: savedToProfile,
convertStars: nil,
canUpgrade: false,
canExportDate: canExportDate,
upgradeStars: nil,
transferStars: transferStars
))
}
}
}
default:
break
}
default:
break
}
return .fail(.generic)
}
return .fail(.generic)
}
}
}
@ -937,16 +966,17 @@ private final class ProfileGiftsContextImpl {
self.dataState = .loading
self.pushState()
let signal: Signal<([ProfileGiftsContext.State.StarGift], Int32, String?), NoError> = self.account.postbox.transaction { transaction -> Api.InputUser? in
return transaction.getPeer(peerId).flatMap(apiInputUser)
let signal: Signal<([ProfileGiftsContext.State.StarGift], Int32, String?), NoError> = self.account.postbox.transaction { transaction -> Api.InputPeer? in
return transaction.getPeer(peerId).flatMap(apiInputPeer)
}
|> mapToSignal { inputUser -> Signal<([ProfileGiftsContext.State.StarGift], Int32, String?), NoError> in
guard let inputUser else {
|> mapToSignal { inputPeer -> Signal<([ProfileGiftsContext.State.StarGift], Int32, String?), NoError> in
guard let inputPeer else {
return .single(([], 0, nil))
}
return network.request(Api.functions.payments.getUserStarGifts(userId: inputUser, offset: initialNextOffset ?? "", limit: 32))
let flags: Int32 = 0
return network.request(Api.functions.payments.getSavedStarGifts(flags: flags, peer: inputPeer, offset: initialNextOffset ?? "", limit: 32))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.payments.UserStarGifts?, NoError> in
|> `catch` { _ -> Signal<Api.payments.SavedStarGifts?, NoError> in
return .single(nil)
}
|> mapToSignal { result -> Signal<([ProfileGiftsContext.State.StarGift], Int32, String?), NoError> in
@ -955,11 +985,11 @@ private final class ProfileGiftsContextImpl {
}
return postbox.transaction { transaction -> ([ProfileGiftsContext.State.StarGift], Int32, String?) in
switch result {
case let .userStarGifts(_, count, apiGifts, nextOffset, users):
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: [], users: users)
case let .savedStarGifts(_, count, apiGifts, nextOffset, chats, users):
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
let gifts = apiGifts.compactMap { ProfileGiftsContext.State.StarGift(apiUserStarGift: $0, transaction: transaction) }
let gifts = apiGifts.compactMap { ProfileGiftsContext.State.StarGift(apiSavedStarGift: $0, peerId: peerId, transaction: transaction) }
return (gifts, count, nextOffset)
}
}
@ -993,50 +1023,50 @@ private final class ProfileGiftsContextImpl {
}
}
func updateStarGiftAddedToProfile(messageId: EngineMessage.Id, added: Bool) {
func updateStarGiftAddedToProfile(reference: StarGiftReference, added: Bool) {
self.actionDisposable.set(
_internal_updateStarGiftAddedToProfile(account: self.account, messageId: messageId, added: added).startStrict()
_internal_updateStarGiftAddedToProfile(account: self.account, reference: reference, added: added).startStrict()
)
if let index = self.gifts.firstIndex(where: { $0.messageId == messageId }) {
if let index = self.gifts.firstIndex(where: { $0.reference == reference }) {
self.gifts[index] = self.gifts[index].withSavedToProfile(added)
}
self.pushState()
}
func convertStarGift(messageId: EngineMessage.Id) {
func convertStarGift(reference: StarGiftReference) {
self.actionDisposable.set(
_internal_convertStarGift(account: self.account, messageId: messageId).startStrict()
_internal_convertStarGift(account: self.account, reference: reference).startStrict()
)
if let count = self.count {
self.count = max(0, count - 1)
}
self.gifts.removeAll(where: { $0.messageId == messageId })
self.gifts.removeAll(where: { $0.reference == reference })
self.pushState()
}
func transferStarGift(prepaid: Bool, messageId: EngineMessage.Id, peerId: EnginePeer.Id) {
func transferStarGift(prepaid: Bool, reference: StarGiftReference, peerId: EnginePeer.Id) {
self.actionDisposable.set(
_internal_transferStarGift(account: self.account, prepaid: prepaid, messageId: messageId, peerId: peerId).startStrict()
_internal_transferStarGift(account: self.account, prepaid: prepaid, reference: reference, peerId: peerId).startStrict()
)
if let count = self.count {
self.count = max(0, count - 1)
}
self.gifts.removeAll(where: { $0.messageId == messageId })
self.gifts.removeAll(where: { $0.reference == reference })
self.pushState()
}
func upgradeStarGift(formId: Int64?, messageId: EngineMessage.Id, keepOriginalInfo: Bool) -> Signal<ProfileGiftsContext.State.StarGift, UpgradeStarGiftError> {
func upgradeStarGift(formId: Int64?, reference: StarGiftReference, keepOriginalInfo: Bool) -> Signal<ProfileGiftsContext.State.StarGift, UpgradeStarGiftError> {
return Signal { [weak self] subscriber in
guard let self else {
return EmptyDisposable
}
let disposable = MetaDisposable()
disposable.set(
_internal_upgradeStarGift(account: self.account, formId: formId, messageId: messageId, keepOriginalInfo: keepOriginalInfo).startStrict(next: { [weak self] result in
_internal_upgradeStarGift(account: self.account, formId: formId, reference: reference, keepOriginalInfo: keepOriginalInfo).startStrict(next: { [weak self] result in
guard let self else {
return
}
if let index = self.gifts.firstIndex(where: { $0.messageId == messageId }) {
if let index = self.gifts.firstIndex(where: { $0.reference == reference }) {
self.gifts[index] = result
self.pushState()
}
@ -1062,6 +1092,7 @@ public final class ProfileGiftsContext {
public struct StarGift: Equatable, Codable {
enum CodingKeys: String, CodingKey {
case gift
case reference
case fromPeerId
case date
case text
@ -1077,11 +1108,11 @@ public final class ProfileGiftsContext {
}
public let gift: TelegramCore.StarGift
public let reference: StarGiftReference
public let fromPeer: EnginePeer?
public let date: Int32
public let text: String?
public let entities: [MessageTextEntity]?
public let messageId: EngineMessage.Id?
public let nameHidden: Bool
public let savedToProfile: Bool
public let convertStars: Int64?
@ -1092,13 +1123,17 @@ public final class ProfileGiftsContext {
fileprivate let _fromPeerId: EnginePeer.Id?
public enum DecodingError: Error {
case generic
}
public init (
gift: TelegramCore.StarGift,
reference: StarGiftReference,
fromPeer: EnginePeer?,
date: Int32,
text: String?,
entities: [MessageTextEntity]?,
messageId: EngineMessage.Id?,
nameHidden: Bool,
savedToProfile: Bool,
convertStars: Int64?,
@ -1108,12 +1143,12 @@ public final class ProfileGiftsContext {
transferStars: Int64?
) {
self.gift = gift
self.reference = reference
self.fromPeer = fromPeer
self._fromPeerId = fromPeer?.id
self.date = date
self.text = text
self.entities = entities
self.messageId = messageId
self.nameHidden = nameHidden
self.savedToProfile = savedToProfile
self.convertStars = convertStars
@ -1127,12 +1162,18 @@ public final class ProfileGiftsContext {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.gift = try container.decode(TelegramCore.StarGift.self, forKey: .gift)
if let reference = try container.decodeIfPresent(StarGiftReference.self, forKey: .reference) {
self.reference = reference
} else if let messageId = try container.decodeIfPresent(EngineMessage.Id.self, forKey: .messageId) {
self.reference = .message(messageId: messageId)
} else {
throw DecodingError.generic
}
self.fromPeer = nil
self._fromPeerId = try container.decodeIfPresent(EnginePeer.Id.self, forKey: .fromPeerId)
self.date = try container.decode(Int32.self, forKey: .date)
self.text = try container.decodeIfPresent(String.self, forKey: .text)
self.entities = try container.decodeIfPresent([MessageTextEntity].self, forKey: .entities)
self.messageId = try container.decodeIfPresent(EngineMessage.Id.self, forKey: .messageId)
self.nameHidden = try container.decode(Bool.self, forKey: .nameHidden)
self.savedToProfile = try container.decode(Bool.self, forKey: .savedToProfile)
self.convertStars = try container.decodeIfPresent(Int64.self, forKey: .convertStars)
@ -1146,11 +1187,11 @@ public final class ProfileGiftsContext {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(self.gift, forKey: .gift)
try container.encode(self.reference, forKey: .reference)
try container.encodeIfPresent(self.fromPeer?.id, forKey: .fromPeerId)
try container.encode(self.date, forKey: .date)
try container.encodeIfPresent(self.text, forKey: .text)
try container.encodeIfPresent(self.entities, forKey: .entities)
try container.encodeIfPresent(self.messageId, forKey: .messageId)
try container.encode(self.nameHidden, forKey: .nameHidden)
try container.encode(self.savedToProfile, forKey: .savedToProfile)
try container.encodeIfPresent(self.convertStars, forKey: .convertStars)
@ -1163,11 +1204,11 @@ public final class ProfileGiftsContext {
public func withSavedToProfile(_ savedToProfile: Bool) -> StarGift {
return StarGift(
gift: self.gift,
reference: self.reference,
fromPeer: self.fromPeer,
date: self.date,
text: self.text,
entities: self.entities,
messageId: self.messageId,
nameHidden: self.nameHidden,
savedToProfile: savedToProfile,
convertStars: self.convertStars,
@ -1181,11 +1222,11 @@ public final class ProfileGiftsContext {
fileprivate func withFromPeer(_ fromPeer: EnginePeer?) -> StarGift {
return StarGift(
gift: self.gift,
reference: self.reference,
fromPeer: fromPeer,
date: self.date,
text: self.text,
entities: self.entities,
messageId: self.messageId,
nameHidden: self.nameHidden,
savedToProfile: savedToProfile,
convertStars: self.convertStars,
@ -1237,29 +1278,29 @@ public final class ProfileGiftsContext {
}
}
public func updateStarGiftAddedToProfile(messageId: EngineMessage.Id, added: Bool) {
public func updateStarGiftAddedToProfile(reference: StarGiftReference, added: Bool) {
self.impl.with { impl in
impl.updateStarGiftAddedToProfile(messageId: messageId, added: added)
impl.updateStarGiftAddedToProfile(reference: reference, added: added)
}
}
public func convertStarGift(messageId: EngineMessage.Id) {
public func convertStarGift(reference: StarGiftReference) {
self.impl.with { impl in
impl.convertStarGift(messageId: messageId)
impl.convertStarGift(reference: reference)
}
}
public func transferStarGift(prepaid: Bool, messageId: EngineMessage.Id, peerId: EnginePeer.Id) {
public func transferStarGift(prepaid: Bool, reference: StarGiftReference, peerId: EnginePeer.Id) {
self.impl.with { impl in
impl.transferStarGift(prepaid: prepaid, messageId: messageId, peerId: peerId)
impl.transferStarGift(prepaid: prepaid, reference: reference, peerId: peerId)
}
}
public func upgradeStarGift(formId: Int64?, messageId: EngineMessage.Id, keepOriginalInfo: Bool) -> Signal<ProfileGiftsContext.State.StarGift, UpgradeStarGiftError> {
public func upgradeStarGift(formId: Int64?, reference: StarGiftReference, keepOriginalInfo: Bool) -> Signal<ProfileGiftsContext.State.StarGift, UpgradeStarGiftError> {
return Signal { subscriber in
let disposable = MetaDisposable()
self.impl.with { impl in
disposable.set(impl.upgradeStarGift(formId: formId, messageId: messageId, keepOriginalInfo: keepOriginalInfo).start(next: { value in
disposable.set(impl.upgradeStarGift(formId: formId, reference: reference, keepOriginalInfo: keepOriginalInfo).start(next: { value in
subscriber.putNext(value)
}, error: { error in
subscriber.putError(error)
@ -1281,9 +1322,9 @@ public final class ProfileGiftsContext {
}
extension ProfileGiftsContext.State.StarGift {
init?(apiUserStarGift: Api.UserStarGift, transaction: Transaction) {
switch apiUserStarGift {
case let .userStarGift(flags, fromId, date, apiGift, message, msgId, convertStars, upgradeStars, canExportDate, transferStars):
init?(apiSavedStarGift: Api.SavedStarGift, peerId: EnginePeer.Id, transaction: Transaction) {
switch apiSavedStarGift {
case let .savedStarGift(flags, fromId, date, apiGift, message, msgId, savedId, convertStars, upgradeStars, canExportDate, transferStars):
guard let gift = StarGift(apiStarGift: apiGift) else {
return nil
}
@ -1306,16 +1347,18 @@ extension ProfileGiftsContext.State.StarGift {
self.text = nil
self.entities = nil
}
if let msgId {
if let savedId {
self.reference = .peer(peerId: peerId, id: savedId)
} else if let msgId {
if let fromPeer = self.fromPeer {
self.messageId = EngineMessage.Id(peerId: fromPeer.id, namespace: Namespaces.Message.Cloud, id: msgId)
self.reference = .message(messageId: EngineMessage.Id(peerId: fromPeer.id, namespace: Namespaces.Message.Cloud, id: msgId))
} else if case .unique = gift {
self.messageId = EngineMessage.Id(peerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(0)), namespace: Namespaces.Message.Cloud, id: msgId)
self.reference = .message(messageId: EngineMessage.Id(peerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(0)), namespace: Namespaces.Message.Cloud, id: msgId))
} else {
self.messageId = nil
return nil
}
} else {
self.messageId = nil
return nil
}
self.nameHidden = (flags & (1 << 0)) != 0
self.savedToProfile = (flags & (1 << 5)) == 0
@ -1380,3 +1423,61 @@ func _internal_getUniqueStarGift(account: Account, slug: String) -> Signal<StarG
}
}
}
public enum StarGiftReference: Equatable, Hashable, Codable {
enum CodingKeys: String, CodingKey {
case type
case messageId
case peerId
case id
}
case message(messageId: EngineMessage.Id)
case peer(peerId: EnginePeer.Id, id: Int64)
public enum DecodingError: Error {
case generic
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let type = try container.decode(Int32.self, forKey: .type)
switch type {
case 0:
self = .message(messageId: try container.decode(EngineMessage.Id.self, forKey: .messageId))
case 1:
self = .peer(peerId: try container.decode(EnginePeer.Id.self, forKey: .peerId), id: try container.decode(Int64.self, forKey: .id))
default:
throw DecodingError.generic
}
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
switch self {
case let .message(messageId):
try container.encode(0 as Int32, forKey: .type)
try container.encode(messageId, forKey: .messageId)
case let .peer(peerId, id):
try container.encode(1 as Int32, forKey: .type)
try container.encode(peerId, forKey: .peerId)
try container.encode(id, forKey: .id)
}
}
}
extension StarGiftReference {
func apiStarGiftReference(transaction: Transaction) -> Api.InputSavedStarGift? {
switch self {
case let .message(messageId):
return .inputSavedStarGiftUser(msgId: messageId.id)
case let .peer(peerId, id):
guard let inputPeer = transaction.getPeer(peerId).flatMap({ apiInputPeer($0) }) else {
return nil
}
return .inputSavedStarGiftChat(peer: inputPeer, savedId: id)
}
}
}

View File

@ -1467,11 +1467,11 @@ func _internal_sendStarsPaymentForm(account: Account, formId: Int64, source: Bot
} else if case let .starGiftUnique(gift, _, _, savedToProfile, canExportDate, transferStars, _) = action.action, case let .Id(messageId) = message.id {
resultGift = ProfileGiftsContext.State.StarGift(
gift: gift,
reference: .message(messageId: messageId),
fromPeer: nil,
date: message.timestamp,
text: nil,
entities: nil,
messageId: messageId,
nameHidden: false,
savedToProfile: savedToProfile,
convertStars: nil,

View File

@ -113,20 +113,20 @@ public extension TelegramEngine {
return _internal_keepCachedStarGiftsUpdated(postbox: self.account.postbox, network: self.account.network)
}
public func convertStarGift(messageId: EngineMessage.Id) -> Signal<Never, NoError> {
return _internal_convertStarGift(account: self.account, messageId: messageId)
public func convertStarGift(reference: StarGiftReference) -> Signal<Never, NoError> {
return _internal_convertStarGift(account: self.account, reference: reference)
}
public func updateStarGiftAddedToProfile(messageId: EngineMessage.Id, added: Bool) -> Signal<Never, NoError> {
return _internal_updateStarGiftAddedToProfile(account: self.account, messageId: messageId, added: added)
public func updateStarGiftAddedToProfile(reference: StarGiftReference, added: Bool) -> Signal<Never, NoError> {
return _internal_updateStarGiftAddedToProfile(account: self.account, reference: reference, added: added)
}
public func transferStarGift(prepaid: Bool, messageId: EngineMessage.Id, peerId: EnginePeer.Id) -> Signal<Never, TransferStarGiftError> {
return _internal_transferStarGift(account: self.account, prepaid: prepaid, messageId: messageId, peerId: peerId)
public func transferStarGift(prepaid: Bool, reference: StarGiftReference, peerId: EnginePeer.Id) -> Signal<Never, TransferStarGiftError> {
return _internal_transferStarGift(account: self.account, prepaid: prepaid, reference: reference, peerId: peerId)
}
public func upgradeStarGift(formId: Int64?, messageId: EngineMessage.Id, keepOriginalInfo: Bool) -> Signal<ProfileGiftsContext.State.StarGift, UpgradeStarGiftError> {
return _internal_upgradeStarGift(account: self.account, formId: formId, messageId: messageId, keepOriginalInfo: keepOriginalInfo)
public func upgradeStarGift(formId: Int64?, reference: StarGiftReference, keepOriginalInfo: Bool) -> Signal<ProfileGiftsContext.State.StarGift, UpgradeStarGiftError> {
return _internal_upgradeStarGift(account: self.account, formId: formId, reference: reference, keepOriginalInfo: keepOriginalInfo)
}
public func starGiftUpgradePreview(giftId: Int64) -> Signal<[StarGift.UniqueGift.Attribute], NoError> {

View File

@ -582,14 +582,14 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee
switch result {
case let .chatFull(fullChat, chats, users):
switch fullChat {
case let .channelFull(_, _, _, _, _, _, _, _, _, _, _, _, _, notifySettings, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
case let .channelFull(_, _, _, _, _, _, _, _, _, _, _, _, _, notifySettings, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
transaction.updateCurrentPeerNotificationSettings([peerId: TelegramPeerNotificationSettings(apiSettings: notifySettings)])
case .chatFull:
break
}
switch fullChat {
case let .channelFull(flags, flags2, _, about, participantsCount, adminsCount, kickedCount, bannedCount, _, _, _, _, chatPhoto, _, apiExportedInvite, apiBotInfos, migratedFromChatId, migratedFromMaxId, pinnedMsgId, stickerSet, minAvailableMsgId, _, linkedChatId, location, slowmodeSeconds, slowmodeNextSendDate, statsDc, _, inputCall, ttl, pendingSuggestions, groupcallDefaultJoinAs, themeEmoticon, requestsPending, _, defaultSendAs, allowedReactions, reactionsLimit, _, wallpaper, appliedBoosts, boostsUnrestrict, emojiSet, verification):
case let .channelFull(flags, flags2, _, about, participantsCount, adminsCount, kickedCount, bannedCount, _, _, _, _, chatPhoto, _, apiExportedInvite, apiBotInfos, migratedFromChatId, migratedFromMaxId, pinnedMsgId, stickerSet, minAvailableMsgId, _, linkedChatId, location, slowmodeSeconds, slowmodeNextSendDate, statsDc, _, inputCall, ttl, pendingSuggestions, groupcallDefaultJoinAs, themeEmoticon, requestsPending, _, defaultSendAs, allowedReactions, reactionsLimit, _, wallpaper, appliedBoosts, boostsUnrestrict, emojiSet, verification, _):
var channelFlags = CachedChannelFlags()
if (flags & (1 << 3)) != 0 {
channelFlags.insert(.canDisplayParticipants)

View File

@ -1066,7 +1066,7 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
attributedString = mutableString
case .prizeStars:
attributedString = NSAttributedString(string: strings.Notification_StarsPrize, font: titleFont, textColor: primaryTextColor)
case let .starGift(gift, _, text, entities, _, _, _, _, _, upgradeStars, _, _):
case let .starGift(gift, _, text, entities, _, _, _, _, _, upgradeStars, _, _, _, _):
if !forAdditionalServiceMessage {
if let text {
let mutableAttributedString = NSMutableAttributedString(attributedString: stringWithAppliedEntities(text, entities: entities ?? [], baseColor: primaryTextColor, linkColor: primaryTextColor, baseFont: titleFont, linkFont: titleBoldFont, boldFont: titleBoldFont, italicFont: titleFont, boldItalicFont: titleBoldFont, fixedFont: titleFont, blockQuoteFont: titleFont, underlineLinks: false, message: message._asMessage()))

View File

@ -23,6 +23,7 @@ swift_library(
"//submodules/TelegramUI/Components/Chat/ChatInputPanelNode",
"//submodules/AccountContext",
"//submodules/TelegramUI/Components/PeerManagement/OldChannelsController",
"//submodules/TooltipUI",
],
visibility = [
"//visibility:public",

View File

@ -469,12 +469,13 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
buttonTitle = item.presentationData.strings.Notification_PremiumPrize_View
hasServiceMessage = false
}
case let .starGift(gift, convertStars, giftText, giftEntities, _, savedToProfile, converted, upgraded, canUpgrade, upgradeStars, isRefunded, _):
case let .starGift(gift, convertStars, giftText, giftEntities, _, savedToProfile, converted, upgraded, canUpgrade, upgradeStars, isRefunded, _, _, _):
if case let .generic(gift) = gift {
isStarGift = true
let authorName = item.message.author.flatMap { EnginePeer($0) }?.compactDisplayTitle ?? ""
let isSelfGift = item.message.id.peerId == item.context.account.peerId
let isChannelGift = item.message.id.peerId.namespace == Namespaces.Peer.CloudChannel
if isSelfGift {
title = item.presentationData.strings.Notification_StarGift_Self_Title
} else {
@ -503,9 +504,13 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
}
} else {
if let convertStars, convertStars > 0 {
text = item.presentationData.strings.Notification_StarGift_Subtitle(item.presentationData.strings.Notification_StarGift_Subtitle_Stars(Int32(convertStars))).string
if isChannelGift {
text = item.presentationData.strings.Notification_StarGift_Subtitle_Channel(item.presentationData.strings.Notification_StarGift_Subtitle_Stars(Int32(convertStars))).string
} else {
text = item.presentationData.strings.Notification_StarGift_Subtitle(item.presentationData.strings.Notification_StarGift_Subtitle_Stars(Int32(convertStars))).string
}
} else {
text = item.presentationData.strings.Notification_StarGift_Bot_Subtitle
text = item.presentationData.strings.Notification_StarGift_Bot_Subtitle
}
}
} else {

View File

@ -282,111 +282,112 @@ public final class ChatMessageWebpageBubbleContentNode: ChatMessageBubbleContent
let themeMimeType = "application/x-tgtheme-ios"
if let file = mainMedia as? TelegramMediaFile, webpage.type != "telegram_theme" {
if let embedUrl = webpage.embedUrl, !embedUrl.isEmpty {
if automaticPlayback {
mediaAndFlags = ([file], [.preferMediaBeforeText])
} else {
mediaAndFlags = ([webpage.image ?? file], [.preferMediaBeforeText])
}
} else if webpage.type == "telegram_background" {
var colors: [UInt32] = []
var rotation: Int32?
var intensity: Int32?
if let wallpaper = parseWallpaperUrl(sharedContext: item.context.sharedContext, url: webpage.url), case let .slug(_, _, colorsValue, intensityValue, rotationValue) = wallpaper {
switch webpage.type {
case "telegram_background":
var colors: [UInt32] = []
var rotation: Int32?
if let wallpaper = parseWallpaperUrl(sharedContext: item.context.sharedContext, url: webpage.url) {
if case let .color(color) = wallpaper {
colors = [color.rgb]
} else if case let .gradient(colorsValue, rotationValue) = wallpaper {
colors = colorsValue
rotation = rotationValue
intensity = intensityValue
}
let media = WallpaperPreviewMedia(content: .file(file: file, colors: colors, rotation: rotation, intensity: intensity, false, false))
mediaAndFlags = ([media], [.preferMediaAspectFilled])
if let fileSize = file.size {
badge = dataSizeString(fileSize, formatting: DataSizeStringFormatting(chatPresentationData: item.presentationData))
}
} else {
mediaAndFlags = ([file], [])
}
} else if let image = mainMedia as? TelegramMediaImage {
if let type = webpage.type, ["photo", "video", "embed", "gif", "document", "telegram_album"].contains(type) {
var flags = ChatMessageAttachedContentNodeMediaFlags()
if webpage.instantPage != nil, let largest = largestImageRepresentation(image.representations) {
if largest.dimensions.width >= 256 {
flags.insert(.preferMediaBeforeText)
var content: WallpaperPreviewMediaContent?
if !colors.isEmpty {
if colors.count >= 2 {
content = .gradient(colors, rotation)
} else {
content = .color(UIColor(rgb: colors[0]))
}
}
if let content = content {
let media = WallpaperPreviewMedia(content: content)
mediaAndFlags = ([media], [])
}
case "telegram_theme":
var file: TelegramMediaFile?
var settings: TelegramThemeSettings?
var isSupported = false
for attribute in webpage.attributes {
if case let .theme(attribute) = attribute {
if let attributeSettings = attribute.settings {
settings = attributeSettings
isSupported = true
} else if let filteredFile = attribute.files.filter({ $0.mimeType == themeMimeType }).first {
file = filteredFile
isSupported = true
}
} else if let embedUrl = webpage.embedUrl, !embedUrl.isEmpty {
flags.insert(.preferMediaBeforeText)
}
mediaAndFlags = ([image], flags)
} else if let _ = largestImageRepresentation(image.representations)?.dimensions {
let flags = ChatMessageAttachedContentNodeMediaFlags()
mediaAndFlags = ([image], flags)
}
} else if let story = mainMedia as? TelegramMediaStory {
mediaAndFlags = ([story], [.preferMediaBeforeText, .titleBeforeMedia])
if let storyItem = item.message.associatedStories[story.storyId]?.get(Stories.StoredItem.self), case let .item(itemValue) = storyItem {
text = itemValue.text
entities = itemValue.entities
if !isSupported, let contentFile = webpage.file {
isSupported = true
file = contentFile
}
} else if let type = webpage.type {
if type == "telegram_background" {
var colors: [UInt32] = []
var rotation: Int32?
if let wallpaper = parseWallpaperUrl(sharedContext: item.context.sharedContext, url: webpage.url) {
if case let .color(color) = wallpaper {
colors = [color.rgb]
} else if case let .gradient(colorsValue, rotationValue) = wallpaper {
if let file = file {
let media = WallpaperPreviewMedia(content: .file(file: file, colors: [], rotation: nil, intensity: nil, true, isSupported))
mediaAndFlags = ([media], ChatMessageAttachedContentNodeMediaFlags())
} else if let settings = settings {
let media = WallpaperPreviewMedia(content: .themeSettings(settings))
mediaAndFlags = ([media], ChatMessageAttachedContentNodeMediaFlags())
}
case "telegram_nft":
for attribute in webpage.attributes {
if case let .starGift(gift) = attribute, case let .unique(uniqueGift) = gift.gift {
let media = UniqueGiftPreviewMedia(content: uniqueGift)
mediaAndFlags = ([media], [])
break
}
}
default:
if let file = mainMedia as? TelegramMediaFile, webpage.type != "telegram_theme" {
if let embedUrl = webpage.embedUrl, !embedUrl.isEmpty {
if automaticPlayback {
mediaAndFlags = ([file], [.preferMediaBeforeText])
} else {
mediaAndFlags = ([webpage.image ?? file], [.preferMediaBeforeText])
}
} else if webpage.type == "telegram_background" {
var colors: [UInt32] = []
var rotation: Int32?
var intensity: Int32?
if let wallpaper = parseWallpaperUrl(sharedContext: item.context.sharedContext, url: webpage.url), case let .slug(_, _, colorsValue, intensityValue, rotationValue) = wallpaper {
colors = colorsValue
rotation = rotationValue
intensity = intensityValue
}
}
var content: WallpaperPreviewMediaContent?
if !colors.isEmpty {
if colors.count >= 2 {
content = .gradient(colors, rotation)
} else {
content = .color(UIColor(rgb: colors[0]))
let media = WallpaperPreviewMedia(content: .file(file: file, colors: colors, rotation: rotation, intensity: intensity, false, false))
mediaAndFlags = ([media], [.preferMediaAspectFilled])
if let fileSize = file.size {
badge = dataSizeString(fileSize, formatting: DataSizeStringFormatting(chatPresentationData: item.presentationData))
}
} else {
mediaAndFlags = ([file], [])
}
if let content = content {
let media = WallpaperPreviewMedia(content: content)
mediaAndFlags = ([media], [])
}
} else if type == "telegram_theme" {
var file: TelegramMediaFile?
var settings: TelegramThemeSettings?
var isSupported = false
for attribute in webpage.attributes {
if case let .theme(attribute) = attribute {
if let attributeSettings = attribute.settings {
settings = attributeSettings
isSupported = true
} else if let filteredFile = attribute.files.filter({ $0.mimeType == themeMimeType }).first {
file = filteredFile
isSupported = true
} else if let image = mainMedia as? TelegramMediaImage {
if let type = webpage.type, ["photo", "video", "embed", "gif", "document", "telegram_album"].contains(type) {
var flags = ChatMessageAttachedContentNodeMediaFlags()
if webpage.instantPage != nil, let largest = largestImageRepresentation(image.representations) {
if largest.dimensions.width >= 256 {
flags.insert(.preferMediaBeforeText)
}
} else if let embedUrl = webpage.embedUrl, !embedUrl.isEmpty {
flags.insert(.preferMediaBeforeText)
}
mediaAndFlags = ([image], flags)
} else if let _ = largestImageRepresentation(image.representations)?.dimensions {
let flags = ChatMessageAttachedContentNodeMediaFlags()
mediaAndFlags = ([image], flags)
}
if !isSupported, let contentFile = webpage.file {
isSupported = true
file = contentFile
}
if let file = file {
let media = WallpaperPreviewMedia(content: .file(file: file, colors: [], rotation: nil, intensity: nil, true, isSupported))
mediaAndFlags = ([media], ChatMessageAttachedContentNodeMediaFlags())
} else if let settings = settings {
let media = WallpaperPreviewMedia(content: .themeSettings(settings))
mediaAndFlags = ([media], ChatMessageAttachedContentNodeMediaFlags())
}
} else if type == "telegram_nft" {
for attribute in webpage.attributes {
if case let .starGift(gift) = attribute, case let .unique(uniqueGift) = gift.gift {
let media = UniqueGiftPreviewMedia(content: uniqueGift)
mediaAndFlags = ([media], [])
break
}
} else if let story = mainMedia as? TelegramMediaStory {
mediaAndFlags = ([story], [.preferMediaBeforeText, .titleBeforeMedia])
if let storyItem = item.message.associatedStories[story.storyId]?.get(Stories.StoredItem.self), case let .item(itemValue) = storyItem {
text = itemValue.text
entities = itemValue.entities
}
}
}

View File

@ -151,7 +151,7 @@ private enum ChatTitleCredibilityIcon: Equatable {
case scam
case verified
case premium
case emojiStatus(PeerEmojiStatus)
case emojiStatus(PeerEmojiStatus, Int32?)
}
public final class ChatTitleView: UIView, NavigationBarTitleView {
@ -275,7 +275,7 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
} else if peer.isScam {
titleCredibilityIcon = .scam
} else if let emojiStatus = peer.emojiStatus, !premiumConfiguration.isPremiumDisabled {
titleStatusIcon = .emojiStatus(emojiStatus)
titleStatusIcon = .emojiStatus(emojiStatus, emojiStatus.color)
} else if peer.isPremium && !premiumConfiguration.isPremiumDisabled {
titleCredibilityIcon = .premium
}
@ -284,7 +284,7 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
titleCredibilityIcon = .verified
}
if let verificationIconFileId = peer.verificationIconFileId {
titleVerifiedIcon = .emojiStatus(PeerEmojiStatus(content: .emoji(fileId: verificationIconFileId), expirationDate: nil))
titleVerifiedIcon = .emojiStatus(PeerEmojiStatus(content: .emoji(fileId: verificationIconFileId), expirationDate: nil), nil)
}
}
}
@ -839,7 +839,7 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
titleCredibilityContent = .text(color: self.theme.chat.message.incoming.scamColor, string: self.strings.Message_FakeAccount.uppercased())
case .scam:
titleCredibilityContent = .text(color: self.theme.chat.message.incoming.scamColor, string: self.strings.Message_ScamAccount.uppercased())
case let .emojiStatus(emojiStatus):
case let .emojiStatus(emojiStatus, _):
titleCredibilityContent = .animation(content: .customEmoji(fileId: emojiStatus.fileId), size: CGSize(width: 32.0, height: 32.0), placeholderColor: self.theme.list.mediaPlaceholderColor, themeColor: self.theme.list.itemAccentColor, loopMode: .count(2))
}
@ -855,14 +855,18 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
titleVerifiedContent = .text(color: self.theme.chat.message.incoming.scamColor, string: self.strings.Message_FakeAccount.uppercased())
case .scam:
titleVerifiedContent = .text(color: self.theme.chat.message.incoming.scamColor, string: self.strings.Message_ScamAccount.uppercased())
case let .emojiStatus(emojiStatus):
case let .emojiStatus(emojiStatus, _):
titleVerifiedContent = .animation(content: .customEmoji(fileId: emojiStatus.fileId), size: CGSize(width: 32.0, height: 32.0), placeholderColor: self.theme.list.mediaPlaceholderColor, themeColor: self.theme.list.itemAccentColor, loopMode: .count(2))
}
let titleStatusContent: EmojiStatusComponent.Content
var titleStatusParticleColor: UIColor?
switch self.titleStatusIcon {
case let .emojiStatus(emojiStatus):
case let .emojiStatus(emojiStatus, color):
titleStatusContent = .animation(content: .customEmoji(fileId: emojiStatus.fileId), size: CGSize(width: 32.0, height: 32.0), placeholderColor: self.theme.list.mediaPlaceholderColor, themeColor: self.theme.list.itemAccentColor, loopMode: .count(2))
if let color {
titleStatusParticleColor = UIColor(rgb: UInt32(bitPattern: color))
}
default:
titleStatusContent = .none
}
@ -902,6 +906,7 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
animationCache: self.animationCache,
animationRenderer: self.animationRenderer,
content: titleStatusContent,
particleColor: titleStatusParticleColor,
isVisibleForAnimations: true,
action: nil
)),

View File

@ -307,7 +307,9 @@ public final class GiftCompositionComponent: Component {
backgroundView.isUserInteractionEnabled = false
self.insertSubview(backgroundView, at: 0)
backgroundView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25)
if previousComponent != nil {
backgroundView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25)
}
}
backgroundTransition.setFrame(view: backgroundView, frame: CGRect(origin: .zero, size: availableSize))
}

View File

@ -491,6 +491,7 @@ final class GiftOptionsScreenComponent: Component {
let _ = sectionSpacing
let isSelfGift = component.peerId == component.context.account.peerId
let isChannelGift = component.peerId.namespace == Namespaces.Peer.CloudChannel
var contentHeight: CGFloat = 0.0
contentHeight += environment.navigationHeight - 56.0 + 188.0
@ -505,7 +506,21 @@ final class GiftOptionsScreenComponent: Component {
isVisible: true,
hasIdleAnimations: true,
color: UIColor(rgb: 0xf9b004),
hasLargeParticles: true
hasLargeParticles: true,
action: { [weak self] in
guard let self, let component = self.component, let controller = controller(), let navigationController = controller.navigationController as? NavigationController else {
return
}
let _ = (component.context.engine.data.get(
TelegramEngine.EngineData.Item.Peer.Peer(id: component.peerId)
)
|> deliverOnMainQueue).start(next: { peer in
guard let peer else {
return
}
component.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, chatController: nil, context: component.context, chatLocation: .peer(peer), subject: nil, botStart: nil, updateTextInputState: nil, keepStack: .always, useExisting: true, purposefulAction: nil, scrollToEndIfExists: false, activateMessageSearch: nil, animated: true))
})
}
)
),
environment: {},
@ -623,10 +638,19 @@ final class GiftOptionsScreenComponent: Component {
balanceIconView.bounds = CGRect(origin: .zero, size: balanceIconSize)
}
let premiumTitleString: String
if isSelfGift {
premiumTitleString = strings.Gift_Options_GiftSelf_Title
} else if isChannelGift {
//TODO:localize
premiumTitleString = "Send a Gift"
} else {
premiumTitleString = strings.Gift_Options_Premium_Title
}
let premiumTitleSize = self.premiumTitle.update(
transition: transition,
component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(string: isSelfGift ? strings.Gift_Options_GiftSelf_Title : strings.Gift_Options_Premium_Title, font: Font.bold(28.0), textColor: theme.rootController.navigationBar.primaryTextColor)),
text: .plain(NSAttributedString(string: premiumTitleString, font: Font.bold(28.0), textColor: theme.rootController.navigationBar.primaryTextColor)),
horizontalAlignment: .center
)),
environment: {},
@ -647,7 +671,16 @@ final class GiftOptionsScreenComponent: Component {
})
let peerName = state.peer?.compactDisplayTitle ?? ""
let premiumDescriptionString = parseMarkdownIntoAttributedString(isSelfGift ? strings.Gift_Options_GiftSelf_Text : strings.Gift_Options_Premium_Text(peerName).string, attributes: markdownAttributes).mutableCopy() as! NSMutableAttributedString
let premiumDescriptionRawString: String
if isSelfGift {
premiumDescriptionRawString = strings.Gift_Options_GiftSelf_Text
} else if isChannelGift {
//TODO:localize
premiumDescriptionRawString = "Select a gift to show appreciation for **\(peerName)**."
} else {
premiumDescriptionRawString = strings.Gift_Options_Premium_Text(peerName).string
}
let premiumDescriptionString = parseMarkdownIntoAttributedString(premiumDescriptionRawString, attributes: markdownAttributes).mutableCopy() as! NSMutableAttributedString
if let range = premiumDescriptionString.string.range(of: ">"), let chevronImage = self.chevronImage?.0 {
premiumDescriptionString.addAttribute(.attachment, value: chevronImage, range: NSRange(range, in: premiumDescriptionString.string))
}
@ -701,7 +734,7 @@ final class GiftOptionsScreenComponent: Component {
let optionSpacing: CGFloat = 10.0
let optionWidth = (availableSize.width - sideInset * 2.0 - optionSpacing * 2.0) / 3.0
if isSelfGift {
if isSelfGift || isChannelGift {
contentHeight += 6.0
} else {
if let premiumProducts = state.premiumProducts {

View File

@ -29,9 +29,9 @@ final class ChatGiftPreviewItem: ListViewItem, ItemListItem, ListItemComponentAd
let dateTimeFormat: PresentationDateTimeFormat
let nameDisplayOrder: PresentationPersonNameOrder
let accountPeer: EnginePeer?
let peers: [EnginePeer]
let subject: ChatGiftPreviewItem.Subject
let isSelf: Bool
let chatPeerId: EnginePeer.Id?
let text: String
let entities: [MessageTextEntity]
let upgradeStars: Int64?
@ -47,9 +47,9 @@ final class ChatGiftPreviewItem: ListViewItem, ItemListItem, ListItemComponentAd
wallpaper: TelegramWallpaper,
dateTimeFormat: PresentationDateTimeFormat,
nameDisplayOrder: PresentationPersonNameOrder,
accountPeer: EnginePeer?,
peers: [EnginePeer],
subject: ChatGiftPreviewItem.Subject,
isSelf: Bool,
chatPeerId: EnginePeer.Id?,
text: String,
entities: [MessageTextEntity],
upgradeStars: Int64?
@ -64,9 +64,9 @@ final class ChatGiftPreviewItem: ListViewItem, ItemListItem, ListItemComponentAd
self.wallpaper = wallpaper
self.dateTimeFormat = dateTimeFormat
self.nameDisplayOrder = nameDisplayOrder
self.accountPeer = accountPeer
self.peers = peers
self.subject = subject
self.isSelf = isSelf
self.chatPeerId = chatPeerId
self.text = text
self.entities = entities
self.upgradeStars = upgradeStars
@ -137,7 +137,7 @@ final class ChatGiftPreviewItem: ListViewItem, ItemListItem, ListItemComponentAd
if lhs.nameDisplayOrder != rhs.nameDisplayOrder {
return false
}
if lhs.accountPeer != rhs.accountPeer {
if lhs.peers != rhs.peers {
return false
}
if lhs.text != rhs.text {
@ -209,10 +209,7 @@ final class ChatGiftPreviewItemNode: ListViewItemNode {
let separatorHeight = UIScreenPixel
let peerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(1))
var chatPeerId = peerId
if item.isSelf {
chatPeerId = item.accountPeer?.id ?? chatPeerId
}
let chatPeerId = item.chatPeerId ?? peerId
var items: [ListViewItem] = []
for _ in 0 ..< 1 {
@ -221,7 +218,9 @@ final class ChatGiftPreviewItemNode: ListViewItemNode {
var peers = SimpleDictionary<PeerId, Peer>()
let messages = SimpleDictionary<MessageId, Message>()
peers[authorPeerId] = item.accountPeer?._asPeer()
for peer in item.peers {
peers[peer.id] = peer._asPeer()
}
let media: [Media]
switch item.subject {
@ -234,7 +233,7 @@ final class ChatGiftPreviewItemNode: ListViewItemNode {
case let .starGift(gift):
media = [
TelegramMediaAction(
action: .starGift(gift: .generic(gift), convertStars: gift.convertStars, text: item.text, entities: item.entities, nameHidden: false, savedToProfile: false, converted: false, upgraded: false, canUpgrade: true, upgradeStars: item.upgradeStars, isRefunded: false, upgradeMessageId: nil)
action: .starGift(gift: .generic(gift), convertStars: gift.convertStars, text: item.text, entities: item.entities, nameHidden: false, savedToProfile: false, converted: false, upgraded: false, canUpgrade: true, upgradeStars: item.upgradeStars, isRefunded: false, upgradeMessageId: nil, peerId: nil, senderId: nil)
)
]
}

View File

@ -481,6 +481,7 @@ final class GiftSetupScreenComponent: Component {
let peerName = self.peerMap[component.peerId]?.compactDisplayTitle ?? ""
let isSelfGift = component.peerId == component.context.account.peerId
let isChannelGift = component.peerId.namespace == Namespaces.Peer.CloudChannel
if self.component == nil {
if isSelfGift {
@ -636,11 +637,20 @@ final class GiftSetupScreenComponent: Component {
}
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }
let navigationTitleString: String
if isSelfGift {
navigationTitleString = environment.strings.Gift_SendSelf_Title
} else if isChannelGift {
//TODO:localize
navigationTitleString = "Gift Preview"
} else {
navigationTitleString = environment.strings.Gift_Send_TitleTo(peerName).string
}
let navigationTitleSize = self.navigationTitle.update(
transition: transition,
component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(string: isSelfGift ? environment.strings.Gift_SendSelf_Title : environment.strings.Gift_Send_TitleTo(peerName).string, font: Font.semibold(17.0), textColor: environment.theme.rootController.navigationBar.primaryTextColor)),
text: .plain(NSAttributedString(string: navigationTitleString, font: Font.semibold(17.0), textColor: environment.theme.rootController.navigationBar.primaryTextColor)),
horizontalAlignment: .center
)),
environment: {},
@ -823,6 +833,11 @@ final class GiftSetupScreenComponent: Component {
upgradeStars = gift.upgradeStars
}
var peers: [EnginePeer] = [accountPeer]
if let peer = self.peerMap[component.peerId] {
peers.append(peer)
}
let introContentSize = self.introContent.update(
transition: transition,
component: AnyComponent(
@ -838,9 +853,9 @@ final class GiftSetupScreenComponent: Component {
wallpaper: presentationData.chatWallpaper,
dateTimeFormat: environment.dateTimeFormat,
nameDisplayOrder: presentationData.nameDisplayOrder,
accountPeer: accountPeer,
peers: peers,
subject: subject,
isSelf: component.peerId == component.context.account.peerId,
chatPeerId: component.peerId,
text: self.textInputState.text.string,
entities: generateChatInputTextEntities(self.textInputState.text),
upgradeStars: self.includeUpgrade ? upgradeStars : nil
@ -865,7 +880,13 @@ final class GiftSetupScreenComponent: Component {
if case let .starGift(gift) = component.subject {
if let upgradeStars = gift.upgradeStars, component.peerId != component.context.account.peerId {
let parsedString = parseMarkdownIntoAttributedString(environment.strings.Gift_Send_Upgrade_Info(peerName).string, attributes: MarkdownAttributes(
let upgradeFooterRawString: String
if isChannelGift {
upgradeFooterRawString = "Enable this to let the admins of \(peerName) turn your gift into a unique collectible. [Learn More >]()"
} else {
upgradeFooterRawString = environment.strings.Gift_Send_Upgrade_Info(peerName).string
}
let parsedString = parseMarkdownIntoAttributedString(upgradeFooterRawString, attributes: MarkdownAttributes(
body: MarkdownAttributeSet(font: Font.regular(13.0), textColor: environment.theme.list.freeTextColor),
bold: MarkdownAttributeSet(font: Font.semibold(13.0), textColor: environment.theme.list.freeTextColor),
link: MarkdownAttributeSet(font: Font.regular(13.0), textColor: environment.theme.list.itemAccentColor),
@ -963,6 +984,15 @@ final class GiftSetupScreenComponent: Component {
contentHeight += sectionSpacing
}
let hideSectionFooterString: String
if isSelfGift {
hideSectionFooterString = environment.strings.Gift_SendSelf_HideMyName_Info
} else if isChannelGift {
//TODO:localize
hideSectionFooterString = "Hide my name and message from visitors of this channel. The channel admins will still see them."
} else {
hideSectionFooterString = environment.strings.Gift_Send_HideMyName_Info(peerName, peerName).string
}
let hideSectionSize = self.hideSection.update(
transition: transition,
component: AnyComponent(ListSectionComponent(
@ -970,7 +1000,7 @@ final class GiftSetupScreenComponent: Component {
header: nil,
footer: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: isSelfGift ? environment.strings.Gift_SendSelf_HideMyName_Info : environment.strings.Gift_Send_HideMyName_Info(peerName, peerName).string,
string: hideSectionFooterString,
font: Font.regular(presentationData.listsFontSize.itemListBaseHeaderFontSize),
textColor: environment.theme.list.freeTextColor
)),

View File

@ -206,8 +206,8 @@ private final class GiftViewSheetContent: CombinedComponent {
self.updated()
}))
if arguments.upgradeStars == nil, let messageId = arguments.messageId {
self.upgradeFormDisposable = (context.engine.payments.fetchBotPaymentForm(source: .starGiftUpgrade(keepOriginalInfo: false, messageId: messageId), themeParams: nil)
if arguments.upgradeStars == nil, let reference = arguments.reference {
self.upgradeFormDisposable = (context.engine.payments.fetchBotPaymentForm(source: .starGiftUpgrade(keepOriginalInfo: false, reference: reference), themeParams: nil)
|> deliverOnMainQueue).start(next: { [weak self] paymentForm in
guard let self else {
return
@ -2126,13 +2126,13 @@ public class GiftViewScreen: ViewControllerComponentContainer {
case soldOutGift(StarGift.Gift)
case upgradePreview([StarGift.UniqueGift.Attribute], String)
var arguments: (peerId: EnginePeer.Id?, fromPeerId: EnginePeer.Id?, fromPeerName: String?, messageId: EngineMessage.Id?, incoming: Bool, gift: StarGift, date: Int32, convertStars: Int64?, text: String?, entities: [MessageTextEntity]?, nameHidden: Bool, savedToProfile: Bool, converted: Bool, upgraded: Bool, canUpgrade: Bool, upgradeStars: Int64?, transferStars: Int64?, canExportDate: Int32?, upgradeMessageId: Int32?)? {
var arguments: (peerId: EnginePeer.Id?, fromPeerId: EnginePeer.Id?, fromPeerName: String?, messageId: EngineMessage.Id?, reference: StarGiftReference?, incoming: Bool, gift: StarGift, date: Int32, convertStars: Int64?, text: String?, entities: [MessageTextEntity]?, nameHidden: Bool, savedToProfile: Bool, converted: Bool, upgraded: Bool, canUpgrade: Bool, upgradeStars: Int64?, transferStars: Int64?, canExportDate: Int32?, upgradeMessageId: Int32?)? {
switch self {
case let .message(message):
if let action = message.media.first(where: { $0 is TelegramMediaAction }) as? TelegramMediaAction {
switch action.action {
case let .starGift(gift, convertStars, text, entities, nameHidden, savedToProfile, converted, upgraded, canUpgrade, upgradeStars, _, upgradeMessageId):
return (message.id.peerId, message.author?.id, message.author?.compactDisplayTitle, message.id, message.flags.contains(.Incoming), gift, message.timestamp, convertStars, text, entities, nameHidden, savedToProfile, converted, upgraded, canUpgrade, upgradeStars, nil, nil, upgradeMessageId)
case let .starGift(gift, convertStars, text, entities, nameHidden, savedToProfile, converted, upgraded, canUpgrade, upgradeStars, _, upgradeMessageId, _, _):
return (message.id.peerId, message.author?.id, message.author?.compactDisplayTitle, message.id, .message(messageId: message.id), message.flags.contains(.Incoming), gift, message.timestamp, convertStars, text, entities, nameHidden, savedToProfile, converted, upgraded, canUpgrade, upgradeStars, nil, nil, upgradeMessageId)
case let .starGiftUnique(gift, isUpgrade, isTransferred, savedToProfile, canExportDate, transferStars, _):
var incoming = false
if isUpgrade {
@ -2146,15 +2146,19 @@ public class GiftViewScreen: ViewControllerComponentContainer {
} else {
incoming = message.flags.contains(.Incoming)
}
return (message.id.peerId, message.author?.id, message.author?.compactDisplayTitle, message.id, incoming, gift, message.timestamp, nil, nil, nil, false, savedToProfile, false, false, false, nil, transferStars, canExportDate, nil)
return (message.id.peerId, message.author?.id, message.author?.compactDisplayTitle, message.id, .message(messageId: message.id), incoming, gift, message.timestamp, nil, nil, nil, false, savedToProfile, false, false, false, nil, transferStars, canExportDate, nil)
default:
return nil
}
}
case let .uniqueGift(gift):
return (nil, nil, nil, nil, false, .unique(gift), 0, nil, nil, nil, false, false, false, false, false, nil, nil, nil, nil)
return (nil, nil, nil, nil, nil, false, .unique(gift), 0, nil, nil, nil, false, false, false, false, false, nil, nil, nil, nil)
case let .profileGift(peerId, gift):
return (peerId, gift.fromPeer?.id, gift.fromPeer?.compactDisplayTitle, gift.messageId, false, gift.gift, gift.date, gift.convertStars, gift.text, gift.entities, gift.nameHidden, gift.savedToProfile, false, false, gift.canUpgrade, gift.upgradeStars, gift.transferStars, gift.canExportDate, nil)
var messageId: EngineMessage.Id?
if case let .message(messageIdValue) = gift.reference {
messageId = messageIdValue
}
return (peerId, gift.fromPeer?.id, gift.fromPeer?.compactDisplayTitle, messageId, gift.reference, false, gift.gift, gift.date, gift.convertStars, gift.text, gift.entities, gift.nameHidden, gift.savedToProfile, false, false, gift.canUpgrade, gift.upgradeStars, gift.transferStars, gift.canExportDate, nil)
case .soldOutGift:
return nil
case .upgradePreview:
@ -2174,7 +2178,7 @@ public class GiftViewScreen: ViewControllerComponentContainer {
context: AccountContext,
subject: GiftViewScreen.Subject,
forceDark: Bool = false,
updateSavedToProfile: ((EngineMessage.Id, Bool) -> Void)? = nil,
updateSavedToProfile: ((StarGiftReference, Bool) -> Void)? = nil,
convertToStars: (() -> Void)? = nil,
transferGift: ((Bool, EnginePeer.Id) -> Void)? = nil,
upgradeGift: ((Int64?, Bool) -> Signal<ProfileGiftsContext.State.StarGift, UpgradeStarGiftError>)? = nil,
@ -2265,7 +2269,7 @@ public class GiftViewScreen: ViewControllerComponentContainer {
let presentationData = self.context.sharedContext.currentPresentationData.with { $0 }
updateSavedToProfileImpl = { [weak self] added in
guard let self, let arguments = self.subject.arguments, let messageId = arguments.messageId else {
guard let self, let arguments = self.subject.arguments, let reference = arguments.reference else {
return
}
@ -2283,9 +2287,9 @@ public class GiftViewScreen: ViewControllerComponentContainer {
}
if let updateSavedToProfile {
updateSavedToProfile(messageId, added)
updateSavedToProfile(reference, added)
} else {
let _ = (context.engine.payments.updateStarGiftAddedToProfile(messageId: messageId, added: added)
let _ = (context.engine.payments.updateStarGiftAddedToProfile(reference: reference, added: added)
|> deliverOnMainQueue).startStandalone()
}
@ -2329,7 +2333,7 @@ public class GiftViewScreen: ViewControllerComponentContainer {
}
convertToStarsImpl = { [weak self] in
guard let self, let arguments = self.subject.arguments, let messageId = arguments.messageId, let fromPeerName = arguments.fromPeerName, let convertStars = arguments.convertStars, let navigationController = self.navigationController as? NavigationController else {
guard let self, let arguments = self.subject.arguments, let reference = arguments.reference, let fromPeerName = arguments.fromPeerName, let convertStars = arguments.convertStars, let navigationController = self.navigationController as? NavigationController else {
return
}
@ -2364,7 +2368,7 @@ public class GiftViewScreen: ViewControllerComponentContainer {
if let convertToStars {
convertToStars()
} else {
let _ = (context.engine.payments.convertStarGift(messageId: messageId)
let _ = (context.engine.payments.convertStarGift(reference: reference)
|> deliverOnMainQueue).startStandalone()
}
self?.dismissAnimated()
@ -2447,20 +2451,20 @@ public class GiftViewScreen: ViewControllerComponentContainer {
}
transferGiftImpl = { [weak self] in
guard let self, let arguments = self.subject.arguments, let navigationController = self.navigationController as? NavigationController, case let .unique(gift) = arguments.gift, let messageId = arguments.messageId, let transferStars = arguments.transferStars else {
guard let self, let arguments = self.subject.arguments, let navigationController = self.navigationController as? NavigationController, case let .unique(gift) = arguments.gift, let reference = arguments.reference, let transferStars = arguments.transferStars else {
return
}
let _ = (context.account.stateManager.contactBirthdays
|> take(1)
|> deliverOnMainQueue).start(next: { birthdays in
let controller = context.sharedContext.makePremiumGiftController(context: context, source: .starGiftTransfer(birthdays, messageId, gift, transferStars, arguments.canExportDate), completion: { peerIds in
let controller = context.sharedContext.makePremiumGiftController(context: context, source: .starGiftTransfer(birthdays, reference, gift, transferStars, arguments.canExportDate), completion: { peerIds in
guard let peerId = peerIds.first else {
return
}
if let transferGift {
transferGift(transferStars == 0, peerId)
} else {
let _ = (context.engine.payments.transferStarGift(prepaid: transferStars == 0, messageId: messageId, peerId: peerId)
let _ = (context.engine.payments.transferStarGift(prepaid: transferStars == 0, reference: reference, peerId: peerId)
|> deliverOnMainQueue).start()
}
Queue.mainQueue().after(1.0, {
@ -2474,13 +2478,13 @@ public class GiftViewScreen: ViewControllerComponentContainer {
}
upgradeGiftImpl = { [weak self] formId, keepOriginalInfo in
guard let self, let arguments = self.subject.arguments, let messageId = arguments.messageId else {
guard let self, let arguments = self.subject.arguments, let reference = arguments.reference else {
return .complete()
}
if let upgradeGift {
return upgradeGift(formId, keepOriginalInfo)
} else {
return self.context.engine.payments.upgradeStarGift(formId: formId, messageId: messageId, keepOriginalInfo: keepOriginalInfo)
return self.context.engine.payments.upgradeStarGift(formId: formId, reference: reference, keepOriginalInfo: keepOriginalInfo)
|> afterCompleted {
if formId != nil {
context.starsContext?.load(force: true)

View File

@ -0,0 +1,293 @@
import Foundation
import UIKit
import AsyncDisplayKit
import Display
import ComponentFlow
import Postbox
import TelegramCore
import TelegramPresentationData
import TelegramUIPreferences
import AccountContext
import AppBundle
import Markdown
import GiftItemComponent
import StarsAvatarComponent
private final class GiftWithdrawAlertContentNode: AlertContentNode {
private let context: AccountContext
private let strings: PresentationStrings
private var presentationTheme: PresentationTheme
private let title: String
private let text: String
private let gift: StarGift.UniqueGift
private let titleNode: ASTextNode
private let giftView = ComponentView<Empty>()
private let textNode: ASTextNode
private let arrowNode: ASImageNode
private let avatarView = ComponentView<Empty>()
private let actionNodesSeparator: ASDisplayNode
private let actionNodes: [TextAlertContentActionNode]
private let actionVerticalSeparators: [ASDisplayNode]
private var validLayout: CGSize?
override var dismissOnOutsideTap: Bool {
return self.isUserInteractionEnabled
}
init(
context: AccountContext,
theme: AlertControllerTheme,
ptheme: PresentationTheme,
strings: PresentationStrings,
gift: StarGift.UniqueGift,
title: String,
text: String,
actions: [TextAlertAction]
) {
self.context = context
self.strings = strings
self.presentationTheme = ptheme
self.title = title
self.text = text
self.gift = gift
self.titleNode = ASTextNode()
self.titleNode.maximumNumberOfLines = 0
self.textNode = ASTextNode()
self.textNode.maximumNumberOfLines = 0
self.arrowNode = ASImageNode()
self.arrowNode.displaysAsynchronously = false
self.arrowNode.displayWithoutProcessing = true
self.actionNodesSeparator = ASDisplayNode()
self.actionNodesSeparator.isLayerBacked = true
self.actionNodes = actions.map { action -> TextAlertContentActionNode in
return TextAlertContentActionNode(theme: theme, action: action)
}
var actionVerticalSeparators: [ASDisplayNode] = []
if actions.count > 1 {
for _ in 0 ..< actions.count - 1 {
let separatorNode = ASDisplayNode()
separatorNode.isLayerBacked = true
actionVerticalSeparators.append(separatorNode)
}
}
self.actionVerticalSeparators = actionVerticalSeparators
super.init()
self.addSubnode(self.titleNode)
self.addSubnode(self.textNode)
self.addSubnode(self.arrowNode)
self.addSubnode(self.actionNodesSeparator)
for actionNode in self.actionNodes {
self.addSubnode(actionNode)
}
for separatorNode in self.actionVerticalSeparators {
self.addSubnode(separatorNode)
}
self.updateTheme(theme)
}
override func updateTheme(_ theme: AlertControllerTheme) {
self.titleNode.attributedText = NSAttributedString(string: self.title, font: Font.semibold(17.0), textColor: theme.primaryColor)
self.textNode.attributedText = parseMarkdownIntoAttributedString(self.text, attributes: MarkdownAttributes(
body: MarkdownAttributeSet(font: Font.regular(13.0), textColor: theme.primaryColor),
bold: MarkdownAttributeSet(font: Font.semibold(13.0), textColor: theme.primaryColor),
link: MarkdownAttributeSet(font: Font.regular(13.0), textColor: theme.primaryColor),
linkAttribute: { url in
return ("URL", url)
}
), textAlignment: .center)
self.arrowNode.image = generateTintedImage(image: UIImage(bundleImageName: "Peer Info/AlertArrow"), color: theme.secondaryColor)
self.actionNodesSeparator.backgroundColor = theme.separatorColor
for actionNode in self.actionNodes {
actionNode.updateTheme(theme)
}
for separatorNode in self.actionVerticalSeparators {
separatorNode.backgroundColor = theme.separatorColor
}
if let size = self.validLayout {
_ = self.updateLayout(size: size, transition: .immediate)
}
}
override func updateLayout(size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize {
var size = size
size.width = min(size.width, 270.0)
self.validLayout = size
var origin: CGPoint = CGPoint(x: 0.0, y: 20.0)
let avatarSize = CGSize(width: 60.0, height: 60.0)
let giftFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - avatarSize.width) / 2.0) - 44.0, y: origin.y), size: avatarSize)
let _ = self.giftView.update(
transition: .immediate,
component: AnyComponent(
GiftItemComponent(
context: self.context,
theme: self.presentationTheme,
peer: nil,
subject: .uniqueGift(gift: self.gift),
mode: .thumbnail
)
),
environment: {},
containerSize: avatarSize
)
if let view = self.giftView.view {
if view.superview == nil {
self.view.addSubview(view)
}
view.frame = giftFrame
}
if let arrowImage = self.arrowNode.image {
let arrowFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - arrowImage.size.width) / 2.0), y: origin.y + floorToScreenPixels((avatarSize.height - arrowImage.size.height) / 2.0)), size: arrowImage.size)
transition.updateFrame(node: self.arrowNode, frame: arrowFrame)
}
let avatarFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - avatarSize.width) / 2.0) + 44.0, y: origin.y), size: avatarSize)
let _ = self.avatarView.update(
transition: .immediate,
component: AnyComponent(
StarsAvatarComponent(
context: self.context,
theme: self.presentationTheme,
peer: .fragment,
photo: nil,
media: [],
uniqueGift: nil,
backgroundColor: .clear
)
),
environment: {},
containerSize: avatarSize
)
if let view = self.avatarView.view {
if view.superview == nil {
self.view.addSubview(view)
}
view.frame = avatarFrame
}
origin.y += avatarSize.height + 17.0
let titleSize = self.titleNode.measure(CGSize(width: size.width - 32.0, height: size.height))
transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - titleSize.width) / 2.0), y: origin.y), size: titleSize))
origin.y += titleSize.height + 5.0
let textSize = self.textNode.measure(CGSize(width: size.width - 32.0, height: size.height))
transition.updateFrame(node: self.textNode, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - textSize.width) / 2.0), y: origin.y), size: textSize))
origin.y += textSize.height + 10.0
let actionButtonHeight: CGFloat = 44.0
var minActionsWidth: CGFloat = 0.0
let maxActionWidth: CGFloat = floor(size.width / CGFloat(self.actionNodes.count))
let actionTitleInsets: CGFloat = 8.0
let effectiveActionLayout = TextAlertContentActionLayout.vertical
for actionNode in self.actionNodes {
let actionTitleSize = actionNode.titleNode.updateLayout(CGSize(width: maxActionWidth, height: actionButtonHeight))
minActionsWidth = max(minActionsWidth, actionTitleSize.width + actionTitleInsets)
}
let insets = UIEdgeInsets(top: 18.0, left: 18.0, bottom: 18.0, right: 18.0)
let contentWidth = max(size.width, minActionsWidth)
let actionsHeight = actionButtonHeight * CGFloat(self.actionNodes.count)
let resultSize = CGSize(width: contentWidth, height: avatarSize.height + titleSize.height + textSize.height + actionsHeight + 24.0 + insets.top + insets.bottom)
transition.updateFrame(node: self.actionNodesSeparator, frame: CGRect(origin: CGPoint(x: 0.0, y: resultSize.height - actionsHeight - UIScreenPixel), size: CGSize(width: resultSize.width, height: UIScreenPixel)))
var actionOffset: CGFloat = 0.0
let actionWidth: CGFloat = floor(resultSize.width / CGFloat(self.actionNodes.count))
var separatorIndex = -1
var nodeIndex = 0
for actionNode in self.actionNodes {
if separatorIndex >= 0 {
let separatorNode = self.actionVerticalSeparators[separatorIndex]
switch effectiveActionLayout {
case .horizontal:
transition.updateFrame(node: separatorNode, frame: CGRect(origin: CGPoint(x: actionOffset - UIScreenPixel, y: resultSize.height - actionsHeight), size: CGSize(width: UIScreenPixel, height: actionsHeight - UIScreenPixel)))
case .vertical:
transition.updateFrame(node: separatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: resultSize.height - actionsHeight + actionOffset - UIScreenPixel), size: CGSize(width: resultSize.width, height: UIScreenPixel)))
}
}
separatorIndex += 1
let currentActionWidth: CGFloat
switch effectiveActionLayout {
case .horizontal:
if nodeIndex == self.actionNodes.count - 1 {
currentActionWidth = resultSize.width - actionOffset
} else {
currentActionWidth = actionWidth
}
case .vertical:
currentActionWidth = resultSize.width
}
let actionNodeFrame: CGRect
switch effectiveActionLayout {
case .horizontal:
actionNodeFrame = CGRect(origin: CGPoint(x: actionOffset, y: resultSize.height - actionsHeight), size: CGSize(width: currentActionWidth, height: actionButtonHeight))
actionOffset += currentActionWidth
case .vertical:
actionNodeFrame = CGRect(origin: CGPoint(x: 0.0, y: resultSize.height - actionsHeight + actionOffset), size: CGSize(width: currentActionWidth, height: actionButtonHeight))
actionOffset += actionButtonHeight
}
transition.updateFrame(node: actionNode, frame: actionNodeFrame)
nodeIndex += 1
}
return resultSize
}
}
public func giftWithdrawAlertController(context: AccountContext, gift: StarGift.UniqueGift, commit: @escaping () -> Void) -> AlertController {
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let strings = presentationData.strings
let title = strings.Gift_Withdraw_Title
let text = strings.Gift_Withdraw_Text("\(gift.title) #\(gift.number)").string
let buttonText = strings.Gift_Withdraw_Proceed
var dismissImpl: ((Bool) -> Void)?
let actions: [TextAlertAction] = [TextAlertAction(type: .defaultAction, title: buttonText, action: {
dismissImpl?(true)
commit()
}), TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {
dismissImpl?(true)
})]
let contentNode = GiftWithdrawAlertContentNode(context: context, theme: AlertControllerTheme(presentationData: presentationData), ptheme: presentationData.theme, strings: strings, gift: gift, title: title, text: text, actions: actions)
let controller = AlertController(theme: AlertControllerTheme(presentationData: presentationData), contentNode: contentNode)
dismissImpl = { [weak controller] animated in
if animated {
controller?.dismissAnimated()
} else {
controller?.dismiss()
}
}
return controller
}

View File

@ -1108,8 +1108,14 @@ private class TrackView: UIView, UIScrollViewDelegate, UIGestureRecognizerDelega
self.rightOpaqueEdge = right
if let params = self.params {
let fullTrackHeight: CGFloat
if case .cover = params.style {
fullTrackHeight = trackHeight
} else {
fullTrackHeight = 33.0
}
self.updateThumbnailContainers(
scrubberSize: CGSize(width: params.availableSize.width, height: 33.0),
scrubberSize: CGSize(width: params.availableSize.width, height: fullTrackHeight),
availableSize: params.availableSize,
transition: transition
)

View File

@ -61,6 +61,7 @@ private func patternScaleValueAt(fraction: CGFloat, t: CGFloat, reverse: Bool) -
public final class PeerInfoCoverComponent: Component {
public enum Subject: Equatable {
case peer(EnginePeer)
case status(PeerEmojiStatus)
case custom(UIColor?, UIColor?, UIColor?, Int64?)
func colors(context: AccountContext, isDark: Bool) -> (UIColor, UIColor)? {
@ -73,6 +74,11 @@ public final class PeerInfoCoverComponent: Component {
} else {
return nil
}
case let .status(status):
if case let .starGift(_, _, _, _, _, innerColor, outerColor, _, _) = status.content {
return (UIColor(rgb: UInt32(bitPattern: innerColor)), UIColor(rgb: UInt32(bitPattern: outerColor)))
}
return nil
case let .custom(color, secondColor, _, _):
if let color {
if let secondColor {
@ -90,6 +96,11 @@ public final class PeerInfoCoverComponent: Component {
switch self {
case let .peer(peer):
return peer.profileBackgroundEmojiId
case let .status(status):
if case let .starGift(_, _, _, _, patternFileId, _, _, _, _) = status.content {
return patternFileId
}
return nil
case let .custom(_, _, _, fileId):
return fileId
}
@ -218,6 +229,9 @@ public final class PeerInfoCoverComponent: Component {
self.layer.addSublayer(self.avatarBackgroundPatternContentsLayer)
self.addSubview(self.backgroundPatternContainer)
self.layer.allowsGroupOpacity = true
self.backgroundView.layer.allowsGroupOpacity = true
}
required public init?(coder aDecoder: NSCoder) {
@ -332,11 +346,7 @@ public final class PeerInfoCoverComponent: Component {
let previousComponent = self.component
self.component = component
self.currentSize = availableSize
if case .custom = component.subject {
self.layer.allowsGroupOpacity = true
}
if previousComponent?.subject?.fileId != component.subject?.fileId {
if let fileId = component.subject?.fileId, fileId != 0 {
if self.patternContentsTarget == nil {
@ -399,6 +409,13 @@ public final class PeerInfoCoverComponent: Component {
self.backgroundGradientLayer.endPoint = CGPoint(x: 1.0, y: 1.0)
self.backgroundGradientLayer.type = .radial
self.backgroundGradientLayer.colors = [secondaryBackgroundColor.cgColor, backgroundColor.cgColor]
} else if case .status = component.subject {
gradientWidth = availableSize.width
self.backgroundView.backgroundColor = secondaryBackgroundColor
self.backgroundGradientLayer.startPoint = CGPoint(x: 0.5, y: component.avatarCenter.y / gradientHeight)
self.backgroundGradientLayer.endPoint = CGPoint(x: 1.0, y: 1.0)
self.backgroundGradientLayer.type = .radial
self.backgroundGradientLayer.colors = [backgroundColor.cgColor, secondaryBackgroundColor.cgColor]
} else {
gradientWidth = availableSize.width
self.backgroundView.backgroundColor = secondaryBackgroundColor
@ -438,6 +455,13 @@ public final class PeerInfoCoverComponent: Component {
patternColor.withAlphaComponent(0.6).cgColor,
patternColor.withAlphaComponent(0.0).cgColor
]
} else if case let .status(status) = component.subject, case let .starGift(_, _, _, _, _, _, _, patternColorValue, _) = status.content {
let patternColor = UIColor(rgb: UInt32(bitPattern: patternColorValue))
self.avatarBackgroundPatternContentsLayer.compositingFilter = nil
self.avatarBackgroundPatternContentsLayer.colors = [
patternColor.withAlphaComponent(0.6).cgColor,
patternColor.withAlphaComponent(0.0).cgColor
]
} else {
if component.subject?.colors(context: component.context, isDark: component.isDark) != nil {
self.avatarBackgroundPatternContentsLayer.compositingFilter = "overlayBlendMode"
@ -456,9 +480,10 @@ public final class PeerInfoCoverComponent: Component {
}
}
if case .custom = component.subject {
switch component.subject {
case .custom, .status:
self.avatarBackgroundGradientLayer.isHidden = true
} else {
default:
self.avatarBackgroundGradientLayer.isHidden = component.subject?.colors(context: component.context, isDark: component.isDark) == nil
}
transition.setFrame(layer: self.avatarBackgroundGradientLayer, frame: CGSize(width: 300.0, height: 300.0).centered(around: component.avatarCenter))

View File

@ -37,50 +37,54 @@ private enum RecommendedPeersListEntry: Comparable, Identifiable {
var stableId: RecommendedPeersListEntryStableId {
switch self {
case let .peer(_, _, peer, _):
return .peer(peer.id)
case let .peer(_, _, peer, _):
return .peer(peer.id)
}
}
static func ==(lhs: RecommendedPeersListEntry, rhs: RecommendedPeersListEntry) -> Bool {
switch lhs {
case let .peer(lhsTheme, lhsIndex, lhsPeer, lhsSubscribers):
if case let .peer(rhsTheme, rhsIndex, rhsPeer, rhsSubscribers) = rhs, lhsTheme === rhsTheme, lhsIndex == rhsIndex, lhsPeer == rhsPeer, lhsSubscribers == rhsSubscribers {
return true
} else {
return false
}
case let .peer(lhsTheme, lhsIndex, lhsPeer, lhsSubscribers):
if case let .peer(rhsTheme, rhsIndex, rhsPeer, rhsSubscribers) = rhs, lhsTheme === rhsTheme, lhsIndex == rhsIndex, lhsPeer == rhsPeer, lhsSubscribers == rhsSubscribers {
return true
} else {
return false
}
}
}
static func <(lhs: RecommendedPeersListEntry, rhs: RecommendedPeersListEntry) -> Bool {
switch lhs {
case let .peer(_, lhsIndex, _, _):
switch rhs {
case let .peer(_, rhsIndex, _, _):
return lhsIndex < rhsIndex
}
case let .peer(_, lhsIndex, _, _):
switch rhs {
case let .peer(_, rhsIndex, _, _):
return lhsIndex < rhsIndex
}
}
}
func item(context: AccountContext, presentationData: PresentationData, action: @escaping (EnginePeer) -> Void, openPeerContextAction: @escaping (Peer, ASDisplayNode, ContextGesture?) -> Void) -> ListViewItem {
switch self {
case let .peer(_, _, peer, subscribers):
let text: ItemListPeerItemText
if subscribers > 0 {
text = .text(presentationData.strings.Conversation_StatusSubscribers(subscribers), .secondary)
} else if let addressName = peer.addressName {
text = .text("@\(addressName)", .secondary)
case let .peer(_, _, peer, subscribers):
let text: ItemListPeerItemText
if subscribers > 0 {
if peer.id.namespace == Namespaces.Peer.CloudChannel {
text = .text(presentationData.strings.SharedMedia_SimilarChannel_Subscribers(subscribers), .secondary)
} else {
text = .none
text = .text(presentationData.strings.SharedMedia_SimilarBot_Users(subscribers), .secondary)
}
} else if let addressName = peer.addressName {
text = .text("@\(addressName)", .secondary)
} else {
text = .none
}
return ItemListPeerItem(presentationData: ItemListPresentationData(presentationData), dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, context: context, peer: peer, presence: nil, text: text, label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: false), switchValue: nil, enabled: true, selectable: true, sectionId: 0, action: {
action(peer)
}, setPeerIdWithRevealedOptions: { _, _ in
}, removePeer: { _ in
}, contextAction: { node, gesture in
openPeerContextAction(peer._asPeer(), node, gesture)
}, hasTopStripe: false, noInsets: true, noCorners: true, style: .plain, disableInteractiveTransitionIfNecessary: true)
action(peer)
}, setPeerIdWithRevealedOptions: { _, _ in
}, removePeer: { _ in
}, contextAction: { node, gesture in
openPeerContextAction(peer._asPeer(), node, gesture)
}, hasTopStripe: false, noInsets: true, noCorners: true, style: .plain, disableInteractiveTransitionIfNecessary: true)
}
}
}

View File

@ -102,6 +102,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
let backgroundBannerView: UIView
let backgroundCover = ComponentView<Empty>()
var didSetupBackgroundCover = false
let buttonsContainerNode: SparseNode
let buttonsBackgroundNode: NavigationBackgroundNode
let buttonsMaskView: UIView
@ -167,6 +168,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
var displayPremiumIntro: ((UIView, PeerEmojiStatus?, Signal<(TelegramMediaFile, LoadedStickerPack)?, NoError>, Bool) -> Void)?
var displayStatusPremiumIntro: (() -> Void)?
var displayUniqueGiftInfo: ((UIView, String) -> Void)?
var openUniqueGift: ((String) -> Void)?
var navigateToForum: (() -> Void)?
@ -175,6 +177,8 @@ final class PeerInfoHeaderNode: ASDisplayNode {
var backgroundAlpha: CGFloat = 1.0
var updateHeaderAlpha: ((CGFloat, ContainedViewLayoutTransition) -> Void)?
private(set) var contentButtonBackgroundColor: UIColor?
let animationCache: AnimationCache
let animationRenderer: MultiAnimationRenderer
@ -184,7 +188,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
var customNavigationContentNode: PeerInfoPanelNodeNavigationContentNode?
private var appliedCustomNavigationContentNode: PeerInfoPanelNodeNavigationContentNode?
private var validLayout: (width: CGFloat, deviceMetrics: DeviceMetrics)?
private var validLayout: (width: CGFloat, statusBarHeight: CGFloat, deviceMetrics: DeviceMetrics)?
init(context: AccountContext, controller: PeerInfoScreenImpl, avatarInitiallyExpanded: Bool, isOpenedFromChat: Bool, isMediaOnly: Bool, isSettings: Bool, isMyProfile: Bool, forumTopicThreadId: Int64?, chatLocation: ChatLocation) {
self.context = context
@ -410,13 +414,10 @@ final class PeerInfoHeaderNode: ASDisplayNode {
}
func invokeDisplayGiftInfo() {
guard case let .emojiStatus(status) = self.currentStatusIcon, case let .starGift(_, _, title, slug, _, _, _, _, _) = status.content else {
guard case let .emojiStatus(status) = self.currentStatusIcon, case let .starGift(_, _, title, _, _, _, _, _, _) = status.content else {
return
}
let slugComponents = slug.components(separatedBy: "-")
if let numberString = slugComponents.last {
self.displayUniqueGiftInfo?(self.isAvatarExpanded ? self.titleExpandedStatusIconView : self.titleStatusIconView, "\(title) #\(numberString)")
}
self.displayUniqueGiftInfo?(self.isAvatarExpanded ? self.titleExpandedStatusIconView : self.titleStatusIconView, title)
}
func initiateAvatarExpansion(gallery: Bool, first: Bool) {
@ -520,7 +521,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
self.avatarListNode.listContainerNode.peer = peer.flatMap(EnginePeer.init)
let isFirstTime = self.validLayout == nil
self.validLayout = (width, deviceMetrics)
self.validLayout = (width, statusBarHeight, deviceMetrics)
let previousPanelStatusData = self.currentPanelStatusData
self.currentPanelStatusData = panelStatusData.0
@ -620,7 +621,20 @@ final class PeerInfoHeaderNode: ASDisplayNode {
let expandedAvatarContentButtonForegroundColor: UIColor = .white
let regularNavigationContentsSecondaryColor: UIColor
if let profileColor = peer?.profileColor {
if let emojiStatus = peer?.emojiStatus, case let .starGift(_, _, _, _, _, innerColor, outerColor, _, _) = emojiStatus.content {
let mainColor = UIColor(rgb: UInt32(bitPattern: innerColor))
let secondaryColor = UIColor(rgb: UInt32(bitPattern: outerColor))
regularNavigationContentsSecondaryColor = UIColor(white: 1.0, alpha: 0.6).blitOver(mainColor.withMultiplied(hue: 1.0, saturation: 2.2, brightness: 1.5), alpha: 1.0)
let baseButtonBackgroundColor: UIColor
if presentationData.theme.overallDarkAppearance {
baseButtonBackgroundColor = UIColor(white: 0.0, alpha: 0.25)
} else {
baseButtonBackgroundColor = UIColor(white: 1.0, alpha: 0.25)
}
regularContentButtonBackgroundColor = baseButtonBackgroundColor.blendOver(background: mainColor)
regularHeaderButtonBackgroundColor = baseButtonBackgroundColor.blendOver(background: secondaryColor.mixedWith(mainColor, alpha: 0.1))
} else if let profileColor = peer?.profileColor {
let backgroundColors = self.context.peerNameColors.getProfile(profileColor, dark: presentationData.theme.overallDarkAppearance)
regularNavigationContentsSecondaryColor = UIColor(white: 1.0, alpha: 0.6).blitOver(backgroundColors.main.withMultiplied(hue: 1.0, saturation: 2.2, brightness: 1.5), alpha: 1.0)
@ -637,6 +651,8 @@ final class PeerInfoHeaderNode: ASDisplayNode {
regularContentButtonBackgroundColor = presentationData.theme.list.itemBlocksBackgroundColor
regularHeaderButtonBackgroundColor = .clear
}
self.contentButtonBackgroundColor = regularContentButtonBackgroundColor
let collapsedHeaderNavigationContentsSecondaryColor = presentationData.theme.list.itemSecondaryTextColor
let expandedAvatarNavigationContentsSecondaryColor: UIColor = .white
@ -700,7 +716,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
}
transition.updateAlpha(node: self.avatarListNode.avatarContainerNode.avatarNode, alpha: 1.0 - transitionFraction)
} else {
if deviceMetrics.hasDynamicIsland && !isLandscape {
if deviceMetrics.hasDynamicIsland && statusBarHeight > 0.0 && !isLandscape {
transitionSourceAvatarFrame = CGRect(origin: CGPoint(x: avatarFrame.minX, y: -20.0), size: avatarFrame.size).insetBy(dx: avatarSize * 0.4, dy: avatarSize * 0.4)
} else {
transitionSourceAvatarFrame = avatarFrame.offsetBy(dx: 0.0, dy: -avatarFrame.maxY).insetBy(dx: avatarSize * 0.4, dy: avatarSize * 0.4)
@ -869,6 +885,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
var currentEmojiStatus: PeerEmojiStatus?
var particleColor: UIColor?
var uniqueGiftSlug: String?
let emojiRegularStatusContent: EmojiStatusComponent.Content
let emojiExpandedStatusContent: EmojiStatusComponent.Content
@ -877,9 +894,9 @@ final class PeerInfoHeaderNode: ASDisplayNode {
currentEmojiStatus = emojiStatus
emojiRegularStatusContent = .animation(content: .customEmoji(fileId: emojiStatus.fileId), size: CGSize(width: 80.0, height: 80.0), placeholderColor: presentationData.theme.list.mediaPlaceholderColor, themeColor: navigationContentsAccentColor, loopMode: .forever)
emojiExpandedStatusContent = .animation(content: .customEmoji(fileId: emojiStatus.fileId), size: CGSize(width: 80.0, height: 80.0), placeholderColor: navigationContentsAccentColor, themeColor: navigationContentsAccentColor, loopMode: .forever)
if let _ = emojiStatus.color {
if case let .starGift(_, _, _, slug, _, _, _, _, _) = emojiStatus.content {
particleColor = UIColor.white
uniqueGiftSlug = slug
}
default:
emojiRegularStatusContent = .none
@ -900,8 +917,8 @@ final class PeerInfoHeaderNode: ASDisplayNode {
guard let strongSelf = self else {
return
}
if let _ = particleColor {
strongSelf.invokeDisplayGiftInfo()
if let uniqueGiftSlug {
strongSelf.openUniqueGift?(uniqueGiftSlug)
} else {
strongSelf.displayPremiumIntro?(strongSelf.titleStatusIconView, currentEmojiStatus, strongSelf.emojiStatusFileAndPackTitle.get(), false)
}
@ -961,8 +978,8 @@ final class PeerInfoHeaderNode: ASDisplayNode {
guard let strongSelf = self else {
return
}
if let _ = particleColor {
strongSelf.invokeDisplayGiftInfo()
if let uniqueGiftSlug {
strongSelf.openUniqueGift?(uniqueGiftSlug)
} else {
strongSelf.displayPremiumIntro?(strongSelf.titleExpandedStatusIconView, currentEmojiStatus, strongSelf.emojiStatusFileAndPackTitle.get(), true)
}
@ -1746,7 +1763,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
controlsClippingFrame = apparentAvatarFrame
}
let avatarClipOffset: CGFloat = !self.isAvatarExpanded && deviceMetrics.hasDynamicIsland && self.avatarClippingNode.clipsToBounds && !isLandscape ? 47.0 : 0.0
let avatarClipOffset: CGFloat = !self.isAvatarExpanded && deviceMetrics.hasDynamicIsland && statusBarHeight > 0.0 && self.avatarClippingNode.clipsToBounds && !isLandscape ? 47.0 : 0.0
let clippingNodeTransition = ContainedViewLayoutTransition.immediate
clippingNodeTransition.updateFrame(layer: self.avatarClippingNode.layer, frame: CGRect(origin: CGPoint(x: 0.0, y: avatarClipOffset), size: CGSize(width: width, height: 1000.0)))
clippingNodeTransition.updateSublayerTransformOffset(layer: self.avatarClippingNode.layer, offset: CGPoint(x: 0.0, y: -avatarClipOffset))
@ -1805,7 +1822,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
transition.updateSublayerTransformScale(node: self.avatarListNode.listContainerTransformNode, scale: avatarListContainerScale)
}
if deviceMetrics.hasDynamicIsland && self.forumTopicThreadId == nil && self.navigationTransition == nil && !isLandscape {
if deviceMetrics.hasDynamicIsland && statusBarHeight > 0.0 && self.forumTopicThreadId == nil && self.navigationTransition == nil && !isLandscape {
let maskValue = max(0.0, min(1.0, contentOffset / 120.0))
self.avatarListNode.containerNode.view.mask = self.avatarListNode.maskNode.view
if maskValue > 0.03 {
@ -2246,15 +2263,18 @@ final class PeerInfoHeaderNode: ASDisplayNode {
let backgroundCoverSubject: PeerInfoCoverComponent.Subject?
var backgroundCoverAnimateIn = false
if let status = peer?.emojiStatus, case let .starGift(_, _, _, _, patternFileId, innerColor, outerColor, patternColor, _) = status.content {
backgroundCoverSubject = .custom(UIColor(rgb: UInt32(bitPattern: innerColor)), UIColor(rgb: UInt32(bitPattern: outerColor)), UIColor(rgb: UInt32(bitPattern: patternColor)), patternFileId)
backgroundCoverAnimateIn = true
if let status = peer?.emojiStatus, case .starGift = status.content {
backgroundCoverSubject = .status(status)
if !self.didSetupBackgroundCover {
backgroundCoverAnimateIn = true
self.didSetupBackgroundCover = true
}
} else if let peer {
backgroundCoverSubject = .peer(EnginePeer(peer))
} else {
backgroundCoverSubject = nil
}
let backgroundCoverSize = self.backgroundCover.update(
transition: ComponentTransition(transition),
component: AnyComponent(PeerInfoCoverComponent(
@ -2274,28 +2294,27 @@ final class PeerInfoHeaderNode: ASDisplayNode {
if let backgroundCoverView = self.backgroundCover.view as? PeerInfoCoverComponent.View {
if backgroundCoverView.superview == nil {
self.backgroundBannerView.addSubview(backgroundCoverView)
if backgroundCoverAnimateIn {
if !self.isAvatarExpanded {
backgroundCoverView.willAnimateIn()
Queue.mainQueue().after(0.2) {
backgroundCoverView.animateIn()
}
Queue.mainQueue().after(0.44) {
self.invokeDisplayGiftInfo()
}
} else {
Queue.mainQueue().after(0.44) {
self.invokeDisplayGiftInfo()
}
}
}
}
if additive {
transition.updateFrameAdditive(view: backgroundCoverView, frame: CGRect(origin: CGPoint(x: -3.0, y: bannerFrame.height - backgroundCoverSize.height - bannerInset), size: backgroundCoverSize))
} else {
transition.updateFrame(view: backgroundCoverView, frame: CGRect(origin: CGPoint(x: 0.0, y: bannerFrame.height - backgroundCoverSize.height - bannerInset), size: backgroundCoverSize))
}
if backgroundCoverAnimateIn {
if !self.isAvatarExpanded {
backgroundCoverView.willAnimateIn()
Queue.mainQueue().after(0.2) {
backgroundCoverView.animateIn()
}
Queue.mainQueue().after(0.44) {
self.invokeDisplayGiftInfo()
}
} else {
Queue.mainQueue().after(0.44) {
self.invokeDisplayGiftInfo()
}
}
}
}
if additive {
@ -2438,7 +2457,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
}
private func updateAvatarMask(transition: ContainedViewLayoutTransition) {
guard let (width, deviceMetrics) = self.validLayout, deviceMetrics.hasDynamicIsland else {
guard let (width, statusBarHeight, deviceMetrics) = self.validLayout, deviceMetrics.hasDynamicIsland && statusBarHeight > 0.0 else {
return
}
let maskScale: CGFloat = isAvatarExpanded ? width / 100.0 : 1.0
@ -2446,7 +2465,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
transition.updateTransformScale(layer: self.avatarListNode.bottomCoverNode.layer, scale: maskScale)
transition.updateTransformScale(layer: self.avatarListNode.topCoverNode.layer, scale: maskScale)
let maskAnchorPoint = CGPoint(x: 0.5, y: isAvatarExpanded ? 0.37 : 0.5)
let maskAnchorPoint = CGPoint(x: 0.5, y: self.isAvatarExpanded ? 0.37 : 0.5)
transition.updateAnchorPoint(layer: self.avatarListNode.maskNode.layer, anchorPoint: maskAnchorPoint)
}
}

View File

@ -2018,7 +2018,7 @@ private func editingItems(data: PeerInfoScreenData?, state: PeerInfoState, chatL
}
if let cachedUserData = data.cachedData as? CachedUserData, let _ = cachedUserData.botInfo?.verifierSettings {
items[.peerVerifySettings]!.append(PeerInfoScreenActionItem(id: ItemVerify, text: "Verify Accounts", icon: UIImage(bundleImageName: "Peer Info/BotVerify"), action: {
items[.peerVerifySettings]!.append(PeerInfoScreenActionItem(id: ItemVerify, text: presentationData.strings.PeerInfo_VerifyAccounts, icon: UIImage(bundleImageName: "Peer Info/BotVerify"), action: {
interaction.editingOpenVerifyAccounts()
}))
}
@ -4666,12 +4666,20 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
return
}
let sourceRect = sourceView.convert(sourceView.bounds, to: controller.view)
let backgroundColor: UIColor
if !self.headerNode.isAvatarExpanded, let contentButtonBackgroundColor = self.headerNode.contentButtonBackgroundColor {
backgroundColor = contentButtonBackgroundColor
} else {
backgroundColor = UIColor(rgb: 0x000000, alpha: 0.65)
}
let tooltipController = TooltipScreen(
context: self.context,
account: self.context.account,
sharedContext: self.context.sharedContext,
text: .attributedString(text: NSAttributedString(string: text, font: Font.semibold(11.0), textColor: .white)),
style: .customBlur(UIColor(rgb: self.headerNode.isAvatarExpanded ? 0x000000 : 0x92c8de, alpha: 0.65), -4.0),
style: .customBlur(backgroundColor, -4.0),
arrowStyle: .small,
location: .point(sourceRect, .bottom),
cornerRadius: 10.0,
@ -4682,6 +4690,13 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
controller.present(tooltipController, in: .current)
}
self.headerNode.openUniqueGift = { [weak self] slug in
guard let self else {
return
}
self.openUrl(url: "https://t.me/nft/\(slug)", concealed: false, external: false)
}
self.headerNode.displayStatusPremiumIntro = { [weak self] in
guard let self else {
return
@ -6482,6 +6497,17 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
}
} else if let channel = peer as? TelegramChannel {
if let cachedData = strongSelf.data?.cachedData as? CachedChannelData {
if case .broadcast = channel.info {
//TODO:localize
items.append(.action(ContextMenuActionItem(text: "Send a Gift", badge: nil, icon: { theme in
generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Gift"), color: theme.contextMenu.primaryColor)
}, action: { [weak self] _, f in
f(.dismissWithoutContent)
self?.openPremiumGift()
})))
}
let boostTitle: String
var isNew = false
switch channel.info {
@ -9798,9 +9824,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
}
private func openPremiumGift() {
guard let premiumGiftOptions = self.data?.premiumGiftOptions else {
return
}
let premiumGiftOptions = self.data?.premiumGiftOptions ?? []
let premiumOptions = premiumGiftOptions.filter { $0.users == 1 }.map { CachedPremiumGiftOption(months: $0.months, currency: $0.currency, amount: $0.amount, botUrl: "", storeProductId: $0.storeProductId) }
let controller = self.context.sharedContext.makeGiftOptionsController(
@ -11906,6 +11930,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
}
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
cancelContextGestures(view: scrollView)
self.canAddVelocity = true
self.canOpenAvatarByDragging = self.headerNode.isAvatarExpanded
self.paneContainerNode.currentPane?.node.cancelPreviewGestures()
@ -14063,3 +14088,16 @@ private final class HeaderContextReferenceContentSource: ContextReferenceContent
return ContextControllerReferenceViewInfo(referenceView: self.sourceView, contentAreaInScreenSpace: UIScreen.main.bounds)
}
}
private func cancelContextGestures(view: UIView) {
if let gestureRecognizers = view.gestureRecognizers {
for gesture in gestureRecognizers {
if let gesture = gesture as? ContextGesture {
gesture.cancel()
}
}
}
for subview in view.subviews {
cancelContextGestures(view: subview)
}
}

View File

@ -226,29 +226,29 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
let controller = GiftViewScreen(
context: self.context,
subject: .profileGift(self.peerId, product),
updateSavedToProfile: { [weak self] messageId, added in
updateSavedToProfile: { [weak self] reference, added in
guard let self else {
return
}
self.profileGifts.updateStarGiftAddedToProfile(messageId: messageId, added: added)
self.profileGifts.updateStarGiftAddedToProfile(reference: reference, added: added)
},
convertToStars: { [weak self] in
guard let self, let messageId = product.messageId else {
guard let self else {
return
}
self.profileGifts.convertStarGift(messageId: messageId)
self.profileGifts.convertStarGift(reference: product.reference)
},
transferGift: { [weak self] prepaid, peerId in
guard let self, let messageId = product.messageId else {
guard let self else {
return
}
self.profileGifts.transferStarGift(prepaid: prepaid, messageId: messageId, peerId: peerId)
self.profileGifts.transferStarGift(prepaid: prepaid, reference: product.reference, peerId: peerId)
},
upgradeGift: { [weak self] formId, keepOriginalInfo in
guard let self, let messageId = product.messageId else {
guard let self else {
return .never()
}
return self.profileGifts.upgradeStarGift(formId: formId, messageId: messageId, keepOriginalInfo: keepOriginalInfo)
return self.profileGifts.upgradeStarGift(formId: formId, reference: product.reference, keepOriginalInfo: keepOriginalInfo)
},
shareStory: { [weak self] in
guard let self, case let .unique(uniqueGift) = product.gift, let parentController = self.parentController else {

View File

@ -28,7 +28,8 @@ public final class GiftAvatarComponent: Component {
let avatarSize: CGFloat
let color: UIColor?
let offset: CGFloat?
var hasLargeParticles: Bool
let hasLargeParticles: Bool
let action: (() -> Void)?
public init(
context: AccountContext,
@ -41,7 +42,8 @@ public final class GiftAvatarComponent: Component {
avatarSize: CGFloat = 100.0,
color: UIColor? = nil,
offset: CGFloat? = nil,
hasLargeParticles: Bool = false
hasLargeParticles: Bool = false,
action: (() -> Void)? = nil
) {
self.context = context
self.theme = theme
@ -54,6 +56,7 @@ public final class GiftAvatarComponent: Component {
self.color = color
self.offset = offset
self.hasLargeParticles = hasLargeParticles
self.action = action
}
public static func ==(lhs: GiftAvatarComponent, rhs: GiftAvatarComponent) -> Bool {
@ -137,7 +140,11 @@ public final class GiftAvatarComponent: Component {
private var delayTapsTill: Double?
@objc private func handleTap(_ gesture: UITapGestureRecognizer) {
self.playAppearanceAnimation(velocity: nil, mirror: false, explode: true)
if let action = self.component?.action {
action()
} else {
self.playAppearanceAnimation(velocity: nil, mirror: false, explode: true)
}
}
private var didSetup = false

View File

@ -2682,38 +2682,37 @@ final class StoryItemSetContainerSendMessage {
return
}
let context = component.context
controller.dismissWithoutTransitionOut(completion: {
switch navigation {
case let .chat(_, subject, peekData):
if case let .channel(channel) = peerId, channel.flags.contains(.isForum) {
context.sharedContext.navigateToForumChannel(context: context, peerId: peerId.id, navigationController: navigationController)
} else {
context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peerId), subject: subject, keepStack: .always, peekData: peekData, pushController: { [weak navigationController] chatController, animated, completion in
Queue.mainQueue().justDispatch {
navigationController?.pushViewController(chatController)
}
}))
}
case .info:
let _ = (context.account.postbox.loadedPeerWithId(peerId.id)
|> take(1)
|> deliverOnMainQueue).start(next: { [weak navigationController] peer in
if peer.restrictionText(platform: "ios", contentSettings: context.currentContentSettings.with { $0 }) == nil {
if let infoController = context.sharedContext.makePeerInfoController(context: context, updatedPresentationData: nil, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false, requestsContext: nil) {
navigationController?.pushViewController(infoController)
}
switch navigation {
case let .chat(_, subject, peekData):
if case let .channel(channel) = peerId, channel.flags.contains(.isForum) {
controller.dismissWithoutTransitionOut()
context.sharedContext.navigateToForumChannel(context: context, peerId: peerId.id, navigationController: navigationController)
} else {
context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peerId), subject: subject, keepStack: .always, peekData: peekData, pushController: { [weak navigationController] chatController, animated, completion in
Queue.mainQueue().justDispatch {
navigationController?.pushViewController(chatController)
}
})
case let .withBotStartPayload(startPayload):
context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peerId), botStart: startPayload, keepStack: .always))
case let .withAttachBot(attachBotStart):
context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peerId), attachBotStart: attachBotStart))
case let .withBotApp(botAppStart):
context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peerId), botAppStart: botAppStart))
default:
break
}))
}
})
case .info:
let _ = (context.account.postbox.loadedPeerWithId(peerId.id)
|> take(1)
|> deliverOnMainQueue).start(next: { [weak navigationController] peer in
if peer.restrictionText(platform: "ios", contentSettings: context.currentContentSettings.with { $0 }) == nil {
if let infoController = context.sharedContext.makePeerInfoController(context: context, updatedPresentationData: nil, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false, requestsContext: nil) {
navigationController?.pushViewController(infoController)
}
}
})
case let .withBotStartPayload(startPayload):
context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peerId), botStart: startPayload, keepStack: .always))
case let .withAttachBot(attachBotStart):
context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peerId), attachBotStart: attachBotStart))
case let .withBotApp(botAppStart):
context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peerId), botAppStart: botAppStart))
default:
break
}
},
sendFile: nil,
sendSticker: nil,
@ -3342,14 +3341,14 @@ final class StoryItemSetContainerSendMessage {
useGesturePosition = true
let action = { [weak self, weak view, weak controller] in
let _ = ((context.engine.messages.getMessagesLoadIfNecessary([messageId], strategy: .cloud(skipLocal: true))
|> mapToSignal { result -> Signal<Message?, GetMessagesError> in
|> mapToSignal { result -> Signal<Message?, GetMessagesError> in
if case let .result(messages) = result {
return .single(messages.first)
} else {
return .complete()
}
})
|> deliverOnMainQueue).startStandalone(next: { [weak self, weak view, weak controller] message in
|> deliverOnMainQueue).startStandalone(next: { [weak self, weak view, weak controller] message in
guard let self, let view else {
return
}
@ -3365,7 +3364,7 @@ final class StoryItemSetContainerSendMessage {
switch error {
case .privateChannel:
let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: messageId.peerId))
|> deliverOnMainQueue).startStandalone(next: { [weak self, weak view] peer in
|> deliverOnMainQueue).startStandalone(next: { [weak self, weak view] peer in
guard let self, let view else {
return
}

View File

@ -1238,7 +1238,7 @@ public class VideoMessageCameraScreen: ViewController {
if let controller = self.controller, let layout = self.validLayout {
let insets = layout.insets(options: .input)
if point.y > layout.size.height - insets.bottom - controller.inputPanelFrame.0.height {
if point.y > layout.size.height - max(insets.bottom, layout.additionalInsets.bottom) - controller.inputPanelFrame.0.height {
if layout.metrics.isTablet {
if point.x < layout.size.width * 0.33 {
return result

View File

@ -4325,12 +4325,17 @@ extension ChatControllerImpl {
return true
}), in: .current)
}, openPremiumGift: { [weak self] in
guard let strongSelf = self, let peerId = strongSelf.chatLocation.peerId else {
guard let self, let peerId = self.chatLocation.peerId else {
return
}
strongSelf.presentAttachmentMenu(subject: .gift)
Queue.mainQueue().after(0.5) {
let _ = ApplicationSpecificNotice.incrementDismissedPremiumGiftSuggestion(accountManager: strongSelf.context.sharedContext.accountManager, peerId: peerId, timestamp: Int32(Date().timeIntervalSince1970)).startStandalone()
if peerId.namespace == Namespaces.Peer.CloudUser {
self.presentAttachmentMenu(subject: .gift)
Queue.mainQueue().after(0.5) {
let _ = ApplicationSpecificNotice.incrementDismissedPremiumGiftSuggestion(accountManager: self.context.sharedContext.accountManager, peerId: peerId, timestamp: Int32(Date().timeIntervalSince1970)).startStandalone()
}
} else {
let controller = self.context.sharedContext.makeGiftOptionsController(context: self.context, peerId: peerId, premiumOptions: [], hasBirthday: false)
self.push(controller)
}
}, openPremiumRequiredForMessaging: { [weak self] in
guard let self else {

View File

@ -1213,8 +1213,21 @@ func openResolvedUrlImpl(
})
case let .collectible(gift):
if let gift {
let controller = context.sharedContext.makeGiftViewScreen(context: context, gift: gift, shareStory: nil)
var dismissedImpl: (() -> Void)?
if let storyProgressPauseContext = contentContext as? StoryProgressPauseContext {
let updateExternalController = storyProgressPauseContext.update
dismissedImpl = {
updateExternalController(nil)
}
}
let controller = context.sharedContext.makeGiftViewScreen(context: context, gift: gift, shareStory: nil, dismissed: {
dismissedImpl?()
})
navigationController?.pushViewController(controller)
if let storyProgressPauseContext = contentContext as? StoryProgressPauseContext {
storyProgressPauseContext.update(controller)
}
} else {
present(textAlertController(context: context, updatedPresentationData: updatedPresentationData, title: nil, text: presentationData.strings.Login_UnknownError, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil)
}

View File

@ -2927,8 +2927,12 @@ public final class SharedAccountContextImpl: SharedAccountContext {
return GiftViewScreen(context: context, subject: .message(message), shareStory: shareStory)
}
public func makeGiftViewScreen(context: AccountContext, gift: StarGift.UniqueGift, shareStory: (() -> Void)?) -> ViewController {
return GiftViewScreen(context: context, subject: .uniqueGift(gift), shareStory: shareStory)
public func makeGiftViewScreen(context: AccountContext, gift: StarGift.UniqueGift, shareStory: (() -> Void)?, dismissed: (() -> Void)?) -> ViewController {
let controller = GiftViewScreen(context: context, subject: .uniqueGift(gift), shareStory: shareStory)
controller.disposed = {
dismissed?()
}
return controller
}
public func makeStorySharingScreen(context: AccountContext, subject: StorySharingSubject, parentController: ViewController) -> ViewController {