From f137e27944c0b3ab1bb8c1896bb86a0aaf7e1efe Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Thu, 16 Jan 2025 02:16:28 +0400 Subject: [PATCH] Update API --- .../Telegram-iOS/en.lproj/Localizable.strings | 11 + .../Sources/AccountContext.swift | 2 +- .../AccountContext/Sources/Premium.swift | 2 +- .../Sources/Node/ChatListItem.swift | 8 +- .../Sources/ContactsPeerItem.swift | 2 +- .../Editor/ArrowRight.imageset/Contents.json | 12 + .../Editor/ArrowRight.imageset/more.pdf | 79 +++++ .../Sources/TGCameraController.m | 2 +- .../Sources/TGCameraMainPhoneView.m | 11 + .../Sources/TGCameraMainTabletView.m | 3 +- .../Sources/TGCameraMainView.m | 2 +- .../Sources/CreateGiveawayController.swift | 12 +- submodules/TelegramApi/Sources/Api0.swift | 25 +- submodules/TelegramApi/Sources/Api10.swift | 62 ++-- submodules/TelegramApi/Sources/Api12.swift | 62 ++++ submodules/TelegramApi/Sources/Api15.swift | 24 +- submodules/TelegramApi/Sources/Api16.swift | 14 +- submodules/TelegramApi/Sources/Api23.swift | 80 +++++ submodules/TelegramApi/Sources/Api35.swift | 138 ++++---- submodules/TelegramApi/Sources/Api38.swift | 105 +++--- submodules/TelegramApi/Sources/Api4.swift | 18 +- .../ApiUtils/TelegramMediaAction.swift | 4 +- .../SyncCore/SyncCore_CachedUserData.swift | 26 ++ .../SyncCore_TelegramMediaAction.swift | 16 +- .../Payments/BotPaymentForm.swift | 18 +- .../TelegramEngine/Payments/StarGifts.swift | 319 ++++++++++++------ .../TelegramEngine/Payments/Stars.swift | 2 +- .../Payments/TelegramEnginePayments.swift | 16 +- .../Peers/UpdateCachedPeerData.swift | 4 +- .../Sources/ServiceMessageStrings.swift | 2 +- .../ChatChannelSubscriberInputPanelNode/BUILD | 1 + .../ChatMessageGiftBubbleContentNode.swift | 11 +- .../ChatMessageWebpageBubbleContentNode.swift | 179 +++++----- .../ChatTitleView/Sources/ChatTitleView.swift | 17 +- .../Sources/GiftCompositionComponent.swift | 4 +- .../Sources/GiftOptionsScreen.swift | 41 ++- .../Sources/ChatGiftPreviewItem.swift | 25 +- .../Sources/GiftSetupScreen.swift | 42 ++- .../Sources/GiftViewScreen.swift | 42 +-- .../Sources/GiftWithdrawAlertController.swift | 293 ++++++++++++++++ .../Sources/MediaScrubberComponent.swift | 8 +- .../Sources/PeerInfoCoverComponent.swift | 39 ++- .../Panes/PeerInfoRecommendedPeersPane.swift | 56 +-- .../Sources/PeerInfoHeaderNode.swift | 97 +++--- .../Sources/PeerInfoScreen.swift | 48 ++- .../Sources/PeerInfoGiftsPaneNode.swift | 16 +- .../Sources/GiftAvatarComponent.swift | 13 +- ...StoryItemSetContainerViewSendMessage.swift | 65 ++-- .../Sources/VideoMessageCameraScreen.swift | 2 +- .../Chat/ChatControllerLoadDisplayNode.swift | 13 +- .../TelegramUI/Sources/OpenResolvedUrl.swift | 15 +- .../Sources/SharedAccountContext.swift | 8 +- 52 files changed, 1523 insertions(+), 593 deletions(-) create mode 100644 submodules/LegacyComponents/LegacyImages.xcassets/Editor/ArrowRight.imageset/Contents.json create mode 100644 submodules/LegacyComponents/LegacyImages.xcassets/Editor/ArrowRight.imageset/more.pdf create mode 100644 submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftWithdrawAlertController.swift diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 44ca74299d..430e787c3f 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -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"; diff --git a/submodules/AccountContext/Sources/AccountContext.swift b/submodules/AccountContext/Sources/AccountContext.swift index 882f544521..8f0efa7d62 100644 --- a/submodules/AccountContext/Sources/AccountContext.swift +++ b/submodules/AccountContext/Sources/AccountContext.swift @@ -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 diff --git a/submodules/AccountContext/Sources/Premium.swift b/submodules/AccountContext/Sources/Premium.swift index 8441c46050..b07630716e 100644 --- a/submodules/AccountContext/Sources/Premium.swift +++ b/submodules/AccountContext/Sources/Premium.swift @@ -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?) } diff --git a/submodules/ChatListUI/Sources/Node/ChatListItem.swift b/submodules/ChatListUI/Sources/Node/ChatListItem.swift index 5146d1deee..33eda799d4 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListItem.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListItem.swift @@ -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) diff --git a/submodules/ContactsPeerItem/Sources/ContactsPeerItem.swift b/submodules/ContactsPeerItem/Sources/ContactsPeerItem.swift index 035ef01b1c..60b5b64dbb 100644 --- a/submodules/ContactsPeerItem/Sources/ContactsPeerItem.swift +++ b/submodules/ContactsPeerItem/Sources/ContactsPeerItem.swift @@ -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 diff --git a/submodules/LegacyComponents/LegacyImages.xcassets/Editor/ArrowRight.imageset/Contents.json b/submodules/LegacyComponents/LegacyImages.xcassets/Editor/ArrowRight.imageset/Contents.json new file mode 100644 index 0000000000..9d3f9124cb --- /dev/null +++ b/submodules/LegacyComponents/LegacyImages.xcassets/Editor/ArrowRight.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "more.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/LegacyComponents/LegacyImages.xcassets/Editor/ArrowRight.imageset/more.pdf b/submodules/LegacyComponents/LegacyImages.xcassets/Editor/ArrowRight.imageset/more.pdf new file mode 100644 index 0000000000..82da70ea58 --- /dev/null +++ b/submodules/LegacyComponents/LegacyImages.xcassets/Editor/ArrowRight.imageset/more.pdf @@ -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 \ No newline at end of file diff --git a/submodules/LegacyComponents/Sources/TGCameraController.m b/submodules/LegacyComponents/Sources/TGCameraController.m index bd0fec83a4..49e7bf16ae 100644 --- a/submodules/LegacyComponents/Sources/TGCameraController.m +++ b/submodules/LegacyComponents/Sources/TGCameraController.m @@ -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) diff --git a/submodules/LegacyComponents/Sources/TGCameraMainPhoneView.m b/submodules/LegacyComponents/Sources/TGCameraMainPhoneView.m index 8887b8165e..2016bea4bf 100644 --- a/submodules/LegacyComponents/Sources/TGCameraMainPhoneView.m +++ b/submodules/LegacyComponents/Sources/TGCameraMainPhoneView.m @@ -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; diff --git a/submodules/LegacyComponents/Sources/TGCameraMainTabletView.m b/submodules/LegacyComponents/Sources/TGCameraMainTabletView.m index c4ce724045..5e92aecb0b 100644 --- a/submodules/LegacyComponents/Sources/TGCameraMainTabletView.m +++ b/submodules/LegacyComponents/Sources/TGCameraMainTabletView.m @@ -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; } diff --git a/submodules/LegacyComponents/Sources/TGCameraMainView.m b/submodules/LegacyComponents/Sources/TGCameraMainView.m index f5a363e0dd..447fa0d9b9 100644 --- a/submodules/LegacyComponents/Sources/TGCameraMainView.m +++ b/submodules/LegacyComponents/Sources/TGCameraMainView.m @@ -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) { } diff --git a/submodules/PremiumUI/Sources/CreateGiveawayController.swift b/submodules/PremiumUI/Sources/CreateGiveawayController.swift index e77b52af64..cb1b3ce206 100644 --- a/submodules/PremiumUI/Sources/CreateGiveawayController.swift +++ b/submodules/PremiumUI/Sources/CreateGiveawayController.swift @@ -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 } diff --git a/submodules/TelegramApi/Sources/Api0.swift b/submodules/TelegramApi/Sources/Api0.swift index 39e076cb80..7f2dc257bb 100644 --- a/submodules/TelegramApi/Sources/Api0.swift +++ b/submodules/TelegramApi/Sources/Api0.swift @@ -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: diff --git a/submodules/TelegramApi/Sources/Api10.swift b/submodules/TelegramApi/Sources/Api10.swift index b5828fb64d..95e3159949 100644 --- a/submodules/TelegramApi/Sources/Api10.swift +++ b/submodules/TelegramApi/Sources/Api10.swift @@ -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 diff --git a/submodules/TelegramApi/Sources/Api12.swift b/submodules/TelegramApi/Sources/Api12.swift index 1d2c67cb5a..a01a8cf8bd 100644 --- a/submodules/TelegramApi/Sources/Api12.swift +++ b/submodules/TelegramApi/Sources/Api12.swift @@ -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) diff --git a/submodules/TelegramApi/Sources/Api15.swift b/submodules/TelegramApi/Sources/Api15.swift index 5ed410d6d3..0f403f507d 100644 --- a/submodules/TelegramApi/Sources/Api15.swift +++ b/submodules/TelegramApi/Sources/Api15.swift @@ -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 diff --git a/submodules/TelegramApi/Sources/Api16.swift b/submodules/TelegramApi/Sources/Api16.swift index 22fdd7dbed..69a2c00f73 100644 --- a/submodules/TelegramApi/Sources/Api16.swift +++ b/submodules/TelegramApi/Sources/Api16.swift @@ -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 diff --git a/submodules/TelegramApi/Sources/Api23.swift b/submodules/TelegramApi/Sources/Api23.swift index a704866611..bac6ae40c7 100644 --- a/submodules/TelegramApi/Sources/Api23.swift +++ b/submodules/TelegramApi/Sources/Api23.swift @@ -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) diff --git a/submodules/TelegramApi/Sources/Api35.swift b/submodules/TelegramApi/Sources/Api35.swift index c6df005355..2cbede3079 100644 --- a/submodules/TelegramApi/Sources/Api35.swift +++ b/submodules/TelegramApi/Sources/Api35.swift @@ -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]?) diff --git a/submodules/TelegramApi/Sources/Api38.swift b/submodules/TelegramApi/Sources/Api38.swift index 3a8468e0ac..ded9ca98a0 100644 --- a/submodules/TelegramApi/Sources/Api38.swift +++ b/submodules/TelegramApi/Sources/Api38.swift @@ -9088,11 +9088,11 @@ public extension Api.functions.payments { } } public extension Api.functions.payments { - static func convertStarGift(msgId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + static func convertStarGift(stargift: Api.InputSavedStarGift) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { 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) { + 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) { + 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) { 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) { - 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) { - 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) { 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) { + static func saveStarGift(flags: Int32, stargift: Api.InputSavedStarGift) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { 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) { + static func transferStarGift(stargift: Api.InputSavedStarGift, toId: Api.InputUser) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { 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) { + static func upgradeStarGift(flags: Int32, stargift: Api.InputSavedStarGift) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { 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() { diff --git a/submodules/TelegramApi/Sources/Api4.swift b/submodules/TelegramApi/Sources/Api4.swift index 5f8b6c89b9..61ec221f34 100644 --- a/submodules/TelegramApi/Sources/Api4.swift +++ b/submodules/TelegramApi/Sources/Api4.swift @@ -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 diff --git a/submodules/TelegramCore/Sources/ApiUtils/TelegramMediaAction.swift b/submodules/TelegramCore/Sources/ApiUtils/TelegramMediaAction.swift index ec8a8046fa..68b3e4b2de 100644 --- a/submodules/TelegramCore/Sources/ApiUtils/TelegramMediaAction.swift +++ b/submodules/TelegramCore/Sources/ApiUtils/TelegramMediaAction.swift @@ -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 diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedUserData.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedUserData.swift index c1d130f18b..97156789d8 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedUserData.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedUserData.swift @@ -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 { diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaAction.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaAction.swift index a0dd0fbc3f..2279d8fc10 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaAction.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaAction.swift @@ -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") diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Payments/BotPaymentForm.swift b/submodules/TelegramCore/Sources/TelegramEngine/Payments/BotPaymentForm.swift index c5ae9f3fce..99b7824487 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Payments/BotPaymentForm.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Payments/BotPaymentForm.swift @@ -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) } } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Payments/StarGifts.swift b/submodules/TelegramCore/Sources/TelegramEngine/Payments/StarGifts.swift index bfeb70e88f..f3de00396c 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Payments/StarGifts.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Payments/StarGifts.swift @@ -668,59 +668,78 @@ func managedStarGiftsUpdates(postbox: Postbox, network: Network) -> Signal then(.complete() |> suspendAwareDelay(1.0 * 60.0 * 60.0, queue: Queue.concurrentDefaultQueue()))) |> restart } -func _internal_convertStarGift(account: Account, messageId: EngineMessage.Id) -> Signal { - return account.network.request(Api.functions.payments.convertStarGift(msgId: messageId.id)) - |> map(Optional.init) - |> `catch` { _ -> Signal in - return .single(nil) +func _internal_convertStarGift(account: Account, reference: StarGiftReference) -> Signal { + 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 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 { +func _internal_updateStarGiftAddedToProfile(account: Account, reference: StarGiftReference, added: Bool) -> Signal { 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 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 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 { - 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 { + 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 in - guard let inputUser else { + |> mapToSignal { inputUserAndStarGift -> Signal 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 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 { +func _internal_upgradeStarGift(account: Account, formId: Int64?, reference: StarGiftReference, keepOriginalInfo: Bool) -> Signal { 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 in + |> `catch` { _ -> Signal 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 { + func upgradeStarGift(formId: Int64?, reference: StarGiftReference, keepOriginalInfo: Bool) -> Signal { 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 { + public func upgradeStarGift(formId: Int64?, reference: StarGiftReference, keepOriginalInfo: Bool) -> Signal { 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 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) + } + } +} diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Payments/Stars.swift b/submodules/TelegramCore/Sources/TelegramEngine/Payments/Stars.swift index 2fb2492280..3797899715 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Payments/Stars.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Payments/Stars.swift @@ -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, diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Payments/TelegramEnginePayments.swift b/submodules/TelegramCore/Sources/TelegramEngine/Payments/TelegramEnginePayments.swift index 6ab372a3d2..ce9b5db187 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Payments/TelegramEnginePayments.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Payments/TelegramEnginePayments.swift @@ -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 { - return _internal_convertStarGift(account: self.account, messageId: messageId) + public func convertStarGift(reference: StarGiftReference) -> Signal { + return _internal_convertStarGift(account: self.account, reference: reference) } - public func updateStarGiftAddedToProfile(messageId: EngineMessage.Id, added: Bool) -> Signal { - return _internal_updateStarGiftAddedToProfile(account: self.account, messageId: messageId, added: added) + public func updateStarGiftAddedToProfile(reference: StarGiftReference, added: Bool) -> Signal { + return _internal_updateStarGiftAddedToProfile(account: self.account, reference: reference, added: added) } - public func transferStarGift(prepaid: Bool, messageId: EngineMessage.Id, peerId: EnginePeer.Id) -> Signal { - return _internal_transferStarGift(account: self.account, prepaid: prepaid, messageId: messageId, peerId: peerId) + public func transferStarGift(prepaid: Bool, reference: StarGiftReference, peerId: EnginePeer.Id) -> Signal { + return _internal_transferStarGift(account: self.account, prepaid: prepaid, reference: reference, peerId: peerId) } - public func upgradeStarGift(formId: Int64?, messageId: EngineMessage.Id, keepOriginalInfo: Bool) -> Signal { - return _internal_upgradeStarGift(account: self.account, formId: formId, messageId: messageId, keepOriginalInfo: keepOriginalInfo) + public func upgradeStarGift(formId: Int64?, reference: StarGiftReference, keepOriginalInfo: Bool) -> Signal { + return _internal_upgradeStarGift(account: self.account, formId: formId, reference: reference, keepOriginalInfo: keepOriginalInfo) } public func starGiftUpgradePreview(giftId: Int64) -> Signal<[StarGift.UniqueGift.Attribute], NoError> { diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift index a7464fce03..4ccd72efa3 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift @@ -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) diff --git a/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift b/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift index d9f2a3ff6b..efa9e9a297 100644 --- a/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift +++ b/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift @@ -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())) diff --git a/submodules/TelegramUI/Components/Chat/ChatChannelSubscriberInputPanelNode/BUILD b/submodules/TelegramUI/Components/Chat/ChatChannelSubscriberInputPanelNode/BUILD index 4762ea4204..418c7fbfa7 100644 --- a/submodules/TelegramUI/Components/Chat/ChatChannelSubscriberInputPanelNode/BUILD +++ b/submodules/TelegramUI/Components/Chat/ChatChannelSubscriberInputPanelNode/BUILD @@ -23,6 +23,7 @@ swift_library( "//submodules/TelegramUI/Components/Chat/ChatInputPanelNode", "//submodules/AccountContext", "//submodules/TelegramUI/Components/PeerManagement/OldChannelsController", + "//submodules/TooltipUI", ], visibility = [ "//visibility:public", diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageGiftBubbleContentNode/Sources/ChatMessageGiftBubbleContentNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageGiftBubbleContentNode/Sources/ChatMessageGiftBubbleContentNode.swift index 11569668ea..ecc44cc1f0 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageGiftBubbleContentNode/Sources/ChatMessageGiftBubbleContentNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageGiftBubbleContentNode/Sources/ChatMessageGiftBubbleContentNode.swift @@ -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 { diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageWebpageBubbleContentNode/Sources/ChatMessageWebpageBubbleContentNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageWebpageBubbleContentNode/Sources/ChatMessageWebpageBubbleContentNode.swift index ab53dd68ed..a15141529b 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageWebpageBubbleContentNode/Sources/ChatMessageWebpageBubbleContentNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageWebpageBubbleContentNode/Sources/ChatMessageWebpageBubbleContentNode.swift @@ -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 } } } diff --git a/submodules/TelegramUI/Components/ChatTitleView/Sources/ChatTitleView.swift b/submodules/TelegramUI/Components/ChatTitleView/Sources/ChatTitleView.swift index b9fad025fe..49baa6bdf6 100644 --- a/submodules/TelegramUI/Components/ChatTitleView/Sources/ChatTitleView.swift +++ b/submodules/TelegramUI/Components/ChatTitleView/Sources/ChatTitleView.swift @@ -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 )), diff --git a/submodules/TelegramUI/Components/Gifts/GiftAnimationComponent/Sources/GiftCompositionComponent.swift b/submodules/TelegramUI/Components/Gifts/GiftAnimationComponent/Sources/GiftCompositionComponent.swift index dff5e42cb3..8a167de994 100644 --- a/submodules/TelegramUI/Components/Gifts/GiftAnimationComponent/Sources/GiftCompositionComponent.swift +++ b/submodules/TelegramUI/Components/Gifts/GiftAnimationComponent/Sources/GiftCompositionComponent.swift @@ -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)) } diff --git a/submodules/TelegramUI/Components/Gifts/GiftOptionsScreen/Sources/GiftOptionsScreen.swift b/submodules/TelegramUI/Components/Gifts/GiftOptionsScreen/Sources/GiftOptionsScreen.swift index aa61c9ecb8..fed1db39b7 100644 --- a/submodules/TelegramUI/Components/Gifts/GiftOptionsScreen/Sources/GiftOptionsScreen.swift +++ b/submodules/TelegramUI/Components/Gifts/GiftOptionsScreen/Sources/GiftOptionsScreen.swift @@ -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 { diff --git a/submodules/TelegramUI/Components/Gifts/GiftSetupScreen/Sources/ChatGiftPreviewItem.swift b/submodules/TelegramUI/Components/Gifts/GiftSetupScreen/Sources/ChatGiftPreviewItem.swift index f9059e1cb8..6849e2ea48 100644 --- a/submodules/TelegramUI/Components/Gifts/GiftSetupScreen/Sources/ChatGiftPreviewItem.swift +++ b/submodules/TelegramUI/Components/Gifts/GiftSetupScreen/Sources/ChatGiftPreviewItem.swift @@ -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() let messages = SimpleDictionary() - 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) ) ] } diff --git a/submodules/TelegramUI/Components/Gifts/GiftSetupScreen/Sources/GiftSetupScreen.swift b/submodules/TelegramUI/Components/Gifts/GiftSetupScreen/Sources/GiftSetupScreen.swift index 4ef057c292..aaa61502d2 100644 --- a/submodules/TelegramUI/Components/Gifts/GiftSetupScreen/Sources/GiftSetupScreen.swift +++ b/submodules/TelegramUI/Components/Gifts/GiftSetupScreen/Sources/GiftSetupScreen.swift @@ -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 )), diff --git a/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift b/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift index bac312a9b3..499b46be2f 100644 --- a/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift +++ b/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift @@ -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)? = 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) diff --git a/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftWithdrawAlertController.swift b/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftWithdrawAlertController.swift new file mode 100644 index 0000000000..fe8da55fdc --- /dev/null +++ b/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftWithdrawAlertController.swift @@ -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() + private let textNode: ASTextNode + private let arrowNode: ASImageNode + private let avatarView = ComponentView() + + 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 +} diff --git a/submodules/TelegramUI/Components/MediaScrubberComponent/Sources/MediaScrubberComponent.swift b/submodules/TelegramUI/Components/MediaScrubberComponent/Sources/MediaScrubberComponent.swift index 14190505c4..3a5b90a3b3 100644 --- a/submodules/TelegramUI/Components/MediaScrubberComponent/Sources/MediaScrubberComponent.swift +++ b/submodules/TelegramUI/Components/MediaScrubberComponent/Sources/MediaScrubberComponent.swift @@ -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 ) diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoCoverComponent/Sources/PeerInfoCoverComponent.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoCoverComponent/Sources/PeerInfoCoverComponent.swift index 1a2253e243..5d5bd6f198 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoCoverComponent/Sources/PeerInfoCoverComponent.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoCoverComponent/Sources/PeerInfoCoverComponent.swift @@ -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)) diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/Panes/PeerInfoRecommendedPeersPane.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/Panes/PeerInfoRecommendedPeersPane.swift index 716cb16119..7db1a84a53 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/Panes/PeerInfoRecommendedPeersPane.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/Panes/PeerInfoRecommendedPeersPane.swift @@ -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) } } } diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoHeaderNode.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoHeaderNode.swift index 162eac20a0..19416cf367 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoHeaderNode.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoHeaderNode.swift @@ -102,6 +102,7 @@ final class PeerInfoHeaderNode: ASDisplayNode { let backgroundBannerView: UIView let backgroundCover = ComponentView() + 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) } } diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift index 6a3bdbfc21..727be1bf6c 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift @@ -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) + } +} diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoGiftsPaneNode.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoGiftsPaneNode.swift index 1a9ba0f76a..c7cf10ca65 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoGiftsPaneNode.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoGiftsPaneNode.swift @@ -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 { diff --git a/submodules/TelegramUI/Components/Premium/PremiumStarComponent/Sources/GiftAvatarComponent.swift b/submodules/TelegramUI/Components/Premium/PremiumStarComponent/Sources/GiftAvatarComponent.swift index 91fbf41205..ca67a9589a 100644 --- a/submodules/TelegramUI/Components/Premium/PremiumStarComponent/Sources/GiftAvatarComponent.swift +++ b/submodules/TelegramUI/Components/Premium/PremiumStarComponent/Sources/GiftAvatarComponent.swift @@ -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 diff --git a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerViewSendMessage.swift b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerViewSendMessage.swift index b491063a4d..7fbb6462be 100644 --- a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerViewSendMessage.swift +++ b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerViewSendMessage.swift @@ -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 in + |> mapToSignal { result -> Signal 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 } diff --git a/submodules/TelegramUI/Components/VideoMessageCameraScreen/Sources/VideoMessageCameraScreen.swift b/submodules/TelegramUI/Components/VideoMessageCameraScreen/Sources/VideoMessageCameraScreen.swift index b2069496b0..716d7584cf 100644 --- a/submodules/TelegramUI/Components/VideoMessageCameraScreen/Sources/VideoMessageCameraScreen.swift +++ b/submodules/TelegramUI/Components/VideoMessageCameraScreen/Sources/VideoMessageCameraScreen.swift @@ -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 diff --git a/submodules/TelegramUI/Sources/Chat/ChatControllerLoadDisplayNode.swift b/submodules/TelegramUI/Sources/Chat/ChatControllerLoadDisplayNode.swift index 00a81deb5a..d30af2886b 100644 --- a/submodules/TelegramUI/Sources/Chat/ChatControllerLoadDisplayNode.swift +++ b/submodules/TelegramUI/Sources/Chat/ChatControllerLoadDisplayNode.swift @@ -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 { diff --git a/submodules/TelegramUI/Sources/OpenResolvedUrl.swift b/submodules/TelegramUI/Sources/OpenResolvedUrl.swift index 37d9bd76f3..ef517b9397 100644 --- a/submodules/TelegramUI/Sources/OpenResolvedUrl.swift +++ b/submodules/TelegramUI/Sources/OpenResolvedUrl.swift @@ -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) } diff --git a/submodules/TelegramUI/Sources/SharedAccountContext.swift b/submodules/TelegramUI/Sources/SharedAccountContext.swift index b16eeaf750..7aaf6bc9db 100644 --- a/submodules/TelegramUI/Sources/SharedAccountContext.swift +++ b/submodules/TelegramUI/Sources/SharedAccountContext.swift @@ -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 {